On Sun, Mar 4, 2012 at 2:52 PM, Uros Bizjak <ubiz...@gmail.com> wrote: > On Sun, Mar 4, 2012 at 11:38 PM, H.J. Lu <hjl.to...@gmail.com> wrote: >> On Sun, Mar 4, 2012 at 2:12 PM, Uros Bizjak <ubiz...@gmail.com> wrote: >>> On Fri, Mar 2, 2012 at 9:36 PM, H.J. Lu <hongjiu...@intel.com> wrote: >>> >>>> X86-64 linker optimizes TLS_MODEL_INITIAL_EXEC to TLS_MODEL_LOCAL_EXEC >>>> by checking >>>> >>>> movq foo@gottpoff(%rip), %reg >>>> >>>> and >>>> >>>> addq foo@gottpoff(%rip), %reg >>>> >>>> It uses the REX prefix to avoid the last byte of the previous >>>> instruction. With 32bit Pmode, we may not have the REX prefix and >>>> the last byte of the previous instruction may be an offset, which >>>> may look like a REX prefix. IE->LE optimization will generate corrupted >>>> binary. This patch makes sure we always output an REX pfrefix for >>>> UNSPEC_GOTNTPOFF. OK for trunk? >>> >>> No, please implement this using UNSPEC in the same way as >>> tls_initial_exec_64_sun implements Sun linker quirk. >>> >> >> I am not sure how it can be done with UNSPEC cleanly. >> Unlike the Sun linker issue, this is an instruction encoding >> issue. At instruction pattern level, there is no difference >> between x32 and x86-64. I need to make sure that there is >> always one and only one REX prefix with UNSPEC_GOTNTPOFF. >> If REG is r8-r15, we shouldn't add another REX prefix. > > (define_insn "tls_initial_exec_x32" > [(set (match_operand:SI 0 "register_operand" "=r") > (unspec:SI > [(match_operand:SI 1 "tls_symbolic_operand" "")] > UNSPEC_TLS_IE_X32)) > (clobber (reg:CC FLAGS_REG))] > "TARGET_X32" > { > if (!REX_INT_REG_P (operands[0]) > fputs (\trex\n", asm_out_file); > output_asm_insn > ("mov{l}\t{%%fs:0, %0|%0, QWORD PTR fs:0}", operands); > if (!REX_INT_REG_P (operands[0]) > fputs (\trex\n", asm_out_file); > return "add{l}\t{%a1@gottpoff(%%rip), %0|%0, %a1@gottpoff[rip]}"; > } > [(set_attr "type" "multi")]) > > rex or rex64 prefix, whatever you wish. >
Will it introduce bugs? The normal code look like off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), type); off = gen_rtx_CONST (Pmode, off); if (pic) off = gen_rtx_PLUS (Pmode, pic, off); off = gen_const_mem (Pmode, off); set_mem_alias_set (off, ix86_GOT_alias_set ()); if (TARGET_64BIT || TARGET_ANY_GNU_TLS) { base = get_thread_pointer (for_mov || !TARGET_TLS_DIRECT_SEG_REFS); off = force_reg (Pmode, off); return gen_rtx_PLUS (Pmode, base, off); } There is a call to set_mem_alias_set (off, ix86_GOT_alias_set ()); -- H.J.