On 02/09/2016 07:27 AM, Bin.Cheng wrote:
On Fri, Feb 5, 2016 at 10:32 AM, Ilya Enkovich <enkovich....@gmail.com> wrote:
2016-02-04 19:16 GMT+03:00 Bin.Cheng <amker.ch...@gmail.com>:
On Thu, Feb 4, 2016 at 3:18 PM, Ilya Enkovich <enkovich....@gmail.com> wrote:
2016-02-04 17:12 GMT+03:00 Bin.Cheng <amker.ch...@gmail.com>:
Hi,
I noticed that pic_offset_table_rtx is initialized twice in GCC. Take
x86_32 as an example.
The first initialization is done in emit_init_regs, with below code:
pic_offset_table_rtx = NULL_RTX;
if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
On x86_32 with pic, we have:
(gdb) call debug_rtx(this_target_rtl->x_pic_offset_table_rtx)
(reg:SI 3 bx)
The second initialization is in expand_used_vars, with below code:
if (targetm.use_pseudo_pic_reg ())
pic_offset_table_rtx = gen_reg_rtx (Pmode);
On x86_32 with pic, we have:
(gdb) call debug_rtx(this_target_rtl->x_pic_offset_table_rtx)
(reg:SI 87)
So basically after expanding the first function, pic_offset_table_rtx
is set to a pseudo register, rather than the one initialized in
emit_init_regs.
Also this causes inconsistent compilation for the first/rest functions
in one compilation unit.
A bug?
For i386 target PIC_OFFSET_TABLE_REGNUM actually checks
ix86_use_pseudo_pic_reg and is supposed to return INVALID_REGNUM
in case we use pseudo register for PIC. BUT we hit a case when PIC
code is generated for cost estimation via target hooks while performing
some GIMPLE pass. In this case we need to return some register to
Thanks IIya. This is exact the case I ran into. See PR69042.
generate PIC usage but we don't have any allocated. In this case we
return a hard register. We detect such situation by checking
pic_offset_table_rtx.
Thus if we use pseudo PIC register but pic_offset_table_rtx is not
initialized yet,
then PIC_OFFSET_TABLE_REGNUM returns a hard register.
So I suppose we may consider the first assignment as a bug.
But I don't quite follow. So hard register is returned so that gimple
passes can construct PIC related addresses? If this is the case, the
first initialization is necessary.
Right, we need some initialization but current way leads to inconsistent
value and we may 'randomly' get hard or pseudo register for different functions
which possibly affects some optimizations. We probably need a better
way to check if we should return a hard reg for PIC register. Or maybe
reset ix86_use_pseudo_pic_reg to NULL when function is finalized or
get rid of hard reg at all and always use a pseudo register.
Another question is about address cost:
if (parts.index
&& (!REG_P (parts.index) || REGNO (parts.index) >= FIRST_PSEUDO_REGISTER)
&& (current_pass->type == GIMPLE_PASS
|| !pic_offset_table_rtx
|| !REG_P (parts.index)
|| REGNO (pic_offset_table_rtx) != REGNO (parts.index)))
cost++;
Is it a bug in the second sub condition? Considering
"current_pass->type == GIMPLE_PASS" in the third sub condition, can I
assume the second is for non-GIMPLE passes only?
There is just a code duplicated for parts.base and parts.index
registers. We use same
conditions for both of them because you can easily swap them if scale is 1.
I don't know why we don't try to recognize PIC registers when in GIMPLE pass.
Could we define PIC_OFFSET_TABLE_REGNUM to a pseudo register when
ix86_use_pseudo_pic_reg returns true, as in this case? Current logic
doesn't look consistent to me. Of course, I know little about x86.
I think defining it as a hard reg was a stopgap. I don't think we've
got the level of consistency we want for PIC register as a pseudo
throughout the generic code or hte x86 backend.
My recollection is that it doesn't appear in the IL as a hard register
anymore.
jeff