4 instruction sequences can be implemented for AArch64 TLS LE model based on relocations provided.
These instruction sequences are the same for tiny/small/large, We just need to choose the most efficient one to use accoding to tls size. the 12bit version give us 4K TLS size, 24bit give us 16M, 32bit give us 4G while 48bit gives us 256TB. sequence 1 ========== add t0, tp, #:tprel_lo12:x1 R_AARCH64_TLSLE_ADD_TPREL_LO12 x1 sequence 2 ========== add t0, tp, #:tprel_hi12:x1, lsl #12 R_AARCH64_TLSLE_ADD_TPREL_HI12 x2 add t0, #:tprel_lo12_nc:x1 R_AARCH64_TLSLE_ADD_TPREL_LO12_NC x2 sequence 2 ========== movz t0, #:tprel_g1:x3 R_AARCH64_TLSLE_MOVW_TPREL_G1 x3 movk t0, #:tprel_g0_nc:x3 R_AARCH64_TLSLE_MOVW_TPREL_G0_NC x3 add t0, tp, t0 sequence 4 ========== movz t0, #:tprel_g2:x4 R_AARCH64_TLSLE_MOVW_TPREL_G2 x4 movk t0, #:tprel_g1_nc:x4 R_AARCH64_TLSLE_MOVW_TPREL_G1_NC x4 movk t0, #:tprel_g0_nc:x4 R_AARCH64_TLSLE_MOVW_TPREL_G0_NC x4 add t0, t0, tp OK for trunk? 2015-05-14 Jiong Wang <jiong.w...@arm.com> gcc/ * config/aarch64/aarch64.c (aarch64_print_operand): Support tls_size. * config/aarch64/aarch64.md (tlsle): Choose proper instruction sequences. (tlsle_<mode>): New define_insn. (tlsle_movsym_<mode>): Ditto. * config/aarch64/constraints.md (Uta): New constraint. (Utb): Ditto. (Utc): Ditto. (Utd): Ditto. gcc/testsuite/ * gcc.target/aarch64/tlsle.c: New test source. * gcc.target/aarch64/tlsle12.c: New testcase. * gcc.target/aarch64/tlsle24.c: New testcase. * gcc.target/aarch64/tlsle32.c: New testcase. -- Regards, Jiong
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index e6aa0e1..569f22d 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -4450,7 +4450,11 @@ aarch64_print_operand (FILE *f, rtx x, char code) break; case SYMBOL_TLSLE: - asm_fprintf (asm_out_file, ":tprel_lo12_nc:"); + if (aarch64_tls_size <= 12) + /* Make sure TLS offset fit into 12bit. */ + asm_fprintf (asm_out_file, ":tprel_lo12:"); + else + asm_fprintf (asm_out_file, ":tprel_lo12_nc:"); break; case SYMBOL_TINY_GOT: diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index b1425a3..8b061ba 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -4304,21 +4304,60 @@ "" { machine_mode mode = GET_MODE (operands[0]); - emit_insn ((mode == DImode - ? gen_tlsle_di - : gen_tlsle_si) (operands[0], operands[1], operands[2])); + rtx (*gen_tlsle_si_special) (rtx , rtx , rtx); + rtx (*gen_tlsle_di_special) (rtx , rtx , rtx); + + /* For tls offset <=24, utilize add to load 12bit offset. */ + if (aarch64_tls_size <= 24) + { + gen_tlsle_si_special = gen_tlsle_si; + gen_tlsle_di_special = gen_tlsle_di; + + emit_insn ((mode == DImode + ? gen_tlsle_di_special + : gen_tlsle_si_special) (operands[0], operands[1], + operands[2])); + DONE; + } + /* Load the sym's offset into operands[0]. */ + else if (aarch64_tls_size <= 48) + emit_insn (mode == DImode + ? gen_tlsle_movsym_di (operands[0], operands[2]) + : gen_tlsle_movsym_si (operands[0], operands[2])); + else + gcc_unreachable (); + + /* Add base address from tp. */ + emit_insn (mode == DImode + ? gen_adddi3 (operands[0], operands[0], operands[1]) + : gen_addsi3 (operands[0], operands[0], operands[1])); + DONE; }) (define_insn "tlsle_<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")] + [(set (match_operand:P 0 "register_operand" "=r, r") + (unspec:P [(match_operand:P 1 "register_operand" "r, r") + (match_operand 2 "aarch64_tls_le_symref" "Uta, Utb")] UNSPEC_TLSLE))] "" - "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2" - [(set_attr "type" "alu_sreg") - (set_attr "length" "8")] + "@ + add\\t%<w>0, %<w>1, #%L2 + add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2" + [(set_attr "type" "alu_sreg, multiple") + (set_attr "length" "4, 8")] +) + +(define_insn "tlsle_movsym_<mode>" + [(set (match_operand:P 0 "register_operand" "=r, r") + (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "Utc, Utd")] + UNSPEC_TLSLE))] + "" + "@ + movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1 + movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1" + [(set_attr "type" "multiple, multiple") + (set_attr "length" "8, 12")] ) (define_insn "tlsdesc_small_<mode>" diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md index 5b189ea..58fe082 100644 --- a/gcc/config/aarch64/constraints.md +++ b/gcc/config/aarch64/constraints.md @@ -109,6 +109,30 @@ A constraint that matches the immediate constant -1." (match_test "op == constm1_rtx")) +(define_constraint "Uta" + "A constraint that matches an absolute symbolic address which needs 12bit" + (and (match_code "const,symbol_ref,label_ref") + (and (match_test "aarch64_symbolic_address_p (op)") + (match_test "aarch64_tls_size <= 12")))) + +(define_constraint "Utb" + "A constraint that matches an absolute symbolic address which needs 24bit" + (and (match_code "const,symbol_ref,label_ref") + (and (match_test "aarch64_symbolic_address_p (op)") + (match_test "aarch64_tls_size > 12 && aarch64_tls_size <= 24")))) + +(define_constraint "Utc" + "A constraint that matches an absolute symbolic address which needs 32bit" + (and (match_code "const,symbol_ref,label_ref") + (and (match_test "aarch64_symbolic_address_p (op)") + (match_test "aarch64_tls_size > 24 && aarch64_tls_size <= 32")))) + +(define_constraint "Utd" + "A constraint that matches an absolute symbolic address which needs 48bit" + (and (match_code "const,symbol_ref,label_ref") + (and (match_test "aarch64_symbolic_address_p (op)") + (match_test "aarch64_tls_size > 32 && aarch64_tls_size <= 48")))) + (define_constraint "Ui1" "@internal A constraint that matches the immediate constant +1." diff --git a/gcc/testsuite/gcc.target/aarch64/tlsle.c b/gcc/testsuite/gcc.target/aarch64/tlsle.c new file mode 100644 index 0000000..d92281b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/tlsle.c @@ -0,0 +1,14 @@ +void abort (void); + +__thread int t0 = 0x10; +__thread int t1 = 0x10; + +int +main (int argc, char **argv) +{ + if (t0 != t1) + abort (); + + return 0; +} + diff --git a/gcc/testsuite/gcc.target/aarch64/tlsle12.c b/gcc/testsuite/gcc.target/aarch64/tlsle12.c new file mode 100644 index 0000000..459a20b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/tlsle12.c @@ -0,0 +1,8 @@ +/* { dg-do run } */ +/* { dg-require-effective-target tls_native } */ +/* { dg-options "-O2 -fpic -ftls-model=local-exec -mtls-size=12 --save-temps" } */ + +#include "tlsle.c" + +/* { dg-final { scan-assembler-times "#:tprel_lo12" 2 } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/tlsle24.c b/gcc/testsuite/gcc.target/aarch64/tlsle24.c new file mode 100644 index 0000000..c7627d7 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/tlsle24.c @@ -0,0 +1,9 @@ +/* { dg-do run } */ +/* { dg-require-effective-target tls_native } */ +/* { dg-options "-O2 -fpic -ftls-model=local-exec -mtls-size=24 --save-temps" } */ + +#include "tlsle.c" + +/* { dg-final { scan-assembler-times "#:tprel_lo12_nc" 2 } } */ +/* { dg-final { scan-assembler-times "#:tprel_hi12" 2 } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/tlsle32.c b/gcc/testsuite/gcc.target/aarch64/tlsle32.c new file mode 100644 index 0000000..4180654 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/tlsle32.c @@ -0,0 +1,9 @@ +/* { dg-do run } */ +/* { dg-require-effective-target tls_native } */ +/* { dg-options "-O2 -fpic -ftls-model=local-exec -mtls-size=32 --save-temps" } */ + +#include "tlsle.c" + +/* { dg-final { scan-assembler-times "#:tprel_g1" 2 } } */ +/* { dg-final { scan-assembler-times "#:tprel_g0_nc" 2 } } */ +/* { dg-final { cleanup-saved-temps } } */