> On Sep 21, 2020, at 2:23 AM, Richard Sandiford <richard.sandif...@arm.com>
> wrote:
>
> Qing Zhao <qing.z...@oracle.com <mailto:qing.z...@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.
Yes, this is what I am currently doing:
First, the middle end computes the initial need_zeroed_hardregs based on user
request, data flow, and function abi. Then pass this “need_zeroed_hardregs” to
target hook;
Then, the target hook will delete some of the registers that should not be
zeroed in that specific target from “need_zeroed_hardregs”, for example,
stack_regs on x86.
>
>> 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.
Yes, the stack_regs currently can be referenced as STACK_REG_P in middle end.
So for X86, we might be able to identify this in middle end.
However, my major concern is other platforms that we are not very familiar
with, there might be some special registers on that platform that should not be
zeroed, and currently, there is no way to identify them in middle end.
For such platform, the default handler will not be correct.
>
>> 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 ®s)
>
> 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.
Even for the general registers on X86, we need some special optimization for
optimal code generation, for example, we might want to optimize
A “mov” to xor on X86;
My major concern with the default implementation of the hook is:
If a target has some special registers that should not be zeroed, and we do not
provide an overridden implementation for this target, then the default
implementation will generate incorrect code for this target.
How to resolve this issue?
thanks.
Qing
>
> Thanks,
> Richard