Uros Bizjak <ubiz...@gmail.com> writes: > On Mon, Jun 20, 2016 at 9:19 PM, H.J. Lu <hjl.to...@gmail.com> wrote: >> On Mon, Jun 20, 2016 at 12:13 PM, Uros Bizjak <ubiz...@gmail.com> wrote: >>> On Mon, Jun 20, 2016 at 7:05 PM, H.J. Lu <hongjiu...@intel.com> wrote: >>>> Hi, >>>> >>>> This patch implements the alternate code sequence recommended in >>>> >>>> https://groups.google.com/forum/#!topic/x86-64-abi/de5_KnLHxtI >>>> >>>> to load external function address via GOT slot with >>>> >>>> movq func@GOTPCREL(%rip), %rax >>>> >>>> so that linker won't create an PLT entry for extern function >>>> address. >>>> >>>> Tested on x86-64. OK for trunk? >>> >>>> + else if (ix86_force_load_from_GOT_p (op1)) >>>> + { >>>> + /* Load the external function address via the GOT slot to >>>> + avoid PLT. */ >>>> + op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op1), >>>> + (TARGET_64BIT >>>> + ? UNSPEC_GOTPCREL >>>> + : UNSPEC_GOT)); >>>> + op1 = gen_rtx_CONST (Pmode, op1); >>>> + op1 = gen_const_mem (Pmode, op1); >>>> + /* This symbol must be referenced via a load from the Global >>>> + Offset Table. */ >>>> + set_mem_alias_set (op1, ix86_GOT_alias_set ()); >>>> + op1 = convert_to_mode (mode, op1, 1); >>>> + op1 = force_reg (mode, op1); >>>> + emit_insn (gen_rtx_SET (op0, op1)); >>>> + /* Generate a CLOBBER so that there will be no REG_EQUAL note >>>> + on the last insn to prevent cse and fwprop from replacing >>>> + a GOT load with a constant. */ >>>> + rtx tmp = gen_reg_rtx (Pmode); >>>> + emit_clobber (tmp); >>>> + return; >>> >>> Jeff, is this the recommended way to prevent CSE, as far as RTL >>> infrastructure is concerned? I didn't find any example of this >>> approach with other targets. >>> >> >> FWIW, the similar approach is used in ix86_expand_vector_move_misalign, >> ix86_expand_convert_uns_didf_sse and ix86_expand_vector_init_general >> as well as other targets: >> >> frv/frv.c: emit_clobber (op0); >> frv/frv.c: emit_clobber (op1); >> im32c/m32c.c: /* emit_clobber (gen_rtx_REG (HImode, R0L_REGNO)); */ >> s390/s390.c: emit_clobber (addr); >> s390/s390.md: emit_clobber (reg0); >> s390/s390.md: emit_clobber (reg1); >> s390/s390.md: emit_clobber (reg0); >> s390/s390.md: emit_clobber (reg0); >> s390/s390.md: emit_clobber (reg1); > > These usages mark the whole register as being "clobbered" > (=undefined), before only a part of register is written, e.g.: > > emit_clobber (int_xmm); > emit_move_insn (gen_lowpart (DImode, int_xmm), input); > > They aren't used to prevent unwanted CSE.
Since it's being called in the move expander, I thought the normal way of preventing the constant being rematerialised would be to reject it in the move define_insn predicates. FWIW, I agree that using a clobber for this is going to be fragile. Thanks, Richard