rtx libfunc_table[LTI_MAX];
/* Tables of patterns for converting one mode to another. */
-convert_optab convert_optab_table[CTI_MAX];
+convert_optab convert_optab_table[COI_MAX];
/* Contains the optab used for each rtx code. */
optab code_to_optab[NUM_RTX_CODE + 1];
this may or may not be TARGET. */
rtx
-expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
- rtx op1, rtx op2, rtx target, int unsignedp)
+expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
+ rtx op1, rtx op2, rtx target, int unsignedp)
{
int icode = (int) ternary_optab->handlers[(int) mode].insn_code;
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
xop0 = convert_modes (mode0,
GET_MODE (op0) != VOIDmode
- ? GET_MODE (op0)
+ ? GET_MODE (op0)
: mode,
xop0, unsignedp);
/* Now, if insn's predicates don't allow our operands, put them into
pseudo regs. */
-
+
if (!insn_data[icode].operand[1].predicate (xop0, mode0)
- && mode0 != VOIDmode)
+ && mode0 != VOIDmode)
xop0 = copy_to_mode_reg (mode0, xop0);
-
+
if (!insn_data[icode].operand[2].predicate (xop1, mode1)
&& mode1 != VOIDmode)
xop1 = copy_to_mode_reg (mode1, xop1);
-
+
if (!insn_data[icode].operand[3].predicate (xop2, mode2)
&& mode2 != VOIDmode)
xop2 = copy_to_mode_reg (mode2, xop2);
-
+
pat = GEN_FCN (icode) (temp, xop0, xop1, xop2);
-
+
emit_insn (pat);
- return temp;
+ return temp;
}
return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
}
+/* Return whether OP0 and OP1 should be swapped when expanding a commutative
+ binop. Order them according to commutative_operand_precedence and, if
+ possible, try to put TARGET or a pseudo first. */
+static bool
+swap_commutative_operands_with_target (rtx target, rtx op0, rtx op1)
+{
+ int op0_prec = commutative_operand_precedence (op0);
+ int op1_prec = commutative_operand_precedence (op1);
+
+ if (op0_prec < op1_prec)
+ return true;
+
+ if (op0_prec > op1_prec)
+ return false;
+
+ /* With equal precedence, both orders are ok, but it is better if the
+ first operand is TARGET, or if both TARGET and OP0 are pseudos. */
+ if (target == 0 || REG_P (target))
+ return (REG_P (op1) && !REG_P (op0)) || target == op1;
+ else
+ return rtx_equal_p (op1, target);
+}
+
+
/* Generate code to perform an operation specified by BINOPTAB
on operands OP0 and OP1, with result having machine-mode MODE.
|| binoptab->code == ROTATERT);
rtx entry_last = get_last_insn ();
rtx last;
+ bool first_pass_p = true;
class = GET_MODE_CLASS (mode);
- if (flag_force_mem)
- {
- /* Load duplicate non-volatile operands once. */
- if (rtx_equal_p (op0, op1) && ! volatile_refs_p (op0))
- {
- op0 = force_not_mem (op0);
- op1 = op0;
- }
- else
- {
- op0 = force_not_mem (op0);
- op1 = force_not_mem (op1);
- }
- }
-
/* If subtracting an integer constant, convert this into an addition of
the negated constant. */
{
commutative_op = 1;
- if (((target == 0 || REG_P (target))
- ? ((REG_P (op1)
- && !REG_P (op0))
- || target == op1)
- : rtx_equal_p (op1, target))
- || GET_CODE (op0) == CONST_INT)
+ if (swap_commutative_operands_with_target (target, op0, op1))
{
temp = op1;
op1 = op0;
}
}
+ retry:
+
/* If we can do it with a three-operand insn, do so. */
if (methods != OPTAB_MUST_WIDEN
delete_insns_since (last);
}
+ /* If we were trying to rotate by a constant value, and that didn't
+ work, try rotating the other direction before falling back to
+ shifts and bitwise-or. */
+ if (first_pass_p
+ && (binoptab == rotl_optab || binoptab == rotr_optab)
+ && class == MODE_INT
+ && GET_CODE (op1) == CONST_INT
+ && INTVAL (op1) > 0
+ && (unsigned int) INTVAL (op1) < GET_MODE_BITSIZE (mode))
+ {
+ first_pass_p = false;
+ op1 = GEN_INT (GET_MODE_BITSIZE (mode) - INTVAL (op1));
+ binoptab = binoptab == rotl_optab ? rotr_optab : rotl_optab;
+ goto retry;
+ }
+
/* If this is a multiply, see if we can do a widening operation that
takes operands of this mode and makes a wider mode. */
- if (binoptab == smul_optab && GET_MODE_WIDER_MODE (mode) != VOIDmode
+ if (binoptab == smul_optab
+ && GET_MODE_WIDER_MODE (mode) != VOIDmode
&& (((unsignedp ? umul_widen_optab : smul_widen_optab)
->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code)
!= CODE_FOR_nothing))
if (temp != 0)
{
- if (GET_MODE_CLASS (mode) == MODE_INT)
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+ GET_MODE_BITSIZE (GET_MODE (temp))))
return gen_lowpart (mode, temp);
else
return convert_to_mode (mode, temp, unsignedp);
can open-code the operation. Check for a widening multiply at the
wider mode as well. */
- if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
+ if (CLASS_HAS_WIDER_MODES_P (class)
&& methods != OPTAB_DIRECT && methods != OPTAB_LIB)
- for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
+ for (wider_mode = GET_MODE_WIDER_MODE (mode);
+ wider_mode != VOIDmode;
wider_mode = GET_MODE_WIDER_MODE (wider_mode))
{
if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
unsignedp, OPTAB_DIRECT);
if (temp)
{
- if (class != MODE_INT)
+ if (class != MODE_INT
+ || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+ GET_MODE_BITSIZE (wider_mode)))
{
if (target == 0)
target = gen_reg_rtx (mode);
/* Look for a wider mode of the same class for which it appears we can do
the operation. */
- if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
+ if (CLASS_HAS_WIDER_MODES_P (class))
{
- for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
+ for (wider_mode = GET_MODE_WIDER_MODE (mode);
+ wider_mode != VOIDmode;
wider_mode = GET_MODE_WIDER_MODE (wider_mode))
{
if ((binoptab->handlers[(int) wider_mode].insn_code
unsignedp, methods);
if (temp)
{
- if (class != MODE_INT)
+ if (class != MODE_INT
+ || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+ GET_MODE_BITSIZE (wider_mode)))
{
if (target == 0)
target = gen_reg_rtx (mode);
class = GET_MODE_CLASS (mode);
- if (flag_force_mem)
- op0 = force_not_mem (op0);
-
if (!targ0)
targ0 = gen_reg_rtx (mode);
if (!targ1)
/* It can't be done in this mode. Can we do it in a wider mode? */
- if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
+ if (CLASS_HAS_WIDER_MODES_P (class))
{
- for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
+ for (wider_mode = GET_MODE_WIDER_MODE (mode);
+ wider_mode != VOIDmode;
wider_mode = GET_MODE_WIDER_MODE (wider_mode))
{
if (unoptab->handlers[(int) wider_mode].insn_code
class = GET_MODE_CLASS (mode);
- if (flag_force_mem)
- {
- op0 = force_not_mem (op0);
- op1 = force_not_mem (op1);
- }
-
/* If we are inside an appropriately-short loop and we are optimizing,
force expensive constants into a register. */
if (CONSTANT_P (op0) && optimize
/* It can't be done in this mode. Can we do it in a wider mode? */
- if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
+ if (CLASS_HAS_WIDER_MODES_P (class))
{
- for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
+ for (wider_mode = GET_MODE_WIDER_MODE (mode);
+ wider_mode != VOIDmode;
wider_mode = GET_MODE_WIDER_MODE (wider_mode))
{
if (binoptab->handlers[(int) wider_mode].insn_code
widen_clz (enum machine_mode mode, rtx op0, rtx target)
{
enum mode_class class = GET_MODE_CLASS (mode);
- if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
+ if (CLASS_HAS_WIDER_MODES_P (class))
{
enum machine_mode wider_mode;
- for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
+ for (wider_mode = GET_MODE_WIDER_MODE (mode);
+ wider_mode != VOIDmode;
wider_mode = GET_MODE_WIDER_MODE (wider_mode))
{
if (clz_optab->handlers[(int) wider_mode].insn_code
expand_parity (enum machine_mode mode, rtx op0, rtx target)
{
enum mode_class class = GET_MODE_CLASS (mode);
- if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
+ if (CLASS_HAS_WIDER_MODES_P (class))
{
enum machine_mode wider_mode;
for (wider_mode = mode; wider_mode != VOIDmode;
return 0;
}
-/* Extract the OMODE lowpart from VAL, which has IMODE. Under certain
+/* Extract the OMODE lowpart from VAL, which has IMODE. Under certain
conditions, VAL may already be a SUBREG against which we cannot generate
a further SUBREG. In this case, we expect forcing the value into a
register will work around the situation. */
{
rtx targ_piece = operand_subword (target, i, 1, mode);
rtx op0_piece = operand_subword_force (op0, i, mode);
-
+
if (i == word)
{
temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
class = GET_MODE_CLASS (mode);
- if (flag_force_mem)
- op0 = force_not_mem (op0);
-
if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
int icode = (int) unoptab->handlers[(int) mode].insn_code;
goto try_libcall;
}
- if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
- for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
+ if (CLASS_HAS_WIDER_MODES_P (class))
+ for (wider_mode = GET_MODE_WIDER_MODE (mode);
+ wider_mode != VOIDmode;
wider_mode = GET_MODE_WIDER_MODE (wider_mode))
{
if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
if (temp)
{
- if (class != MODE_INT)
+ if (class != MODE_INT
+ || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+ GET_MODE_BITSIZE (wider_mode)))
{
if (target == 0)
target = gen_reg_rtx (mode);
if (unoptab->code == NEG)
{
/* Try negating floating point values by flipping the sign bit. */
- if (class == MODE_FLOAT)
+ if (SCALAR_FLOAT_MODE_P (mode))
{
temp = expand_absneg_bit (NEG, mode, op0, target);
if (temp)
/* It can't be done in this mode. Can we do it in a wider mode? */
- if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
+ if (CLASS_HAS_WIDER_MODES_P (class))
{
- for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
+ for (wider_mode = GET_MODE_WIDER_MODE (mode);
+ wider_mode != VOIDmode;
wider_mode = GET_MODE_WIDER_MODE (wider_mode))
{
if ((unoptab->handlers[(int) wider_mode].insn_code
return temp;
/* For floating point modes, try clearing the sign bit. */
- if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ if (SCALAR_FLOAT_MODE_P (mode))
{
temp = expand_absneg_bit (ABS, mode, op0, target);
if (temp)
{
rtx targ_piece = operand_subword (target, i, 1, mode);
rtx op0_piece = operand_subword_force (op0, i, mode);
-
+
if (i == word)
{
if (!op0_is_abs)
return target;
}
-/* Expand the C99 copysign operation. OP0 and OP1 must be the same
+/* Expand the C99 copysign operation. OP0 and OP1 must be the same
scalar floating point mode. Return NULL if we do not know how to
expand the operation inline. */
temp = target;
- /* Sign and zero extension from memory is often done specially on
- RISC machines, so forcing into a register here can pessimize
- code. */
- if (flag_force_mem && code != SIGN_EXTEND && code != ZERO_EXTEND)
- op0 = force_not_mem (op0);
-
/* Now, if insn does not accept our operands, put them into pseudos. */
if (!insn_data[icode].operand[1].predicate (op0, mode0))
op0 = copy_to_mode_reg (mode0, op0);
- if (!insn_data[icode].operand[0].predicate (temp, GET_MODE (temp))
- || (flag_force_mem && MEM_P (temp)))
+ if (!insn_data[icode].operand[0].predicate (temp, GET_MODE (temp)))
temp = gen_reg_rtx (GET_MODE (temp));
pat = GEN_FCN (icode) (temp, op0);
bool must_stay;
};
-/* Called via note_stores by emit_no_conflict_block. Set P->must_stay
- if the currently examined clobber / store has to stay in the list of
- insns that constitute the actual no_conflict block. */
+/* Called via note_stores by emit_no_conflict_block and emit_libcall_block.
+ Set P->must_stay if the currently examined clobber / store has to stay
+ in the list of insns that constitute the actual no_conflict block /
+ libcall block. */
static void
no_conflict_move_test (rtx dest, rtx set, void *p0)
{
return;
/* If this insn sets / clobbers a register that feeds one of the insns
already in the list, this insn has to stay too. */
- else if (reg_mentioned_p (dest, PATTERN (p->first))
+ else if (reg_overlap_mentioned_p (dest, PATTERN (p->first))
+ || (CALL_P (p->first) && (find_reg_fusage (p->first, USE, dest)))
|| reg_used_between_p (dest, p->first, p->insn)
/* Likewise if this insn depends on a register set by a previous
- insn in the list. */
+ insn in the list, or if it sets a result (presumably a hard
+ register) that is set or clobbered by a previous insn.
+ N.B. the modified_*_p (SET_DEST...) tests applied to a MEM
+ SET_DEST perform the former check on the address, and the latter
+ check on the MEM. */
|| (GET_CODE (set) == SET
&& (modified_in_p (SET_SRC (set), p->first)
- || modified_between_p (SET_SRC (set), p->first, p->insn))))
+ || modified_in_p (SET_DEST (set), p->first)
+ || modified_between_p (SET_SRC (set), p->first, p->insn)
+ || modified_between_p (SET_DEST (set), p->first, p->insn))))
p->must_stay = true;
}
next = NEXT_INSN (insn);
if (set != 0 && REG_P (SET_DEST (set))
- && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
- && (insn == insns
- || ((! INSN_P(insns)
- || ! reg_mentioned_p (SET_DEST (set), PATTERN (insns)))
- && ! reg_used_between_p (SET_DEST (set), insns, insn)
- && ! modified_in_p (SET_SRC (set), insns)
- && ! modified_between_p (SET_SRC (set), insns, insn))))
+ && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
{
- if (PREV_INSN (insn))
- NEXT_INSN (PREV_INSN (insn)) = next;
- else
- insns = next;
+ struct no_conflict_data data;
+
+ data.target = const0_rtx;
+ data.first = insns;
+ data.insn = insn;
+ data.must_stay = 0;
+ note_stores (PATTERN (insn), no_conflict_move_test, &data);
+ if (! data.must_stay)
+ {
+ if (PREV_INSN (insn))
+ NEXT_INSN (PREV_INSN (insn)) = next;
+ else
+ insns = next;
- if (next)
- PREV_INSN (next) = PREV_INSN (insn);
+ if (next)
+ PREV_INSN (next) = PREV_INSN (insn);
- add_insn (insn);
+ add_insn (insn);
+ }
}
/* Some ports use a loop to copy large arguments onto the stack.
enum machine_mode mode = *pmode;
rtx x = *px, y = *py;
int unsignedp = *punsignedp;
- enum mode_class class;
-
- class = GET_MODE_CLASS (mode);
-
- if (mode != BLKmode && flag_force_mem)
- {
- /* Load duplicate non-volatile operands once. */
- if (rtx_equal_p (x, y) && ! volatile_refs_p (x))
- {
- x = force_not_mem (x);
- y = x;
- }
- else
- {
- x = force_not_mem (x);
- y = force_not_mem (y);
- }
- }
/* If we are inside an appropriately-short loop and we are optimizing,
force expensive constants into a register. */
if (cmp_code == CODE_FOR_nothing)
cmp_code = cmpstr_optab[cmp_mode];
if (cmp_code == CODE_FOR_nothing)
+ cmp_code = cmpstrn_optab[cmp_mode];
+ if (cmp_code == CODE_FOR_nothing)
continue;
/* Must make sure the size fits the insn's mode. */
/* Handle a lib call just for the mode we are using. */
- if (cmp_optab->handlers[(int) mode].libfunc && class != MODE_FLOAT)
+ if (cmp_optab->handlers[(int) mode].libfunc && !SCALAR_FLOAT_MODE_P (mode))
{
rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
rtx result;
return;
}
- gcc_assert (class == MODE_FLOAT);
+ gcc_assert (SCALAR_FLOAT_MODE_P (mode));
prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
}
return;
}
- if (class != MODE_INT && class != MODE_FLOAT
- && class != MODE_COMPLEX_FLOAT)
+ if (!CLASS_HAS_WIDER_MODES_P (class))
break;
wider_mode = GET_MODE_WIDER_MODE (wider_mode);
rtx libfunc = 0;
bool reversed_p = false;
- for (mode = orig_mode; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
+ for (mode = orig_mode;
+ mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
{
if ((libfunc = code_to_optab[comparison]->handlers[mode].libfunc))
break;
if (icode == CODE_FOR_nothing)
return 0;
- if (flag_force_mem)
- {
- op2 = force_not_mem (op2);
- op3 = force_not_mem (op3);
- }
-
if (!target)
target = gen_reg_rtx (mode);
if (icode == CODE_FOR_nothing)
return 0;
- if (flag_force_mem)
- {
- op2 = force_not_mem (op2);
- op3 = force_not_mem (op3);
- }
-
if (!target)
target = gen_reg_rtx (mode);
enum insn_code icode;
rtx target = to;
enum machine_mode fmode, imode;
+ bool can_do_signed = false;
/* Crash now, because we won't be able to decide which mode to use. */
gcc_assert (GET_MODE (from) != VOIDmode);
continue;
icode = can_float_p (fmode, imode, unsignedp);
- if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
- icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
+ if (icode == CODE_FOR_nothing && unsignedp)
+ {
+ enum insn_code scode = can_float_p (fmode, imode, 0);
+ if (scode != CODE_FOR_nothing)
+ can_do_signed = true;
+ if (imode != GET_MODE (from))
+ icode = scode, doing_unsigned = 0;
+ }
if (icode != CODE_FOR_nothing)
{
/* Unsigned integer, and no way to convert directly.
Convert as signed, then conditionally adjust the result. */
- if (unsignedp)
+ if (unsignedp && can_do_signed)
{
rtx label = gen_label_rtx ();
rtx temp;
REAL_VALUE_TYPE offset;
- if (flag_force_mem)
- from = force_not_mem (from);
-
/* Look for a usable floating mode FMODE wider than the source and at
least as wide as the target. Using FMODE will avoid rounding woes
with unsigned values greater than the signed maximum value. */
if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
from = convert_to_mode (SImode, from, unsignedp);
- if (flag_force_mem)
- from = force_not_mem (from);
-
libfunc = tab->handlers[GET_MODE (to)][GET_MODE (from)].libfunc;
gcc_assert (libfunc);
lab1 = gen_label_rtx ();
lab2 = gen_label_rtx ();
- if (flag_force_mem)
- from = force_not_mem (from);
-
if (fmode != GET_MODE (from))
from = convert_to_mode (fmode, from, 0);
libfunc = tab->handlers[GET_MODE (to)][GET_MODE (from)].libfunc;
gcc_assert (libfunc);
- if (flag_force_mem)
- from = force_not_mem (from);
-
start_sequence ();
value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
umul_highpart_optab = init_optab (UNKNOWN);
smul_widen_optab = init_optab (UNKNOWN);
umul_widen_optab = init_optab (UNKNOWN);
+ usmul_widen_optab = init_optab (UNKNOWN);
sdiv_optab = init_optab (DIV);
sdivv_optab = init_optabv (DIV);
sdivmod_optab = init_optab (UNKNOWN);
for (i = 0; i < NUM_MACHINE_MODES; i++)
{
movmem_optab[i] = CODE_FOR_nothing;
- clrmem_optab[i] = CODE_FOR_nothing;
cmpstr_optab[i] = CODE_FOR_nothing;
+ cmpstrn_optab[i] = CODE_FOR_nothing;
cmpmem_optab[i] = CODE_FOR_nothing;
+ setmem_optab[i] = CODE_FOR_nothing;
sync_add_optab[i] = CODE_FOR_nothing;
sync_sub_optab[i] = CODE_FOR_nothing;
sync_lock_test_and_set[i] = CODE_FOR_nothing;
sync_lock_release[i] = CODE_FOR_nothing;
-#ifdef HAVE_SECONDARY_RELOADS
reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
-#endif
}
/* Fill in the optabs with the insns we support. */
/* Conversions. */
init_interclass_conv_libfuncs (sfloat_optab, "float",
MODE_INT, MODE_FLOAT);
+ init_interclass_conv_libfuncs (ufloat_optab, "floatun",
+ MODE_INT, MODE_FLOAT);
init_interclass_conv_libfuncs (sfix_optab, "fix",
MODE_FLOAT, MODE_INT);
init_interclass_conv_libfuncs (ufix_optab, "fixuns",
memset_libfunc = init_one_libfunc ("memset");
setbits_libfunc = init_one_libfunc ("__setbits");
- unwind_resume_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
- ? "_Unwind_SjLj_Resume"
- : "_Unwind_Resume");
#ifndef DONT_USE_BUILTIN_SETJMP
setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
}
/* Dump the conversion optabs. */
- for (i = 0; i < (int) CTI_MAX; ++i)
+ for (i = 0; i < (int) COI_MAX; ++i)
for (j = 0; j < NUM_MACHINE_MODES; ++j)
for (k = 0; k < NUM_MACHINE_MODES; ++k)
{
case GE_EXPR:
code = unsignedp ? GEU : GE;
break;
-
+
case UNORDERED_EXPR:
code = UNORDERED;
break;
ensures that condition is a relational operation. */
gcc_assert (COMPARISON_CLASS_P (cond));
- rcode = get_rtx_code (TREE_CODE (cond), unsignedp);
+ rcode = get_rtx_code (TREE_CODE (cond), unsignedp);
t_op0 = TREE_OPERAND (cond, 0);
t_op1 = TREE_OPERAND (cond, 1);
-
+
/* Expand operands. */
rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)), 1);
rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)), 1);
if (!insn_data[icode].operand[4].predicate (rtx_op0, GET_MODE (rtx_op0))
&& GET_MODE (rtx_op0) != VOIDmode)
rtx_op0 = force_reg (GET_MODE (rtx_op0), rtx_op0);
-
+
if (!insn_data[icode].operand[5].predicate (rtx_op1, GET_MODE (rtx_op1))
&& GET_MODE (rtx_op1) != VOIDmode)
rtx_op1 = force_reg (GET_MODE (rtx_op1), rtx_op1);
}
/* Return insn code for VEC_COND_EXPR EXPR. */
-
-static inline enum insn_code
+
+static inline enum insn_code
get_vcond_icode (tree expr, enum machine_mode mode)
{
enum insn_code icode = CODE_FOR_nothing;
if (icode == CODE_FOR_nothing)
return 0;
- if (!target)
+ if (!target || !insn_data[icode].operand[0].predicate (target, mode))
target = gen_reg_rtx (mode);
/* Get comparison rtx. First expand both cond expr operands. */
- comparison = vector_compare_rtx (TREE_OPERAND (vec_cond_expr, 0),
+ comparison = vector_compare_rtx (TREE_OPERAND (vec_cond_expr, 0),
unsignedp, icode);
cc_op0 = XEXP (comparison, 0);
cc_op1 = XEXP (comparison, 1);
/* Expand both operands and force them in reg, if required. */
rtx_op1 = expand_expr (TREE_OPERAND (vec_cond_expr, 1),
- NULL_RTX, VOIDmode, 1);
+ NULL_RTX, VOIDmode, EXPAND_NORMAL);
if (!insn_data[icode].operand[1].predicate (rtx_op1, mode)
&& mode != VOIDmode)
rtx_op1 = force_reg (mode, rtx_op1);
rtx_op2 = expand_expr (TREE_OPERAND (vec_cond_expr, 2),
- NULL_RTX, VOIDmode, 1);
+ NULL_RTX, VOIDmode, EXPAND_NORMAL);
if (!insn_data[icode].operand[2].predicate (rtx_op2, mode)
&& mode != VOIDmode)
rtx_op2 = force_reg (mode, rtx_op2);
/* Emit instruction! */
- emit_insn (GEN_FCN (icode) (target, rtx_op1, rtx_op2,
+ emit_insn (GEN_FCN (icode) (target, rtx_op1, rtx_op2,
comparison, cc_op0, cc_op1));
return target;
}
}
- /* Without an appropriate setcc instruction, use a set of branches to
- get 1 and 0 stored into target. Presumably if the target has a
+ /* Without an appropriate setcc instruction, use a set of branches to
+ get 1 and 0 stored into target. Presumably if the target has a
STORE_FLAG_VALUE that isn't 1, then this will get cleaned up by ifcvt. */
label0 = gen_label_rtx ();
}
/* This function generates the atomic operation MEM CODE= VAL. In this
- case, we do not care about any resulting value. Returns NULL if we
+ case, we do not care about any resulting value. Returns NULL if we
cannot generate the operation. */
rtx
val = convert_modes (mode, GET_MODE (val), val, 1);
if (!insn_data[icode].operand[1].predicate (val, mode))
val = force_reg (mode, val);
-
+
insn = GEN_FCN (icode) (mem, val);
if (insn)
{
/* This function generates the atomic operation MEM CODE= VAL. In this
case, we do care about the resulting value: if AFTER is true then
- return the value MEM holds after the operation, if AFTER is false
+ return the value MEM holds after the operation, if AFTER is false
then return the value MEM holds before the operation. TARGET is an
optional place for the result value to be stored. */
val = convert_modes (mode, GET_MODE (val), val, 1);
if (!insn_data[icode].operand[2].predicate (val, mode))
val = force_reg (mode, val);
-
+
insn = GEN_FCN (icode) (target, mem, val);
if (insn)
{
/* This function expands a test-and-set operation. Ideally we atomically
store VAL in MEM and return the previous value in MEM. Some targets
may not support this operation and only support VAL with the constant 1;
- in this case while the return value will be 0/1, but the exact value
+ in this case while the return value will be 0/1, but the exact value
stored in MEM is target defined. TARGET is an option place to stick
the return value. */