/* Put complex operands first and constants second if commutative. */
if (GET_RTX_CLASS (code) == 'c'
- && ((CONSTANT_P (op0) && GET_CODE (op1) != CONST_INT)
- || (GET_RTX_CLASS (GET_CODE (op0)) == 'o'
- && GET_RTX_CLASS (GET_CODE (op1)) != 'o')
- || (GET_CODE (op0) == SUBREG
- && GET_RTX_CLASS (GET_CODE (SUBREG_REG (op0))) == 'o'
- && GET_RTX_CLASS (GET_CODE (op1)) != 'o')))
+ && swap_commutative_operands_p (op0, op1))
tem = op0, op0 = op1, op1 = tem;
/* If this simplifies, do it. */
return tem;
/* Put complex operands first and constants second. */
- if ((CONSTANT_P (op0) && GET_CODE (op1) != CONST_INT)
- || (GET_RTX_CLASS (GET_CODE (op0)) == 'o'
- && GET_RTX_CLASS (GET_CODE (op1)) != 'o')
- || (GET_CODE (op0) == SUBREG
- && GET_RTX_CLASS (GET_CODE (SUBREG_REG (op0))) == 'o'
- && GET_RTX_CLASS (GET_CODE (op1)) != 'o'))
+ if (swap_commutative_operands_p (op0, op1))
tem = op0, op0 = op1, op1 = tem, code = swap_condition (code);
return gen_rtx_fmt_ee (code, mode, op0, op1);
simplify_replace_rtx (XEXP (x, 2), old, new));
case 'x':
- /* The only case we try to handle is a lowpart SUBREG of a single-word
- CONST_INT. */
- if (code == SUBREG && subreg_lowpart_p (x) && old == SUBREG_REG (x)
- && GET_CODE (new) == CONST_INT
- && GET_MODE_SIZE (GET_MODE (old)) <= UNITS_PER_WORD)
- return GEN_INT (INTVAL (new) & GET_MODE_MASK (mode));
-
+ /* The only case we try to handle is a SUBREG. */
+ if (code == SUBREG)
+ {
+ rtx exp;
+ exp = simplify_gen_subreg (GET_MODE (x),
+ simplify_replace_rtx (SUBREG_REG (x),
+ old, new),
+ GET_MODE (SUBREG_REG (x)),
+ SUBREG_BYTE (x));
+ if (exp)
+ x = exp;
+ }
return x;
default:
return 0;
/* Make sure the constant is second. */
- if ((CONSTANT_P (op0) && ! CONSTANT_P (op1))
- || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT))
+ if (swap_commutative_operands_p (op0, op1))
{
tem = op0, op0 = op1, op1 = tem;
code = swap_condition (code);
|| byte >= GET_MODE_SIZE (innermode))
abort ();
+ if (outermode == innermode && !byte)
+ return op;
+
/* Attempt to simplify constant to non-SUBREG expression. */
if (CONSTANT_P (op))
{
% UNITS_PER_WORD));
}
+ /* Bail out in case resulting subreg would be incorrect. */
+ if (final_offset % GET_MODE_SIZE (outermode)
+ || final_offset >= GET_MODE_SIZE (innermostmode))
+ return NULL;
/* Recurse for futher possible simplifications. */
- new = simplify_subreg (outermode, op, GET_MODE (op),
+ new = simplify_subreg (outermode, SUBREG_REG (op),
+ GET_MODE (SUBREG_REG (op)),
final_offset);
if (new)
return new;
- return gen_rtx_SUBREG (outermode, op, final_offset);
+ return gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
}
/* SUBREG of a hard register => just change the register number
suppress this simplification. If the hard register is the stack,
frame, or argument pointer, leave this as a SUBREG. */
- if (REG_P (op) == REG
+ if (REG_P (op)
&& REGNO (op) < FIRST_PSEUDO_REGISTER
&& REGNO (op) != FRAME_POINTER_REGNUM
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
MEM_COPY_ATTRIBUTES (new, op);
return new;
}
+
+ /* Handle complex values represented as CONCAT
+ of real and imaginary part. */
+ if (GET_CODE (op) == CONCAT)
+ {
+ int is_realpart = byte < GET_MODE_UNIT_SIZE (innermode) / 2;
+ rtx part = is_realpart ? XEXP (op, 0) : XEXP (op, 1);
+ unsigned int final_offset;
+
+ final_offset = byte % (GET_MODE_UNIT_SIZE (innermode) / 2);
+ return simplify_subreg (outermode, part, GET_MODE (part), final_offset);
+ }
+
return NULL_RTX;
}
+/* Make a SUBREG operation or equivalent if it folds. */
+
+rtx
+simplify_gen_subreg (outermode, op, innermode, byte)
+ rtx op;
+ unsigned int byte;
+ enum machine_mode outermode, innermode;
+{
+ rtx new;
+ /* Little bit of sanity checking. */
+ if (innermode == VOIDmode || outermode == VOIDmode
+ || innermode == BLKmode || outermode == BLKmode)
+ abort ();
+
+ if (GET_MODE (op) != innermode
+ && GET_MODE (op) != VOIDmode)
+ abort ();
+
+ if (byte % GET_MODE_SIZE (outermode)
+ || byte >= GET_MODE_SIZE (innermode))
+ abort ();
+
+ new = simplify_subreg (outermode, op, innermode, byte);
+ if (new)
+ return new;
+
+ if (GET_CODE (op) == SUBREG || GET_MODE (op) == VOIDmode)
+ return NULL_RTX;
+
+ return gen_rtx_SUBREG (outermode, op, byte);
+}
/* Simplify X, an rtx expression.
Return the simplified expression or NULL if no simplifications
? GET_MODE (XEXP (x, 0))
: GET_MODE (XEXP (x, 1))),
XEXP (x, 0), XEXP (x, 1));
+ case 'x':
+ /* The only case we try to handle is a SUBREG. */
+ if (code == SUBREG)
+ return simplify_gen_subreg (mode, SUBREG_REG (x),
+ GET_MODE (SUBREG_REG (x)),
+ SUBREG_BYTE (x));
+ return NULL;
default:
return NULL;
}