[AArch64] Improve bit-test-branch pattern to avoid unnecessary register clobber
authorJiong Wang <jiwang@gcc.gnu.org>
Tue, 27 Jan 2015 15:20:14 +0000 (15:20 +0000)
committerJiong Wang <jiwang@gcc.gnu.org>
Tue, 27 Jan 2015 15:20:14 +0000 (15:20 +0000)
2015-01-27  Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
            Jiong Wang  <jiong.wang@arm.com>

  gcc/
    * config/aarch64/aarch64.md (tb<optab><mode>1): Clobber CC reg instead of
    scratch reg.
    (cb<optab><mode>1): Likewise.
    * config/aarch64/iterators.md (bcond): New define_code_attr.

  gcc/testsuite/
    * gcc.dg/long_branch.c: New testcase.

From-SVN: r220170

gcc/ChangeLog
gcc/config/aarch64/aarch64.md
gcc/config/aarch64/iterators.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/long_branch.c [new file with mode: 0644]

index 5642c5b3bbacb238075d7c48a20ea2b098b31bbf..e7a9241668b05574255a7a39f0618daea7d68515 100644 (file)
@@ -1,3 +1,11 @@
+2015-01-27  Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
+           Jiong Wang  <jiong.wang@arm.com>
+
+       * config/aarch64/aarch64.md (tb<optab><mode>1): Clobber CC reg instead
+       of scratch reg.
+       (cb<optab><mode>1): Likewise.
+       * config/aarch64/iterators.md (bcond): New define_code_attr.
+
 2015-01-27  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
 
        * config/s390/s390.c (s390_memory_move_cost): Increase costs for
index b81ecb273ae378004641adb58fe1f6bd884c83f8..1f4169ee76e7f3f321e5ed7a4d0f08b54ee3bf17 100644 (file)
                   (const_int 0))
             (label_ref (match_operand 2 "" ""))
             (pc)))
-   (clobber (match_scratch:DI 3 "=r"))]
+   (clobber (reg:CC CC_REGNUM))]
   ""
-  "*
-  if (get_attr_length (insn) == 8)
-    return \"ubfx\\t%<w>3, %<w>0, %1, #1\;<cbz>\\t%<w>3, %l2\";
-  return \"<tbz>\\t%<w>0, %1, %l2\";
-  "
+  {
+    if (get_attr_length (insn) == 8)
+      {
+       operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
+       return "tst\t%<w>0, %1\;<bcond>\t%l2";
+      }
+    else
+      return "<tbz>\t%<w>0, %1, %l2";
+  }
   [(set_attr "type" "branch")
    (set (attr "length")
        (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
                                 (const_int 0))
                           (label_ref (match_operand 1 "" ""))
                           (pc)))
-   (clobber (match_scratch:DI 2 "=r"))]
+   (clobber (reg:CC CC_REGNUM))]
   ""
