void
init_expmed ()
{
- /* This is "some random pseudo register" for purposes of calling recog
- to see what insns exist. */
- rtx reg = gen_rtx_REG (word_mode, 10000);
- rtx shift_insn, shiftadd_insn, shiftsub_insn;
+ rtx reg, shift_insn, shiftadd_insn, shiftsub_insn;
int dummy;
int m;
enum machine_mode mode, wider_mode;
start_sequence ();
+ /* This is "some random pseudo register" for purposes of calling recog
+ to see what insns exist. */
reg = gen_rtx_REG (word_mode, 10000);
zero_cost = rtx_cost (const0_rtx, 0);
for (m = 1; m < MAX_BITS_PER_WORD; m++)
{
+ rtx c_int = GEN_INT ((HOST_WIDE_INT) 1 << m);
shift_cost[m] = shiftadd_cost[m] = shiftsub_cost[m] = 32000;
XEXP (SET_SRC (PATTERN (shift_insn)), 1) = GEN_INT (m);
if (recog (PATTERN (shift_insn), shift_insn, &dummy) >= 0)
shift_cost[m] = rtx_cost (SET_SRC (PATTERN (shift_insn)), SET);
- XEXP (XEXP (SET_SRC (PATTERN (shiftadd_insn)), 0), 1)
- = GEN_INT ((HOST_WIDE_INT) 1 << m);
+ XEXP (XEXP (SET_SRC (PATTERN (shiftadd_insn)), 0), 1) = c_int;
if (recog (PATTERN (shiftadd_insn), shiftadd_insn, &dummy) >= 0)
shiftadd_cost[m] = rtx_cost (SET_SRC (PATTERN (shiftadd_insn)), SET);
- XEXP (XEXP (SET_SRC (PATTERN (shiftsub_insn)), 0), 1)
- = GEN_INT ((HOST_WIDE_INT) 1 << m);
+ XEXP (XEXP (SET_SRC (PATTERN (shiftsub_insn)), 0), 1) = c_int;
if (recog (PATTERN (shiftsub_insn), shiftsub_insn, &dummy) >= 0)
shiftsub_cost[m] = rtx_cost (SET_SRC (PATTERN (shiftsub_insn)), SET);
}
&& (GET_CODE (op0) != MEM
? ((GET_MODE_SIZE (fieldmode) >= UNITS_PER_WORD
|| GET_MODE_SIZE (GET_MODE (op0)) == GET_MODE_SIZE (fieldmode))
- && byte_offset % GET_MODE_SIZE (fieldmode) == 0)
+ && byte_offset % GET_MODE_SIZE (fieldmode) == 0)
: (! SLOW_UNALIGNED_ACCESS (fieldmode, MEM_ALIGN (op0))
|| (offset * BITS_PER_UNIT % bitsize == 0
&& MEM_ALIGN (op0) % GET_MODE_BITSIZE (fieldmode) == 0))))
if (pat)
emit_insn (pat);
else
- {
+ {
delete_insns_since (last);
store_fixed_bit_field (op0, offset, bitsize, bitpos, value);
}
mode = GET_MODE (op0);
if (GET_MODE_BITSIZE (mode) == 0
- || GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (word_mode))
- mode = word_mode;
+ || GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (word_mode))
+ mode = word_mode;
mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0));
+ (offset * UNITS_PER_WORD);
mode1 = (VECTOR_MODE_P (tmode)
- ? mode
- : mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0));
+ ? mode
+ : mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0));
if (((GET_CODE (op0) != MEM
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
/* Else we've got some float mode source being extracted into
a different float mode destination -- this combination of
subregs results in Severe Tire Damage. */
- abort ();
+ goto no_subreg_mode_swap;
}
if (GET_CODE (op0) == REG)
op0 = gen_rtx_SUBREG (mode1, op0, byte_offset);
return convert_to_mode (tmode, op0, unsignedp);
return op0;
}
+ no_subreg_mode_swap:
/* Handle fields bigger than a word. */
if (SHIFT_COUNT_TRUNCATED)
{
if (GET_CODE (op1) == CONST_INT
- && ((unsigned HOST_WIDE_INT) INTVAL (op1) >=
+ && ((unsigned HOST_WIDE_INT) INTVAL (op1) >=
(unsigned HOST_WIDE_INT) GET_MODE_BITSIZE (mode)))
- op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1)
+ op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1)
% GET_MODE_BITSIZE (mode));
else if (GET_CODE (op1) == SUBREG
&& subreg_lowpart_p (op1))
there is no difference between signed and unsigned. */
op0 = expand_binop (mode,
! unsignedp
- && flag_trapv && (GET_MODE_CLASS(mode) == MODE_INT)
- ? smulv_optab : smul_optab,
+ && flag_trapv && (GET_MODE_CLASS(mode) == MODE_INT)
+ ? smulv_optab : smul_optab,
op0, op1, target, unsignedp, OPTAB_LIB_WIDEN);
if (op0 == 0)
abort ();
if (! unsignedp && op1 == constm1_rtx)
{
if (rem_flag)
- return const0_rtx;
+ return const0_rtx;
return expand_unop (mode, flag_trapv && GET_MODE_CLASS(mode) == MODE_INT
- ? negv_optab : neg_optab, op0, target, 0);
+ ? negv_optab : neg_optab, op0, target, 0);
}
if (target
not straightforward to generalize this. Maybe we should make an array
of possible modes in init_expmed? Save this for GCC 2.7. */
- optab1 = (op1_is_pow2 ? (unsignedp ? lshr_optab : ashr_optab)
+ optab1 = ((op1_is_pow2 && op1 != const0_rtx)
+ ? (unsignedp ? lshr_optab : ashr_optab)
: (unsignedp ? udiv_optab : sdiv_optab));
- optab2 = (op1_is_pow2 ? optab1 : (unsignedp ? udivmod_optab : sdivmod_optab));
+ optab2 = ((op1_is_pow2 && op1 != const0_rtx)
+ ? optab1
+ : (unsignedp ? udivmod_optab : sdivmod_optab));
for (compute_mode = mode; compute_mode != VOIDmode;
compute_mode = GET_MODE_WIDER_MODE (compute_mode))
make_tree (type, XEXP (x, 1))));
case LSHIFTRT:
+ t = (*lang_hooks.types.unsigned_type) (type);
return fold (convert (type,
- build (RSHIFT_EXPR, unsigned_type (type),
- make_tree (unsigned_type (type),
- XEXP (x, 0)),
+ build (RSHIFT_EXPR, t,
+ make_tree (t, XEXP (x, 0)),
make_tree (type, XEXP (x, 1)))));
case ASHIFTRT:
+ t = (*lang_hooks.types.signed_type) (type);
return fold (convert (type,
- build (RSHIFT_EXPR, signed_type (type),
- make_tree (signed_type (type), XEXP (x, 0)),
+ build (RSHIFT_EXPR, t,
+ make_tree (t, XEXP (x, 0)),
make_tree (type, XEXP (x, 1)))));
case DIV:
if (TREE_CODE (type) != REAL_TYPE)
- t = signed_type (type);
+ t = (*lang_hooks.types.signed_type) (type);
else
t = type;
make_tree (t, XEXP (x, 0)),
make_tree (t, XEXP (x, 1)))));
case UDIV:
- t = unsigned_type (type);
+ t = (*lang_hooks.types.unsigned_type) (type);
return fold (convert (type,
build (TRUNC_DIV_EXPR, t,
make_tree (t, XEXP (x, 0)),
make_tree (t, XEXP (x, 1)))));
+
+ case SIGN_EXTEND:
+ case ZERO_EXTEND:
+ t = (*lang_hooks.types.type_for_mode) (GET_MODE (XEXP (x, 0)),
+ GET_CODE (x) == ZERO_EXTEND);
+ return fold (convert (type, make_tree (t, XEXP (x, 0))));
+
default:
t = make_node (RTL_EXPR);
TREE_TYPE (t) = type;
}
}
+/* Check whether the multiplication X * MULT + ADD overflows.
+ X, MULT and ADD must be CONST_*.
+ MODE is the machine mode for the computation.
+ X and MULT must have mode MODE. ADD may have a different mode.
+ So can X (defaults to same as MODE).
+ UNSIGNEDP is non-zero to do unsigned multiplication. */
+
+bool
+const_mult_add_overflow_p (x, mult, add, mode, unsignedp)
+ rtx x, mult, add;
+ enum machine_mode mode;
+ int unsignedp;
+{
+ tree type, mult_type, add_type, result;
+
+ type = (*lang_hooks.types.type_for_mode) (mode, unsignedp);
+
+ /* In order to get a proper overflow indication from an unsigned
+ type, we have to pretend that it's a sizetype. */
+ mult_type = type;
+ if (unsignedp)
+ {
+ mult_type = copy_node (type);
+ TYPE_IS_SIZETYPE (mult_type) = 1;
+ }
+
+ add_type = (GET_MODE (add) == VOIDmode ? mult_type
+ : (*lang_hooks.types.type_for_mode) (GET_MODE (add), unsignedp));
+
+ result = fold (build (PLUS_EXPR, mult_type,
+ fold (build (MULT_EXPR, mult_type,
+ make_tree (mult_type, x),
+ make_tree (mult_type, mult))),
+ make_tree (add_type, add)));
+
+ return TREE_CONSTANT_OVERFLOW (result);
+}
+
/* Return an rtx representing the value of X * MULT + ADD.
TARGET is a suggestion for where to store the result (an rtx).
MODE is the machine mode for the computation.