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. Thanks, bin > > Thanks, > Ilya > >> >> Thanks, >> bin >>> >>> Thanks, >>> Ilya >>> >>>> >>>> Thanks, >>>> bin