-  "*
-  if (get_attr_length (insn) == 8)
-    return \"ubfx\\t%<w>2, %<w>0, <sizem1>, #1\;<cbz>\\t%<w>2, %l1\";
-  return \"<tbz>\\t%<w>0, <sizem1>, %l1\";
-  "
+  {
+    if (get_attr_length (insn) == 8)
+      {
+       char buf[64];
+       uint64_t val = ((uint64_t ) 1)
+                       << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
+       sprintf (buf, "tst\t%%<w>0, %"PRId64, val);
+       output_asm_insn (buf, operands);
+       return "<bcond>\t%l1";
+      }
+    else
+      return "<tbz>\t%<w>0, <sizem1>, %l1";
+  }
   [(set_attr "type" "branch")
    (set (attr "length")
        (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
index 606ccc33eec3941715f0ed6f365d2e60551c7251..65a2849155c9b331dc6179853501f0a6207d1773 100644 (file)
                      (smax "s") (umax "u")
                      (smin "s") (umin "u")])
 
+;; Emit conditional branch instructions.
+(define_code_attr bcond [(eq "beq") (ne "bne") (lt "bne") (ge "beq")])
+
 ;; Emit cbz/cbnz depending on comparison type.
 (define_code_attr cbz [(eq "cbz") (ne "cbnz") (lt "cbnz") (ge "cbz")])
 
index a27bf71ffc2d7b50b258f26a8013073c70872b4a..9f775968b0e2f261459af40cc171437763993188 100644 (file)
@@ -1,3 +1,7 @@
+2015-01-27  Jiong Wang  <jiong.wang@arm.com>
+
+       * gcc.dg/long_branch.c: New testcase.
+
 2015-01-27  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/56273
diff --git a/gcc/testsuite/gcc.dg/long_branch.c b/gcc/testsuite/gcc.dg/long_branch.c
new file mode 100644 (file)
index 0000000..f388a80
--- /dev/null
@@ -0,0 +1,198 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-reorder-blocks" } */
+
+void abort ();
+
+__attribute__((noinline, noclone)) int
+restore (int a, int b)
+{
+  return a * b;
+}
+
+__attribute__((noinline, noclone)) void
+do_nothing (int *input)
+{
+  *input = restore (*input, 1);
+  return;
+}
+
+#define CASE_ENTRY(n) \
+  case n: \
+    sum = sum / (n + 1); \
+    sum = restore (sum, n + 1); \
+    if (sum == (n + addend)) \
+      break;\
+    sum = sum / (n + 2); \
+    sum = restore (sum, n + 2); \
+    sum = sum / (n + 3); \
+    sum = restore (sum, n + 3); \
+    sum = sum / (n + 4); \
+    sum = restore (sum, n + 4); \
+    sum = sum / (n + 5); \
+    sum = restore (sum, n + 5); \
+    sum = sum / (n + 6); \
+    sum = restore (sum, n + 6); \
+    sum = sum / (n + 7); \
+    sum = restore (sum, n + 7); \
+    sum = sum / (n + 8); \
+    sum = restore (sum, n + 8); \
+    sum = sum / (n + 9); \
+    sum = restore (sum, n + 9); \
+    sum = sum / (n + 10); \
+    sum = restore (sum, n + 10); \
+    sum = sum / (n + 11); \
+    sum = restore (sum, n + 11); \
+    sum = sum / (n + 12); \
+    sum = restore (sum, n + 12); \
+    sum = sum / (n + 13); \
+    sum = restore (sum, n + 13); \
+    sum = sum / (n + 14); \
+    sum = restore (sum, n + 14); \
+    sum = sum / (n + 15); \
+    sum = restore (sum, n + 15); \
+    sum = sum / (n + 16); \
+    sum = restore (sum, n + 16); \
+    sum = sum / (n + 17); \
+    sum = restore (sum, n + 17); \
+    sum = sum / (n + 18); \
+    sum = restore (sum, n + 18); \
+    sum = sum / (n + 19); \
+    sum = restore (sum, n + 19); \
+    sum = sum / (n + 20); \
+    sum = restore (sum, n + 20); \
+    sum = sum / (n + 21); \
+    sum = restore (sum, n + 21); \
+    sum = sum / (n + 22); \
+    sum = restore (sum, n + 22); \
+    sum = sum / (n + 23); \
+    sum = restore (sum, n + 23); \
+    sum = sum / (n + 24); \
+    sum = restore (sum, n + 24); \
+    sum = sum / (n + 25); \
+    sum = restore (sum, n + 25); \
+    sum = sum / (n + 26); \
+    sum = restore (sum, n + 26); \
+    sum = sum / (n + 27); \
+    sum = restore (sum, n + 27); \
+    sum = sum / (n + 28); \
+    sum = restore (sum, n + 28); \
+    sum = sum / (n + 29); \
+    sum = restore (sum, n + 29); \
+    sum = sum / (n + 30); \
+    sum = restore (sum, n + 30); \
+    sum = sum / (n + 31); \
+    sum = restore (sum, n + 31); \
+    sum = sum / (n + 32); \
+    sum = restore (sum, n + 32); \
+    sum = sum / (n + 33); \
+    sum = restore (sum, n + 33); \
+    sum = sum / (n + 34); \
+    sum = restore (sum, n + 34); \
+    sum = sum / (n + 35); \
+    sum = restore (sum, n + 35); \
+    sum = sum / (n + 36); \
+    sum = restore (sum, n + 36); \
+    break;
+
+__attribute__((noinline, noclone)) long long
+test_and_branch (int selector, int addend)
+{
+  long long sum = selector + 1;
+
+  if (selector > 64)
+    {
+start:
+      return sum - 1;
+    }
+  else
+    {
+      switch (selector)
+       {
+         CASE_ENTRY (1)
+         CASE_ENTRY (2)
+         CASE_ENTRY (3)
+         CASE_ENTRY (4)
+         CASE_ENTRY (5)
+         CASE_ENTRY (6)
+         CASE_ENTRY (7)
+         CASE_ENTRY (8)
+         CASE_ENTRY (9)
+         CASE_ENTRY (10)
+         CASE_ENTRY (11)
+         CASE_ENTRY (12)
+         CASE_ENTRY (13)
+         CASE_ENTRY (14)
+         CASE_ENTRY (15)
+         CASE_ENTRY (16)
+         CASE_ENTRY (17)
+         CASE_ENTRY (18)
+         CASE_ENTRY (19)
+         CASE_ENTRY (20)
+         CASE_ENTRY (21)
+         CASE_ENTRY (22)
+         CASE_ENTRY (23)
+         CASE_ENTRY (24)
+         CASE_ENTRY (25)
+         CASE_ENTRY (26)
+         CASE_ENTRY (27)
+         CASE_ENTRY (28)
+         CASE_ENTRY (29)
+         CASE_ENTRY (30)
+         CASE_ENTRY (31)
+         CASE_ENTRY (32)
+         CASE_ENTRY (33)
+         CASE_ENTRY (34)
+         CASE_ENTRY (35)
+         CASE_ENTRY (36)
+         CASE_ENTRY (37)
+         CASE_ENTRY (38)
+         CASE_ENTRY (39)
+         CASE_ENTRY (40)
+         CASE_ENTRY (41)
+         CASE_ENTRY (42)
+         CASE_ENTRY (43)
+         CASE_ENTRY (44)
+         CASE_ENTRY (45)
+         CASE_ENTRY (46)
+         CASE_ENTRY (47)
+         CASE_ENTRY (48)
+         CASE_ENTRY (49)
+         CASE_ENTRY (50)
+         CASE_ENTRY (51)
+         CASE_ENTRY (52)
+         CASE_ENTRY (53)
+         CASE_ENTRY (54)
+         CASE_ENTRY (55)
+         CASE_ENTRY (56)
+         CASE_ENTRY (57)
+         CASE_ENTRY (58)
+         CASE_ENTRY (59)
+         CASE_ENTRY (60)
+         CASE_ENTRY (61)
+         CASE_ENTRY (62)
+         CASE_ENTRY (63)
+         CASE_ENTRY (64)
+       }
+
+      do_nothing ((int *)&sum);
+
+      if (sum & 0x40)
+       goto start;
+    }
+
+  return -1;
+}
+
+int
+main (int argc, char **argv)
+{
+  long long ret = test_and_branch (64, 1);
+  if (ret != 64)
+    abort ();
+
+  ret = test_and_branch (7, 1);
+  if (ret != -1)
+    abort ();
+
+  return 0;
+}