re PR rtl-optimization/89313 (ICE in process_alt_operands, at lra-constraints.c:2962)
authorPeter Bergner <bergner@linux.ibm.com>
Wed, 27 Mar 2019 16:59:15 +0000 (16:59 +0000)
committerPeter Bergner <bergner@gcc.gnu.org>
Wed, 27 Mar 2019 16:59:15 +0000 (11:59 -0500)
gcc/
PR rtl-optimization/89313
* function.c (matching_constraint_num): New static function.
(match_asm_constraints_1): Use it.  Fixup white space and comment.
Don't replace inputs with non-matching constraints which conflict
with early clobber outputs.

gcc/testsuite/
PR rtl-optimization/89313
* gcc.dg/pr89313.c: New test.

From-SVN: r269969

gcc/ChangeLog
gcc/function.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr89313.c [new file with mode: 0644]

index f8a353d16c096bab262c87d722dafa3f7e17eb66..132af149fe75508564a6c2900e9428111eee0121 100644 (file)
@@ -1,3 +1,11 @@
+2019-03-27  Peter Bergner  <bergner@linux.ibm.com>
+
+       PR rtl-optimization/89313
+       * function.c (matching_constraint_num): New static function.
+       (match_asm_constraints_1): Use it.  Fixup white space and comment.
+       Don't replace inputs with non-matching constraints which conflict
+       with early clobber outputs.
+
 2019-03-27  Jeff Law  <law@redhat.com>
 
 
index dc035707c208f039fbd25b6add567fc426ccf0d6..bf5ba3d7b73e3f3869a9961f3cc91be8fa4d8f50 100644 (file)
@@ -6395,6 +6395,21 @@ make_pass_thread_prologue_and_epilogue (gcc::context *ctxt)
 }
 \f
 
+/* If CONSTRAINT is a matching constraint, then return its number.
+   Otherwise, return -1.  */
+
+static int
+matching_constraint_num (const char *constraint)
+{
+  if (*constraint == '%')
+    constraint++;
+
+  if (IN_RANGE (*constraint, '0', '9'))
+    return strtoul (constraint, NULL, 10);
+
+  return -1;
+}
+
 /* This mini-pass fixes fall-out from SSA in asm statements that have
    in-out constraints.  Say you start with
 
@@ -6453,14 +6468,10 @@ match_asm_constraints_1 (rtx_insn *insn, rtx *p_sets, int noutputs)
       rtx input, output;
       rtx_insn *insns;
       const char *constraint = ASM_OPERANDS_INPUT_CONSTRAINT (op, i);
-      char *end;
       int match, j;
 
-      if (*constraint == '%')
-       constraint++;
-
-      match = strtoul (constraint, &end, 10);
-      if (end == constraint)
+      match = matching_constraint_num (constraint);
+      if (match < 0)
        continue;
 
       gcc_assert (match < noutputs);
@@ -6477,14 +6488,14 @@ match_asm_constraints_1 (rtx_insn *insn, rtx *p_sets, int noutputs)
       /* We can't do anything if the output is also used as input,
         as we're going to overwrite it.  */
       for (j = 0; j < ninputs; j++)
-        if (reg_overlap_mentioned_p (output, RTVEC_ELT (inputs, j)))
+       if (reg_overlap_mentioned_p (output, RTVEC_ELT (inputs, j)))
          break;
       if (j != ninputs)
        continue;
 
       /* Avoid changing the same input several times.  For
         asm ("" : "=mr" (out1), "=mr" (out2) : "0" (in), "1" (in));
-        only change in once (to out1), rather than changing it
+        only change it once (to out1), rather than changing it
         first to out1 and afterwards to out2.  */
       if (i > 0)
        {
@@ -6502,6 +6513,9 @@ match_asm_constraints_1 (rtx_insn *insn, rtx *p_sets, int noutputs)
       end_sequence ();
       emit_insn_before (insns, insn);
 
+      constraint = ASM_OPERANDS_OUTPUT_CONSTRAINT(SET_SRC(p_sets[match]));
+      bool early_clobber_p = strchr (constraint, '&') != NULL;
+
       /* Now replace all mentions of the input with output.  We can't
         just replace the occurrence in inputs[i], as the register might
         also be used in some other input (or even in an address of an
@@ -6523,7 +6537,14 @@ match_asm_constraints_1 (rtx_insn *insn, rtx *p_sets, int noutputs)
         value, but different pseudos) where we formerly had only one.
         With more complicated asms this might lead to reload failures
         which wouldn't have happen without this pass.  So, iterate over
-        all operands and replace all occurrences of the register used.  */
+        all operands and replace all occurrences of the register used.
+
+        However, if one or more of the 'input' uses have a non-matching
+        constraint and the matched output operand is an early clobber
+        operand, then do not replace the input operand, since by definition
+        it conflicts with the output operand and cannot share the same
+        register.  See PR89313 for details.  */
+
       for (j = 0; j < noutputs; j++)
        if (!rtx_equal_p (SET_DEST (p_sets[j]), input)
            && reg_overlap_mentioned_p (input, SET_DEST (p_sets[j])))
@@ -6531,8 +6552,13 @@ match_asm_constraints_1 (rtx_insn *insn, rtx *p_sets, int noutputs)
                                              input, output);
       for (j = 0; j < ninputs; j++)
        if (reg_overlap_mentioned_p (input, RTVEC_ELT (inputs, j)))
-         RTVEC_ELT (inputs, j) = replace_rtx (RTVEC_ELT (inputs, j),
-                                              input, output);
+         {
+           if (!early_clobber_p
+               || match == matching_constraint_num
+                             (ASM_OPERANDS_INPUT_CONSTRAINT (op, j)))
+             RTVEC_ELT (inputs, j) = replace_rtx (RTVEC_ELT (inputs, j),
+                                                  input, output);
+         }
 
       changed = true;
     }
index b2c649cfb3e970ea2d78086e0a81276760f1892c..472b4ed7c2a31b46dcc2ca8fef764bdcf2e811ed 100644 (file)
@@ -1,3 +1,8 @@
+2019-03-27  Peter Bergner  <bergner@linux.ibm.com>
+
+       PR rtl-optimization/89313
+       * gcc.dg/pr89313.c: New test.
+
 2019-03-26  Jeff Law  <law@redhat.com>
 
        PR rtl-optimization/87761
diff --git a/gcc/testsuite/gcc.dg/pr89313.c b/gcc/testsuite/gcc.dg/pr89313.c
new file mode 100644 (file)
index 0000000..6688323
--- /dev/null
@@ -0,0 +1,26 @@
+/* PR rtl-optimization/89313  */
+/* { dg-do compile { target aarch64*-*-* arm*-*-* i?86-*-* powerpc*-*-* s390*-*-* x86_64-*-* } } */
+/* { dg-options "-O2" } */
+
+#if defined (__aarch64__)
+# define REG "x0"
+#elif defined (__arm__)
+# define REG "r0"
+#elif defined (__i386__)
+# define REG "%eax"
+#elif defined (__powerpc__)
+# define REG "r3"
+#elif defined (__s390__)
+# define REG "0"
+#elif defined (__x86_64__)
+# define REG "rax"
+#endif
+
+long
+bug (long arg)
+{
+  register long output asm (REG);
+  long input = arg;
+  asm ("blah %0, %1, %2" : "=&r" (output) : "r" (input), "0" (input));
+  return output;
+}