Inconsistent initialization for pic_offset_table_rtx?
Jeff Law
law@redhat.com
Tue Feb 9 16:24:00 GMT 2016
On 02/09/2016 07:27 AM, Bin.Cheng wrote:
> On Fri, Feb 5, 2016 at 10:32 AM, Ilya Enkovich <enkovich.gnu@gmail.com> wrote:
>> 2016-02-04 19:16 GMT+03:00 Bin.Cheng <amker.cheng@gmail.com>:
>>> On Thu, Feb 4, 2016 at 3:18 PM, Ilya Enkovich <enkovich.gnu@gmail.com> wrote:
>>>> 2016-02-04 17:12 GMT+03:00 Bin.Cheng <amker.cheng@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
More information about the Gcc
mailing list