/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
- Copyright (C) 1987-2014 Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
This file is part of GCC.
is properly defined. */
#include "insn-config.h"
#include "rtl.h"
+#include "alias.h"
+#include "symtab.h"
#include "tree.h"
#include "tree-hasher.h"
#include "stor-layout.h"
#include "varasm.h"
#include "tm_p.h"
#include "flags.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "vec.h"
-#include "machmode.h"
#include "hard-reg-set.h"
-#include "input.h"
#include "function.h"
#include "except.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "stmt.h"
#include "expr.h"
+#include "insn-codes.h"
#include "optabs.h"
#include "libfuncs.h"
#include "recog.h"
#include "reload.h"
-#include "ggc.h"
#include "predict.h"
#include "dominance.h"
#include "cfg.h"
case REDUC_PLUS_EXPR:
return reduc_plus_scal_optab;
- case VEC_RSHIFT_EXPR:
- return vec_shr_optab;
-
case VEC_WIDEN_MULT_HI_EXPR:
return TYPE_UNSIGNED (type) ?
vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
return true;
}
-/* Generate insns for VEC_RSHIFT_EXPR. */
-
-rtx
-expand_vec_shift_expr (sepops ops, rtx target)
-{
- struct expand_operand eops[3];
- enum insn_code icode;
- rtx rtx_op1, rtx_op2;
- machine_mode mode = TYPE_MODE (ops->type);
- tree vec_oprnd = ops->op0;
- tree shift_oprnd = ops->op1;
-
- gcc_assert (ops->code == VEC_RSHIFT_EXPR);
-
- icode = optab_handler (vec_shr_optab, mode);
- gcc_assert (icode != CODE_FOR_nothing);
-
- rtx_op1 = expand_normal (vec_oprnd);
- rtx_op2 = expand_normal (shift_oprnd);
-
- create_output_operand (&eops[0], target, mode);
- create_input_operand (&eops[1], rtx_op1, GET_MODE (rtx_op1));
- create_convert_operand_from_type (&eops[2], rtx_op2, TREE_TYPE (shift_oprnd));
- expand_insn (icode, 3, eops);
-
- return eops[0].value;
-}
-
/* Create a new vector value in VMODE with all elements set to OP. The
mode of OP must be the element mode of VMODE. If OP is a constant,
then the return value will be a constant. */
}
-#ifdef HAVE_conditional_move
/* Try implementing expand_doubleword_shift using conditional moves.
The shift is by < BITS_PER_WORD if (CMP_CODE CMP1 CMP2) is true,
otherwise it is by >= BITS_PER_WORD. SUBWORD_OP1 and SUPERWORD_OP1
return true;
}
-#endif
/* Expand a doubleword shift (ashl, ashr or lshr) using word-mode shifts.
OUTOF_INPUT and INTO_INPUT are the two word-sized halves of the first
unsignedp, methods, shift_mask);
}
-#ifdef HAVE_conditional_move
/* Try using conditional moves to generate straight-line code. */
- {
- rtx_insn *start = get_last_insn ();
- if (expand_doubleword_shift_condmove (op1_mode, binoptab,
- cmp_code, cmp1, cmp2,
- outof_input, into_input,
- op1, superword_op1,
- outof_target, into_target,
- unsignedp, methods, shift_mask))
- return true;
- delete_insns_since (start);
- }
-#endif
+ if (HAVE_conditional_move)
+ {
+ rtx_insn *start = get_last_insn ();
+ if (expand_doubleword_shift_condmove (op1_mode, binoptab,
+ cmp_code, cmp1, cmp2,
+ outof_input, into_input,
+ op1, superword_op1,
+ outof_target, into_target,
+ unsignedp, methods, shift_mask))
+ return true;
+ delete_insns_since (start);
+ }
/* As a last resort, use branches to select the correct alternative. */
rtx_code_label *subword_label = gen_label_rtx ();
machine_mode mode0, mode1, tmp_mode;
struct expand_operand ops[3];
bool commutative_p;
- rtx pat;
+ rtx_insn *pat;
rtx xop0 = op0, xop1 = op1;
- rtx swap;
/* If it is a commutative operator and the modes would match
if we would swap the operands, we can save the conversions. */
if (commutative_p
&& GET_MODE (xop0) != xmode0 && GET_MODE (xop1) != xmode1
&& GET_MODE (xop0) == xmode1 && GET_MODE (xop1) == xmode1)
- {
- swap = xop0;
- xop0 = xop1;
- xop1 = swap;
- }
+ std::swap (xop0, xop1);
/* If we are optimizing, force expensive constants into a register. */
xop0 = avoid_expensive_constant (xmode0, binoptab, 0, xop0, unsignedp);
Also try to make the last operand a constant. */
if (commutative_p
&& swap_commutative_operands_with_target (target, xop0, xop1))
- {
- swap = xop1;
- xop1 = xop0;
- xop0 = swap;
- }
+ std::swap (xop0, xop1);
/* Now, if insn's predicates don't allow our operands, put them into
pseudo regs. */
/* If PAT is composed of more than one insn, try to add an appropriate
REG_EQUAL note to it. If we can't because TEMP conflicts with an
operand, call expand_binop again, this time without a target. */
- if (INSN_P (pat) && NEXT_INSN (as_a <rtx_insn *> (pat)) != NULL_RTX
- && ! add_equal_note (as_a <rtx_insn *> (pat), ops[0].value,
+ if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
+ && ! add_equal_note (pat, ops[0].value,
optab_to_code (binoptab),
ops[1].value, ops[2].value))
{
Also try to make the last operand a constant. */
if (commutative_optab_p (binoptab)
&& swap_commutative_operands_with_target (target, op0, op1))
- {
- temp = op1;
- op1 = op0;
- op0 = temp;
- }
+ std::swap (op0, op1);
/* These can be done a word at a time. */
if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
if (optab_handler (mov_optab, mode) != CODE_FOR_nothing
|| ! rtx_equal_p (target, xtarget))
{
- rtx temp = emit_move_insn (target, xtarget);
+ rtx_insn *temp = emit_move_insn (target, xtarget);
set_dst_reg_note (temp, REG_EQUAL,
gen_rtx_fmt_ee (optab_to_code (binoptab),
struct expand_operand ops[2];
enum insn_code icode = optab_handler (unoptab, mode);
rtx_insn *last = get_last_insn ();
- rtx pat;
+ rtx_insn *pat;
create_output_operand (&ops[0], target, mode);
create_convert_operand_from (&ops[1], op0, mode, unsignedp);
pat = maybe_gen_insn (icode, 2, ops);
if (pat)
{
- if (INSN_P (pat) && NEXT_INSN (as_a <rtx_insn *> (pat)) != NULL_RTX
- && ! add_equal_note (as_a <rtx_insn *> (pat), ops[0].value,
+ if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
+ && ! add_equal_note (pat, ops[0].value,
optab_to_code (unoptab),
ops[1].value, NULL_RTX))
{
NO_DEFER_POP;
do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
- NULL_RTX, NULL_RTX, op1, -1);
+ NULL_RTX, NULL, op1, -1);
op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
target, target, 0);
enum rtx_code code)
{
struct expand_operand ops[2];
- rtx pat;
+ rtx_insn *pat;
create_output_operand (&ops[0], target, GET_MODE (target));
create_input_operand (&ops[1], op0, GET_MODE (op0));
if (!pat)
return false;
- if (INSN_P (pat) && NEXT_INSN (as_a <rtx_insn *> (pat)) != NULL_RTX
+ if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
&& code != UNKNOWN)
- add_equal_note (as_a <rtx_insn *> (pat), ops[0].value, code, ops[1].value,
- NULL_RTX);
+ add_equal_note (pat, ops[0].value, code, ops[1].value, NULL_RTX);
emit_insn (pat);
> COSTS_N_INSNS (1)))
y = force_reg (mode, y);
-#ifdef HAVE_cc0
+#if HAVE_cc0
/* Make sure if we have a canonical comparison. The RTL
documentation states that canonical comparisons are required only
for targets which have cc0. */
if (GET_MODE_CLASS (mode) == MODE_CC)
{
- gcc_assert (can_compare_p (comparison, CCmode, ccp_jump));
- *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
+ enum insn_code icode = optab_handler (cbranch_optab, CCmode);
+ test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
+ gcc_assert (icode != CODE_FOR_nothing
+ && insn_operand_matches (icode, 0, test));
+ *ptest = test;
return;
}
if (!insn_operand_matches (icode, opnum, x))
{
+ machine_mode op_mode = insn_data[(int) icode].operand[opnum].mode;
if (reload_completed)
return NULL_RTX;
- x = copy_to_mode_reg (insn_data[(int) icode].operand[opnum].mode, x);
+ if (GET_MODE (x) != op_mode && GET_MODE (x) != VOIDmode)
+ return NULL_RTX;
+ x = copy_to_mode_reg (op_mode, x);
}
return x;
if (code_to_optab (swapped)
&& (libfunc = optab_libfunc (code_to_optab (swapped), mode)))
{
- rtx tmp;
- tmp = x; x = y; y = tmp;
+ std::swap (x, y);
comparison = swapped;
break;
}
/* Generate code to indirectly jump to a location given in the rtx LOC. */
void
-emit_indirect_jump (rtx loc)
+emit_indirect_jump (rtx loc ATTRIBUTE_UNUSED)
{
+#ifndef HAVE_indirect_jump
+ sorry ("indirect jumps are not available on this target");
+#else
struct expand_operand ops[1];
-
create_address_operand (&ops[0], loc);
expand_jump_insn (CODE_FOR_indirect_jump, 1, ops);
emit_barrier ();
+#endif
}
\f
-#ifdef HAVE_conditional_move
/* Emit a conditional move instruction if the machine supports one for that
condition and machine mode.
machine_mode cmode, rtx op2, rtx op3,
machine_mode mode, int unsignedp)
{
- rtx tem, comparison;
+ rtx comparison;
rtx_insn *last;
enum insn_code icode;
enum rtx_code reversed;
if (swap_commutative_operands_p (op0, op1))
{
- tem = op0;
- op0 = op1;
- op1 = tem;
+ std::swap (op0, op1);
code = swap_condition (code);
}
&& ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
!= UNKNOWN))
{
- tem = op2;
- op2 = op3;
- op3 = tem;
+ std::swap (op2, op3);
code = reversed;
}
return 0;
}
-#endif /* HAVE_conditional_move */
-
/* Emit a conditional addition instruction if the machine supports one for that
condition and machine mode.
machine_mode cmode, rtx op2, rtx op3,
machine_mode mode, int unsignedp)
{
- rtx tem, comparison;
+ rtx comparison;
rtx_insn *last;
enum insn_code icode;
if (swap_commutative_operands_p (op0, op1))
{
- tem = op0;
- op0 = op1;
- op1 = tem;
+ std::swap (op0, op1);
code = swap_condition (code);
}
/* Generate and return an insn body to add Y to X. */
-rtx
+rtx_insn *
gen_add2_insn (rtx x, rtx y)
{
enum insn_code icode = optab_handler (add_optab, GET_MODE (x));
/* Generate and return an insn body to add r1 and c,
storing the result in r0. */
-rtx
+rtx_insn *
gen_add3_insn (rtx r0, rtx r1, rtx c)
{
enum insn_code icode = optab_handler (add_optab, GET_MODE (r0));
|| !insn_operand_matches (icode, 0, r0)
|| !insn_operand_matches (icode, 1, r1)
|| !insn_operand_matches (icode, 2, c))
- return NULL_RTX;
+ return NULL;
return GEN_FCN (icode) (r0, r1, c);
}
/* Generate and return an insn body to add Y to X. */
-rtx
+rtx_insn *
gen_addptr3_insn (rtx x, rtx y, rtx z)
{
enum insn_code icode = optab_handler (addptr3_optab, GET_MODE (x));
/* Generate and return an insn body to subtract Y from X. */
-rtx
+rtx_insn *
gen_sub2_insn (rtx x, rtx y)
{
enum insn_code icode = optab_handler (sub_optab, GET_MODE (x));
/* Generate and return an insn body to subtract r1 and c,
storing the result in r0. */
-rtx
+rtx_insn *
gen_sub3_insn (rtx r0, rtx r1, rtx c)
{
enum insn_code icode = optab_handler (sub_optab, GET_MODE (r0));
|| !insn_operand_matches (icode, 0, r0)
|| !insn_operand_matches (icode, 1, r1)
|| !insn_operand_matches (icode, 2, c))
- return NULL_RTX;
+ return NULL;
return GEN_FCN (icode) (r0, r1, c);
}
return 1;
}
-
-/* Generate the body of an instruction to copy Y into X.
- It may be a list of insns, if one insn isn't enough. */
-
-rtx
-gen_move_insn (rtx x, rtx y)
-{
- rtx_insn *seq;
-
- start_sequence ();
- emit_move_insn_1 (x, y);
- seq = get_insns ();
- end_sequence ();
- return seq;
-}
\f
/* Return the insn code used to extend FROM_MODE to TO_MODE.
UNSIGNEDP specifies zero-extension instead of sign-extension. If
/* Generate the body of an insn to extend Y (with mode MFROM)
into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
-rtx
+rtx_insn *
gen_extend_insn (rtx x, rtx y, machine_mode mto,
machine_mode mfrom, int unsignedp)
{
/* Hashtable callbacks for libfunc_decls. */
-struct libfunc_decl_hasher : ggc_hasher<tree>
+struct libfunc_decl_hasher : ggc_ptr_hash<tree_node>
{
static hashval_t
hash (tree entry)
/* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
CODE. Return 0 on failure. */
-rtx
+rtx_insn *
gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
{
machine_mode mode = GET_MODE (op1);
enum insn_code icode;
- rtx insn;
+ rtx_insn *insn;
rtx trap_rtx;
if (mode == VOIDmode)
prepare_cmp_insn (op1, op2, code, NULL_RTX, false, OPTAB_DIRECT,
&trap_rtx, &mode);
if (!trap_rtx)
- insn = NULL_RTX;
+ insn = NULL;
else
insn = GEN_FCN (icode) (trap_rtx, XEXP (trap_rtx, 0), XEXP (trap_rtx, 1),
tcode);
/* Return rtx code for TCODE. Use UNSIGNEDP to select signed
or unsigned operation code. */
-static enum rtx_code
+enum rtx_code
get_rtx_code (enum tree_code tcode, bool unsignedp)
{
enum rtx_code code;
code = LTGT;
break;
+ case BIT_AND_EXPR:
+ code = AND;
+ break;
+
+ case BIT_IOR_EXPR:
+ code = IOR;
+ break;
+
default:
gcc_unreachable ();
}
{
struct expand_operand ops[2];
rtx rtx_op0, rtx_op1;
+ machine_mode m0, m1;
enum rtx_code rcode = get_rtx_code (tcode, unsignedp);
gcc_assert (TREE_CODE_CLASS (tcode) == tcc_comparison);
- /* Expand operands. */
+ /* Expand operands. For vector types with scalar modes, e.g. where int64x1_t
+ has mode DImode, this can produce a constant RTX of mode VOIDmode; in such
+ cases, use the original mode. */
rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)),
EXPAND_STACK_PARM);
+ m0 = GET_MODE (rtx_op0);
+ if (m0 == VOIDmode)
+ m0 = TYPE_MODE (TREE_TYPE (t_op0));
+
rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)),
EXPAND_STACK_PARM);
+ m1 = GET_MODE (rtx_op1);
+ if (m1 == VOIDmode)
+ m1 = TYPE_MODE (TREE_TYPE (t_op1));
- create_input_operand (&ops[0], rtx_op0, GET_MODE (rtx_op0));
- create_input_operand (&ops[1], rtx_op1, GET_MODE (rtx_op1));
+ create_input_operand (&ops[0], rtx_op0, m0);
+ create_input_operand (&ops[1], rtx_op1, m1);
if (!maybe_legitimize_operands (icode, 4, 2, ops))
gcc_unreachable ();
return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value);
}
-/* Return true if VEC_PERM_EXPR can be expanded using SIMD extensions
- of the CPU. SEL may be NULL, which stands for an unknown constant. */
+/* Return true if VEC_PERM_EXPR of arbitrary input vectors can be expanded using
+ SIMD extensions of the CPU. SEL may be NULL, which stands for an unknown
+ constant. Note that additional permutations representing whole-vector shifts
+ may also be handled via the vec_shr optab, but only where the second input
+ vector is entirely constant zeroes; this case is not dealt with here. */
bool
can_vec_perm_p (machine_mode mode, bool variable,
return true;
}
+/* Checks if vec_perm mask SEL is a constant equivalent to a shift of the first
+ vec_perm operand, assuming the second operand is a constant vector of zeroes.
+ Return the shift distance in bits if so, or NULL_RTX if the vec_perm is not a
+ shift. */
+static rtx
+shift_amt_for_vec_perm_mask (rtx sel)
+{
+ unsigned int i, first, nelt = GET_MODE_NUNITS (GET_MODE (sel));
+ unsigned int bitsize = GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (sel)));
+
+ if (GET_CODE (sel) != CONST_VECTOR)
+ return NULL_RTX;
+
+ first = INTVAL (CONST_VECTOR_ELT (sel, 0));
+ if (first >= 2*nelt)
+ return NULL_RTX;
+ for (i = 1; i < nelt; i++)
+ {
+ int idx = INTVAL (CONST_VECTOR_ELT (sel, i));
+ unsigned int expected = (i + first) & (2 * nelt - 1);
+ /* Indices into the second vector are all equivalent. */
+ if (idx < 0 || (MIN (nelt, (unsigned) idx) != MIN (nelt, expected)))
+ return NULL_RTX;
+ }
+
+ return GEN_INT (first * bitsize);
+}
+
/* A subroutine of expand_vec_perm for expanding one vec_perm insn. */
static rtx
else
{
create_input_operand (&ops[1], v0, tmode);
+ /* See if this can be handled with a vec_shr. We only do this if the
+ second vector is all zeroes. */
+ enum insn_code shift_code = optab_handler (vec_shr_optab, GET_MODE (v0));
+ if (v1 == CONST0_RTX (GET_MODE (v1)) && shift_code)
+ if (rtx shift_amt = shift_amt_for_vec_perm_mask (sel))
+ {
+ create_convert_operand_from_type (&ops[2], shift_amt,
+ sizetype_tab[(int) stk_sizetype]);
+ if (maybe_expand_insn (shift_code, 3, ops))
+ return ops[0].value;
+ }
create_input_operand (&ops[2], v1, tmode);
}
machine_mode selmode = GET_MODE (sel);
if (u == 2)
sel = expand_simple_binop (selmode, PLUS, sel, sel,
- sel, 0, OPTAB_DIRECT);
+ NULL, 0, OPTAB_DIRECT);
else
sel = expand_simple_binop (selmode, ASHIFT, sel,
GEN_INT (exact_log2 (u)),
- sel, 0, OPTAB_DIRECT);
+ NULL, 0, OPTAB_DIRECT);
gcc_assert (sel != NULL);
/* Broadcast the low byte each element into each of its bytes. */
tab1 = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
tab2 = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
if (BYTES_BIG_ENDIAN)
- {
- optab t = tab1;
- tab1 = tab2;
- tab2 = t;
- }
+ std::swap (tab1, tab2);
break;
default:
gcc_unreachable ();
success = NULL_RTX;
oldval = cmp_reg;
if (!expand_atomic_compare_and_swap (&success, &oldval, mem, old_reg,
- new_reg, false, MEMMODEL_SEQ_CST,
+ new_reg, false, MEMMODEL_SYNC_SEQ_CST,
MEMMODEL_RELAXED))
return false;
exists, and the memory model is stronger than acquire, add a release
barrier before the instruction. */
- if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST
- || (model & MEMMODEL_MASK) == MEMMODEL_RELEASE
- || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
+ if (is_mm_seq_cst (model) || is_mm_release (model) || is_mm_acq_rel (model))
expand_mem_thread_fence (model);
if (icode != CODE_FOR_nothing)
rtx ret;
/* Try an atomic_exchange first. */
- ret = maybe_emit_atomic_exchange (target, mem, val, MEMMODEL_ACQUIRE);
+ ret = maybe_emit_atomic_exchange (target, mem, val, MEMMODEL_SYNC_ACQUIRE);
if (ret)
return ret;
- ret = maybe_emit_sync_lock_test_and_set (target, mem, val, MEMMODEL_ACQUIRE);
+ ret = maybe_emit_sync_lock_test_and_set (target, mem, val,
+ MEMMODEL_SYNC_ACQUIRE);
if (ret)
return ret;
/* If there are no other options, try atomic_test_and_set if the value
being stored is 1. */
if (val == const1_rtx)
- ret = maybe_emit_atomic_test_and_set (target, mem, MEMMODEL_ACQUIRE);
+ ret = maybe_emit_atomic_test_and_set (target, mem, MEMMODEL_SYNC_ACQUIRE);
return ret;
}
/* This routine will either emit the mem_thread_fence pattern or issue a
sync_synchronize to generate a fence for memory model MEMMODEL. */
-#ifndef HAVE_mem_thread_fence
-# define HAVE_mem_thread_fence 0
-# define gen_mem_thread_fence(x) (gcc_unreachable (), NULL_RTX)
-#endif
-#ifndef HAVE_memory_barrier
-# define HAVE_memory_barrier 0
-# define gen_memory_barrier() (gcc_unreachable (), NULL_RTX)
-#endif
-
void
expand_mem_thread_fence (enum memmodel model)
{
if (HAVE_mem_thread_fence)
emit_insn (gen_mem_thread_fence (GEN_INT (model)));
- else if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED)
+ else if (!is_mm_relaxed (model))
{
if (HAVE_memory_barrier)
emit_insn (gen_memory_barrier ());
/* This routine will either emit the mem_signal_fence pattern or issue a
sync_synchronize to generate a fence for memory model MEMMODEL. */
-#ifndef HAVE_mem_signal_fence
-# define HAVE_mem_signal_fence 0
-# define gen_mem_signal_fence(x) (gcc_unreachable (), NULL_RTX)
-#endif
-
void
expand_mem_signal_fence (enum memmodel model)
{
if (HAVE_mem_signal_fence)
emit_insn (gen_mem_signal_fence (GEN_INT (model)));
- else if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED)
+ else if (!is_mm_relaxed (model))
{
/* By default targets are coherent between a thread and the signal
handler running on the same thread. Thus this really becomes a
target = gen_reg_rtx (mode);
/* For SEQ_CST, emit a barrier before the load. */
- if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST)
+ if (is_mm_seq_cst (model))
expand_mem_thread_fence (model);
emit_move_insn (target, mem);
if (maybe_expand_insn (icode, 2, ops))
{
/* lock_release is only a release barrier. */
- if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST)
+ if (is_mm_seq_cst (model))
expand_mem_thread_fence (model);
return const0_rtx;
}
emit_move_insn (mem, val);
/* For SEQ_CST, also emit a barrier after the store. */
- if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST)
+ if (is_mm_seq_cst (model))
expand_mem_thread_fence (model);
return const0_rtx;
and emit any necessary set-up code. Return null and emit no
code on failure. */
-rtx
+rtx_insn *
maybe_gen_insn (enum insn_code icode, unsigned int nops,
struct expand_operand *ops)
{
gcc_assert (nops == (unsigned int) insn_data[(int) icode].n_generator_args);
if (!maybe_legitimize_operands (icode, 0, nops, ops))
- return NULL_RTX;
+ return NULL;
switch (nops)
{
maybe_expand_insn (enum insn_code icode, unsigned int nops,
struct expand_operand *ops)
{
- rtx pat = maybe_gen_insn (icode, nops, ops);
+ rtx_insn *pat = maybe_gen_insn (icode, nops, ops);
if (pat)
{
emit_insn (pat);
maybe_expand_jump_insn (enum insn_code icode, unsigned int nops,
struct expand_operand *ops)
{
- rtx pat = maybe_gen_insn (icode, nops, ops);
+ rtx_insn *pat = maybe_gen_insn (icode, nops, ops);
if (pat)
{
emit_jump_insn (pat);