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  <james.greenha...@arm.com>

        * config/aarch64/aarch64.md (add<mode>3_pluslong): Add register
        constraints.

gcc/testsuite/

2015-12-04  James Greenhalgh  <james.greenha...@arm.com>

        * 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;
+}

Reply via email to