Hi,
This patch fixes a bug I spotted in the add<mode>3_pluslong insn_and_split
pattern. We need to give register constraints, otherwise the register
allocator can do whatever it likes. This manifests as an ICE on AArch64
with -mabi=ilp32:
gcc foo.c -O2 -mabi=ilp32
error: could not split insn
}
^
(insn:TI 85 95 7 (set (mem/c:DI (plus:DI (reg/f:DI 29 x29)
(const_int 40 [0x28])) [1 %sfp+-65528 S8 A64])
(plus:DI (plus:DI (reg/f:DI 29 x29)
(const_int 16 [0x10]))
(const_int 65552 [0x10010]))) foo.c:7 95 {*adddi3_pluslong}
(nil))
The patch simply constrains the pattern to use w/x registers.
Bootstrapped on aarch64-none-linux-gnu and cross-tested on aarch64-none-elf
with no issues.
OK?
Thanks,
James
---
gcc/
2015-12-04 James Greenhalgh <[email protected]>
* config/aarch64/aarch64.md (add<mode>3_pluslong): Add register
constraints.
gcc/testsuite/
2015-12-04 James Greenhalgh <[email protected]>
* gcc.c-torture/compile/20151204.c: New.
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 765df6a..79d1414 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -1613,9 +1613,9 @@
(define_insn_and_split "*add<mode>3_pluslong"
[(set
- (match_operand:GPI 0 "register_operand" "")
- (plus:GPI (match_operand:GPI 1 "register_operand" "")
- (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
+ (match_operand:GPI 0 "register_operand" "=r")
+ (plus:GPI (match_operand:GPI 1 "register_operand" "r")
+ (match_operand:GPI 2 "aarch64_pluslong_immediate" "i")))]
"!aarch64_plus_operand (operands[2], VOIDmode)
&& !aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
"#"
diff --git a/gcc/testsuite/gcc.c-torture/compile/20151204.c b/gcc/testsuite/gcc.c-torture/compile/20151204.c
new file mode 100644
index 0000000..4a05671
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20151204.c
@@ -0,0 +1,19 @@
+typedef __SIZE_TYPE__ size_t;
+
+int strcmp (const char*, const char*);
+void *memchr (const void *, int, size_t);
+char* strncpy (char *, const char *, size_t);
+
+int
+main(int argc, char** argv)
+{
+ char target[32753] = "A";
+ char buffer[32753];
+ char *x;
+ x = buffer;
+
+ if (strcmp (target, "A")
+ || memchr (target, 'A', 0) != ((void *) 0))
+ if (strncpy (x, "", 4) != x);
+ return 0;
+}