PING [Patch][Middle-end]Add -fzero-call-used-regs=[skip|used-gpr|all-gpr|used|all]

Qing Zhao QING.ZHAO@ORACLE.COM
Fri Sep 11 22:24:58 GMT 2020



> On Sep 11, 2020, at 4:44 PM, Richard Sandiford <richard.sandiford@arm.com> wrote:
> 
> Qing Zhao <QING.ZHAO@ORACLE.COM> writes:
>>> On Sep 11, 2020, at 12:32 PM, Richard Sandiford <richard.sandiford@arm.com> >>  If we go for (2), then I think it would be better to do
>>> it at the start of pass_late_compilation instead.  (Some targets wouldn't
>>> cope with doing it later.)  The reason for doing it so late is that the
>>> set of used “volatile”/caller-saved registers is not fixed at prologue
>>> and epilogue generation: later optimisation passes can introduce uses
>>> of volatile registers that weren't used previously.  (Sorry if this
>>> has already been suggested.)
>> 
>> Yes, I agree.
>> 
>> I thought that it might be better to move this task at the very late of the RTL stage, i.e, before “final” phase. 
>> 
>> Another solution is (discussed with Hongjiu):
>> 
>> 1. Define a new target hook:
>> 
>> targetm.return_with_zeroing(bool simple_return_p, HARD_REG_SET need_zeroed_hardregs, bool gpr_only)
>> 
>> 2. Add the following routine in middle end:
>> 
>> rtx_insn *
>> generate_return_rtx (bool simple_return_p)
>> {
>>  if (targetm.return_with_zeroing)
>>    {
>>      Compute the hardregs set for clearing into “need_zeroed_hardregs”;
>>     return targetm.return_with_zeroing (simple_return_p, need_zeroed_hardregs, gpr_only);
>>   }
>> else
>>    {
>>     if (simple_return_p)
>>       return targetm.gen_simple_return ( );
>>    else
>>       return targetm.gen_return ();
>>  }
>> }
>> 
>> Then replace all call to “targetm.gen_simple_return” and “targetm.gen_return” to “generate_return_rtx()”.
>> 
>> 3. In the target, 
>> Implement “return_with_zeroing”.
>> 
>> 
>> Let me know your comments on this.
> 
> I think having a separate pass is better.  We don't normally know
> at the point of generating the return which registers will need
> to be cleared.  

At the point of generating the return, we can compute the “need_zeroed_hardregs” HARD_REG_SET 
by using data flow information, the function abi of the routine, and also the user option and source code 
attribute information together. These information should be available at each point when generating the return.


> So IMO the pass should just search for all the
> returns in a function and insert the zeroing instructions before
> each one.

I was considering this approach too for some time, however, there is one major issue with this as 
Segher mentioned, The middle end does not know some details on the registers, lacking such 
detailed information might result incorrect code generation at middle end.

For example, on x86_64 target, when “return” with pop, the scratch register “ECX” will be 
used for returning, then it’s incorrect to zero “ecx” before generating the return. Since middle end
doesn't have such information, it cannot avoid to zero “ecx”. Therefore incorrect code might be 
generated. 

Segher also mentioned that on Power, there are some scratch registers also are used for 
Other purpose, clearing them before return is not correct. 


> 
> Having a target hook sounds good, but I think it should have a
> default definition that just uses the move patterns to zero each
> selected register.  I expect the default will be good enough for
> most targets.

Based on the above, I think that generating the zeroing instructions at middle end is not correct. 

Thanks.

Qing
> 
> Thanks,
> Richard



More information about the Gcc-patches mailing list