if (mode != VOIDmode
&& optimize
&& CONSTANT_P (x)
- && rtx_cost (x, binoptab->code) > COSTS_N_INSNS (1))
+ && rtx_cost (x, binoptab->code, optimize_insn_for_speed_p ())
+ > COSTS_N_INSNS (1))
{
if (GET_CODE (x) == CONST_INT)
{
enum optab_methods next_methods
= (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
? OPTAB_WIDEN : methods);
- enum mode_class class;
+ enum mode_class mclass;
enum machine_mode wider_mode;
rtx libfunc;
rtx temp;
rtx entry_last = get_last_insn ();
rtx last;
- class = GET_MODE_CLASS (mode);
+ mclass = GET_MODE_CLASS (mode);
/* If subtracting an integer constant, convert this into an addition of
the negated constant. */
&& optab_handler (rotr_optab, mode)->insn_code != CODE_FOR_nothing)
|| (binoptab == rotr_optab
&& optab_handler (rotl_optab, mode)->insn_code != CODE_FOR_nothing))
- && class == MODE_INT)
+ && mclass == MODE_INT)
{
optab otheroptab = (binoptab == rotl_optab ? rotr_optab : rotl_optab);
rtx newop1;
can open-code the operation. Check for a widening multiply at the
wider mode as well. */
- if (CLASS_HAS_WIDER_MODES_P (class)
+ if (CLASS_HAS_WIDER_MODES_P (mclass)
&& methods != OPTAB_DIRECT && methods != OPTAB_LIB)
for (wider_mode = GET_MODE_WIDER_MODE (mode);
wider_mode != VOIDmode;
|| binoptab == xor_optab
|| binoptab == add_optab || binoptab == sub_optab
|| binoptab == smul_optab || binoptab == ashl_optab)
- && class == MODE_INT)
+ && mclass == MODE_INT)
{
no_extend = 1;
xop0 = avoid_expensive_constant (mode, binoptab,
unsignedp, OPTAB_DIRECT);
if (temp)
{
- if (class != MODE_INT
+ if (mclass != MODE_INT
|| !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
GET_MODE_BITSIZE (wider_mode)))
{
/* These can be done a word at a time. */
if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
- && class == MODE_INT
+ && mclass == MODE_INT
&& GET_MODE_SIZE (mode) > UNITS_PER_WORD
&& optab_handler (binoptab, word_mode)->insn_code != CODE_FOR_nothing)
{
/* Synthesize double word shifts from single word shifts. */
if ((binoptab == lshr_optab || binoptab == ashl_optab
|| binoptab == ashr_optab)
- && class == MODE_INT
- && (GET_CODE (op1) == CONST_INT || !optimize_size)
+ && mclass == MODE_INT
+ && (GET_CODE (op1) == CONST_INT || optimize_insn_for_speed_p ())
&& GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
&& optab_handler (binoptab, word_mode)->insn_code != CODE_FOR_nothing
&& optab_handler (ashl_optab, word_mode)->insn_code != CODE_FOR_nothing
/* Synthesize double word rotates from single word shifts. */
if ((binoptab == rotl_optab || binoptab == rotr_optab)
- && class == MODE_INT
+ && mclass == MODE_INT
&& GET_CODE (op1) == CONST_INT
&& GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
&& optab_handler (ashl_optab, word_mode)->insn_code != CODE_FOR_nothing
/* These can be done a word at a time by propagating carries. */
if ((binoptab == add_optab || binoptab == sub_optab)
- && class == MODE_INT
+ && mclass == MODE_INT
&& GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
&& optab_handler (binoptab, word_mode)->insn_code != CODE_FOR_nothing)
{
try using a signed widening multiply. */
if (binoptab == smul_optab
- && class == MODE_INT
+ && mclass == MODE_INT
&& GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
&& optab_handler (smul_optab, word_mode)->insn_code != CODE_FOR_nothing
&& optab_handler (add_optab, word_mode)->insn_code != CODE_FOR_nothing)
/* Look for a wider mode of the same class for which it appears we can do
the operation. */
- if (CLASS_HAS_WIDER_MODES_P (class))
+ if (CLASS_HAS_WIDER_MODES_P (mclass))
{
for (wider_mode = GET_MODE_WIDER_MODE (mode);
wider_mode != VOIDmode;
|| binoptab == xor_optab
|| binoptab == add_optab || binoptab == sub_optab
|| binoptab == smul_optab || binoptab == ashl_optab)
- && class == MODE_INT)
+ && mclass == MODE_INT)
no_extend = 1;
xop0 = widen_operand (xop0, wider_mode, mode,
unsignedp, methods);
if (temp)
{
- if (class != MODE_INT
+ if (mclass != MODE_INT
|| !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
GET_MODE_BITSIZE (wider_mode)))
{
int unsignedp)
{
enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
- enum mode_class class;
+ enum mode_class mclass;
enum machine_mode wider_mode;
rtx entry_last = get_last_insn ();
rtx last;
- class = GET_MODE_CLASS (mode);
+ mclass = GET_MODE_CLASS (mode);
if (!targ0)
targ0 = gen_reg_rtx (mode);
/* It can't be done in this mode. Can we do it in a wider mode? */
- if (CLASS_HAS_WIDER_MODES_P (class))
+ if (CLASS_HAS_WIDER_MODES_P (mclass))
{
for (wider_mode = GET_MODE_WIDER_MODE (mode);
wider_mode != VOIDmode;
int unsignedp)
{
enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
- enum mode_class class;
+ enum mode_class mclass;
enum machine_mode wider_mode;
rtx entry_last = get_last_insn ();
rtx last;
- class = GET_MODE_CLASS (mode);
+ mclass = GET_MODE_CLASS (mode);
if (!targ0)
targ0 = gen_reg_rtx (mode);
/* It can't be done in this mode. Can we do it in a wider mode? */
- if (CLASS_HAS_WIDER_MODES_P (class))
+ if (CLASS_HAS_WIDER_MODES_P (mclass))
{
for (wider_mode = GET_MODE_WIDER_MODE (mode);
wider_mode != VOIDmode;
static rtx
widen_clz (enum machine_mode mode, rtx op0, rtx target)
{
- enum mode_class class = GET_MODE_CLASS (mode);
- if (CLASS_HAS_WIDER_MODES_P (class))
+ enum mode_class mclass = GET_MODE_CLASS (mode);
+ if (CLASS_HAS_WIDER_MODES_P (mclass))
{
enum machine_mode wider_mode;
for (wider_mode = GET_MODE_WIDER_MODE (mode);
static rtx
widen_bswap (enum machine_mode mode, rtx op0, rtx target)
{
- enum mode_class class = GET_MODE_CLASS (mode);
+ enum mode_class mclass = GET_MODE_CLASS (mode);
enum machine_mode wider_mode;
rtx x, last;
- if (!CLASS_HAS_WIDER_MODES_P (class))
+ if (!CLASS_HAS_WIDER_MODES_P (mclass))
return NULL_RTX;
for (wider_mode = GET_MODE_WIDER_MODE (mode);
static rtx
expand_parity (enum machine_mode mode, rtx op0, rtx target)
{
- enum mode_class class = GET_MODE_CLASS (mode);
- if (CLASS_HAS_WIDER_MODES_P (class))
+ enum mode_class mclass = GET_MODE_CLASS (mode);
+ if (CLASS_HAS_WIDER_MODES_P (mclass))
{
enum machine_mode wider_mode;
for (wider_mode = mode; wider_mode != VOIDmode;
expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
int unsignedp)
{
- enum mode_class class = GET_MODE_CLASS (mode);
+ enum mode_class mclass = GET_MODE_CLASS (mode);
enum machine_mode wider_mode;
rtx temp;
rtx libfunc;
goto try_libcall;
}
- if (CLASS_HAS_WIDER_MODES_P (class))
+ if (CLASS_HAS_WIDER_MODES_P (mclass))
for (wider_mode = GET_MODE_WIDER_MODE (mode);
wider_mode != VOIDmode;
wider_mode = GET_MODE_WIDER_MODE (wider_mode))
xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
(unoptab == neg_optab
|| unoptab == one_cmpl_optab)
- && class == MODE_INT);
+ && mclass == MODE_INT);
temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
unsignedp);
if (temp)
{
- if (class != MODE_INT
+ if (mclass != MODE_INT
|| !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
GET_MODE_BITSIZE (wider_mode)))
{
/* These can be done a word at a time. */
if (unoptab == one_cmpl_optab
- && class == MODE_INT
+ && mclass == MODE_INT
&& GET_MODE_SIZE (mode) > UNITS_PER_WORD
&& optab_handler (unoptab, word_mode)->insn_code != CODE_FOR_nothing)
{
/* It can't be done in this mode. Can we do it in a wider mode? */
- if (CLASS_HAS_WIDER_MODES_P (class))
+ if (CLASS_HAS_WIDER_MODES_P (mclass))
{
for (wider_mode = GET_MODE_WIDER_MODE (mode);
wider_mode != VOIDmode;
xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
(unoptab == neg_optab
|| unoptab == one_cmpl_optab)
- && class == MODE_INT);
+ && mclass == MODE_INT);
temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
unsignedp);
if (temp)
{
- if (class != MODE_INT)
+ if (mclass != MODE_INT)
{
if (target == 0)
target = gen_reg_rtx (mode);
value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
where W is the width of MODE. */
- if (GET_MODE_CLASS (mode) == MODE_INT && BRANCH_COST >= 2)
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && BRANCH_COST (optimize_insn_for_speed_p (),
+ false) >= 2)
{
rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
size_int (GET_MODE_BITSIZE (mode) - 1),
with two operands: an output TARGET and an input OP0.
TARGET *must* be nonzero, and the output is always stored there.
CODE is an rtx code such that (CODE OP0) is an rtx that describes
- the value that is stored into TARGET. */
+ the value that is stored into TARGET.
-void
-emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
+ Return false if expansion failed. */
+
+bool
+maybe_emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
{
rtx temp;
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
rtx pat;
+ rtx last = get_last_insn ();
temp = target;
temp = gen_reg_rtx (GET_MODE (temp));
pat = GEN_FCN (icode) (temp, op0);
+ if (!pat)
+ {
+ delete_insns_since (last);
+ return false;
+ }
if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX && code != UNKNOWN)
add_equal_note (pat, temp, code, op0, NULL_RTX);
if (temp != target)
emit_move_insn (target, temp);
+ return true;
+}
+/* Generate an instruction whose insn-code is INSN_CODE,
+ with two operands: an output TARGET and an input OP0.
+ TARGET *must* be nonzero, and the output is always stored there.
+ CODE is an rtx code such that (CODE OP0) is an rtx that describes
+ the value that is stored into TARGET. */
+
+void
+emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
+{
+ bool ok = maybe_emit_unop_insn (icode, target, op0, code);
+ gcc_assert (ok);
}
\f
struct no_conflict_data
if (note != 0)
XEXP (note, 0) = constm1_rtx;
else
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, constm1_rtx,
- REG_NOTES (insn));
+ add_reg_note (insn, REG_EH_REGION, constm1_rtx);
}
/* First emit all insns that set pseudos. Remove them from the list as
/* If we are inside an appropriately-short loop and we are optimizing,
force expensive constants into a register. */
if (CONSTANT_P (x) && optimize
- && rtx_cost (x, COMPARE) > COSTS_N_INSNS (1))
+ && (rtx_cost (x, COMPARE, optimize_insn_for_speed_p ())
+ > COSTS_N_INSNS (1)))
x = force_reg (mode, x);
if (CONSTANT_P (y) && optimize
- && rtx_cost (y, COMPARE) > COSTS_N_INSNS (1))
+ && (rtx_cost (y, COMPARE, optimize_insn_for_speed_p ())
+ > COSTS_N_INSNS (1)))
y = force_reg (mode, y);
#ifdef HAVE_cc0
enum rtx_code comparison, int unsignedp, rtx label)
{
rtx test = gen_rtx_fmt_ee (comparison, mode, x, y);
- enum mode_class class = GET_MODE_CLASS (mode);
+ enum mode_class mclass = GET_MODE_CLASS (mode);
enum machine_mode wider_mode = mode;
/* Try combined insns first. */
return;
}
- if (!CLASS_HAS_WIDER_MODES_P (class))
+ if (!CLASS_HAS_WIDER_MODES_P (mclass))
break;
wider_mode = GET_MODE_WIDER_MODE (wider_mode);
if (icode != CODE_FOR_nothing)
{
+ rtx last = get_last_insn ();
if (fmode != GET_MODE (from))
from = convert_to_mode (fmode, from, 0);
if (imode != GET_MODE (to))
target = gen_reg_rtx (imode);
- emit_unop_insn (icode, target, from,
- doing_unsigned ? UNSIGNED_FIX : FIX);
- if (target != to)
- convert_move (to, target, unsignedp);
- return;
+ if (maybe_emit_unop_insn (icode, target, from,
+ doing_unsigned ? UNSIGNED_FIX : FIX))
+ {
+ if (target != to)
+ convert_move (to, target, unsignedp);
+ return;
+ }
+ delete_insns_since (last);
}
}
icode = convert_optab_handler (tab, imode, fmode)->insn_code;
if (icode != CODE_FOR_nothing)
{
+ rtx last = get_last_insn ();
if (fmode != GET_MODE (from))
from = convert_to_mode (fmode, from, 0);
if (imode != GET_MODE (to))
target = gen_reg_rtx (imode);
- emit_unop_insn (icode, target, from, UNKNOWN);
+ if (!maybe_emit_unop_insn (icode, target, from, UNKNOWN))
+ {
+ delete_insns_since (last);
+ continue;
+ }
if (target != to)
convert_move (to, target, 0);
return true;
t1 = t0;
if (code == NOT)
{
- t1 = expand_simple_unop (mode, NOT, t1, NULL_RTX, true);
- code = AND;
+ t1 = expand_simple_binop (mode, AND, t1, val, NULL_RTX,
+ true, OPTAB_LIB_WIDEN);
+ t1 = expand_simple_unop (mode, code, t1, NULL_RTX, true);
}
- t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
- true, OPTAB_LIB_WIDEN);
-
+ else
+ t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
+ true, OPTAB_LIB_WIDEN);
insn = get_insns ();
end_sequence ();
}
if (code == NOT)
- target = expand_simple_unop (mode, NOT, target, NULL_RTX, true);
- target = expand_simple_binop (mode, code, target, val, NULL_RTX,
- true, OPTAB_LIB_WIDEN);
+ {
+ target = expand_simple_binop (mode, AND, target, val,
+ NULL_RTX, true,
+ OPTAB_LIB_WIDEN);
+ target = expand_simple_unop (mode, code, target,
+ NULL_RTX, true);
+ }
+ else
+ target = expand_simple_binop (mode, code, target, val,
+ NULL_RTX, true,
+ OPTAB_LIB_WIDEN);
}
return target;
t1 = t0;
if (code == NOT)
{
- t1 = expand_simple_unop (mode, NOT, t1, NULL_RTX, true);
- code = AND;
+ t1 = expand_simple_binop (mode, AND, t1, val, NULL_RTX,
+ true, OPTAB_LIB_WIDEN);
+ t1 = expand_simple_unop (mode, code, t1, NULL_RTX, true);
}
- t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
- true, OPTAB_LIB_WIDEN);
+ else
+ t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
+ true, OPTAB_LIB_WIDEN);
if (after)
emit_move_insn (target, t1);