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

Richard Sandiford richard.sandiford@arm.com
Mon Sep 21 07:23:10 GMT 2020


Qing Zhao <QING.ZHAO@ORACLE.COM> writes:
> Hi, Richard,
>
> During my implementation of the new version of the patch. I still feel that it’s not practical to add a default definition in the middle end to just use move patterns to zero each selected register. 
>
> The major issues are:
>
> There are some target specific information on how to define “general register” set and “all register” set,  we have to add a new specific target hook to get such target specific information and pass to middle-end. 

GENERAL_REGS and ALL_REGS are already concepts that target-independent
code knows about though.  I think the non-fixed subsets of those would
make good starting sets, which the target could whittle down it wanted
or needed to.

> For example, on X86, for CALL_USED_REGISTERS, we have:
>
> #define CALL_USED_REGISTERS                                     \
> /*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7*/      \
> {  1, 1, 1, 0, 4, 4, 0, 1, 1,  1,  1,  1,  1,  1,  1,  1,       \
> /*arg,flags,fpsr,frame*/                                        \
>     1,   1,    1,    1,                                         \
> /*xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7*/                     \
>      1,   1,   1,   1,   1,   1,   6,   6,                      \
> /* mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7*/   
>
>
> From the above, we can see “st0 to st7” are call_used_registers for x86, however, we should not zero these registers on x86. 
>
> Such details is only known by x86 backend. 
>
> I guess that other platforms might have similar issue. 

They might, but that doesn't disprove that there's a sensisble default
choice that works for most targets.

FWIW, stack registers themselves are already exposed outside targets
(see reg-stack.c, although since x86 is the only port that uses it,
the main part of it is effectively target-dependent at the moment).
Similarly for register windows.

> If we still want  a default definition in middle end to generate the zeroing insn for selected registers, I have to add another target hook, say, “ZERO_CALL_USED_REGNO_P(REGNO, GPR_ONLY)” to check whether a register should be zeroed based on gpr_only (general register only)  and target specific decision.   I will provide a x86 implementation for this target hook in this patch. 
>
> Other targets have to implement this new target hook to utilize the default handler. 
>
> Let me know your opinion:
>
> A.  Will not provide default definition in middle end to generate the zeroing insn for selected registers.  Move the generation work all to target; X86 implementation will be provided;
>
> OR:
>
> B.  Will provide a default definition in middle end to generate the zeroing insn for selected registers. Then need to add a new target hook “ZERO_CALL_USED_REGNO_P(REGNO, GPR_ONLY)”, same as A, X86 implementation will be provided in my patch. 

The kind of target hook interface I was thinking of was:

  HARD_REG_SET TARGET_EMIT_MOVE_ZEROS (const HARD_REG_SET &regs)

which:

- emits zeroing instructions for some target-specific subset of REGS

- returns the set of registers that were actually cleared

The default implementation would clear all registers in REGS,
using reg_raw_mode[R] as the mode for register R.  Targets could
then override the hook and:

- drop registers that shouldn't be cleared

- handle some or all of the remaining registers in a more optimal,
  target-specific way

The targets could then use the default implementation of the hook
to handle any residue.  E.g. the default implementation would be
able to handle general registers on x86.

Thanks,
Richard


More information about the Gcc-patches mailing list