On Fri, 2022-03-11 at 16:08 +0000, Qing Zhao wrote:
> Why there is “mthi $0” instruction, but there is NO emit_move_insn(HI,
> CONST_0)?
> Is such mismatch a bug? If not, why?
>
> > In theory it's possible
> > to emit the mthi instruction explicitly here though, but we'll need to
> > clear something NOT in need_zeroed_hardregs for MIPS anyway (see below).
>
> One question here, is there situation when only HI is cleared but LO is not
> cleared?
No, if I interpret the document of -fzero_call_used_regs and
attribute((zero_call_used_regs(...))) correctly. A 2-reg multiplication
(or division) always set the value of both HI and LO. Richard has added
a comment for this in mips.cc:
> 12868 /* After a multiplication or division, clobbering HI makes
> 1 the value of LO unpredictable, and vice versa. This means
> 2 that, for all interesting cases, HI and LO are effectively
> 3 a single register.
> 4
> 5 We model this by requiring that any value that uses HI
> 6 also uses LO. */
This is also why the handling of emit_move_insn(HI, CONST_0) was
removed, I guess (the removal happened in the same commit adding this
comment).
> > >
> Okay, I see. So, each ST_REGi register is a 1-bit pseudo register?
> But physically each of them is 1-bit in a physical register?
Yes.
> >
> > Because there is no elegant way to clear one specific FCC bit in MIPS.
> > A "ctc1 $0, $25" instruction will zero them altogether. If we really
> > need to clear only one of them (let's say ST_REG3), we'll have to emit
> > something like
> >
> > mtc1 $0, $0 # zero FPR0 to ensure it won't contain sNaN
> > c.f.s $3, $0, $0
> >
> > Then we'll still need to clobber FPR0 with zero. So anyway we'll have
> > to clear some registers not specified in need_zeroed_hardregs.
>
> So, “c.f.s” instruction can be used to clear ONLY one specific FCC bit?
> But you have to clear one FPR (floating pointer register?) first to avoid
> raising exception?
> My question here is: is there a case when only FCC need to be cleared but no
> FPR need to be cleared?
Yes, for example:
double a, b;
struct x
{
double a, b;
};
struct x
f(void)
{
struct x x =
{
.a = a,
.b = b
};
if (a < b)
x.a = x.b;
return x;
}
It does not need to zero the two FPRs, as they contain the return value.
But a FCC bit needs to be cleared.
> If NOT, then we can always pick one FPRi before c.f.s to avoid the
> issue you mentioned (We’ll have to clear some registers not specified
> in need_zeroed_hardregs).
I'm now thinking: is there always at least one *GPR* which need to be
cleared? If it's true, let's say GPR $12, and fcc0 & fcc2 needs to be
cleared, we can use something like:
cfc1 $12, $25
andi $25, 5
ctc1 $12, $25
move $12, $0
> > And the question is: is it really allowed to return something other than
> > a subset of need_zeroed_hardregs for a TARGET_ZERO_CALL_USED_REGS hook?
>
> Although currently there is no assertion added to force this
> requirement, I still think that we should keep it.
>
> The “need_zeroed_hardregs” is computed based on
>
> 1. User’s request from command line option;
> 2. Data flow info of the routine;
> 3. Abi info of the target;
>
> If zero_call_used_regs target hook return registers out of
> “need_zeroed_hardregs” set, then it might out of the user’s exception,
> it should be considered as a bug, I think.
I have the same concern. But now I'm too sleepy... Will try to improve
this tomorrow.
--
Xi Ruoyao <[email protected]>
School of Aerospace Science and Technology, Xidian University