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")])