/* Medium-level subroutines: convert bit-field store and extract
and shifts, multiplies and divides to rtl instructions.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of GCC.
if (HAVE_insv
&& GET_MODE (value) != BLKmode
- && !(bitsize == 1 && GET_CODE (value) == CONST_INT)
&& bitsize > 0
&& GET_MODE_BITSIZE (op_mode) >= bitsize
&& ! ((REG_P (op0) || GET_CODE (op0) == SUBREG)
and shifted in the other direction; but that does not work
on all machines. */
- op1 = expand_expr (amount, NULL_RTX, VOIDmode, 0);
+ op1 = expand_normal (amount);
if (SHIFT_COUNT_TRUNCATED)
{
return t;
}
}
-
-/* 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 nonzero to do unsigned multiplication. */
-
-bool
-const_mult_add_overflow_p (rtx x, rtx mult, rtx 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)
- {
- /* FIXME:It would be nice if we could step directly from this
- type to its sizetype equivalent. */
- mult_type = build_distinct_type_copy (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_build2 (PLUS_EXPR, mult_type,
- fold_build2 (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.
- X and MULT must have mode MODE. ADD may have a different mode.
- So can X (defaults to same as MODE).
- UNSIGNEDP is nonzero to do unsigned multiplication.
- This may emit insns. */
-
-rtx
-expand_mult_add (rtx x, rtx target, rtx mult, rtx add, enum machine_mode mode,
- int unsignedp)
-{
- tree type = lang_hooks.types.type_for_mode (mode, unsignedp);
- tree add_type = (GET_MODE (add) == VOIDmode
- ? type: lang_hooks.types.type_for_mode (GET_MODE (add),
- unsignedp));
- tree result = fold_build2 (PLUS_EXPR, type,
- fold_build2 (MULT_EXPR, type,
- make_tree (type, x),
- make_tree (type, mult)),
- make_tree (add_type, add));
-
- return expand_expr (result, target, VOIDmode, 0);
-}
\f
/* Compute the logical-and of OP0 and OP1, storing it in TARGET
and returning TARGET.
}
\f
/* Perform possibly multi-word comparison and conditional jump to LABEL
- if ARG1 OP ARG2 true where ARG1 and ARG2 are of mode MODE
-
- The algorithm is based on the code in expr.c:do_jump.
-
- Note that this does not perform a general comparison. Only
- variants generated within expmed.c are correctly handled, others
- could be handled if needed. */
+ if ARG1 OP ARG2 true where ARG1 and ARG2 are of mode MODE. This is
+ now a thin wrapper around do_compare_rtx_and_jump. */
static void
do_cmp_and_jump (rtx arg1, rtx arg2, enum rtx_code op, enum machine_mode mode,
rtx label)
{
- /* If this mode is an integer too wide to compare properly,
- compare word by word. Rely on cse to optimize constant cases. */
-
- if (GET_MODE_CLASS (mode) == MODE_INT
- && ! can_compare_p (op, mode, ccp_jump))
- {
- rtx label2 = gen_label_rtx ();
-
- switch (op)
- {
- case LTU:
- do_jump_by_parts_greater_rtx (mode, 1, arg2, arg1, label2, label);
- break;
-
- case LEU:
- do_jump_by_parts_greater_rtx (mode, 1, arg1, arg2, label, label2);
- break;
-
- case LT:
- do_jump_by_parts_greater_rtx (mode, 0, arg2, arg1, label2, label);
- break;
-
- case GT:
- do_jump_by_parts_greater_rtx (mode, 0, arg1, arg2, label2, label);
- break;
-
- case GE:
- do_jump_by_parts_greater_rtx (mode, 0, arg2, arg1, label, label2);
- break;
-
- /* do_jump_by_parts_equality_rtx compares with zero. Luckily
- that's the only equality operations we do */
- case EQ:
- gcc_assert (arg2 == const0_rtx && mode == GET_MODE(arg1));
- do_jump_by_parts_equality_rtx (arg1, label2, label);
- break;
-
- case NE:
- gcc_assert (arg2 == const0_rtx && mode == GET_MODE(arg1));
- do_jump_by_parts_equality_rtx (arg1, label, label2);
- break;
-
- default:
- gcc_unreachable ();
- }
-
- emit_label (label2);
- }
- else
- emit_cmp_and_jump_insns (arg1, arg2, op, NULL_RTX, mode, 0, label);
+ int unsignedp = (op == LTU || op == LEU || op == GTU || op == GEU);
+ do_compare_rtx_and_jump (arg1, arg2, op, unsignedp, mode,
+ NULL_RTX, NULL_RTX, label);
}