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.

Reply via email to