From 096e8448caeeb8ea78fd8ba0b839986e2ffe2c20 Mon Sep 17 00:00:00 2001 From: Jiong Wang Date: Tue, 27 Jan 2015 15:20:14 +0000 Subject: [PATCH] [AArch64] Improve bit-test-branch pattern to avoid unnecessary register clobber 2015-01-27 Ramana Radhakrishnan Jiong Wang gcc/ * config/aarch64/aarch64.md (tb1): Clobber CC reg instead of scratch reg. (cb1): Likewise. * config/aarch64/iterators.md (bcond): New define_code_attr. gcc/testsuite/ * gcc.dg/long_branch.c: New testcase. From-SVN: r220170 --- gcc/ChangeLog | 8 ++ gcc/config/aarch64/aarch64.md | 36 ++++-- gcc/config/aarch64/iterators.md | 3 + gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.dg/long_branch.c | 198 +++++++++++++++++++++++++++++ 5 files changed, 237 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/long_branch.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5642c5b3bba..e7a9241668b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2015-01-27 Ramana Radhakrishnan + Jiong Wang + + * config/aarch64/aarch64.md (tb1): Clobber CC reg instead + of scratch reg. + (cb1): Likewise. + * config/aarch64/iterators.md (bcond): New define_code_attr. + 2015-01-27 Andreas Krebbel * config/s390/s390.c (s390_memory_move_cost): Increase costs for diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index b81ecb273ae..1f4169ee76e 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -499,13 +499,17 @@ (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%3, %0, %1, #1\;\\t%3, %l2\"; - return \"\\t%0, %1, %l2\"; - " + { + if (get_attr_length (insn) == 8) + { + operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1])); + return "tst\t%0, %1\;\t%l2"; + } + else + return "\t%0, %1, %l2"; + } [(set_attr "type" "branch") (set (attr "length") (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768)) @@ -519,13 +523,21 @@ (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%2, %0, , #1\;\\t%2, %l1\"; - return \"\\t%0, , %l1\"; - " + { + if (get_attr_length (insn) == 8) + { + char buf[64]; + uint64_t val = ((uint64_t ) 1) + << (GET_MODE_SIZE (mode) * BITS_PER_UNIT - 1); + sprintf (buf, "tst\t%%0, %"PRId64, val); + output_asm_insn (buf, operands); + return "\t%l1"; + } + else + return "\t%0, , %l1"; + } [(set_attr "type" "branch") (set (attr "length") (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768)) diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index 606ccc33eec..65a2849155c 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -814,6 +814,9 @@ (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")]) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a27bf71ffc2..9f775968b0e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2015-01-27 Jiong Wang + + * gcc.dg/long_branch.c: New testcase. + 2015-01-27 Richard Biener 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 index 00000000000..f388a80c892 --- /dev/null +++ b/gcc/testsuite/gcc.dg/long_branch.c @@ -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; +} -- 2.30.2