===================================================================
@@ -4973,6 +4973,46 @@ find_split_point (rtx *loc, rtx insn, bo
}
}
+/* Replace operand I of *LOC with NEW_RTX.
+
+ In some cases, substituting a constant into an existing rtx can
+ lose vital information, such as the inner mode of a SUBREG or a
+ ZERO_EXTEND operation. Return true if this substitution falls into
+ that category, and replace *LOC with a simplified form of the result.
+ Return false if *LOC points to the same rtx as before. */
+
+static bool
+subst_operand (rtx *loc, int i, rtx new_rtx)
+{
+ rtx x, tem;
+
+ x = *loc;
+ if (CONST_INT_P (new_rtx) || GET_CODE (new_rtx) == CONST_DOUBLE)
+ {
+ if (GET_CODE (x) == SUBREG)
+ {
+ tem = simplify_subreg (GET_MODE (x), new_rtx,
+ GET_MODE (SUBREG_REG (x)),
+ SUBREG_BYTE (x));
+ if (!tem)
+ tem = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
+ }
+ else if (UNARY_P (x))
+ tem = simplify_unary_operation (GET_CODE (x), GET_MODE (x),
+ new_rtx, GET_MODE (XEXP (x, 0)));
+ else
+ tem = NULL_RTX;
+
+ if (tem)
+ {
+ *loc = tem;
+ return true;
+ }
+ }
+ SUBST (XEXP (x, i), new_rtx);
+ return false;
+}
+
/* Throughout X, replace FROM with TO, and return the result.
The result is TO if X is FROM;
otherwise the result is X, but its contents may have been modified.
@@ -5210,27 +5250,8 @@ #define COMBINE_RTX_EQUAL_P(X,Y) \
if (GET_CODE (new_rtx) == CLOBBER && XEXP (new_rtx, 0) == const0_rtx)
return new_rtx;
- if (GET_CODE (x) == SUBREG
- && (CONST_INT_P (new_rtx)
- || GET_CODE (new_rtx) == CONST_DOUBLE))
- {
- enum machine_mode mode = GET_MODE (x);
-
- x = simplify_subreg (GET_MODE (x), new_rtx,
- GET_MODE (SUBREG_REG (x)),
- SUBREG_BYTE (x));
- if (! x)
- x = gen_rtx_CLOBBER (mode, const0_rtx);
- }
- else if (CONST_INT_P (new_rtx)
- && GET_CODE (x) == ZERO_EXTEND)
- {
- x = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
- new_rtx, GET_MODE (XEXP (x, 0)));
- gcc_assert (x);
- }
- else
- SUBST (XEXP (x, i), new_rtx);
+ if (subst_operand (&x, i, new_rtx))
+ break;
}
}
}
@@ -7887,7 +7908,8 @@ make_compound_operation (rtx x, enum rtx
if (fmt[i] == 'e')
{
new_rtx = make_compound_operation (XEXP (x, i), next_code);
- SUBST (XEXP (x, i), new_rtx);
+ if (subst_operand (&x, i, new_rtx))
+ break;
}
else if (fmt[i] == 'E')
for (j = 0; j < XVECLEN (x, i); j++)
@@ -8942,37 +8964,15 @@ known_cond (rtx x, enum rtx_code cond, r
return x;
}
- /* We don't have to handle SIGN_EXTEND here, because even in the
- case of replacing something with a modeless CONST_INT, a
- CONST_INT is already (supposed to be) a valid sign extension for
- its narrower mode, which implies it's already properly
- sign-extended for the wider mode. Now, for ZERO_EXTEND, the
- story is different. */
- else if (code == ZERO_EXTEND)
- {
- enum machine_mode inner_mode = GET_MODE (XEXP (x, 0));
- rtx new_rtx, r = known_cond (XEXP (x, 0), cond, reg, val);
-
- if (XEXP (x, 0) != r)
- {
- /* We must simplify the zero_extend here, before we lose
- track of the original inner_mode. */
- new_rtx = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
- r, inner_mode);
- if (new_rtx)
- return new_rtx;
- else
- SUBST (XEXP (x, 0), r);
- }
-
- return x;
- }
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- SUBST (XEXP (x, i), known_cond (XEXP (x, i), cond, reg, val));
+ {
+ if (subst_operand (&x, i, known_cond (XEXP (x, i), cond, reg, val)))
+ break;
+ }
else if (fmt[i] == 'E')
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
SUBST (XVECEXP (x, i, j), known_cond (XVECEXP (x, i, j),
===================================================================
@@ -0,0 +1,30 @@
+static int
+func1 (int a, int b)
+{
+ return b ? a : a / b;
+}
+
+static unsigned char
+func2 (unsigned char a, int b)
+{
+ return b ? a : b;
+}
+
+int i;
+
+void
+func3 (const int arg)
+{
+ for (i = 0; i != 10; i = foo ())
+ {
+ if (!arg)
+ {
+ int j;
+ for (j = 0; j < 5; j += 1)
+ {
+ int *ptr;
+ *ptr = func2 (func1 (arg, *ptr), foo (arg));
+ }
+ }
+ }
+}