summaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c324
1 files changed, 193 insertions, 131 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 2763dc91991..3e5d18bdebc 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
#include "df.h"
#include "diagnostic.h"
#include "ssaexpand.h"
+#include "target-globals.h"
/* Decide whether a function's arguments should be processed
from first to last or from last to first.
@@ -158,17 +159,6 @@ static void do_tablejump (rtx, enum machine_mode, rtx, rtx, rtx);
static rtx const_vector_from_tree (tree);
static void write_complex_part (rtx, rtx, bool);
-/* Record for each mode whether we can move a register directly to or
- from an object of that mode in memory. If we can't, we won't try
- to use that mode directly when accessing a field of that mode. */
-
-static char direct_load[NUM_MACHINE_MODES];
-static char direct_store[NUM_MACHINE_MODES];
-
-/* Record for each mode whether we can float-extend from memory. */
-
-static bool float_extend_from_mem[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
-
/* This macro is used to determine whether move_by_pieces should be called
to perform a structure copy. */
#ifndef MOVE_BY_PIECES_P
@@ -201,41 +191,6 @@ static bool float_extend_from_mem[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
< (unsigned int) MOVE_RATIO (optimize_insn_for_speed_p ()))
#endif
-/* This array records the insn_code of insns to perform block moves. */
-enum insn_code movmem_optab[NUM_MACHINE_MODES];
-
-/* This array records the insn_code of insns to perform block sets. */
-enum insn_code setmem_optab[NUM_MACHINE_MODES];
-
-/* These arrays record the insn_code of three different kinds of insns
- to perform block compares. */
-enum insn_code cmpstr_optab[NUM_MACHINE_MODES];
-enum insn_code cmpstrn_optab[NUM_MACHINE_MODES];
-enum insn_code cmpmem_optab[NUM_MACHINE_MODES];
-
-/* Synchronization primitives. */
-enum insn_code sync_add_optab[NUM_MACHINE_MODES];
-enum insn_code sync_sub_optab[NUM_MACHINE_MODES];
-enum insn_code sync_ior_optab[NUM_MACHINE_MODES];
-enum insn_code sync_and_optab[NUM_MACHINE_MODES];
-enum insn_code sync_xor_optab[NUM_MACHINE_MODES];
-enum insn_code sync_nand_optab[NUM_MACHINE_MODES];
-enum insn_code sync_old_add_optab[NUM_MACHINE_MODES];
-enum insn_code sync_old_sub_optab[NUM_MACHINE_MODES];
-enum insn_code sync_old_ior_optab[NUM_MACHINE_MODES];
-enum insn_code sync_old_and_optab[NUM_MACHINE_MODES];
-enum insn_code sync_old_xor_optab[NUM_MACHINE_MODES];
-enum insn_code sync_old_nand_optab[NUM_MACHINE_MODES];
-enum insn_code sync_new_add_optab[NUM_MACHINE_MODES];
-enum insn_code sync_new_sub_optab[NUM_MACHINE_MODES];
-enum insn_code sync_new_ior_optab[NUM_MACHINE_MODES];
-enum insn_code sync_new_and_optab[NUM_MACHINE_MODES];
-enum insn_code sync_new_xor_optab[NUM_MACHINE_MODES];
-enum insn_code sync_new_nand_optab[NUM_MACHINE_MODES];
-enum insn_code sync_compare_and_swap[NUM_MACHINE_MODES];
-enum insn_code sync_lock_test_and_set[NUM_MACHINE_MODES];
-enum insn_code sync_lock_release[NUM_MACHINE_MODES];
-
/* SLOW_UNALIGNED_ACCESS is nonzero if unaligned accesses are very slow. */
#ifndef SLOW_UNALIGNED_ACCESS
@@ -434,7 +389,7 @@ convert_move (rtx to, rtx from, int unsignedp)
/* Try converting directly if the insn is supported. */
- code = convert_optab_handler (tab, to_mode, from_mode)->insn_code;
+ code = convert_optab_handler (tab, to_mode, from_mode);
if (code != CODE_FOR_nothing)
{
emit_unop_insn (code, to, from,
@@ -468,12 +423,12 @@ convert_move (rtx to, rtx from, int unsignedp)
enum machine_mode full_mode
= smallest_mode_for_size (GET_MODE_BITSIZE (to_mode), MODE_INT);
- gcc_assert (convert_optab_handler (trunc_optab, to_mode, full_mode)->insn_code
+ gcc_assert (convert_optab_handler (trunc_optab, to_mode, full_mode)
!= CODE_FOR_nothing);
if (full_mode != from_mode)
from = convert_to_mode (full_mode, from, unsignedp);
- emit_unop_insn (convert_optab_handler (trunc_optab, to_mode, full_mode)->insn_code,
+ emit_unop_insn (convert_optab_handler (trunc_optab, to_mode, full_mode),
to, from, UNKNOWN);
return;
}
@@ -483,18 +438,19 @@ convert_move (rtx to, rtx from, int unsignedp)
enum machine_mode full_mode
= smallest_mode_for_size (GET_MODE_BITSIZE (from_mode), MODE_INT);
- gcc_assert (convert_optab_handler (sext_optab, full_mode, from_mode)->insn_code
+ gcc_assert (convert_optab_handler (sext_optab, full_mode, from_mode)
!= CODE_FOR_nothing);
if (to_mode == full_mode)
{
- emit_unop_insn (convert_optab_handler (sext_optab, full_mode, from_mode)->insn_code,
+ emit_unop_insn (convert_optab_handler (sext_optab, full_mode,
+ from_mode),
to, from, UNKNOWN);
return;
}
new_from = gen_reg_rtx (full_mode);
- emit_unop_insn (convert_optab_handler (sext_optab, full_mode, from_mode)->insn_code,
+ emit_unop_insn (convert_optab_handler (sext_optab, full_mode, from_mode),
new_from, from, UNKNOWN);
/* else proceed to integer conversions below. */
@@ -695,9 +651,10 @@ convert_move (rtx to, rtx from, int unsignedp)
}
/* Support special truncate insns for certain modes. */
- if (convert_optab_handler (trunc_optab, to_mode, from_mode)->insn_code != CODE_FOR_nothing)
+ if (convert_optab_handler (trunc_optab, to_mode,
+ from_mode) != CODE_FOR_nothing)
{
- emit_unop_insn (convert_optab_handler (trunc_optab, to_mode, from_mode)->insn_code,
+ emit_unop_insn (convert_optab_handler (trunc_optab, to_mode, from_mode),
to, from, UNKNOWN);
return;
}
@@ -990,7 +947,7 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
if (mode == VOIDmode)
break;
- icode = optab_handler (mov_optab, mode)->insn_code;
+ icode = optab_handler (mov_optab, mode);
if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
move_by_pieces_1 (GEN_FCN (icode), mode, &data);
@@ -1071,7 +1028,7 @@ move_by_pieces_ninsns (unsigned HOST_WIDE_INT l, unsigned int align,
if (mode == VOIDmode)
break;
- icode = optab_handler (mov_optab, mode)->insn_code;
+ icode = optab_handler (mov_optab, mode);
if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
n_insns += l / GET_MODE_SIZE (mode), l %= GET_MODE_SIZE (mode);
@@ -1163,6 +1120,11 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method,
rtx retval = 0;
unsigned int align;
+ gcc_assert (size);
+ if (CONST_INT_P (size)
+ && INTVAL (size) == 0)
+ return 0;
+
switch (method)
{
case BLOCK_OP_NORMAL:
@@ -1186,13 +1148,10 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method,
gcc_unreachable ();
}
+ gcc_assert (MEM_P (x) && MEM_P (y));
align = MIN (MEM_ALIGN (x), MEM_ALIGN (y));
gcc_assert (align >= BITS_PER_UNIT);
- gcc_assert (MEM_P (x));
- gcc_assert (MEM_P (y));
- gcc_assert (size);
-
/* Make sure we've got BLKmode addresses; store_one_arg can decide that
block copy is more efficient for other large modes, e.g. DCmode. */
x = adjust_address (x, BLKmode, 0);
@@ -1202,9 +1161,6 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method,
can be incorrect is coming from __builtin_memcpy. */
if (CONST_INT_P (size))
{
- if (INTVAL (size) == 0)
- return 0;
-
x = shallow_copy_rtx (x);
y = shallow_copy_rtx (y);
set_mem_size (x, size);
@@ -1313,7 +1269,7 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align,
for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
- enum insn_code code = movmem_optab[(int) mode];
+ enum insn_code code = direct_optab_handler (movmem_optab, mode);
insn_operand_predicate_fn pred;
if (code != CODE_FOR_nothing
@@ -2352,7 +2308,7 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len,
if (mode == VOIDmode)
break;
- icode = optab_handler (mov_optab, mode)->insn_code;
+ icode = optab_handler (mov_optab, mode);
if (icode != CODE_FOR_nothing
&& align >= GET_MODE_ALIGNMENT (mode))
{
@@ -2565,7 +2521,7 @@ store_by_pieces_1 (struct store_by_pieces_d *data ATTRIBUTE_UNUSED,
if (mode == VOIDmode)
break;
- icode = optab_handler (mov_optab, mode)->insn_code;
+ icode = optab_handler (mov_optab, mode);
if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
store_by_pieces_2 (GEN_FCN (icode), mode, data);
@@ -2789,7 +2745,7 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align,
for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
- enum insn_code code = setmem_optab[(int) mode];
+ enum insn_code code = direct_optab_handler (setmem_optab, mode);
insn_operand_predicate_fn pred;
if (code != CODE_FOR_nothing
@@ -3034,7 +2990,7 @@ emit_move_via_integer (enum machine_mode mode, rtx x, rtx y, bool force)
return NULL_RTX;
/* The target must support moves in this mode. */
- code = optab_handler (mov_optab, imode)->insn_code;
+ code = optab_handler (mov_optab, imode);
if (code == CODE_FOR_nothing)
return NULL_RTX;
@@ -3184,7 +3140,7 @@ emit_move_complex (enum machine_mode mode, rtx x, rtx y)
/* Move floating point as parts. */
if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
- && optab_handler (mov_optab, GET_MODE_INNER (mode))->insn_code != CODE_FOR_nothing)
+ && optab_handler (mov_optab, GET_MODE_INNER (mode)) != CODE_FOR_nothing)
try_int = false;
/* Not possible if the values are inherently not adjacent. */
else if (GET_CODE (x) == CONCAT || GET_CODE (y) == CONCAT)
@@ -3235,7 +3191,7 @@ emit_move_ccmode (enum machine_mode mode, rtx x, rtx y)
/* Assume all MODE_CC modes are equivalent; if we have movcc, use it. */
if (mode != CCmode)
{
- enum insn_code code = optab_handler (mov_optab, CCmode)->insn_code;
+ enum insn_code code = optab_handler (mov_optab, CCmode);
if (code != CODE_FOR_nothing)
{
x = emit_move_change_mode (CCmode, mode, x, true);
@@ -3375,7 +3331,7 @@ emit_move_insn_1 (rtx x, rtx y)
gcc_assert ((unsigned int) mode < (unsigned int) MAX_MACHINE_MODE);
- code = optab_handler (mov_optab, mode)->insn_code;
+ code = optab_handler (mov_optab, mode);
if (code != CODE_FOR_nothing)
return emit_insn (GEN_FCN (code) (x, y));
@@ -3627,7 +3583,7 @@ emit_single_push_insn (enum machine_mode mode, rtx x, tree type)
stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
/* If there is push pattern, use it. Otherwise try old way of throwing
MEM representing push operation to move expander. */
- icode = optab_handler (push_optab, mode)->insn_code;
+ icode = optab_handler (push_optab, mode);
if (icode != CODE_FOR_nothing)
{
if (((pred = insn_data[(int) icode].operand[0].predicate)
@@ -4213,6 +4169,10 @@ expand_assignment (tree to, tree from, bool nontemporal)
an array element in an unaligned packed structure field, has the same
problem. */
if (handled_component_p (to)
+ /* ??? We only need to handle MEM_REF here if the access is not
+ a full access of the base object. */
+ || (TREE_CODE (to) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (to, 0)) == ADDR_EXPR)
|| TREE_CODE (TREE_TYPE (to)) == ARRAY_TYPE)
{
enum machine_mode mode1;
@@ -4359,7 +4319,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
set_mem_attributes (mem, to, 0);
set_mem_addr_space (mem, as);
- icode = movmisalign_optab->handlers[mode].insn_code;
+ icode = optab_handler (movmisalign_optab, mode);
gcc_assert (icode != CODE_FOR_nothing);
op_mode1 = insn_data[icode].operand[1].mode;
@@ -4492,7 +4452,7 @@ bool
emit_storent_insn (rtx to, rtx from)
{
enum machine_mode mode = GET_MODE (to), imode;
- enum insn_code code = optab_handler (storent_optab, mode)->insn_code;
+ enum insn_code code = optab_handler (storent_optab, mode);
rtx pattern;
if (code == CODE_FOR_nothing)
@@ -4686,6 +4646,51 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)
BLOCK_OP_NORMAL);
return NULL_RTX;
}
+ else if (TREE_CODE (exp) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == STRING_CST
+ && integer_zerop (TREE_OPERAND (exp, 1))
+ && !nontemporal && !call_param_p
+ && TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
+ {
+ /* Optimize initialization of an array with a STRING_CST. */
+ HOST_WIDE_INT exp_len, str_copy_len;
+ rtx dest_mem;
+ tree str = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+
+ exp_len = int_expr_size (exp);
+ if (exp_len <= 0)
+ goto normal_expr;
+
+ str_copy_len = strlen (TREE_STRING_POINTER (str));
+ if (str_copy_len < TREE_STRING_LENGTH (str) - 1)
+ goto normal_expr;
+
+ str_copy_len = TREE_STRING_LENGTH (str);
+ if ((STORE_MAX_PIECES & (STORE_MAX_PIECES - 1)) == 0)
+ {
+ str_copy_len += STORE_MAX_PIECES - 1;
+ str_copy_len &= ~(STORE_MAX_PIECES - 1);
+ }
+ str_copy_len = MIN (str_copy_len, exp_len);
+ if (!can_store_by_pieces (str_copy_len, builtin_strncpy_read_str,
+ CONST_CAST(char *, TREE_STRING_POINTER (str)),
+ MEM_ALIGN (target), false))
+ goto normal_expr;
+
+ dest_mem = target;
+
+ dest_mem = store_by_pieces (dest_mem,
+ str_copy_len, builtin_strncpy_read_str,
+ CONST_CAST(char *, TREE_STRING_POINTER (str)),
+ MEM_ALIGN (target), false,
+ exp_len > str_copy_len ? 1 : 0);
+ if (exp_len > str_copy_len)
+ clear_storage (adjust_address (dest_mem, BLKmode, 0),
+ GEN_INT (exp_len - str_copy_len),
+ BLOCK_OP_NORMAL);
+ return NULL_RTX;
+ }
else
{
rtx tmp_target;
@@ -5048,7 +5053,7 @@ count_type_elements (const_tree type, bool allow_flexarr)
HOST_WIDE_INT n = 0, t;
tree f;
- for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
+ for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
if (TREE_CODE (f) == FIELD_DECL)
{
t = count_type_elements (TREE_TYPE (f), false);
@@ -5057,7 +5062,7 @@ count_type_elements (const_tree type, bool allow_flexarr)
/* Check for structures with flexible array member. */
tree tf = TREE_TYPE (f);
if (allow_flexarr
- && TREE_CHAIN (f) == NULL
+ && DECL_CHAIN (f) == NULL
&& TREE_CODE (tf) == ARRAY_TYPE
&& TYPE_DOMAIN (tf)
&& TYPE_MIN_VALUE (TYPE_DOMAIN (tf))
@@ -5654,7 +5659,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
{
enum machine_mode mode = GET_MODE (target);
- icode = (int) optab_handler (vec_init_optab, mode)->insn_code;
+ icode = (int) optab_handler (vec_init_optab, mode);
if (icode != CODE_FOR_nothing)
{
unsigned int i;
@@ -5852,7 +5857,15 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
operations. */
|| (bitsize >= 0
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
- && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0))
+ && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0)
+ /* If we are expanding a MEM_REF of a non-BLKmode non-addressable
+ decl we must use bitfield operations. */
+ || (bitsize >= 0
+ && TREE_CODE (exp) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
+ && DECL_P (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
+ && !TREE_ADDRESSABLE (TREE_OPERAND (TREE_OPERAND (exp, 0),0 ))
+ && DECL_MODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) != BLKmode))
{
rtx temp;
gimple nop_def;
@@ -6113,6 +6126,24 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
goto done;
break;
+ case MEM_REF:
+ /* Hand back the decl for MEM[&decl, off]. */
+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
+ {
+ tree off = TREE_OPERAND (exp, 1);
+ if (!integer_zerop (off))
+ {
+ double_int boff, coff = mem_ref_offset (exp);
+ boff = double_int_lshift (coff,
+ BITS_PER_UNIT == 8
+ ? 3 : exact_log2 (BITS_PER_UNIT),
+ HOST_BITS_PER_DOUBLE_INT, true);
+ bit_offset = double_int_add (bit_offset, boff);
+ }
+ exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ }
+ goto done;
+
default:
goto done;
}
@@ -6628,7 +6659,6 @@ safe_from_p (const_rtx x, tree exp, int top_p)
break;
case MISALIGNED_INDIRECT_REF:
- case ALIGN_INDIRECT_REF:
case INDIRECT_REF:
if (MEM_P (x)
&& alias_sets_conflict_p (MEM_ALIAS_SET (x),
@@ -6796,8 +6826,7 @@ emutls_var_address (tree var)
tree emuvar = emutls_decl (var);
tree fn = built_in_decls [BUILT_IN_EMUTLS_GET_ADDRESS];
tree arg = build_fold_addr_expr_with_type (emuvar, ptr_type_node);
- tree arglist = build_tree_list (NULL_TREE, arg);
- tree call = build_function_call_expr (UNKNOWN_LOCATION, fn, arglist);
+ tree call = build_call_expr (fn, 1, arg);
return fold_convert (build_pointer_type (TREE_TYPE (var)), call);
}
@@ -6873,6 +6902,16 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
/* This case will happen via recursion for &a->b. */
return expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
+ case MEM_REF:
+ {
+ tree tem = TREE_OPERAND (exp, 0);
+ if (!integer_zerop (TREE_OPERAND (exp, 1)))
+ tem = build2 (POINTER_PLUS_EXPR, TREE_TYPE (TREE_OPERAND (exp, 1)),
+ tem,
+ double_int_to_tree (sizetype, mem_ref_offset (exp)));
+ return expand_expr (tem, target, tmode, modifier);
+ }
+
case CONST_DECL:
/* Expand the initializer like constants above. */
return XEXP (expand_expr_constant (DECL_INITIAL (exp), 0, modifier), 0);
@@ -7619,7 +7658,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
this_optab = usmul_widen_optab;
if (mode == GET_MODE_2XWIDER_MODE (innermode))
{
- if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
+ if (optab_handler (this_optab, mode) != CODE_FOR_nothing)
{
if (TYPE_UNSIGNED (TREE_TYPE (treeop0)))
expand_operands (treeop0, treeop1, subtarget, &op0, &op1,
@@ -7645,7 +7684,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
if (mode == GET_MODE_2XWIDER_MODE (innermode))
{
- if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
+ if (optab_handler (this_optab, mode) != CODE_FOR_nothing)
{
expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1,
EXPAND_NORMAL);
@@ -7653,7 +7692,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
unsignedp, this_optab);
return REDUCE_BIT_FIELD (temp);
}
- if (optab_handler (other_optab, mode)->insn_code != CODE_FOR_nothing
+ if (optab_handler (other_optab, mode) != CODE_FOR_nothing
&& innermode == word_mode)
{
rtx htem, hipart;
@@ -8594,12 +8633,10 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
return expand_constructor (exp, target, modifier, false);
case MISALIGNED_INDIRECT_REF:
- case ALIGN_INDIRECT_REF:
case INDIRECT_REF:
{
tree exp1 = treeop0;
addr_space_t as = ADDR_SPACE_GENERIC;
- enum machine_mode address_mode = Pmode;
if (modifier != EXPAND_WRITE)
{
@@ -8611,21 +8648,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
}
if (POINTER_TYPE_P (TREE_TYPE (exp1)))
- {
- as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp1)));
- address_mode = targetm.addr_space.address_mode (as);
- }
+ as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp1)));
op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
op0 = memory_address_addr_space (mode, op0, as);
- if (code == ALIGN_INDIRECT_REF)
- {
- int align = TYPE_ALIGN_UNIT (type);
- op0 = gen_rtx_AND (address_mode, op0, GEN_INT (-align));
- op0 = memory_address_addr_space (mode, op0, as);
- }
-
temp = gen_rtx_MEM (mode, op0);
set_mem_attributes (temp, exp, 0);
@@ -8642,7 +8669,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|| modifier == EXPAND_STACK_PARM);
/* The vectorizer should have already checked the mode. */
- icode = optab_handler (movmisalign_optab, mode)->insn_code;
+ icode = optab_handler (movmisalign_optab, mode);
gcc_assert (icode != CODE_FOR_nothing);
/* We've already validated the memory, and we're creating a
@@ -8684,6 +8711,74 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
}
return temp;
+ case MEM_REF:
+ {
+ addr_space_t as
+ = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1))));
+ enum machine_mode address_mode;
+ tree base = TREE_OPERAND (exp, 0);
+ gimple def_stmt;
+ /* Handle expansion of non-aliased memory with non-BLKmode. That
+ might end up in a register. */
+ if (TREE_CODE (base) == ADDR_EXPR)
+ {
+ HOST_WIDE_INT offset = mem_ref_offset (exp).low;
+ tree bit_offset;
+ base = TREE_OPERAND (base, 0);
+ if (!DECL_P (base))
+ {
+ HOST_WIDE_INT off;
+ base = get_addr_base_and_unit_offset (base, &off);
+ gcc_assert (base);
+ offset += off;
+ }
+ /* If we are expanding a MEM_REF of a non-BLKmode non-addressable
+ decl we must use bitfield operations. */
+ if (DECL_P (base)
+ && !TREE_ADDRESSABLE (base)
+ && DECL_MODE (base) != BLKmode
+ && DECL_RTL_SET_P (base)
+ && !MEM_P (DECL_RTL (base)))
+ {
+ tree bftype;
+ if (offset == 0
+ && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
+ && (GET_MODE_BITSIZE (DECL_MODE (base))
+ == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp)))))
+ return expand_expr (build1 (VIEW_CONVERT_EXPR,
+ TREE_TYPE (exp), base),
+ target, tmode, modifier);
+ bit_offset = bitsize_int (offset * BITS_PER_UNIT);
+ bftype = TREE_TYPE (base);
+ if (TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
+ bftype = TREE_TYPE (exp);
+ return expand_expr (build3 (BIT_FIELD_REF, bftype,
+ base,
+ TYPE_SIZE (TREE_TYPE (exp)),
+ bit_offset),
+ target, tmode, modifier);
+ }
+ }
+ address_mode = targetm.addr_space.address_mode (as);
+ base = TREE_OPERAND (exp, 0);
+ if ((def_stmt = get_def_for_expr (base, BIT_AND_EXPR)))
+ base = build2 (BIT_AND_EXPR, TREE_TYPE (base),
+ gimple_assign_rhs1 (def_stmt),
+ gimple_assign_rhs2 (def_stmt));
+ if (!integer_zerop (TREE_OPERAND (exp, 1)))
+ base = build2 (POINTER_PLUS_EXPR, TREE_TYPE (base),
+ base, double_int_to_tree (sizetype,
+ mem_ref_offset (exp)));
+ op0 = expand_expr (base, NULL_RTX, address_mode, EXPAND_SUM);
+ op0 = memory_address_addr_space (mode, op0, as);
+ temp = gen_rtx_MEM (mode, op0);
+ set_mem_attributes (temp, exp, 0);
+ set_mem_addr_space (temp, as);
+ if (TREE_THIS_VOLATILE (exp))
+ MEM_VOLATILE_P (temp) = 1;
+ return temp;
+ }
+
case ARRAY_REF:
{
@@ -10145,39 +10240,6 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
return 1;
}
-/* Nonzero if the mode is a valid vector mode for this architecture.
- This returns nonzero even if there is no hardware support for the
- vector mode, but we can emulate with narrower modes. */
-
-int
-vector_mode_valid_p (enum machine_mode mode)
-{
- enum mode_class mclass = GET_MODE_CLASS (mode);
- enum machine_mode innermode;
-
- /* Doh! What's going on? */
- if (mclass != MODE_VECTOR_INT
- && mclass != MODE_VECTOR_FLOAT
- && mclass != MODE_VECTOR_FRACT
- && mclass != MODE_VECTOR_UFRACT
- && mclass != MODE_VECTOR_ACCUM
- && mclass != MODE_VECTOR_UACCUM)
- return 0;
-
- /* Hardware support. Woo hoo! */
- if (targetm.vector_mode_supported_p (mode))
- return 1;
-
- innermode = GET_MODE_INNER (mode);
-
- /* We should probably return 1 if requesting V4DI and we have no DI,
- but we have V2DI, but this is probably very unlikely. */
-
- /* If we have support for the inner mode, we can safely emulate it.
- We may not have V2DI, but me can emulate with a pair of DIs. */
- return targetm.scalar_mode_supported_p (innermode);
-}
-
/* Return a CONST_VECTOR rtx for a VECTOR_CST tree. */
static rtx
const_vector_from_tree (tree exp)