#include "target.h"
#include "timevar.h"
#include "df.h"
+#include "diagnostic.h"
/* Decide whether a function's arguments should be processed
from first to last or from last to first.
void
init_expr (void)
{
- cfun->expr = ggc_alloc_cleared (sizeof (struct expr_status));
+ memset (&crtl->expr, 0, sizeof (crtl->expr));
}
\f
/* Copy data from FROM to TO, where the machine modes are not the same.
&& ((code = can_extend_p (to_mode, word_mode, unsignedp))
!= CODE_FOR_nothing))
{
+ rtx word_to = gen_reg_rtx (word_mode);
if (REG_P (to))
{
if (reg_overlap_mentioned_p (to, from))
from = force_reg (from_mode, from);
- emit_insn (gen_rtx_CLOBBER (VOIDmode, to));
+ emit_clobber (to);
}
- convert_move (gen_lowpart (word_mode, to), from, unsignedp);
- emit_unop_insn (code, to,
- gen_lowpart (word_mode, to), equiv_code);
+ convert_move (word_to, from, unsignedp);
+ emit_unop_insn (code, to, word_to, equiv_code);
return;
}
insns = get_insns ();
end_sequence ();
- emit_no_conflict_block (insns, to, from, NULL_RTX,
- gen_rtx_fmt_e (equiv_code, to_mode, copy_rtx (from)));
+ emit_insn (insns);
return;
}
static bool
block_move_libcall_safe_for_call_parm (void)
{
+#if defined (REG_PARM_STACK_SPACE)
+ tree fn;
+#endif
+
/* If arguments are pushed on the stack, then they're safe. */
if (PUSH_ARGS)
return true;
/* If registers go on the stack anyway, any argument is sure to clobber
an outgoing argument. */
#if defined (REG_PARM_STACK_SPACE)
- if (OUTGOING_REG_PARM_STACK_SPACE)
- {
- tree fn;
- fn = emit_block_move_libcall_fn (false);
- if (REG_PARM_STACK_SPACE (fn) != 0)
- return false;
- }
+ fn = emit_block_move_libcall_fn (false);
+ if (OUTGOING_REG_PARM_STACK_SPACE ((!fn ? NULL_TREE : TREE_TYPE (fn)))
+ && REG_PARM_STACK_SPACE (fn) != 0)
+ return false;
#endif
/* If any argument goes in memory, then it might clobber an outgoing
rtx src = NULL, dst = NULL;
unsigned HOST_WIDE_INT bitsize = MIN (TYPE_ALIGN (type), BITS_PER_WORD);
unsigned HOST_WIDE_INT bitpos, xbitpos, padding_correction = 0;
+ enum machine_mode copy_mode;
if (tgtblk == 0)
{
padding_correction
= (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT));
- /* Copy the structure BITSIZE bites at a time.
+ /* Copy the structure BITSIZE bits at a time. If the target lives in
+ memory, take care of not reading/writing past its end by selecting
+ a copy mode suited to BITSIZE. This should always be possible given
+ how it is computed.
We could probably emit more efficient code for machines which do not use
strict alignment, but it doesn't seem worth the effort at the current
time. */
+
+ copy_mode = word_mode;
+ if (MEM_P (tgtblk))
+ {
+ enum machine_mode mem_mode = mode_for_size (bitsize, MODE_INT, 1);
+ if (mem_mode != BLKmode)
+ copy_mode = mem_mode;
+ }
+
for (bitpos = 0, xbitpos = padding_correction;
bitpos < bytes * BITS_PER_UNIT;
bitpos += bitsize, xbitpos += bitsize)
dst = operand_subword (tgtblk, bitpos / BITS_PER_WORD, 1, BLKmode);
/* Use xbitpos for the source extraction (right justified) and
- xbitpos for the destination store (left justified). */
- store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, word_mode,
+ bitpos for the destination store (left justified). */
+ store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, copy_mode,
extract_bit_field (src, bitsize,
xbitpos % BITS_PER_WORD, 1,
- NULL_RTX, word_mode, word_mode));
+ NULL_RTX, copy_mode, copy_mode));
}
return tgtblk;
hard regs shouldn't appear here except as return values. */
if (!reload_completed && !reload_in_progress
&& REG_P (x) && !reg_overlap_mentioned_p (x, y))
- emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
+ emit_clobber (x);
write_complex_part (x, read_complex_part (y, false), false);
write_complex_part (x, read_complex_part (y, true), true);
if (x != y
&& ! (reload_in_progress || reload_completed)
&& need_clobber != 0)
- emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
+ emit_clobber (x);
emit_insn (seq);
/* If X or Y are memory references, verify that their addresses are valid
for the machine. */
if (MEM_P (x)
- && ((! memory_address_p (GET_MODE (x), XEXP (x, 0))
- && ! push_operand (x, GET_MODE (x)))
- || (flag_force_addr
- && CONSTANT_ADDRESS_P (XEXP (x, 0)))))
+ && (! memory_address_p (GET_MODE (x), XEXP (x, 0))
+ && ! push_operand (x, GET_MODE (x))))
x = validize_mem (x);
if (MEM_P (y)
- && (! memory_address_p (GET_MODE (y), XEXP (y, 0))
- || (flag_force_addr
- && CONSTANT_ADDRESS_P (XEXP (y, 0)))))
+ && ! memory_address_p (GET_MODE (y), XEXP (y, 0)))
y = validize_mem (y);
gcc_assert (mode != BLKmode);
the place the value is being stored, use a safe function when copying
a value through a pointer into a structure value return block. */
if (TREE_CODE (to) == RESULT_DECL && TREE_CODE (from) == INDIRECT_REF
- && current_function_returns_struct
- && !current_function_returns_pcc_struct)
+ && cfun->returns_struct
+ && !cfun->returns_pcc_struct)
{
rtx from_rtx, size;
converting modes. */
if (INTEGRAL_TYPE_P (TREE_TYPE (exp))
&& TREE_TYPE (TREE_TYPE (exp)) == 0
- && (!lang_hooks.reduce_bit_field_operations
- || (GET_MODE_PRECISION (GET_MODE (target))
- == TYPE_PRECISION (TREE_TYPE (exp)))))
+ && GET_MODE_PRECISION (GET_MODE (target))
+ == TYPE_PRECISION (TREE_TYPE (exp)))
{
if (TYPE_UNSIGNED (TREE_TYPE (exp))
!= SUBREG_PROMOTED_UNSIGNED_P (target))
temp = convert_to_mode (GET_MODE (target), temp, unsignedp);
emit_move_insn (target, temp);
}
- else if (GET_MODE (target) == BLKmode)
+ else if (GET_MODE (target) == BLKmode
+ || GET_MODE (temp) == BLKmode)
emit_block_move (target, temp, expr_size (exp),
(call_param_p
? BLOCK_OP_CALL_PARM
case UNION_TYPE:
case QUAL_UNION_TYPE:
- {
- /* Ho hum. How in the world do we guess here? Clearly it isn't
- right to count the fields. Guess based on the number of words. */
- HOST_WIDE_INT n = int_size_in_bytes (type);
- if (n < 0)
- return -1;
- return n / UNITS_PER_WORD;
- }
+ return -1;
case COMPLEX_TYPE:
return 2;
}
if (REG_P (target) && !cleared)
- emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
+ emit_clobber (target);
/* Store each element of the constructor into the
corresponding field of TARGET. */
if (!cleared && REG_P (target))
/* Inform later passes that the old value is dead. */
- emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
+ emit_clobber (target);
/* Store each element of the constructor into the
corresponding element of TARGET, determined by counting the
&& mode != TYPE_MODE (TREE_TYPE (exp)))
temp = convert_modes (mode, TYPE_MODE (TREE_TYPE (exp)), temp, 1);
- /* If the modes of TARGET and TEMP are both BLKmode, both
+ /* If the modes of TEMP and TARGET are both BLKmode, both
must be in memory and BITPOS must be aligned on a byte
- boundary. If so, we simply do a block copy. */
- if (GET_MODE (target) == BLKmode && GET_MODE (temp) == BLKmode)
+ boundary. If so, we simply do a block copy. Likewise
+ for a BLKmode-like TARGET. */
+ if (GET_MODE (temp) == BLKmode
+ && (GET_MODE (target) == BLKmode
+ || (MEM_P (target)
+ && GET_MODE_CLASS (GET_MODE (target)) == MODE_INT
+ && (bitpos % BITS_PER_UNIT) == 0
+ && (bitsize % BITS_PER_UNIT) == 0)))
{
gcc_assert (MEM_P (target) && MEM_P (temp)
- && !(bitpos % BITS_PER_UNIT));
+ && (bitpos % BITS_PER_UNIT) == 0);
target = adjust_address (target, VOIDmode, bitpos / BITS_PER_UNIT);
emit_block_move (target, temp,
If any of the extraction expressions is volatile,
we store 1 in *PVOLATILEP. Otherwise we don't change that.
- If the field is a bit-field, *PMODE is set to VOIDmode. Otherwise, it
- is a mode that can be used to access the field. In that case, *PBITSIZE
- is redundant.
+ If the field is a non-BLKmode bit-field, *PMODE is set to VOIDmode.
+ Otherwise, it is a mode that can be used to access the field.
If the field describes a variable-sized object, *PMODE is set to
- VOIDmode and *PBITSIZE is set to -1. An access cannot be made in
+ BLKmode and *PBITSIZE is set to -1. An access cannot be made in
this case, but the address of the object can be found.
If KEEP_ALIGNING is true and the target is STRICT_ALIGNMENT, we don't
{
tree size_tree = 0;
enum machine_mode mode = VOIDmode;
+ bool blkmode_bitfield = false;
tree offset = size_zero_node;
tree bit_offset = bitsize_zero_node;
outermost expression. */
if (TREE_CODE (exp) == COMPONENT_REF)
{
- size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
- if (! DECL_BIT_FIELD (TREE_OPERAND (exp, 1)))
- mode = DECL_MODE (TREE_OPERAND (exp, 1));
+ tree field = TREE_OPERAND (exp, 1);
+ size_tree = DECL_SIZE (field);
+ if (!DECL_BIT_FIELD (field))
+ mode = DECL_MODE (field);
+ else if (DECL_MODE (field) == BLKmode)
+ blkmode_bitfield = true;
- *punsignedp = DECL_UNSIGNED (TREE_OPERAND (exp, 1));
+ *punsignedp = DECL_UNSIGNED (field);
}
else if (TREE_CODE (exp) == BIT_FIELD_REF)
{
size_tree = TREE_OPERAND (exp, 1);
- *punsignedp = BIT_FIELD_REF_UNSIGNED (exp);
+ *punsignedp = (! INTEGRAL_TYPE_P (TREE_TYPE (exp))
+ || TYPE_UNSIGNED (TREE_TYPE (exp)));
/* For vector types, with the correct size of access, use the mode of
inner type. */
*pbitsize = tree_low_cst (size_tree, 1);
}
- *pmode = mode;
-
/* Compute cumulative bit-offset for nested component-refs and array-refs,
and find the ultimate containing object. */
while (1)
if (double_int_fits_in_shwi_p (tem))
{
*pbitpos = double_int_to_shwi (tem);
- *poffset = NULL_TREE;
- return exp;
+ *poffset = offset = NULL_TREE;
}
}
/* Otherwise, split it up. */
- *pbitpos = tree_low_cst (bit_offset, 0);
- *poffset = offset;
+ if (offset)
+ {
+ *pbitpos = tree_low_cst (bit_offset, 0);
+ *poffset = offset;
+ }
+
+ /* We can use BLKmode for a byte-aligned BLKmode bitfield. */
+ if (mode == VOIDmode
+ && blkmode_bitfield
+ && (*pbitpos % BITS_PER_UNIT) == 0
+ && (*pbitsize % BITS_PER_UNIT) == 0)
+ *pmode = BLKmode;
+ else
+ *pmode = mode;
return exp;
}
}
break;
- case NON_LVALUE_EXPR: case NOP_EXPR: case CONVERT_EXPR:
+ case BIT_AND_EXPR:
+ /* The highest power of two of a bit-and expression is the maximum of
+ that of its operands. We typically get here for a complex LHS and
+ a constant negative power of two on the RHS to force an explicit
+ alignment, so don't bother looking at the LHS. */
+ return highest_pow2_factor (TREE_OPERAND (exp, 1));
+
+ CASE_CONVERT:
case SAVE_EXPR:
return highest_pow2_factor (TREE_OPERAND (exp, 0));
return fold_convert (build_pointer_type (TREE_TYPE (var)), call);
}
\f
-/* Expands variable VAR. */
-
-void
-expand_var (tree var)
-{
- if (DECL_EXTERNAL (var))
- return;
-
- if (TREE_STATIC (var))
- /* If this is an inlined copy of a static local variable,
- look up the original decl. */
- var = DECL_ORIGIN (var);
-
- if (TREE_STATIC (var)
- ? !TREE_ASM_WRITTEN (var)
- : !DECL_RTL_SET_P (var))
- {
- if (TREE_CODE (var) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (var))
- /* Should be ignored. */;
- else if (lang_hooks.expand_decl (var))
- /* OK. */;
- else if (TREE_CODE (var) == VAR_DECL && !TREE_STATIC (var))
- expand_decl (var);
- else if (TREE_CODE (var) == VAR_DECL && TREE_STATIC (var))
- rest_of_decl_compilation (var, 0, 0);
- else
- /* No expansion needed. */
- gcc_assert (TREE_CODE (var) == TYPE_DECL
- || TREE_CODE (var) == CONST_DECL
- || TREE_CODE (var) == FUNCTION_DECL
- || TREE_CODE (var) == LABEL_DECL);
- }
-}
/* Subroutine of expand_expr. Expand the two operands of a binary
expression EXP0 and EXP1 placing the results in OP0 and OP1.
/* ??? This should be considered a front-end bug. We should not be
generating ADDR_EXPR of something that isn't an LVALUE. The only
exception here is STRING_CST. */
- if (TREE_CODE (exp) == CONSTRUCTOR
- || CONSTANT_CLASS_P (exp))
+ if (CONSTANT_CLASS_P (exp))
return XEXP (expand_expr_constant (exp, 0, modifier), 0);
/* Everything must be something allowed by is_gimple_addressable. */
default:
/* If the object is a DECL, then expand it for its rtl. Don't bypass
expand_expr, as that can have various side effects; LABEL_DECLs for
- example, may not have their DECL_RTL set yet. Assume language
- specific tree nodes can be expanded in some interesting way. */
+ example, may not have their DECL_RTL set yet. Expand the rtl of
+ CONSTRUCTORs too, which should yield a memory reference for the
+ constructor's contents. Assume language specific tree nodes can
+ be expanded in some interesting way. */
if (DECL_P (exp)
+ || TREE_CODE (exp) == CONSTRUCTOR
|| TREE_CODE (exp) >= LAST_AND_UNUSED_TREE_CODE)
{
result = expand_expr (exp, target, tmode,
/* Handle ERROR_MARK before anybody tries to access its type. */
if (TREE_CODE (exp) == ERROR_MARK
+ || TREE_CODE (exp) == PREDICT_EXPR
|| (!GIMPLE_TUPLE_P (exp) && TREE_CODE (TREE_TYPE (exp)) == ERROR_MARK))
{
ret = CONST0_RTX (tmode);
rtx subtarget, original_target;
int ignore;
tree context, subexp0, subexp1;
- bool reduce_bit_field = false;
-#define REDUCE_BIT_FIELD(expr) (reduce_bit_field && !ignore \
+ bool reduce_bit_field;
+#define REDUCE_BIT_FIELD(expr) (reduce_bit_field \
? reduce_to_bit_field_precision ((expr), \
target, \
type) \
mode = TYPE_MODE (type);
unsignedp = TYPE_UNSIGNED (type);
}
- if (lang_hooks.reduce_bit_field_operations
- && TREE_CODE (type) == INTEGER_TYPE
- && GET_MODE_PRECISION (mode) > TYPE_PRECISION (type))
- {
- /* An operation in what may be a bit-field type needs the
- result to be reduced to the precision of the bit-field type,
- which is narrower than that of the type's mode. */
- reduce_bit_field = true;
- if (modifier == EXPAND_STACK_PARM)
- target = 0;
- }
- /* Use subtarget as the target for operand 0 of a binary operation. */
- subtarget = get_subtarget (target);
- original_target = target;
ignore = (target == const0_rtx
- || ((code == NON_LVALUE_EXPR || code == NOP_EXPR
- || code == CONVERT_EXPR || code == COND_EXPR
- || code == VIEW_CONVERT_EXPR)
+ || ((code == NOP_EXPR || code == CONVERT_EXPR
+ || code == COND_EXPR || code == VIEW_CONVERT_EXPR)
&& TREE_CODE (type) == VOID_TYPE));
+ /* An operation in what may be a bit-field type needs the
+ result to be reduced to the precision of the bit-field type,
+ which is narrower than that of the type's mode. */
+ reduce_bit_field = (!ignore
+ && TREE_CODE (type) == INTEGER_TYPE
+ && GET_MODE_PRECISION (mode) > TYPE_PRECISION (type));
+
/* If we are going to ignore this result, we need only do something
if there is a side-effect somewhere in the expression. If there
is, short-circuit the most common cases here. Note that we must
target = 0;
}
+ if (reduce_bit_field && modifier == EXPAND_STACK_PARM)
+ target = 0;
+
+ /* Use subtarget as the target for operand 0 of a binary operation. */
+ subtarget = get_subtarget (target);
+ original_target = target;
switch (code)
{
if (MEM_P (decl_rtl) && REG_P (XEXP (decl_rtl, 0)))
temp = validize_mem (decl_rtl);
- /* If DECL_RTL is memory, we are in the normal case and either
- the address is not valid or it is not a register and -fforce-addr
- is specified, get the address into a register. */
+ /* If DECL_RTL is memory, we are in the normal case and the
+ address is not valid, get the address into a register. */
else if (MEM_P (decl_rtl) && modifier != EXPAND_INITIALIZER)
{
decl_rtl = use_anchored_address (decl_rtl);
if (modifier != EXPAND_CONST_ADDRESS
&& modifier != EXPAND_SUM
- && (!memory_address_p (DECL_MODE (exp), XEXP (decl_rtl, 0))
- || (flag_force_addr && !REG_P (XEXP (decl_rtl, 0)))))
+ && !memory_address_p (DECL_MODE (exp), XEXP (decl_rtl, 0)))
temp = replace_equiv_address (decl_rtl,
copy_rtx (XEXP (decl_rtl, 0)));
}
if (modifier != EXPAND_CONST_ADDRESS
&& modifier != EXPAND_INITIALIZER
&& modifier != EXPAND_SUM
- && (! memory_address_p (mode, XEXP (temp, 0))
- || flag_force_addr))
+ && ! memory_address_p (mode, XEXP (temp, 0)))
return replace_equiv_address (temp,
copy_rtx (XEXP (temp, 0)));
return temp;
/* If this is a constant, put it into a register if it is a legitimate
constant, OFFSET is 0, and we won't try to extract outside the
register (in case we were passed a partially uninitialized object
- or a view_conversion to a larger size). Force the constant to
- memory otherwise. */
+ or a view_conversion to a larger size) or a BLKmode piece of it
+ (e.g. if it is unchecked-converted to a record type in Ada). Force
+ the constant to memory otherwise. */
if (CONSTANT_P (op0))
{
enum machine_mode mode = TYPE_MODE (TREE_TYPE (tem));
if (mode != BLKmode && LEGITIMATE_CONSTANT_P (op0)
&& offset == 0
+ && mode1 != BLKmode
&& bitpos + bitsize <= GET_MODE_BITSIZE (mode))
op0 = force_reg (mode, op0);
else
for an ARRAY_RANGE_REF whose type is BLKmode. */
else if (!MEM_P (op0)
&& (offset != 0
- || (bitpos + bitsize > GET_MODE_BITSIZE (GET_MODE (op0)))
- || (code == ARRAY_RANGE_REF && mode == BLKmode)))
+ || mode1 == BLKmode
+ || (bitpos + bitsize
+ > GET_MODE_BITSIZE (GET_MODE (op0)))))
{
tree nt = build_qualified_type (TREE_TYPE (tem),
(TYPE_QUALS (TREE_TYPE (tem))
}
return expand_call (exp, target, ignore);
- case NON_LVALUE_EXPR:
- case NOP_EXPR:
- case CONVERT_EXPR:
+ case PAREN_EXPR:
+ CASE_CONVERT:
if (TREE_OPERAND (exp, 0) == error_mark_node)
return const0_rtx;
if (modifier == EXPAND_STACK_PARM)
target = 0;
temp = expand_unop (mode,
- optab_for_tree_code (NEGATE_EXPR, type),
+ optab_for_tree_code (NEGATE_EXPR, type,
+ optab_default),
op0, target, 0);
gcc_assert (temp);
return REDUCE_BIT_FIELD (temp);
/* First try to do it with a special MIN or MAX instruction.
If that does not win, use a conditional jump to select the proper
value. */
- this_optab = optab_for_tree_code (code, type);
+ this_optab = optab_for_tree_code (code, type, optab_default);
temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
OPTAB_WIDEN);
if (temp != 0)
case BIT_XOR_EXPR:
goto binop;
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
case LROTATE_EXPR:
case RROTATE_EXPR:
+ gcc_assert (VECTOR_MODE_P (TYPE_MODE (type))
+ || (GET_MODE_PRECISION (TYPE_MODE (type))
+ == TYPE_PRECISION (type)));
+ /* fall through */
+
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
/* If this is a fixed-point operation, then we cannot use the code
below because "expand_shift" doesn't support sat/no-sat fixed-point
shifts. */
target = 0;
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget,
VOIDmode, EXPAND_NORMAL);
- return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target,
+ temp = expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target,
unsignedp);
+ if (code == LSHIFT_EXPR)
+ temp = REDUCE_BIT_FIELD (temp);
+ return temp;
/* Could determine the answer when only additive constants differ. Also,
the addition of one can be handled by changing the condition. */
return const0_rtx;
case EXC_PTR_EXPR:
- return get_exception_pointer (cfun);
+ return get_exception_pointer ();
case FILTER_EXPR:
- return get_exception_filter (cfun);
+ return get_exception_filter ();
case FDESC_EXPR:
/* Function descriptors are not valid except for as
tree oprnd2 = TREE_OPERAND (exp, 2);
rtx op2;
- this_optab = optab_for_tree_code (code, type);
+ this_optab = optab_for_tree_code (code, type, optab_default);
expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
op2 = expand_normal (oprnd2);
temp = expand_ternary_op (mode, this_optab, op0, op1, op2,
case REDUC_PLUS_EXPR:
{
op0 = expand_normal (TREE_OPERAND (exp, 0));
- this_optab = optab_for_tree_code (code, type);
+ this_optab = optab_for_tree_code (code, type, optab_default);
temp = expand_unop (mode, this_optab, op0, target, unsignedp);
gcc_assert (temp);
return temp;
{
expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
NULL_RTX, &op0, &op1, 0);
- this_optab = optab_for_tree_code (code, type);
+ this_optab = optab_for_tree_code (code, type, optab_default);
temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
OPTAB_WIDEN);
gcc_assert (temp);
{
expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
NULL_RTX, &op0, &op1, 0);
- this_optab = optab_for_tree_code (code, type);
+ this_optab = optab_for_tree_code (code, type, optab_default);
temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
OPTAB_WIDEN);
gcc_assert (temp);
case VEC_UNPACK_LO_EXPR:
{
op0 = expand_normal (TREE_OPERAND (exp, 0));
- this_optab = optab_for_tree_code (code, type);
+ this_optab = optab_for_tree_code (code, type, optab_default);
temp = expand_widen_pattern_expr (exp, op0, NULL_RTX, NULL_RTX,
target, unsignedp);
gcc_assert (temp);
op0 = expand_normal (TREE_OPERAND (exp, 0));
/* The signedness is determined from input operand. */
this_optab = optab_for_tree_code (code,
- TREE_TYPE (TREE_OPERAND (exp, 0)));
+ TREE_TYPE (TREE_OPERAND (exp, 0)),
+ optab_default);
temp = expand_widen_pattern_expr
(exp, op0, NULL_RTX, NULL_RTX,
target, TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
goto binop;
}
+ case OMP_ATOMIC_LOAD:
+ case OMP_ATOMIC_STORE:
+ /* OMP expansion is not run when there were errors, so these codes
+ can get here. */
+ gcc_assert (errorcount != 0);
+ return NULL_RTX;
+
default:
return lang_hooks.expand_expr (exp, original_target, tmode,
modifier, alt_rtl);
expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
subtarget, &op0, &op1, 0);
binop2:
- this_optab = optab_for_tree_code (code, type);
+ this_optab = optab_for_tree_code (code, type, optab_default);
binop3:
if (modifier == EXPAND_STACK_PARM)
target = 0;
is_aligning_offset (const_tree offset, const_tree exp)
{
/* Strip off any conversions. */
- while (TREE_CODE (offset) == NON_LVALUE_EXPR
- || TREE_CODE (offset) == NOP_EXPR
- || TREE_CODE (offset) == CONVERT_EXPR)
+ while (CONVERT_EXPR_P (offset))
offset = TREE_OPERAND (offset, 0);
/* We must now have a BIT_AND_EXPR with a constant that is one less than
/* Look at the first operand of BIT_AND_EXPR and strip any conversion.
It must be NEGATE_EXPR. Then strip any more conversions. */
offset = TREE_OPERAND (offset, 0);
- while (TREE_CODE (offset) == NON_LVALUE_EXPR
- || TREE_CODE (offset) == NOP_EXPR
- || TREE_CODE (offset) == CONVERT_EXPR)
+ while (CONVERT_EXPR_P (offset))
offset = TREE_OPERAND (offset, 0);
if (TREE_CODE (offset) != NEGATE_EXPR)
return 0;
offset = TREE_OPERAND (offset, 0);
- while (TREE_CODE (offset) == NON_LVALUE_EXPR
- || TREE_CODE (offset) == NOP_EXPR
- || TREE_CODE (offset) == CONVERT_EXPR)
+ while (CONVERT_EXPR_P (offset))
offset = TREE_OPERAND (offset, 0);
/* This must now be the address of EXP. */
0 otherwise (i.e. if there is no casesi instruction). */
int
try_casesi (tree index_type, tree index_expr, tree minval, tree range,
- rtx table_label ATTRIBUTE_UNUSED, rtx default_label)
+ rtx table_label ATTRIBUTE_UNUSED, rtx default_label,
+ rtx fallback_label ATTRIBUTE_UNUSED)
{
enum machine_mode index_mode = SImode;
int index_bits = GET_MODE_BITSIZE (index_mode);
index_expr, minval);
minval = integer_zero_node;
index = expand_normal (index_expr);
- emit_cmp_and_jump_insns (rangertx, index, LTU, NULL_RTX,
- omode, 1, default_label);
+ if (default_label)
+ emit_cmp_and_jump_insns (rangertx, index, LTU, NULL_RTX,
+ omode, 1, default_label);
/* Now we can safely truncate. */
index = convert_to_mode (index_mode, index, 0);
}
op2 = copy_to_mode_reg (op_mode, op2);
emit_jump_insn (gen_casesi (index, op1, op2,
- table_label, default_label));
+ table_label, !default_label
+ ? fallback_label : default_label));
return 1;
}
{
rtx temp, vector;
- if (INTVAL (range) > cfun->max_jumptable_ents)
- cfun->max_jumptable_ents = INTVAL (range);
+ if (INTVAL (range) > cfun->cfg->max_jumptable_ents)
+ cfun->cfg->max_jumptable_ents = INTVAL (range);
/* Do an unsigned comparison (in the proper mode) between the index
expression and the value which represents the length of the range.
or equal to the minimum value of the range and less than or equal to
the maximum value of the range. */
- emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, mode, 1,
- default_label);
+ if (default_label)
+ emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, mode, 1,
+ default_label);
/* If index is in range, it must fit in Pmode.
Convert to Pmode so we can index with it. */
index = copy_to_mode_reg (Pmode, index);
#endif
- /* If flag_force_addr were to affect this address
- it could interfere with the tricky assumptions made
- about addresses that contain label-refs,
- which may be valid only very near the tablejump itself. */
/* ??? The only correct use of CASE_VECTOR_MODE is the one inside the
GET_MODE_SIZE, because this indicates how large insns are. The other
uses should all be Pmode, because they are addresses. This code
index = PIC_CASE_VECTOR_ADDRESS (index);
else
#endif
- index = memory_address_noforce (CASE_VECTOR_MODE, index);
+ index = memory_address (CASE_VECTOR_MODE, index);
temp = gen_reg_rtx (CASE_VECTOR_MODE);
vector = gen_const_mem (CASE_VECTOR_MODE, index);
convert_move (temp, vector, 0);