if (GET_CODE (op) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op)
&& ! SUBREG_PROMOTED_UNSIGNED_P (op)
- && GET_MODE (XEXP (op, 0)) == mode)
- return XEXP (op, 0);
+ && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0))))
+ return rtl_hooks.gen_lowpart_no_emit (mode, op);
#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
if (! POINTERS_EXTEND_UNSIGNED
if (GET_CODE (op) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op)
&& SUBREG_PROMOTED_UNSIGNED_P (op) > 0
- && GET_MODE (XEXP (op, 0)) == mode)
- return XEXP (op, 0);
+ && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0))))
+ return rtl_hooks.gen_lowpart_no_emit (mode, op);
#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
if (POINTERS_EXTEND_UNSIGNED > 0
to CONST_INT since overflow won't be computed properly if wider
than HOST_BITS_PER_WIDE_INT. */
- if (CONSTANT_P (op0) && GET_MODE (op0) != VOIDmode
+ if ((GET_CODE (op0) == CONST
+ || GET_CODE (op0) == SYMBOL_REF
+ || GET_CODE (op0) == LABEL_REF)
&& GET_CODE (op1) == CONST_INT)
return plus_constant (op0, INTVAL (op1));
- else if (CONSTANT_P (op1) && GET_MODE (op1) != VOIDmode
+ else if ((GET_CODE (op1) == CONST
+ || GET_CODE (op1) == SYMBOL_REF
+ || GET_CODE (op1) == LABEL_REF)
&& GET_CODE (op0) == CONST_INT)
return plus_constant (op1, INTVAL (op0));
rtx coeff;
unsigned HOST_WIDE_INT l;
HOST_WIDE_INT h;
+ bool speed = optimize_function_for_speed_p (cfun);
add_double (coeff0l, coeff0h, coeff1l, coeff1h, &l, &h);
coeff = immed_double_const (l, h, mode);
tem = simplify_gen_binary (MULT, mode, lhs, coeff);
- return rtx_cost (tem, SET) <= rtx_cost (orig, SET)
+ return rtx_cost (tem, SET, speed) <= rtx_cost (orig, SET, speed)
? tem : 0;
}
}
so we can distinguish it from a register-register-copy.
In IEEE floating point, x-0 is not the same as x. */
-
- if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
+ if (!(HONOR_SIGNED_ZEROS (mode)
+ && HONOR_SIGN_DEPENDENT_ROUNDING (mode))
&& trueop1 == CONST0_RTX (mode))
return op0;
#endif
rtx coeff;
unsigned HOST_WIDE_INT l;
HOST_WIDE_INT h;
+ bool speed = optimize_function_for_speed_p (cfun);
add_double (coeff0l, coeff0h, negcoeff1l, negcoeff1h, &l, &h);
coeff = immed_double_const (l, h, mode);
tem = simplify_gen_binary (MULT, mode, lhs, coeff);
- return rtx_cost (tem, SET) <= rtx_cost (orig, SET)
+ return rtx_cost (tem, SET, speed) <= rtx_cost (orig, SET, speed)
? tem : 0;
}
}
return simplify_gen_binary (code, mode, tem, op1);
}
}
+
+ /* (and X (ior (not X) Y) -> (and X Y) */
+ if (GET_CODE (op1) == IOR
+ && GET_CODE (XEXP (op1, 0)) == NOT
+ && op0 == XEXP (XEXP (op1, 0), 0))
+ return simplify_gen_binary (AND, mode, op0, XEXP (op1, 1));
+
+ /* (and (ior (not X) Y) X) -> (and X Y) */
+ if (GET_CODE (op0) == IOR
+ && GET_CODE (XEXP (op0, 0)) == NOT
+ && op1 == XEXP (XEXP (op0, 0), 0))
+ return simplify_gen_binary (AND, mode, op1, XEXP (op0, 1));
+
tem = simplify_associative_operation (code, mode, op0, op1);
if (tem)
return tem;
&& (unsigned HOST_WIDE_INT) INTVAL (trueop0) == GET_MODE_MASK (mode)
&& ! side_effects_p (op1))
return op0;
+ canonicalize_shift:
+ if (SHIFT_COUNT_TRUNCATED && GET_CODE (op1) == CONST_INT)
+ {
+ val = INTVAL (op1) & (GET_MODE_BITSIZE (mode) - 1);
+ if (val != INTVAL (op1))
+ return simplify_gen_binary (code, mode, op0, GEN_INT (val));
+ }
break;
case ASHIFT:
return op0;
if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1))
return op0;
- break;
+ goto canonicalize_shift;
case LSHIFTRT:
if (trueop1 == CONST0_RTX (mode))
return simplify_gen_relational (EQ, mode, imode,
XEXP (op0, 0), const0_rtx);
}
- break;
+ goto canonicalize_shift;
case SMIN:
if (width <= HOST_BITS_PER_WIDE_INT
if (VECTOR_MODE_P (mode)
&& code == VEC_CONCAT
- && CONSTANT_P (op0) && CONSTANT_P (op1))
+ && (CONST_INT_P (op0)
+ || GET_CODE (op0) == CONST_DOUBLE
+ || GET_CODE (op0) == CONST_FIXED)
+ && (CONST_INT_P (op1)
+ || GET_CODE (op1) == CONST_DOUBLE
+ || GET_CODE (op1) == CONST_FIXED))
{
unsigned n_elts = GET_MODE_NUNITS (mode);
rtvec v = rtvec_alloc (n_elts);
is unable to accurately represent the result. */
if ((flag_rounding_math
- || (REAL_MODE_FORMAT_COMPOSITE_P (mode)
- && !flag_unsafe_math_optimizations))
+ || (MODE_COMPOSITE_P (mode) && !flag_unsafe_math_optimizations))
&& (inexact || !real_identical (&result, &value)))
return NULL_RTX;
one CONST_INT, and the sort will have ensured that it is last
in the array and that any other constant will be next-to-last. */
+ if (GET_CODE (ops[n_ops - 1].op) == CONST_INT)
+ i = n_ops - 2;
+ else
+ i = n_ops - 1;
+
+ if (i >= 1
+ && ops[i].neg
+ && !ops[i - 1].neg
+ && CONSTANT_P (ops[i].op)
+ && GET_CODE (ops[i].op) == GET_CODE (ops[i - 1].op))
+ {
+ ops[i - 1].op = gen_rtx_MINUS (mode, ops[i - 1].op, ops[i].op);
+ ops[i - 1].op = gen_rtx_CONST (mode, ops[i - 1].op);
+ if (i < n_ops - 1)
+ ops[i] = ops[i + 1];
+ n_ops--;
+ }
+
if (n_ops > 1
&& GET_CODE (ops[n_ops - 1].op) == CONST_INT
&& CONSTANT_P (ops[n_ops - 2].op))
else
{
rtx mmin_rtx, mmax_rtx;
- unsigned int sign_copies = num_sign_bit_copies (trueop0, mode);
get_mode_bounds (mode, sign, mode, &mmin_rtx, &mmax_rtx);
- /* Since unsigned mmin will never be interpreted as negative, use
- INTVAL (and an arithmetic right shift). */
- mmin = INTVAL (mmin_rtx) >> (sign_copies - 1);
- /* Since signed mmax will always be positive, use UINTVAL (and
- a logical right shift). */
- mmax = UINTVAL (mmax_rtx) >> (sign_copies - 1);
+ mmin = INTVAL (mmin_rtx);
+ mmax = INTVAL (mmax_rtx);
+ if (sign)
+ {
+ unsigned int sign_copies = num_sign_bit_copies (trueop0, mode);
+
+ mmin >>= (sign_copies - 1);
+ mmax >>= (sign_copies - 1);
+ }
}
switch (code)
return newx;
if (validate_subreg (outermode, innermostmode,
SUBREG_REG (op), final_offset))
- return gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
+ {
+ newx = gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
+ if (SUBREG_PROMOTED_VAR_P (op)
+ && SUBREG_PROMOTED_UNSIGNED_P (op) >= 0
+ && GET_MODE_CLASS (outermode) == MODE_INT
+ && IN_RANGE (GET_MODE_SIZE (outermode),
+ GET_MODE_SIZE (innermode),
+ GET_MODE_SIZE (innermostmode))
+ && subreg_lowpart_p (newx))
+ {
+ SUBREG_PROMOTED_VAR_P (newx) = 1;
+ SUBREG_PROMOTED_UNSIGNED_SET
+ (newx, SUBREG_PROMOTED_UNSIGNED_P (op));
+ }
+ return newx;
+ }
return NULL_RTX;
}
suppress this simplification. If the hard register is the stack,
frame, or argument pointer, leave this as a SUBREG. */
- if (REG_P (op)
- && REGNO (op) < FIRST_PSEUDO_REGISTER
-#ifdef CANNOT_CHANGE_MODE_CLASS
- && ! (REG_CANNOT_CHANGE_MODE_P (REGNO (op), innermode, outermode)
- && GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT
- && GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT)
-#endif
- && ((reload_completed && !frame_pointer_needed)
- || (REGNO (op) != FRAME_POINTER_REGNUM
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
- && REGNO (op) != HARD_FRAME_POINTER_REGNUM
-#endif
- ))
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- && REGNO (op) != ARG_POINTER_REGNUM
-#endif
- && REGNO (op) != STACK_POINTER_REGNUM
- && subreg_offset_representable_p (REGNO (op), innermode,
- byte, outermode))
+ if (REG_P (op) && HARD_REGISTER_P (op))
{
- unsigned int regno = REGNO (op);
- unsigned int final_regno
- = regno + subreg_regno_offset (regno, innermode, byte, outermode);
-
- /* ??? We do allow it if the current REG is not valid for
- its mode. This is a kludge to work around how float/complex
- arguments are passed on 32-bit SPARC and should be fixed. */
- if (HARD_REGNO_MODE_OK (final_regno, outermode)
- || ! HARD_REGNO_MODE_OK (regno, innermode))
+ unsigned int regno, final_regno;
+
+ regno = REGNO (op);
+ final_regno = simplify_subreg_regno (regno, innermode, byte, outermode);
+ if (HARD_REGISTER_NUM_P (final_regno))
{
rtx x;
int final_offset = byte;
return simplify_gen_binary (ASHIFT, outermode,
XEXP (XEXP (op, 0), 0), XEXP (op, 1));
+ /* Recognize a word extraction from a multi-word subreg. */
+ if ((GET_CODE (op) == LSHIFTRT
+ || GET_CODE (op) == ASHIFTRT)
+ && SCALAR_INT_MODE_P (outermode)
+ && GET_MODE_BITSIZE (outermode) >= BITS_PER_WORD
+ && GET_MODE_BITSIZE (innermode) >= (2 * GET_MODE_BITSIZE (outermode))
+ && GET_CODE (XEXP (op, 1)) == CONST_INT
+ && (INTVAL (XEXP (op, 1)) & (GET_MODE_BITSIZE (outermode) - 1)) == 0
+ && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (innermode)
+ && byte == subreg_lowpart_offset (outermode, innermode))
+ {
+ int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT;
+ return simplify_gen_subreg (outermode, XEXP (op, 0), innermode,
+ (WORDS_BIG_ENDIAN
+ ? byte - shifted_bytes : byte + shifted_bytes));
+ }
+
return NULL_RTX;
}