re PR rtl-optimization/71878 (ICE in cselib_record_set)
authorThomas Preud'homme <thomas.preudhomme@arm.com>
Thu, 14 Jul 2016 16:41:06 +0000 (16:41 +0000)
committerThomas Preud'homme <thopre01@gcc.gnu.org>
Thu, 14 Jul 2016 16:41:06 +0000 (16:41 +0000)
2016-07-14  Thomas Preud'homme  <thomas.preudhomme@arm.com>

    gcc/
    PR rtl-optimization/71878
    * lra-constraints.c (match_reload): Pass information about other
    output operands.  Create new unique register value if matching input
    operand shares same register value as output operand being considered.
    (curr_insn_transform): Record output operands already processed.

From-SVN: r238346

gcc/ChangeLog
gcc/lra-constraints.c

index 4b099bed410e87459dcb2c70e1ab3466744ad6a9..3232bafa118d3140da2b26ad8f229229e5e1e3ae 100644 (file)
@@ -1,3 +1,11 @@
+2016-07-14  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       PR rtl-optimization/71878
+       * lra-constraints.c (match_reload): Pass information about other
+       output operands.  Create new unique register value if matching input
+       operand shares same register value as output operand being considered.
+       (curr_insn_transform): Record output operands already processed.
+
 2016-07-14  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        PR target/65951
index a1119ac70fdabc4afbec04cc9140de6ac69c0564..45b65069e68729e53af3181ceec60134c52f9437 100644 (file)
@@ -871,15 +871,18 @@ regno_val_use_in (unsigned int regno, rtx x)
 }
 
 /* Generate reloads for matching OUT and INS (array of input operand
-   numbers with end marker -1) with reg class GOAL_CLASS.  Add input
-   and output reloads correspondingly to the lists *BEFORE and *AFTER.
-   OUT might be negative.  In this case we generate input reloads for
-   matched input operands INS.  EARLY_CLOBBER_P is a flag that the
-   output operand is early clobbered for chosen alternative.  */
+   numbers with end marker -1) with reg class GOAL_CLASS, considering
+   output operands OUTS (similar array to INS) needing to be in different
+   registers.  Add input and output reloads correspondingly to the lists
+   *BEFORE and *AFTER.  OUT might be negative.  In this case we generate
+   input reloads for matched input operands INS.  EARLY_CLOBBER_P is a flag
+   that the output operand is early clobbered for chosen alternative.  */
 static void
-match_reload (signed char out, signed char *ins, enum reg_class goal_class,
-             rtx_insn **before, rtx_insn **after, bool early_clobber_p)
+match_reload (signed char out, signed char *ins, signed char *outs,
+             enum reg_class goal_class, rtx_insn **before,
+             rtx_insn **after, bool early_clobber_p)
 {
+  bool out_conflict;
   int i, in;
   rtx new_in_reg, new_out_reg, reg;
   machine_mode inmode, outmode;
@@ -968,12 +971,32 @@ match_reload (signed char out, signed char *ins, enum reg_class goal_class,
         We don't care about eliminable hard regs here as we are
         interesting only in pseudos.  */
 
+      /* Matching input's register value is the same as one of the other
+        output operand.  Output operands in a parallel insn must be in
+        different registers.  */
+      out_conflict = false;
+      if (REG_P (in_rtx))
+       {
+         for (i = 0; outs[i] >= 0; i++)
+           {
+             rtx other_out_rtx = *curr_id->operand_loc[outs[i]];
+             if (REG_P (other_out_rtx)
+                 && (regno_val_use_in (REGNO (in_rtx), other_out_rtx)
+                     != NULL_RTX))
+               {
+                 out_conflict = true;
+                 break;
+               }
+           }
+       }
+
       new_in_reg = new_out_reg
        = (! early_clobber_p && ins[1] < 0 && REG_P (in_rtx)
           && (int) REGNO (in_rtx) < lra_new_regno_start
           && find_regno_note (curr_insn, REG_DEAD, REGNO (in_rtx))
           && (out < 0
               || regno_val_use_in (REGNO (in_rtx), out_rtx) == NULL_RTX)
+          && !out_conflict
           ? lra_create_new_reg (inmode, in_rtx, goal_class, "")
           : lra_create_new_reg_with_unique_value (outmode, out_rtx,
                                                   goal_class, ""));
@@ -3469,9 +3492,11 @@ curr_insn_transform (bool check_only_p)
   int i, j, k;
   int n_operands;
   int n_alternatives;
+  int n_outputs;
   int commutative;
   signed char goal_alt_matched[MAX_RECOG_OPERANDS][MAX_RECOG_OPERANDS];
   signed char match_inputs[MAX_RECOG_OPERANDS + 1];
+  signed char outputs[MAX_RECOG_OPERANDS + 1];
   rtx_insn *before, *after;
   bool alt_p = false;
   /* Flag that the insn has been changed through a transformation.  */
@@ -3881,6 +3906,8 @@ curr_insn_transform (bool check_only_p)
          }
       }
 
+  n_outputs = 0;
+  outputs[0] = -1;
   for (i = 0; i < n_operands; i++)
     {
       int regno;
@@ -4038,7 +4065,7 @@ curr_insn_transform (bool check_only_p)
          /* generate reloads for input and matched outputs.  */
          match_inputs[0] = i;
          match_inputs[1] = -1;
-         match_reload (goal_alt_matched[i][0], match_inputs,
+         match_reload (goal_alt_matched[i][0], match_inputs, outputs,
                        goal_alt[i], &before, &after,
                        curr_static_id->operand_alternative
                        [goal_alt_number * n_operands + goal_alt_matched[i][0]]
@@ -4048,9 +4075,9 @@ curr_insn_transform (bool check_only_p)
               && (curr_static_id->operand[goal_alt_matched[i][0]].type
                   == OP_IN))
        /* Generate reloads for output and matched inputs.  */
-       match_reload (i, goal_alt_matched[i], goal_alt[i], &before, &after,
-                     curr_static_id->operand_alternative
-                     [goal_alt_number * n_operands + i].earlyclobber);
+       match_reload (i, goal_alt_matched[i], outputs, goal_alt[i], &before,
+                     &after, curr_static_id->operand_alternative
+                             [goal_alt_number * n_operands + i].earlyclobber);
       else if (curr_static_id->operand[i].type == OP_IN
               && (curr_static_id->operand[goal_alt_matched[i][0]].type
                   == OP_IN))
@@ -4060,12 +4087,22 @@ curr_insn_transform (bool check_only_p)
          for (j = 0; (k = goal_alt_matched[i][j]) >= 0; j++)
            match_inputs[j + 1] = k;
          match_inputs[j + 1] = -1;
-         match_reload (-1, match_inputs, goal_alt[i], &before, &after, false);
+         match_reload (-1, match_inputs, outputs, goal_alt[i], &before,
+                       &after, false);
        }
       else
        /* We must generate code in any case when function
           process_alt_operands decides that it is possible.  */
        gcc_unreachable ();
+
+      /* Memorise processed outputs so that output remaining to be processed
+        can avoid using the same register value (see match_reload).  */
+      if (curr_static_id->operand[i].type == OP_OUT)
+       {
+         outputs[n_outputs++] = i;
+         outputs[n_outputs] = -1;
+       }
+
       if (optional_p)
        {
          lra_assert (REG_P (op));