Index: gcc/ChangeLog =================================================================== --- gcc/ChangeLog (revision 226682) +++ gcc/ChangeLog (working copy) @@ -1,3 +1,16 @@ +2015-08-06 Ramana Radhakrishnan + Jiong Wang + + * config/aarch64/aarch64.d (tlsdesc_small_pseudo_): New pattern. + * config/aarch64/aarch64.h (reg_class): New enumeration FIXED_REG0. + (REG_CLASS_NAMES): Likewise. + (REG_CLASS_CONTENTS): Likewise. + * config/aarch64/aarch64.c (aarch64_class_max_nregs): Likewise. + (aarch64_register_move_cost): Likewise. + (aarch64_load_symref_appropriately): Invoke the new added pattern if + possible. + * config/aarch64/constraints.md (Uc0): New constraint. + 2015-08-06 Jiong Wang * config/aarch64/constraints.md (Usf): Add the test of Index: gcc/config/aarch64/aarch64.c =================================================================== --- gcc/config/aarch64/aarch64.c (revision 226681) +++ gcc/config/aarch64/aarch64.c (working copy) @@ -1048,12 +1048,26 @@ gcc_assert (mode == Pmode || mode == ptr_mode); - /* In ILP32, the got entry is always of SImode size. Unlike - small GOT, the dest is fixed at reg 0. */ - if (TARGET_ILP32) - emit_insn (gen_tlsdesc_small_si (imm)); + if (can_create_pseudo_p ()) + { + rtx reg = gen_reg_rtx (mode); + + if (TARGET_ILP32) + emit_insn (gen_tlsdesc_small_pseudo_si (imm, reg)); + else + emit_insn (gen_tlsdesc_small_pseudo_di (imm, reg)); + + emit_use (reg); + } else - emit_insn (gen_tlsdesc_small_di (imm)); + { + /* In ILP32, the got entry is always of SImode size. Unlike + small GOT, the dest is fixed at reg 0. */ + if (TARGET_ILP32) + emit_insn (gen_tlsdesc_small_si (imm)); + else + emit_insn (gen_tlsdesc_small_di (imm)); + } tp = aarch64_load_tp (NULL); if (mode != Pmode) Index: gcc/config/aarch64/aarch64.md =================================================================== --- gcc/config/aarch64/aarch64.md (revision 226681) +++ gcc/config/aarch64/aarch64.md (working copy) @@ -4549,6 +4549,23 @@ [(set_attr "type" "call") (set_attr "length" "16")]) +;; The same as tlsdesc_small_ except that we don't expose hard register X0 +;; as the destination of set as it will cause trouble for RTL loop iv. +;; RTL loop iv will abort ongoing optimization once it finds there is hard reg +;; as destination of set. This pattern thus could help these tlsdesc +;; instruction sequences hoisted out of loop. +(define_insn "tlsdesc_small_pseudo_" + [(set (match_operand:PTR 1 "register_operand" "=r") + (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")] + UNSPEC_TLSDESC)) + (clobber (reg:DI R0_REGNUM)) + (clobber (reg:DI LR_REGNUM)) + (clobber (reg:CC CC_REGNUM))] + "TARGET_TLS_DESC" + "adrp\\tx0, %A0\;ldr\\t%1, [x0, #%L0]\;add\\t0, 0, %L0\;.tlsdesccall\\t%0\;blr\\t%1" + [(set_attr "type" "call") + (set_attr "length" "16")]) + (define_insn "stack_tie" [(set (mem:BLK (scratch)) (unspec:BLK [(match_operand:DI 0 "register_operand" "rk") Index: gcc/testsuite/ChangeLog =================================================================== --- gcc/testsuite/ChangeLog (revision 226682) +++ gcc/testsuite/ChangeLog (working copy) @@ -1,5 +1,9 @@ 2015-08-06 Jiong Wang + * gcc.target/aarch64/tlsdesc_hoist.c: New testcase. + +2015-08-06 Jiong Wang + * gcc.target/aarch64/noplt_3.c: New testcase. 2015-08-06 Jiong Wang Index: gcc/testsuite/gcc.target/aarch64/tlsdesc_hoist.c =================================================================== --- gcc/testsuite/gcc.target/aarch64/tlsdesc_hoist.c (revision 0) +++ gcc/testsuite/gcc.target/aarch64/tlsdesc_hoist.c (working copy) @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target tls_native } */ +/* { dg-options "-O2 -fpic -fdump-rtl-loop2_invariant" } */ +/* { dg-skip-if "-mcmodel=large, no support for -fpic" { aarch64-*-* } { "-mcmodel=large" } { "" } } */ + +int cal (int, int); +__thread int tls_data; + +int +foo (int bound) +{ + int i = 0; + int sum = 0; + + for (i; i < bound; i++) + sum = cal (sum, tls_data); + + return sum; +} + +/* Insn sequences for TLS descriptor should be hoisted out of the loop. */ +/* { dg-final { scan-rtl-dump "Decided" "loop2_invariant" } } */