diff options
author | Jiong Wang <jiwang@gcc.gnu.org> | 2015-01-27 15:20:14 +0000 |
---|---|---|
committer | Jiong Wang <jiwang@gcc.gnu.org> | 2015-01-27 15:20:14 +0000 |
commit | 096e8448caeeb8ea78fd8ba0b839986e2ffe2c20 (patch) | |
tree | a5dceab703799e53f4065be6de96635b78ffbe7e /gcc | |
parent | fb1a3f8f57e3f6a64da3557349a506044bd948e6 (diff) | |
download | gcc-096e8448caeeb8ea78fd8ba0b839986e2ffe2c20.zip gcc-096e8448caeeb8ea78fd8ba0b839986e2ffe2c20.tar.gz gcc-096e8448caeeb8ea78fd8ba0b839986e2ffe2c20.tar.bz2 |
[AArch64] Improve bit-test-branch pattern to avoid unnecessary register clobber
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.md | 36 | ||||
-rw-r--r-- | gcc/config/aarch64/iterators.md | 3 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/long_branch.c | 198 |
5 files changed, 237 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5642c5b..e7a9241 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index b81ecb2..1f4169e 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%<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)) @@ -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%<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)) diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index 606ccc3..65a2849 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 a27bf71..9f77596 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..f388a80 --- /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; +} |