> On Sep 25, 2020, at 10:28 AM, Richard Sandiford <richard.sandif...@arm.com>
> wrote:
>
> Qing Zhao <qing.z...@oracle.com <mailto:qing.z...@oracle.com>> writes:
>>> On Sep 25, 2020, at 7:53 AM, Richard Sandiford <richard.sandif...@arm.com>
>>> wrote:
>>>
>>> Qing Zhao <qing.z...@oracle.com> writes:
>>>> Hi, Richard,
>>>>
>>>> As you suggested, I added a default implementation of the target hook
>>>> “zero_cal_used_regs (HARD_REG_SET)” as following in my latest patch
>>>>
>>>>
>>>> /* The default hook for TARGET_ZERO_CALL_USED_REGS. */
>>>>
>>>> void
>>>> default_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
>>>
>>> FWIW, I was suggesting to return the set of registers that are actually
>>> cleared too. Here you have the hook emit the asm statement, but IMO the
>>> way we generate the asm for a given set of registers should be entirely
>>> target-independent, and happen outside the hook.
>>>
>>> So the hook returning the set of cleared registers does two things:
>>>
>>> (1) It indicates which registers should be clobbered by the asm
>>> (which would be generated after calling the hook, but emitted
>>> before the sequence of instructions generated by the hook).
>>
>> For this purpose, this hook should return a Set of RTX that hold the cleared
>> registers, a HARD_REG_SET is not enough.
>>
>> Since in the ASM_OPERANDS, we will need the RTX for the register (not the
>> REGNO).
>>
>> Which data structure in GCC should be used here to hold this returned value
>> as Set of RTX ?
>
> A HARD_REG_SET is enough. All the caller needs to know is: which registers
> were clobbered? It can then represent a clobber of R with a clobber of
> reg_regno_rtx[R].
I did not find reg_regno_rtx in the current gcc source, not sure how to use it?
>
> The mode isn't important for single-register clobbers: clobbering a single
> register in one mode is equivalent to clobbering it in another mode.
> None of the register contents survive the clobber.
Okay, I see.
Then is the following good enough:
/* Generate asm volatile("" : : : "memory") as a memory blockage, at the
same time clobbering the register set specified by ZEROED_REGS. */
void
expand_asm_memory_blockage_clobber_regs (HARD_REG_SET zeroed_regs)
{
rtx asm_op, clob_mem, clob_reg;
/* first get the number of registers that have been zeroed from ZEROED_REGS
set. */
unsigned int num_of_regs = ….;
asm_op = gen_rtx_ASM_OPERANDS (VOIDmode, "", "", 0,
rtvec_alloc (0), rtvec_alloc (0),
rtvec_alloc (0), UNKNOWN_LOCATION);
MEM_VOLATILE_P (asm_op) = 1;
rtvec v = rtvec_alloc (num_of_regs + 2);
clob_mem = gen_rtx_SCRATCH (VOIDmode);
clob_mem = gen_rtx_MEM (BLKmode, clob_mem);
clob_mem = gen_rtx_CLOBBER (VOIDmode, clob_mem);
RTVEC_ELT (v,0) = asm_op;
RTVEC_ELT (v,1) = clob_mem;
for (unsigned int I = 0; i < FIRST_PSEUDO_REGISTER; i++)
If (TEST_HARD_REG_BIT (zeroed_regs, i))
{
clob_reg = gen_rtx_CLOBBER (VOIDmode, reg_regno_rtx[i]);
RTVEC_ELT (v,i+2) = clob_reg;
}
emit_insn (gen_rtx_PARALLEL (VOIDmode, v));
}
How to come up with the above:’
clob_reg = gen_rtx_CLOBBER (VOIDmode, reg_regno_rtx[i]);?
>
>>> (2) It indicates which registers should be treated as live on return.
>>>
>>> FWIW, for (2), I'd recommend storing the returned HARD_REG_SET in crtl.
>>
>> Instead of storing this info in crtl, in my current patch, I added the
>> following in “df-scan.c":
>> +static HARD_REG_SET zeroed_reg_set;
>>
>> And routines that manipulate this HARD_REG_SET.
>> I think that this should serve the same purpose as storing it to crtl?
>
> Storing it in crtl is better for two reasons:
>
> - Using global statics for this kind of thing makes it harder to
> compile functions in parallel. (Work is underway to allow that.)
>
> - Having the information in crtl reduces the risk that information
> from one function will get reused for another function, without the
> variable being reinitialised inbetween.
Okay, will add a new field zeroed_reg_set into crtl.
Thanks.
Qing
>
> Thanks,
> Richard