[AArch64] Improve TLS Descriptor pattern to release RTL loop IV opt
authorJiong Wang <jiwang@gcc.gnu.org>
Thu, 6 Aug 2015 16:08:39 +0000 (16:08 +0000)
committerJiong Wang <jiwang@gcc.gnu.org>
Thu, 6 Aug 2015 16:08:39 +0000 (16:08 +0000)
The instruction sequences for preparing argument for TLS descriptor
runtime resolver and the later function call to resolver can actually be
hoisted out of the loop.

Currently we can't because we have exposed the hard register X0 as
destination of "set".  While GCC's RTL data flow infrastructure will
skip or do very conservative assumption when hard register involved in
and thus some loop IV opportunities are missed.

This patch add another "tlsdesc_small_pseudo_<mode>" pattern, and avoid
expose x0 to gcc generic code.

Generally, we define a new register class FIXED_R0 which only contains register
0, so the instruction sequences generated from the new add pattern is the same
as tlsdesc_small_<mode>, while the operand 0 is wrapped as pseudo register that
RTL IV opt can handle it.

Ideally, we should allow operand 0 to be any pseudo register, but then
we can't model the override of x0 caused by the function call which is
hidded by the UNSPEC.

So here, we restricting operand 0 to be x0, the override of x0 can be
reflected to the gcc.

2015-08-06    Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
      Jiong Wang  <jiong.wang@arm.com>
gcc/
  * config/aarch64/aarch64.d (tlsdesc_small_pseudo_<mode>): 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.

gcc/testsuite/
  * gcc.target/aarch64/tlsdesc_hoist.c: New testcase.

From-SVN: r226683

gcc/ChangeLog
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/tlsdesc_hoist.c [new file with mode: 0644]

index 795867a165640ee2e3aa4aa8e1ce3d3e15a8cccc..ffcd947a7d6f84561ac231d0d8442826960cce20 100644 (file)
@@ -1,3 +1,16 @@
+2015-08-06    Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
+             Jiong Wang  <jiong.wang@arm.com>
+
+       * config/aarch64/aarch64.d (tlsdesc_small_pseudo_<mode>): 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  <jiong.wang@arm.com>
 
        * config/aarch64/constraints.md (Usf): Add the test of
index e991a494cfc29ea2b4a0aa2ba8df1febb27806c2..6da7245a8534ef2e5e3a51b996913e4b13c7b8ce 100644 (file)
@@ -1048,12 +1048,26 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm,
 
        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 7f9975328950bc72f083041dfb25a0fc437dbb5f..5e8f210af03dfd631b5aba205407fc1591b282f1 100644 (file)
   [(set_attr "type" "call")
    (set_attr "length" "16")])
 
+;; The same as tlsdesc_small_<mode> 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_<mode>"
+  [(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%<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")])
+
 (define_insn "stack_tie"
   [(set (mem:BLK (scratch))
        (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
index 0cd004b4c1d29ecc17aef3176eff5e55a13f7c10..0d4937c3b54fe87fbc6af083ca432702220d6aec 100644 (file)
@@ -1,3 +1,7 @@
+2015-08-06  Jiong Wang  <jiong.wang@arm.com>
+
+       * gcc.target/aarch64/tlsdesc_hoist.c: New testcase.
+
 2015-08-06  Jiong Wang  <jiong.wang@arm.com>
 
        * gcc.target/aarch64/noplt_3.c: New testcase.
diff --git a/gcc/testsuite/gcc.target/aarch64/tlsdesc_hoist.c b/gcc/testsuite/gcc.target/aarch64/tlsdesc_hoist.c
new file mode 100644 (file)
index 0000000..a1fd3b0
--- /dev/null
@@ -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" } } */