> On Sep 30, 2020, at 4:21 AM, Richard Sandiford <richard.sandif...@arm.com> 
> wrote:
> 
> Qing Zhao <qing.z...@oracle.com <mailto:qing.z...@oracle.com>> writes:
>> Hi, Richard,
>> 
>> At the same time testing aarch64, I also tested the default implementation 
>> on rs6000 target. 
>> 
>> The default implementation now is:
>> 
>> +/* The default hook for TARGET_ZERO_CALL_USED_REGS.  */
>> +
>> +HARD_REG_SET
>> +default_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
>> +{
>> +  gcc_assert (!hard_reg_set_empty_p (need_zeroed_hardregs));
>> +
>> +  for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
>> +    if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
>> +      {
>> +       machine_mode mode = reg_raw_mode[regno];
>> +       rtx reg = gen_rtx_REG (mode, regno);
>> +       emit_move_insn (reg, const0_rtx);
> 
> This should just be:
> 
>       rtx zero = CONST0_RTX (reg_raw_mode[regno]);
>       emit_move_insn (regno_reg_rtx[regno], zero);

Okay. Will update the code.

> 
>> +      }
>> +  return need_zeroed_hardregs;
>> +}
>> +
>> 
>> With the small testing case:
>> int
>> test ()
>> {
>>  return 1;
>> }
>> 
>> If I compiled it with 
>> 
>> /home/qinzhao/Install/latest/bin/gcc -O2 -fzero-call-used-regs=all-arg t.c
>> 
>> It will failed as:
>> 
>> t.c: In function ‘test’:
>> t.c:6:1: error: insn does not satisfy its constraints:
>>    6 | }
>>      | ^
>> (insn 28 27 29 (set (reg:DI 33 1)
>>        (const_int 0 [0])) "t.c":6:1 647 {*movdi_internal64}
>>     (nil))
>> during RTL pass: shorten
>> dump file: t.c.319r.shorten
>> t.c:6:1: internal compiler error: in extract_constrain_insn_cached, at 
>> recog.c:2207
>> 0x1018d693 _fatal_insn(char const*, rtx_def const*, char const*, int, char 
>> const*)
>>      ../../latest-gcc-x86/gcc/rtl-error.c:108
>> 0x1018d6e7 _fatal_insn_not_found(rtx_def const*, char const*, int, char 
>> const*)
>>      ../../latest-gcc-x86/gcc/rtl-error.c:118
>> 0x1099a82b extract_constrain_insn_cached(rtx_insn*)
>>      ../../latest-gcc-x86/gcc/recog.c:2207
>> 0x11393917 insn_min_length(rtx_insn*)
>>      ../../latest-gcc-x86/gcc/config/rs6000/rs6000.md:721
>> 0x105bece3 shorten_branches(rtx_insn*)
>>      ../../latest-gcc-x86/gcc/final.c:1118
>> 
>> 
>> As I checked, when the FP registers are zeroed, the above failure happened.
>> 
>> I suspect that the issue still relate to the following statement:
>> 
>> machine_mode mode = reg_raw_mode[regno];
>> 
>> As I checked, the reg_raw_mode always return the integer mode that can be 
>> hold by the hard registers, even though it’s FP register.
> 
> Well, more precisely: it's the largest mode that the target allows the
> registers to hold.  If there are multiple candidate modes of the same
> size, the integer one wins, like you say.  But the point is that DI only
> wins over DF because the target allows both DI and DF to be stored in
> the register, and therefore supports both DI and DF moves for that
> register.
> 
> So I don't think the mode is the issue.  Integer zero and floating-point
> zero have the same bit representation after all.

theoritically  yes. 
However, as we have noticed in Aarch64, the integer TI move has not been 
supported before your fix today. As a result, the Ti move have to be splitted.
With your fix today on aarch64,  Yes, the default implementation works well for 
those vector registers. Thanks a lot.

Potentially there will be other targets that have the same issue. Then those 
targets need to fix those issues too in order to make the default 
implementation work.

> 
> AIUI, without VSX, Power needs to load the zero from the constant pool.
> 
>> So, I still wondering:
>> 
>> 1. Is there another available utility routine that returns the proper MODE 
>> for the hard registers that can be readily used to zero the hard register?
>> 2. If not, should I add one more target hook for this purpose? i.e 
>> 
>> /* Return the proper machine mode that can be used to zero this hard 
>> register specified by REGNO.  */
>> machine_mode zero-call-used-regs-mode (unsigned int REGNO)
>> 
>> 3. Or should I just delete the default implemeantion, and let the target to 
>> implement it.
> 
> IMO no.  This goes back to what we discussed earlier.  It isn't the
> case that a default target hook has to be correct for all targets,
> with targets only overriding them as an optimisation.  The default
> versions of many hooks and macros are not conservatively correct.
> They are just reaonable default assumptions.  And IMO that's true
> of the hook above too.
> 
> The way to flush out whether a target needs to override the hook
> is to add tests that run on all targets.
I planned to add these new test cases, so currently I have been testing the 
simple testing cases on aarch64 and rs6000 to see any issue 
With the default implementation. So far, I have found these issues with the 
very simple testing cases.

For me, at most I can test aarch64 and rs6000 targets for some small testing 
cases for checking correctness.
> 
> That said, one way of erring on the side of caution from an ICE
> perspective would be to do something like:
> 
>    rtx_insn *last_insn = get_last_insn ();
>    rtx zero = CONST0_RTX (reg_raw_mode[regno]);
>    rtx_insn *insn = emit_insn (gen_rtx_SET (regno_reg_rtx[regno], zero));
>    if (!valid_insn_p (insn))
>      {
>        delete_insns_since (last_insn);
>        ...remove regno from the set of cleared registers...;
>      }
> 
> where valid_insn_p abstracts out this code from ira.c:
> 
>         recog_memoized (move_insn);
>         if (INSN_CODE (move_insn) < 0)
>           continue;
>         extract_insn (move_insn);
>         /* We don't know whether the move will be in code that is optimized
>            for size or speed, so consider all enabled alternatives.  */
>         if (! constrain_operands (1, get_enabled_alternatives (move_insn)))
>           continue;
> 
> (but keeping the comment where it is).  The default behaviour would then
> be to drop any register that can't be zeroed easily.

I will check whether the above fix the ICE on rs6000.
> 
> Doing this would make the default hook usable for more targets.
> The question is whether dropping registers that can't be zeroed
> easily is acceptable as a default policy for a security feature.

If a “move_insn” is Not a valid insn per the above checking, can that “hard 
register” still be zeroed? 
> 
> I'm still a bit unsure what criteria are being applied to decide whether
> a register is worth zeroing or not, given that you were also talking about
> dropping mm0-7 and k0-7.

Should leaving such decision to targets make more sense?

Thanks.

Qing

> 
> Thanks,
> Richard

Reply via email to