2016-02-09 19:24 GMT+03:00 Jeff Law <l...@redhat.com>: > 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.
Unfortunately we still use it as EBX. It happens when we try to compute address cost and call target hook to legitimize address for that. It involves pic_offset_table_rtx usage and would ICE if we don't initialize it. Since pic_offset_table_rtx initialization in init_emit_regs happens only if PIC_OFFSET_TABLE_REGNUM holds some hard reg, we use EBX_REG value as workaround. When some function is expanded pic_offset_table_rtx gets a pseudo register which is used for address legitimization during next function optimization. Thus we have a kind of inconsistency using either hard or pseudo register for address cost estimation depending on function compilation order. Thanks, Ilya > jeff >