On Wed, Dec 4, 2013 at 10:12 AM, Yufeng Zhang <yufeng.zh...@arm.com> wrote:
> On 12/03/13 21:24, Andrew Pinski wrote:
>>
>> Hi,
>>    With ILP32, some simple usage of TLS variables causes an unrecognizable
>> instruction due to needing to use SImode for loading pointers from memory.
>> This fixes the three (tlsie_small, tlsle_small, tlsdesc_small) patterns to
>> support SImode for pointers.
>>
>> OK?  Build and tested on aarch64-elf with no regressions.
>>
>> Thanks,
>> Andrew Pinski
>>
>>         * config/aarch64/aarch64.c (aarch64_load_symref_appropriately):
>>         Handle TLS for ILP32.
>>         * config/aarch64/aarch64.md (tlsie_small): Change to an expand to
>>         handle ILP32.
>>         (tlsie_small_<mode>): New pattern.
>>         (tlsle_small): Change to an expand to handle ILP32.
>>         (tlsle_small_<mode>): New pattern.
>>         (tlsdesc_small): Change to an expand to handle ILP32.
>>         (tlsdesc_small_<mode>): New pattern.
>> ---
>>   gcc/ChangeLog                 |   12 ++++++
>>   gcc/config/aarch64/aarch64.c  |   23 ++++++++++--
>>   gcc/config/aarch64/aarch64.md |   76
>> ++++++++++++++++++++++++++++++++++-------
>>   3 files changed, 94 insertions(+), 17 deletions(-)
>>
>> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
>> index b1b4eef..a3e4532 100644
>> --- a/gcc/config/aarch64/aarch64.c
>> +++ b/gcc/config/aarch64/aarch64.c
>> @@ -628,22 +628,37 @@ aarch64_load_symref_appropriately (rtx dest, rtx
>> imm,
>>
>>       case SYMBOL_SMALL_TLSDESC:
>>         {
>> -       rtx x0 = gen_rtx_REG (Pmode, R0_REGNUM);
>> +       enum machine_mode mode = GET_MODE (dest);
>> +       rtx x0 = gen_rtx_REG (mode, R0_REGNUM);
>>         rtx tp;
>>
>> +       gcc_assert (mode == Pmode || mode == ptr_mode);
>> +
>>         emit_insn (gen_tlsdesc_small (imm));
>>         tp = aarch64_load_tp (NULL);
>> -       emit_insn (gen_rtx_SET (Pmode, dest, gen_rtx_PLUS (Pmode, tp,
>> x0)));
>> +
>> +       if (mode != Pmode)
>> +         tp = gen_lowpart (mode, tp);
>> +
>> +       emit_insn (gen_rtx_SET (mode, dest, gen_rtx_PLUS (mode, tp, x0)));
>>         set_unique_reg_note (get_last_insn (), REG_EQUIV, imm);
>>         return;
>>         }
>>
>>       case SYMBOL_SMALL_GOTTPREL:
>>         {
>> -       rtx tmp_reg = gen_reg_rtx (Pmode);
>> +       enum machine_mode mode = GET_MODE (dest);
>> +       rtx tmp_reg = gen_reg_rtx (mode);
>>         rtx tp = aarch64_load_tp (NULL);
>> +
>> +       gcc_assert (mode == Pmode || mode == ptr_mode);
>> +
>>         emit_insn (gen_tlsie_small (tmp_reg, imm));
>> -       emit_insn (gen_rtx_SET (Pmode, dest, gen_rtx_PLUS (Pmode, tp,
>> tmp_reg)));
>> +
>> +       if (mode != Pmode)
>> +         tp = gen_lowpart (mode, tp);
>> +
>> +       emit_insn (gen_rtx_SET (mode, dest, gen_rtx_PLUS (mode, tp,
>> tmp_reg)));
>>         set_unique_reg_note (get_last_insn (), REG_EQUIV, imm);
>>         return;
>>         }
>> diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
>> index 313517f..08fcc94 100644
>> --- a/gcc/config/aarch64/aarch64.md
>> +++ b/gcc/config/aarch64/aarch64.md
>> @@ -3577,35 +3577,85 @@
>>     [(set_attr "type" "call")
>>      (set_attr "length" "16")])
>>
>> -(define_insn "tlsie_small"
>> -  [(set (match_operand:DI 0 "register_operand" "=r")
>> -        (unspec:DI [(match_operand:DI 1 "aarch64_tls_ie_symref" "S")]
>> +(define_expand "tlsie_small"
>> +  [(set (match_operand 0 "register_operand" "=r")
>> +        (unspec [(match_operand 1 "aarch64_tls_ie_symref" "S")]
>> +                  UNSPEC_GOTSMALLTLS))]
>> +  ""
>> +{
>> +  if (TARGET_ILP32)
>> +    {
>> +      operands[0] = gen_lowpart (ptr_mode, operands[0]);
>> +      emit_insn (gen_tlsie_small_si (operands[0], operands[1]));
>> +    }
>> +  else
>> +    emit_insn (gen_tlsie_small_di (operands[0], operands[1]));
>> +  DONE;
>> +})
>> +
>> +(define_insn "tlsie_small_<mode>"
>> +  [(set (match_operand:PTR 0 "register_operand" "=r")
>> +        (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
>>                    UNSPEC_GOTSMALLTLS))]
>>     ""
>> -  "adrp\\t%0, %A1\;ldr\\t%0, [%0, #%L1]"
>> +  "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
>>     [(set_attr "type" "load1")
>>      (set_attr "length" "8")]
>>   )
>>
>> -(define_insn "tlsle_small"
>> -  [(set (match_operand:DI 0 "register_operand" "=r")
>> -        (unspec:DI [(match_operand:DI 1 "register_operand" "r")
>> -                   (match_operand:DI 2 "aarch64_tls_le_symref" "S")]
>> +
>> +(define_expand "tlsle_small"
>> +  [(set (match_operand 0 "register_operand" "=r")
>> +        (unspec [(match_operand 1 "register_operand" "r")
>> +                   (match_operand 2 "aarch64_tls_le_symref" "S")]
>> +                   UNSPEC_GOTSMALLTLS))]
>> +  ""
>> +{
>> +  if (TARGET_ILP32)
>> +    {
>> +      rtx temp = gen_reg_rtx (ptr_mode);
>> +      operands[1] = gen_lowpart (ptr_mode, operands[1]);
>> +      emit_insn (gen_tlsle_small_si (temp, operands[1], operands[2]));
>> +      emit_move_insn (operands[0], gen_lowpart (GET_MODE (operands[0]),
>> temp));
>> +    }
>
>
> Looks like you hit the similar issue where the matched RTX can have either
> SImode or DImode in ILP32.  The mechanism looks OK but I think the approach
> that 'add_losym' adopts is neater, which checks on the mode instead of
> TARGET_ILP32 and calls gen_add_losym_di or gen_add_losym_si accordingly.
> Note that the iterator used in add_losym_<mode> is P instead of PTR.

Yes I agree with this and will fix this.

>
> Same for tlsie_small above.

But not with this one, tlsie_small should rather be similar to
ldr_got_small instead.

>
>
>> +  else
>> +    emit_insn (gen_tlsle_small_di (operands[0], operands[1],
>> operands[2]));
>> +  DONE;
>
>
> Brackets for the else body to align with the if body; same for tlsie_small
> above.

There is no requirement in the coding style for this.  In fact there
are examples of the coding style I used here all over GCC; even in
aarch64.md (rotl<mode>3) and aarch64.c
(aarch64_function_arg_alignment).

>
>
> Yufeng
>

Reply via email to