(try_combine): Always call set_significant on new patterns, so don't call
authorRichard Kenner <kenner@gcc.gnu.org>
Mon, 21 Sep 1992 00:05:40 +0000 (20:05 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Mon, 21 Sep 1992 00:05:40 +0000 (20:05 -0400)
just in split case.

(subst): Move sign extension inside arithmetic when we have a constant
computation inside another computation.

From-SVN: r2194

gcc/combine.c

index aaf376c63c0f5efbbd6ac3a3fddcc8996eb438cb..6654e17078d9b74ac94c9742491a3a1c748497e3 100644 (file)
@@ -1585,17 +1585,12 @@ try_combine (i3, i2, i1)
            newpat = newi3pat;
 
          /* It is possible that both insns now set the destination of I3.
-            If so, we must show an extra use of it and update
-            reg_significant.  */
+            If so, we must show an extra use of it.  */
 
          if (insn_code_number >= 0 && GET_CODE (SET_DEST (i3set)) == REG
              && GET_CODE (SET_DEST (i2set)) == REG
              && REGNO (SET_DEST (i3set)) == REGNO (SET_DEST (i2set)))
-           {
-             reg_n_sets[REGNO (SET_DEST (i2set))]++;
-             set_significant (SET_DEST (i2set), i2set);
-             set_significant (SET_DEST (i3set), i3set);
-           }
+           reg_n_sets[REGNO (SET_DEST (i2set))]++;
        }
 
       /* If we can split it and use I2DEST, go ahead and see if that
@@ -2073,6 +2068,13 @@ try_combine (i3, i2, i1)
          }
       }
 
+    /* Update reg_significant et al for any changes that may have been made
+       to this insn.  */
+
+    note_stores (newpat, set_significant);
+    if (newi2pat)
+      note_stores (newi2pat, set_significant);
+
     /* If I3 is now an unconditional jump, ensure that it has a 
        BARRIER following it since it may have initially been a
        conditional jump.  */
@@ -2670,6 +2672,47 @@ subst (x, from, to, in_dest, unique_copy)
       SUBST (XEXP (x, 1), temp);
     }
 
+  /* If this is a PLUS, MINUS, or MULT, and the first operand is the
+     sign extension of a PLUS with a constant, reverse the order of the sign
+     extension and the addition. Note that this not the same as the original
+     code, but overflow is undefined for signed values.  Also note that the
+     PLUS will have been partially moved "inside" the sign-extension, so that
+     the first operand of X will really look like:
+         (ashiftrt (plus (ashift A C4) C5) C4).
+     We convert this to
+         (plus (ashiftrt (ashift A C4) C2) C4)
+     and replace the first operand of X with that expression.  Later parts
+     of this function may simplify the expression further.
+
+     For example, if we start with (mult (sign_extend (plus A C1)) C2),
+     we swap the SIGN_EXTEND and PLUS.  Later code will apply the
+     distributive law to produce (plus (mult (sign_extend X) C1) C3).
+
+     We do this to simplify address expressions.  */
+
+  if ((code == PLUS || code == MINUS || code == MULT)
+      && GET_CODE (XEXP (x, 0)) == ASHIFTRT
+      && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS
+      && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ASHIFT
+      && GET_CODE (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 1)) == CONST_INT
+      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
+      && XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 1) == XEXP (XEXP (x, 0), 1)
+      && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT
+      && (temp = simplify_binary_operation (ASHIFTRT, mode,
+                                           XEXP (XEXP (XEXP (x, 0), 0), 1),
+                                           XEXP (XEXP (x, 0), 1))) != 0)
+    {
+      rtx new
+       = simplify_shift_const (NULL_RTX, ASHIFT, mode,
+                               XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 0),
+                               INTVAL (XEXP (XEXP (x, 0), 1)));
+
+      new = simplify_shift_const (NULL_RTX, ASHIFTRT, mode, new,
+                                 INTVAL (XEXP (XEXP (x, 0), 1)));
+
+      SUBST (XEXP (x, 0), gen_binary (PLUS, mode, new, temp));
+    }
+
   /* If this is a simple operation applied to an IF_THEN_ELSE, try 
      applying it to the arms of the IF_THEN_ELSE.  This often simplifies
      things.  Don't deal with operations that change modes here.  */