Hi, On 02/26/14 02:25, 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. I modified them to be like what was done for the GOT patterns.
The patch looks good to me (but I cannot approve). There are some minor indentation issues though; see below.
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): Rename to ... (tlsie_small_<mode>): this and handle PTR. (tlsie_small_sidi): New pattern. (tlsle_small): Change to an expand to handle ILP32. (tlsle_small_<mode>): New pattern. (tlsdesc_small): Rename to ... (tlsdesc_small_<mode>): this and handle PTR. --- gcc/ChangeLog | 12 +++++++++ gcc/config/aarch64/aarch64.c | 48 +++++++++++++++++++++++++++++++---- gcc/config/aarch64/aarch64.md | 54 +++++++++++++++++++++++++++++++--------- 3 files changed, 96 insertions(+), 18 deletions(-)
[snip]
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 99a6ac8..7d8a645 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -3581,35 +3581,65 @@ [(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_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" + +(define_insn "tlsie_small_sidi" [(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")] + (zero_extend:DI + (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")] + UNSPEC_GOTSMALLTLS)))] + "" + "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]" + [(set_attr "type" "load1") + (set_attr "length" "8")] +) + + +(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))]
The last two lines were not indented well.
+ "" +{ + enum machine_mode mode = GET_MODE (operands[0]); + emit_insn ((mode == DImode + ? gen_tlsle_small_di + : gen_tlsle_small_si) (operands[0], + operands[1], + operands[2]));
Likewise here. Thanks, Yufeng
+ DONE; + +}) + +(define_insn "tlsle_small_<mode>" + [(set (match_operand:P 0 "register_operand" "=r") + (unspec:P [(match_operand:P 1 "register_operand" "r") + (match_operand 2 "aarch64_tls_le_symref" "S")] UNSPEC_GOTSMALLTLS))] "" - "add\\t%0, %1, #%G2\;add\\t%0, %0, #%L2" + "add\\t%<w>0, %<w>1, #%G2\;add\\t%<w>0, %<w>0, #%L2" [(set_attr "type" "alu_reg") (set_attr "length" "8")] ) -(define_insn "tlsdesc_small" - [(set (reg:DI R0_REGNUM) - (unspec:DI [(match_operand:DI 0 "aarch64_valid_symref" "S")] +(define_insn "tlsdesc_small_<mode>" + [(set (reg:PTR R0_REGNUM) + (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")] UNSPEC_TLSDESC)) (clobber (reg:DI LR_REGNUM)) (clobber (match_scratch:DI 1 "=r"))] "TARGET_TLS_DESC" - "adrp\\tx0, %A0\;ldr\\t%1, [x0, #%L0]\;add\\tx0, x0, %L0\;.tlsdesccall\\t%0\;blr\\t%1" + "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0,<w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1" [(set_attr "type" "call") (set_attr "length" "16")])