On 19/01/15 10:58, Jakub Jelinek wrote:
On Mon, Jan 19, 2015 at 10:52:14AM +0000, Ramana Radhakrishnan wrote:
What is aarch64 specific on the testcase?
The number of if-then-else's required to get the compiler to generate
<cmp> branch sequences rather than the tbnz instruction.
That doesn't mean the same testcase couldn't be tested on other targets and
perhaps find bugs in there.
That said, if the testcase is too expensive to compile (several seconds is
ok, minutes is not), then perhaps it shouldn't be included at all, or should
be guarded with run_expensive_tests target.
Jakub
testcase changed to execution version, and moved to gcc.dg. the compile time
only
take several seconds. (previously I am using cc1 built by O0 which at most take
24s)
ok to install?
Thanks.
2015-01-19 Ramana Radhakrishnan <ramana.radhakrish...@arm.com>
Jiong Wang <jiong.w...@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.
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 597ff8c..1e00396 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -466,13 +466,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))
@@ -486,13 +490,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 7dd3917..bd144f9 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -823,6 +823,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/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;
+}