+ else if (code == SUBREG)
+ {
+ enum machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
+ rtx new, r = known_cond (SUBREG_REG (x), cond, reg, val);
+
+ if (SUBREG_REG (x) != r)
+ {
+ /* We must simplify subreg here, before we lose track of the
+ original inner_mode. */
+ new = simplify_subreg (GET_MODE (x), r,
+ inner_mode, SUBREG_BYTE (x));
+ if (new)
+ return new;
+ else
+ SUBST (SUBREG_REG (x), 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, 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 = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
+ r, inner_mode);
+ if (new)
+ return new;
+ else
+ SUBST (XEXP (x, 0), r);
+ }
+
+ return x;
+ }