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;
}
}
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))
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;
}