the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
#include "config.h"
#include "system.h"
#include "machmode.h"
#include "insn-flags.h"
#include "insn-codes.h"
#include "insn-config.h"
-/* Include expr.h after insn-config.h so we get HAVE_conditional_move. */
+/* Include expr.h after insn-config.h so we get HAVE_conditional_move. */
#include "expr.h"
#include "recog.h"
+#include "reload.h"
#include "output.h"
#include "typeclass.h"
#include "defaults.h"
#include "toplev.h"
#include "ggc.h"
+#include "intl.h"
#include "tm_p.h"
+#ifndef ACCUMULATE_OUTGOING_ARGS
+#define ACCUMULATE_OUTGOING_ARGS 0
+#endif
+
+/* Supply a default definition for PUSH_ARGS. */
+#ifndef PUSH_ARGS
+#ifdef PUSH_ROUNDING
+#define PUSH_ARGS !ACCUMULATE_OUTGOING_ARGS
+#else
+#define PUSH_ARGS 0
+#endif
+#endif
+
/* Decide whether a function's arguments should be processed
from first to last or from last to first.
#ifdef PUSH_ROUNDING
#if defined (STACK_GROWS_DOWNWARD) != defined (ARGS_GROW_DOWNWARD)
-#define PUSH_ARGS_REVERSED /* If it's last to first */
+#define PUSH_ARGS_REVERSED /* If it's last to first. */
#endif
#endif
#define CASE_VECTOR_PC_RELATIVE 0
#endif
+/* Hook called by safe_from_p for language-specific tree codes. It is
+ up to the language front-end to install a hook if it has any such
+ codes that safe_from_p needs to know about. Since same_from_p will
+ recursively explore the TREE_OPERANDs of an expression, this hook
+ should not reexamine those pieces. This routine may recursively
+ call safe_from_p; it should always pass `0' as the TOP_P
+ parameter. */
+int (*lang_safe_from_p) PARAMS ((rtx, tree));
+
/* If this is nonzero, we do not bother generating VOLATILE
around volatile memory references, and we are willing to
output indirect addresses. If cse is to follow, we reject
rtx to_addr;
int autinc_to;
int explicit_inc_to;
- int to_struct;
- int to_readonly;
rtx from;
rtx from_addr;
int autinc_from;
int explicit_inc_from;
- int from_struct;
- int from_readonly;
- int len;
- int offset;
+ unsigned HOST_WIDE_INT len;
+ HOST_WIDE_INT offset;
int reverse;
};
rtx to_addr;
int autinc_to;
int explicit_inc_to;
- int to_struct;
- int len;
- int offset;
+ unsigned HOST_WIDE_INT len;
+ HOST_WIDE_INT offset;
int reverse;
};
static rtx get_push_address PARAMS ((int));
static rtx enqueue_insn PARAMS ((rtx, rtx));
-static int move_by_pieces_ninsns PARAMS ((unsigned int, unsigned int));
+static unsigned HOST_WIDE_INT move_by_pieces_ninsns
+ PARAMS ((unsigned HOST_WIDE_INT,
+ unsigned int));
static void move_by_pieces_1 PARAMS ((rtx (*) (rtx, ...), enum machine_mode,
struct move_by_pieces *));
-static void clear_by_pieces PARAMS ((rtx, int, unsigned int));
+static void clear_by_pieces PARAMS ((rtx, unsigned HOST_WIDE_INT,
+ unsigned int));
static void clear_by_pieces_1 PARAMS ((rtx (*) (rtx, ...),
enum machine_mode,
struct clear_by_pieces *));
+static rtx get_subtarget PARAMS ((rtx));
static int is_zeros_p PARAMS ((tree));
static int mostly_zeros_p PARAMS ((tree));
-static void store_constructor_field PARAMS ((rtx, int, int, enum machine_mode,
- tree, tree, unsigned int, int));
-static void store_constructor PARAMS ((tree, rtx, unsigned int, int, int));
-static rtx store_field PARAMS ((rtx, int, int, enum machine_mode,
+static void store_constructor_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
+ HOST_WIDE_INT, enum machine_mode,
+ tree, tree, unsigned int, int,
+ int));
+static void store_constructor PARAMS ((tree, rtx, unsigned int, int,
+ HOST_WIDE_INT));
+static rtx store_field PARAMS ((rtx, HOST_WIDE_INT,
+ HOST_WIDE_INT, enum machine_mode,
tree, enum machine_mode, int,
- unsigned int, int, int));
+ unsigned int, HOST_WIDE_INT, int));
static enum memory_use_mode
get_memory_usage_from_modifier PARAMS ((enum expand_modifier));
static tree save_noncopied_parts PARAMS ((tree, tree));
static tree init_noncopied_parts PARAMS ((tree, tree));
-static int safe_from_p PARAMS ((rtx, tree, int));
static int fixed_type_p PARAMS ((tree));
static rtx var_rtx PARAMS ((tree));
static int readonly_fields_p PARAMS ((tree));
static void preexpand_calls PARAMS ((tree));
static void do_jump_by_parts_greater PARAMS ((tree, int, rtx, rtx));
static void do_jump_by_parts_equality PARAMS ((tree, rtx, rtx));
-static void do_compare_and_jump PARAMS ((tree, enum rtx_code, enum rtx_code, rtx, rtx));
+static void do_compare_and_jump PARAMS ((tree, enum rtx_code, enum rtx_code,
+ rtx, rtx));
static rtx do_store_flag PARAMS ((tree, rtx, enum machine_mode, int));
/* Record for each mode whether we can move a register directly to or
#if defined (HAVE_movstrqi) || defined (HAVE_movstrhi) || defined (HAVE_movstrsi) || defined (HAVE_movstrdi) || defined (HAVE_movstrti)
#define MOVE_RATIO 2
#else
-/* If we are optimizing for space (-Os), cut down the default move ratio */
+/* If we are optimizing for space (-Os), cut down the default move ratio. */
#define MOVE_RATIO (optimize_size ? 3 : 15)
#endif
#endif
/* This macro is used to determine whether move_by_pieces should be called
- to perform a structure copy. */
+ to perform a structure copy. */
#ifndef MOVE_BY_PIECES_P
-#define MOVE_BY_PIECES_P(SIZE, ALIGN) (move_by_pieces_ninsns \
- (SIZE, ALIGN) < MOVE_RATIO)
+#define MOVE_BY_PIECES_P(SIZE, ALIGN) \
+ (move_by_pieces_ninsns (SIZE, ALIGN) < MOVE_RATIO)
#endif
/* This array records the insn_code of insns to perform block moves. */
pending_chain = 0;
pending_stack_adjust = 0;
+ stack_pointer_delta = 0;
inhibit_defer_pop = 0;
saveregs_value = 0;
apply_args_value = 0;
}
/* Small sanity check that the queue is empty at the end of a function. */
+
void
finish_expr_for_function ()
{
register rtx y = XEXP (x, 0);
register rtx new = gen_rtx_MEM (GET_MODE (x), QUEUED_VAR (y));
- RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
MEM_COPY_ATTRIBUTES (new, x);
- MEM_ALIAS_SET (new) = MEM_ALIAS_SET (x);
if (QUEUED_INSN (y))
{
return;
}
+ if (VECTOR_MODE_P (to_mode) || VECTOR_MODE_P (from_mode))
+ {
+ if (GET_MODE_BITSIZE (from_mode) != GET_MODE_BITSIZE (to_mode))
+ abort ();
+
+ if (VECTOR_MODE_P (to_mode))
+ from = gen_rtx_SUBREG (to_mode, from, 0);
+ else
+ to = gen_rtx_SUBREG (from_mode, to, 0);
+
+ emit_move_insn (to, from);
+ return;
+ }
+
+ if (to_real != from_real)
+ abort ();
+
if (to_real)
{
- rtx value;
+ rtx value, insns;
if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode))
{
return;
}
}
-
+
#ifdef HAVE_trunchfqf2
if (HAVE_trunchfqf2 && from_mode == HFmode && to_mode == QFmode)
{
case TFmode:
libcall = extendsftf2_libfunc;
break;
-
+
default:
break;
}
case TFmode:
libcall = extenddftf2_libfunc;
break;
-
+
default:
break;
}
case DFmode:
libcall = truncxfdf2_libfunc;
break;
-
+
default:
break;
}
case DFmode:
libcall = trunctfdf2_libfunc;
break;
-
+
default:
break;
}
break;
-
+
default:
break;
}
/* This conversion is not implemented yet. */
abort ();
- value = emit_library_call_value (libcall, NULL_RTX, 1, to_mode,
+ start_sequence ();
+ value = emit_library_call_value (libcall, NULL_RTX, LCT_CONST, to_mode,
1, from, from_mode);
- emit_move_insn (to, value);
+ insns = get_insns ();
+ end_sequence ();
+ emit_libcall_block (insns, to, value, gen_rtx_FLOAT_TRUNCATE (to_mode,
+ from));
return;
}
return;
}
- /* Handle pointer conversion */ /* SPEE 900220 */
+ /* Handle pointer conversion. */ /* SPEE 900220. */
if (to_mode == PQImode)
{
if (from_mode != QImode)
else
{
#ifdef HAVE_extendpsisi2
- if (HAVE_extendpsisi2)
+ if (! unsignedp && HAVE_extendpsisi2)
{
emit_unop_insn (CODE_FOR_extendpsisi2, to, from, UNKNOWN);
return;
}
#endif /* HAVE_extendpsisi2 */
+#ifdef HAVE_zero_extendpsisi2
+ if (unsignedp && HAVE_zero_extendpsisi2)
+ {
+ emit_unop_insn (CODE_FOR_zero_extendpsisi2, to, from, UNKNOWN);
+ return;
+ }
+#endif /* HAVE_zero_extendpsisi2 */
abort ();
}
}
}
/* No suitable intermediate mode.
- Generate what we need with shifts. */
+ Generate what we need with shifts. */
shift_amount = build_int_2 (GET_MODE_BITSIZE (to_mode)
- GET_MODE_BITSIZE (from_mode), 0);
from = gen_lowpart (to_mode, force_reg (from_mode, from));
tmp = expand_shift (LSHIFT_EXPR, to_mode, from, shift_amount,
to, unsignedp);
- tmp = expand_shift (RSHIFT_EXPR, to_mode, tmp, shift_amount,
+ tmp = expand_shift (RSHIFT_EXPR, to_mode, tmp, shift_amount,
to, unsignedp);
if (tmp != to)
emit_move_insn (to, tmp);
}
}
- /* Support special truncate insns for certain modes. */
+ /* Support special truncate insns for certain modes. */
if (from_mode == DImode && to_mode == SImode)
{
if (GET_MODE (x) != VOIDmode)
oldmode = GET_MODE (x);
-
+
if (mode == oldmode)
return x;
return temp;
}
\f
-
/* This macro is used to determine what the largest unit size that
- move_by_pieces can use is. */
+ move_by_pieces can use is. */
/* MOVE_MAX_PIECES is the number of bytes at a time which we can
move efficiently, as opposed to MOVE_MAX which is the maximum
- number of bhytes we can move with a single instruction. */
+ number of bytes we can move with a single instruction. */
#ifndef MOVE_MAX_PIECES
#define MOVE_MAX_PIECES MOVE_MAX
from block FROM to block TO. (These are MEM rtx's with BLKmode).
The caller must pass FROM and TO
through protect_from_queue before calling.
- ALIGN (in bytes) is maximum alignment we can assume. */
+ ALIGN is maximum alignment we can assume. */
void
move_by_pieces (to, from, len, align)
rtx to, from;
- int len;
+ unsigned HOST_WIDE_INT len;
unsigned int align;
{
struct move_by_pieces data;
rtx to_addr = XEXP (to, 0), from_addr = XEXP (from, 0);
- int max_size = MOVE_MAX_PIECES + 1;
+ unsigned int max_size = MOVE_MAX_PIECES + 1;
enum machine_mode mode = VOIDmode, tmode;
enum insn_code icode;
if (data.reverse) data.offset = len;
data.len = len;
- data.to_struct = MEM_IN_STRUCT_P (to);
- data.from_struct = MEM_IN_STRUCT_P (from);
- data.to_readonly = RTX_UNCHANGING_P (to);
- data.from_readonly = RTX_UNCHANGING_P (from);
-
/* If copying requires more than two move insns,
copy addresses to registers (to make displacements shorter)
and use post-increment if available. */
if (!(data.autinc_from && data.autinc_to)
&& move_by_pieces_ninsns (len, align) > 2)
{
- /* Find the mode of the largest move... */
+ /* Find the mode of the largest move... */
for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
if (GET_MODE_SIZE (tmode) < max_size)
}
if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
- || align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
- align = MOVE_MAX;
+ || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
+ align = MOVE_MAX * BITS_PER_UNIT;
/* First move what we can in the largest integer mode, then go to
successively smaller modes. */
break;
icode = mov_optab->handlers[(int) mode].insn_code;
- if (icode != CODE_FOR_nothing
- && align >= MIN (BIGGEST_ALIGNMENT / BITS_PER_UNIT,
- (unsigned int) GET_MODE_SIZE (mode)))
+ if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
move_by_pieces_1 (GEN_FCN (icode), mode, &data);
max_size = GET_MODE_SIZE (mode);
/* Return number of insns required to move L bytes by pieces.
ALIGN (in bytes) is maximum alignment we can assume. */
-static int
+static unsigned HOST_WIDE_INT
move_by_pieces_ninsns (l, align)
- unsigned int l;
+ unsigned HOST_WIDE_INT l;
unsigned int align;
{
- register int n_insns = 0;
- int max_size = MOVE_MAX + 1;
+ unsigned HOST_WIDE_INT n_insns = 0;
+ unsigned HOST_WIDE_INT max_size = MOVE_MAX + 1;
if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
- || align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
- align = MOVE_MAX;
+ || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
+ align = MOVE_MAX * BITS_PER_UNIT;
while (max_size > 1)
{
break;
icode = mov_optab->handlers[(int) mode].insn_code;
- if (icode != CODE_FOR_nothing
- && align >= GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT)
+ if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
n_insns += l / GET_MODE_SIZE (mode), l %= GET_MODE_SIZE (mode);
max_size = GET_MODE_SIZE (mode);
enum machine_mode mode;
struct move_by_pieces *data;
{
- register int size = GET_MODE_SIZE (mode);
- register rtx to1, from1;
+ unsigned int size = GET_MODE_SIZE (mode);
+ rtx to1, from1;
while (data->len >= size)
{
- if (data->reverse) data->offset -= size;
-
- to1 = (data->autinc_to
- ? gen_rtx_MEM (mode, data->to_addr)
- : copy_rtx (change_address (data->to, mode,
- plus_constant (data->to_addr,
- data->offset))));
- MEM_IN_STRUCT_P (to1) = data->to_struct;
- RTX_UNCHANGING_P (to1) = data->to_readonly;
-
- from1
- = (data->autinc_from
- ? gen_rtx_MEM (mode, data->from_addr)
- : copy_rtx (change_address (data->from, mode,
- plus_constant (data->from_addr,
- data->offset))));
- MEM_IN_STRUCT_P (from1) = data->from_struct;
- RTX_UNCHANGING_P (from1) = data->from_readonly;
+ if (data->reverse)
+ data->offset -= size;
+
+ if (data->autinc_to)
+ {
+ to1 = gen_rtx_MEM (mode, data->to_addr);
+ MEM_COPY_ATTRIBUTES (to1, data->to);
+ }
+ else
+ to1 = change_address (data->to, mode,
+ plus_constant (data->to_addr, data->offset));
+
+ if (data->autinc_from)
+ {
+ from1 = gen_rtx_MEM (mode, data->from_addr);
+ MEM_COPY_ATTRIBUTES (from1, data->from);
+ }
+ else
+ from1 = change_address (data->from, mode,
+ plus_constant (data->from_addr, data->offset));
if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));
emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size)));
emit_insn ((*genfun) (to1, from1));
+
if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
if (HAVE_POST_INCREMENT && data->explicit_inc_from > 0)
emit_insn (gen_add2_insn (data->from_addr, GEN_INT (size)));
- if (! data->reverse) data->offset += size;
+ if (! data->reverse)
+ data->offset += size;
data->len -= size;
}
Both X and Y must be MEM rtx's (perhaps inside VOLATILE)
with mode BLKmode.
SIZE is an rtx that says how long they are.
- ALIGN is the maximum alignment we can assume they have,
- measured in bytes.
+ ALIGN is the maximum alignment we can assume they have.
Return the address of the new block, if memcpy is called and returns it,
0 otherwise. */
including more than one in the machine description unless
the more limited one has some advantage. */
- rtx opalign = GEN_INT (align);
+ rtx opalign = GEN_INT (align / BITS_PER_UNIT);
enum machine_mode mode;
+ /* Since this is a move insn, we don't care about volatility. */
+ volatile_ok = 1;
+
for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
if (pat)
{
emit_insn (pat);
+ volatile_ok = 0;
return 0;
}
else
}
}
+ volatile_ok = 0;
+
/* X, Y, or SIZE may have been passed through protect_from_queue.
It is unsafe to save the value generated by protect_from_queue
To avoid this problem we go ahead and emit code to copy X, Y &
SIZE into new pseudos. We can then place those new pseudos
into an RTL_EXPR and use them later, even after a call to
- emit_queue.
+ emit_queue.
Note this is not strictly needed for library calls since they
do not call emit_queue before loading their arguments. However,
examine the return value from memcpy.
For targets where libcalls and normal calls have different conventions
- for returning pointers, we could end up generating incorrect code.
+ for returning pointers, we could end up generating incorrect code.
So instead of using a libcall sequence we build up a suitable
CALL_EXPR and expand the call in the normal fashion. */
fntype = build_pointer_type (void_type_node);
fntype = build_function_type (fntype, NULL_TREE);
fn = build_decl (FUNCTION_DECL, fn, fntype);
- ggc_add_tree_root (&fn, 1);
+ ggc_add_tree_root (&fn, 1);
DECL_EXTERNAL (fn) = 1;
TREE_PUBLIC (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
pop_obstacks ();
}
- /* We need to make an argument list for the function call.
+ /* We need to make an argument list for the function call.
memcpy has three arguments, the first two are void * addresses and
the last is a size_t byte count for the copy. */
retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
#else
- emit_library_call (bcopy_libfunc, 0,
+ emit_library_call (bcopy_libfunc, LCT_NORMAL,
VOIDmode, 3, y, Pmode, x, Pmode,
convert_to_mode (TYPE_MODE (integer_type_node), size,
TREE_UNSIGNED (integer_type_node)),
{
int i;
#ifdef HAVE_load_multiple
- rtx pat;
+ rtx pat;
rtx last;
#endif
The number of registers to be filled is NREGS. SIZE indicates the number
of bytes in the object X. */
-
void
move_block_from_reg (regno, x, nregs, size)
int regno;
{
int i;
#ifdef HAVE_store_multiple
- rtx pat;
+ rtx pat;
rtx last;
#endif
enum machine_mode mode;
gen_rtx_REG (mode, regno));
return;
}
-
+
/* Blocks smaller than a word on a BYTES_BIG_ENDIAN machine must be aligned
to the left before storing to memory. Note that the previous test
doesn't handle all cases (e.g. SIZE == 3). */
else
start = 1;
- tmps = (rtx *) alloca (sizeof(rtx) * XVECLEN (dst, 0));
+ tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (dst, 0));
/* If we won't be loading directly from memory, protect the real source
from strange tricks we might play. */
src = orig_src;
- if (GET_CODE (src) != MEM)
+ if (GET_CODE (src) != MEM && ! CONSTANT_P (src))
{
- if (GET_CODE (src) == VOIDmode)
+ if (GET_MODE (src) == VOIDmode)
src = gen_reg_rtx (GET_MODE (dst));
else
src = gen_reg_rtx (GET_MODE (orig_src));
for (i = start; i < XVECLEN (dst, 0); i++)
{
enum machine_mode mode = GET_MODE (XEXP (XVECEXP (dst, 0, i), 0));
- int bytepos = INTVAL (XEXP (XVECEXP (dst, 0, i), 1));
- int bytelen = GET_MODE_SIZE (mode);
+ HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (dst, 0, i), 1));
+ unsigned int bytelen = GET_MODE_SIZE (mode);
int shift = 0;
/* Handle trailing fragments that run over the size of the struct. */
/* Optimize the access just a bit. */
if (GET_CODE (src) == MEM
- && align * BITS_PER_UNIT >= GET_MODE_ALIGNMENT (mode)
+ && align >= GET_MODE_ALIGNMENT (mode)
&& bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
&& bytelen == GET_MODE_SIZE (mode))
{
else
abort ();
}
+ else if ((CONSTANT_P (src)
+ && (GET_MODE (src) == VOIDmode || GET_MODE (src) == mode))
+ || (GET_CODE (src) == REG && GET_MODE (src) == mode))
+ tmps[i] = src;
else
- {
- tmps[i] = extract_bit_field (src, bytelen*BITS_PER_UNIT,
- bytepos*BITS_PER_UNIT, 1, NULL_RTX,
- mode, mode, align, ssize);
- }
+ tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT,
+ bytepos * BITS_PER_UNIT, 1, NULL_RTX,
+ mode, mode, align, ssize);
if (BYTES_BIG_ENDIAN && shift)
- {
- expand_binop (mode, ashl_optab, tmps[i], GEN_INT (shift),
- tmps[i], 0, OPTAB_WIDEN);
- }
+ expand_binop (mode, ashl_optab, tmps[i], GEN_INT (shift),
+ tmps[i], 0, OPTAB_WIDEN);
}
- emit_queue();
+
+ emit_queue ();
/* Copy the extracted pieces into the proper (probable) hard regs. */
for (i = start; i < XVECLEN (dst, 0); i++)
else
start = 1;
- tmps = (rtx *) alloca (sizeof(rtx) * XVECLEN (src, 0));
+ tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (src, 0));
/* Copy the (probable) hard regs into pseudos. */
for (i = start; i < XVECLEN (src, 0); i++)
tmps[i] = gen_reg_rtx (GET_MODE (reg));
emit_move_insn (tmps[i], reg);
}
- emit_queue();
+ emit_queue ();
/* If we won't be storing directly into memory, protect the real destination
from strange tricks we might play. */
/* Make life a bit easier for combine. */
emit_move_insn (dst, const0_rtx);
}
- else if (! MEM_IN_STRUCT_P (dst))
- {
- /* store_bit_field requires that memory operations have
- mem_in_struct_p set; we might not. */
-
- dst = copy_rtx (orig_dst);
- MEM_SET_IN_STRUCT_P (dst, 1);
- }
/* Process the pieces. */
for (i = start; i < XVECLEN (src, 0); i++)
{
- int bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1));
+ HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1));
enum machine_mode mode = GET_MODE (tmps[i]);
- int bytelen = GET_MODE_SIZE (mode);
+ unsigned int bytelen = GET_MODE_SIZE (mode);
/* Handle trailing fragments that run over the size of the struct. */
if (ssize >= 0 && bytepos + bytelen > ssize)
/* Optimize the access just a bit. */
if (GET_CODE (dst) == MEM
- && align * BITS_PER_UNIT >= GET_MODE_ALIGNMENT (mode)
+ && align >= GET_MODE_ALIGNMENT (mode)
&& bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
&& bytelen == GET_MODE_SIZE (mode))
emit_move_insn (change_address (dst, mode,
mode, tmps[i], align, ssize);
}
- emit_queue();
+ emit_queue ();
/* Copy from the pseudo into the (probable) hard reg. */
if (GET_CODE (dst) == REG)
The primary purpose of this routine is to handle functions
that return BLKmode structures in registers. Some machines
(the PA for example) want to return all small structures
- in registers regardless of the structure's alignment. */
+ in registers regardless of the structure's alignment. */
rtx
-copy_blkmode_from_reg (tgtblk,srcreg,type)
+copy_blkmode_from_reg (tgtblk, srcreg, type)
rtx tgtblk;
rtx srcreg;
tree type;
{
- int bytes = int_size_in_bytes (type);
- rtx src = NULL, dst = NULL;
- int bitsize = MIN (TYPE_ALIGN (type), BITS_PER_WORD);
- int bitpos, xbitpos, big_endian_correction = 0;
-
- if (tgtblk == 0)
- {
- tgtblk = assign_stack_temp (BLKmode, bytes, 0);
- MEM_SET_IN_STRUCT_P (tgtblk, AGGREGATE_TYPE_P (type));
- preserve_temp_slots (tgtblk);
- }
-
- /* This code assumes srcreg is at least a full word. If it isn't,
- copy it into a new pseudo which is a full word. */
- if (GET_MODE (srcreg) != BLKmode
- && GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
- srcreg = convert_to_mode (word_mode, srcreg,
- TREE_UNSIGNED (type));
-
- /* Structures whose size is not a multiple of a word are aligned
- to the least significant byte (to the right). On a BYTES_BIG_ENDIAN
- machine, this means we must skip the empty high order bytes when
- calculating the bit offset. */
- if (BYTES_BIG_ENDIAN && bytes % UNITS_PER_WORD)
- big_endian_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
- * BITS_PER_UNIT));
-
- /* Copy the structure BITSIZE bites at a time.
-
- 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. */
- for (bitpos = 0, xbitpos = big_endian_correction;
- bitpos < bytes * BITS_PER_UNIT;
- bitpos += bitsize, xbitpos += bitsize)
- {
-
- /* We need a new source operand each time xbitpos is on a
- word boundary and when xbitpos == big_endian_correction
- (the first time through). */
- if (xbitpos % BITS_PER_WORD == 0
- || xbitpos == big_endian_correction)
- src = operand_subword_force (srcreg,
- xbitpos / BITS_PER_WORD,
- BLKmode);
-
- /* We need a new destination operand each time bitpos is on
- a word boundary. */
- if (bitpos % BITS_PER_WORD == 0)
- 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,
- extract_bit_field (src, bitsize,
- xbitpos % BITS_PER_WORD, 1,
- NULL_RTX, word_mode,
- word_mode,
- bitsize / BITS_PER_UNIT,
- BITS_PER_WORD),
- bitsize / BITS_PER_UNIT, BITS_PER_WORD);
- }
- return tgtblk;
+ unsigned HOST_WIDE_INT bytes = int_size_in_bytes (type);
+ rtx src = NULL, dst = NULL;
+ unsigned HOST_WIDE_INT bitsize = MIN (TYPE_ALIGN (type), BITS_PER_WORD);
+ unsigned HOST_WIDE_INT bitpos, xbitpos, big_endian_correction = 0;
+
+ if (tgtblk == 0)
+ {
+ tgtblk = assign_stack_temp (BLKmode, bytes, 0);
+ MEM_SET_IN_STRUCT_P (tgtblk, AGGREGATE_TYPE_P (type));
+ preserve_temp_slots (tgtblk);
+ }
+
+ /* This code assumes srcreg is at least a full word. If it isn't,
+ copy it into a new pseudo which is a full word. */
+ if (GET_MODE (srcreg) != BLKmode
+ && GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
+ srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type));
+
+ /* Structures whose size is not a multiple of a word are aligned
+ to the least significant byte (to the right). On a BYTES_BIG_ENDIAN
+ machine, this means we must skip the empty high order bytes when
+ calculating the bit offset. */
+ if (BYTES_BIG_ENDIAN && bytes % UNITS_PER_WORD)
+ big_endian_correction
+ = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT));
+
+ /* Copy the structure BITSIZE bites at a time.
+
+ 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. */
+ for (bitpos = 0, xbitpos = big_endian_correction;
+ bitpos < bytes * BITS_PER_UNIT;
+ bitpos += bitsize, xbitpos += bitsize)
+ {
+ /* We need a new source operand each time xbitpos is on a
+ word boundary and when xbitpos == big_endian_correction
+ (the first time through). */
+ if (xbitpos % BITS_PER_WORD == 0
+ || xbitpos == big_endian_correction)
+ src = operand_subword_force (srcreg, xbitpos / BITS_PER_WORD, BLKmode);
+
+ /* We need a new destination operand each time bitpos is on
+ a word boundary. */
+ if (bitpos % BITS_PER_WORD == 0)
+ 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,
+ extract_bit_field (src, bitsize,
+ xbitpos % BITS_PER_WORD, 1,
+ NULL_RTX, word_mode, word_mode,
+ bitsize, BITS_PER_WORD),
+ bitsize, BITS_PER_WORD);
+ }
+
+ return tgtblk;
}
-
/* Add a USE expression for REG to the (possibly empty) list pointed
to by CALL_FUSAGE. REG must denote a hard register. */
{
if (GET_CODE (reg) != REG
|| REGNO (reg) >= FIRST_PSEUDO_REGISTER)
- abort();
+ abort ();
*call_fusage
= gen_rtx_EXPR_LIST (VOIDmode,
}
}
\f
-/* Generate several move instructions to clear LEN bytes of block TO.
- (A MEM rtx with BLKmode). The caller must pass TO through
- protect_from_queue before calling. ALIGN (in bytes) is maximum alignment
- we can assume. */
+/* Generate several move instructions to clear LEN bytes of block TO. (A MEM
+ rtx with BLKmode). The caller must pass TO through protect_from_queue
+ before calling. ALIGN is maximum alignment we can assume. */
static void
clear_by_pieces (to, len, align)
rtx to;
- int len;
+ unsigned HOST_WIDE_INT len;
unsigned int align;
{
struct clear_by_pieces data;
rtx to_addr = XEXP (to, 0);
- int max_size = MOVE_MAX_PIECES + 1;
+ unsigned HOST_WIDE_INT max_size = MOVE_MAX_PIECES + 1;
enum machine_mode mode = VOIDmode, tmode;
enum insn_code icode;
data.explicit_inc_to = 0;
data.reverse
= (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
- if (data.reverse) data.offset = len;
+ if (data.reverse)
+ data.offset = len;
data.len = len;
- data.to_struct = MEM_IN_STRUCT_P (to);
-
/* If copying requires more than two move insns,
copy addresses to registers (to make displacements shorter)
and use post-increment if available. */
if (!data.autinc_to
&& move_by_pieces_ninsns (len, align) > 2)
{
- /* Determine the main mode we'll be using */
+ /* Determine the main mode we'll be using. */
for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
if (GET_MODE_SIZE (tmode) < max_size)
data.autinc_to = 1;
data.explicit_inc_to = -1;
}
- if (USE_STORE_POST_INCREMENT (mode) && ! data.reverse && ! data.autinc_to)
+
+ if (USE_STORE_POST_INCREMENT (mode) && ! data.reverse
+ && ! data.autinc_to)
{
data.to_addr = copy_addr_to_reg (to_addr);
data.autinc_to = 1;
data.explicit_inc_to = 1;
}
- if (!data.autinc_to && CONSTANT_P (to_addr))
+
+ if ( !data.autinc_to && CONSTANT_P (to_addr))
data.to_addr = copy_addr_to_reg (to_addr);
}
if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
- || align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
- align = MOVE_MAX;
+ || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
+ align = MOVE_MAX * BITS_PER_UNIT;
/* First move what we can in the largest integer mode, then go to
successively smaller modes. */
break;
icode = mov_optab->handlers[(int) mode].insn_code;
- if (icode != CODE_FOR_nothing
- && align >= GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT)
+ if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
clear_by_pieces_1 (GEN_FCN (icode), mode, &data);
max_size = GET_MODE_SIZE (mode);
enum machine_mode mode;
struct clear_by_pieces *data;
{
- register int size = GET_MODE_SIZE (mode);
- register rtx to1;
+ unsigned int size = GET_MODE_SIZE (mode);
+ rtx to1;
while (data->len >= size)
{
- if (data->reverse) data->offset -= size;
+ if (data->reverse)
+ data->offset -= size;
- to1 = (data->autinc_to
- ? gen_rtx_MEM (mode, data->to_addr)
- : copy_rtx (change_address (data->to, mode,
- plus_constant (data->to_addr,
- data->offset))));
- MEM_IN_STRUCT_P (to1) = data->to_struct;
+ if (data->autinc_to)
+ {
+ to1 = gen_rtx_MEM (mode, data->to_addr);
+ MEM_COPY_ATTRIBUTES (to1, data->to);
+ }
+ else
+ to1 = change_address (data->to, mode,
+ plus_constant (data->to_addr, data->offset));
if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));
emit_insn ((*genfun) (to1, const0_rtx));
+
if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
- if (! data->reverse) data->offset += size;
+ if (! data->reverse)
+ data->offset += size;
data->len -= size;
}
}
\f
-/* Write zeros through the storage of OBJECT.
- If OBJECT has BLKmode, SIZE is its length in bytes and ALIGN is
- the maximum alignment we can is has, measured in bytes.
+/* Write zeros through the storage of OBJECT. If OBJECT has BLKmode, SIZE is
+ its length in bytes and ALIGN is the maximum alignment we can is has.
If we call a function that returns the length of the block, return it. */
#endif
rtx retval = 0;
- if (GET_MODE (object) == BLKmode)
+ /* If OBJECT is not BLKmode and SIZE is the same size as its mode,
+ just move a zero. Otherwise, do this a piece at a time. */
+ if (GET_MODE (object) != BLKmode
+ && GET_CODE (size) == CONST_INT
+ && GET_MODE_SIZE (GET_MODE (object)) == INTVAL (size))
+ emit_move_insn (object, CONST0_RTX (GET_MODE (object)));
+ else
{
object = protect_from_queue (object, 1);
size = protect_from_queue (size, 0);
if (GET_CODE (size) == CONST_INT
&& MOVE_BY_PIECES_P (INTVAL (size), align))
clear_by_pieces (object, INTVAL (size), align);
-
else
{
/* Try the most limited insn first, because there's no point
including more than one in the machine description unless
the more limited one has some advantage. */
- rtx opalign = GEN_INT (align);
+ rtx opalign = GEN_INT (align / BITS_PER_UNIT);
enum machine_mode mode;
for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
size = copy_to_mode_reg (TYPE_MODE (integer_type_node), size);
#endif
-
#ifdef TARGET_MEM_FUNCTIONS
/* It is incorrect to use the libcall calling conventions to call
memset in this context.
For targets where libcalls and normal calls have different
conventions for returning pointers, we could end up generating
- incorrect code.
+ incorrect code.
So instead of using a libcall sequence we build up a suitable
CALL_EXPR and expand the call in the normal fashion. */
pop_obstacks ();
}
- /* We need to make an argument list for the function call.
+ /* We need to make an argument list for the function call.
memset has three arguments, the first is a void * addresses, the
second a integer with the initialization value, the last is a
object));
TREE_CHAIN (arg_list)
= build_tree_list (NULL_TREE,
- make_tree (integer_type_node, const0_rtx));
+ make_tree (integer_type_node, const0_rtx));
TREE_CHAIN (TREE_CHAIN (arg_list))
= build_tree_list (NULL_TREE, make_tree (sizetype, size));
TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE;
retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
#else
- emit_library_call (bzero_libfunc, 0,
+ emit_library_call (bzero_libfunc, LCT_NORMAL,
VOIDmode, 2, object, Pmode, size,
TYPE_MODE (integer_type_node));
#endif
}
}
- else
- emit_move_insn (object, CONST0_RTX (GET_MODE (object)));
return retval;
}
enum machine_mode mode = GET_MODE (x);
enum machine_mode submode;
enum mode_class class = GET_MODE_CLASS (mode);
- int i;
+ unsigned int i;
if (mode >= MAX_MACHINE_MODE)
- abort ();
+ abort ();
if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
return
regardless of machine's endianness. */
#ifdef STACK_GROWS_DOWNWARD
emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
- (gen_rtx_MEM (submode, (XEXP (x, 0))),
+ (gen_rtx_MEM (submode, XEXP (x, 0)),
gen_imagpart (submode, y)));
emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
- (gen_rtx_MEM (submode, (XEXP (x, 0))),
+ (gen_rtx_MEM (submode, XEXP (x, 0)),
gen_realpart (submode, y)));
#else
emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
- (gen_rtx_MEM (submode, (XEXP (x, 0))),
+ (gen_rtx_MEM (submode, XEXP (x, 0)),
gen_realpart (submode, y)));
emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
- (gen_rtx_MEM (submode, (XEXP (x, 0))),
+ (gen_rtx_MEM (submode, XEXP (x, 0)),
gen_imagpart (submode, y)));
#endif
}
memory and reload. FIXME, we should see about using extract and
insert on integer registers, but complex short and complex char
variables should be rarely used. */
- if (GET_MODE_BITSIZE (mode) < 2*BITS_PER_WORD
+ if (GET_MODE_BITSIZE (mode) < 2 * BITS_PER_WORD
&& (reload_in_progress | reload_completed) == 0)
{
int packed_dest_p = (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER);
enum mode_class reg_class = ((class == MODE_COMPLEX_FLOAT)
? MODE_FLOAT : MODE_INT);
- enum machine_mode reg_mode =
+ enum machine_mode reg_mode =
mode_for_size (GET_MODE_BITSIZE (mode), reg_class, 1);
if (reg_mode != BLKmode)
rtx cmem = change_address (mem, mode, NULL_RTX);
- cfun->cannot_inline = "function uses short complex types";
+ cfun->cannot_inline = N_("function using short complex types cannot be inline");
if (packed_dest_p)
{
else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
{
rtx last_insn = 0;
- rtx seq;
+ rtx seq, inner;
int need_clobber;
-
+
#ifdef PUSH_ROUNDING
/* If X is a push on the stack, do the push now and replace
x = change_address (x, VOIDmode, stack_pointer_rtx);
}
#endif
-
+
+ /* If we are in reload, see if either operand is a MEM whose address
+ is scheduled for replacement. */
+ if (reload_in_progress && GET_CODE (x) == MEM
+ && (inner = find_replacement (&XEXP (x, 0))) != XEXP (x, 0))
+ {
+ rtx new = gen_rtx_MEM (GET_MODE (x), inner);
+
+ MEM_COPY_ATTRIBUTES (new, x);
+ x = new;
+ }
+ if (reload_in_progress && GET_CODE (y) == MEM
+ && (inner = find_replacement (&XEXP (y, 0))) != XEXP (y, 0))
+ {
+ rtx new = gen_rtx_MEM (GET_MODE (y), inner);
+
+ MEM_COPY_ATTRIBUTES (new, y);
+ y = new;
+ }
+
start_sequence ();
need_clobber = 0;
for (i = 0;
- i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
+ i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
i++)
{
rtx xpart = operand_subword (x, i, 1, mode);
anti_adjust_stack (size);
else
{
- rtx temp = copy_to_mode_reg (Pmode, size);
+ temp = copy_to_mode_reg (Pmode, size);
if (extra != 0)
temp = expand_binop (Pmode, add_optab, temp, GEN_INT (extra),
temp, 0, OPTAB_LIB_WIDEN);
anti_adjust_stack (temp);
}
-#if defined (STACK_GROWS_DOWNWARD) \
- || (defined (ARGS_GROW_DOWNWARD) \
- && !defined (ACCUMULATE_OUTGOING_ARGS))
-
- /* Return the lowest stack address when STACK or ARGS grow downward and
- we are not aaccumulating outgoing arguments (the c4x port uses such
- conventions). */
- temp = virtual_outgoing_args_rtx;
- if (extra != 0 && below)
- temp = plus_constant (temp, extra);
+#ifndef STACK_GROWS_DOWNWARD
+#ifdef ARGS_GROW_DOWNWARD
+ if (!ACCUMULATE_OUTGOING_ARGS)
#else
- if (GET_CODE (size) == CONST_INT)
- temp = plus_constant (virtual_outgoing_args_rtx,
- - INTVAL (size) - (below ? 0 : extra));
- else if (extra != 0 && !below)
- temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
- negate_rtx (Pmode, plus_constant (size, extra)));
- else
- temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
- negate_rtx (Pmode, size));
+ if (0)
+#endif
+#else
+ if (1)
#endif
+ {
+ /* Return the lowest stack address when STACK or ARGS grow downward and
+ we are not aaccumulating outgoing arguments (the c4x port uses such
+ conventions). */
+ temp = virtual_outgoing_args_rtx;
+ if (extra != 0 && below)
+ temp = plus_constant (temp, extra);
+ }
+ else
+ {
+ if (GET_CODE (size) == CONST_INT)
+ temp = plus_constant (virtual_outgoing_args_rtx,
+ -INTVAL (size) - (below ? 0 : extra));
+ else if (extra != 0 && !below)
+ temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
+ negate_rtx (Pmode, plus_constant (size, extra)));
+ else
+ temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
+ negate_rtx (Pmode, size));
+ }
return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp);
}
static rtx
get_push_address (size)
- int size;
+ int size;
{
register rtx temp;
SIZE is an rtx for the size of data to be copied (in bytes),
needed only if X is BLKmode.
- ALIGN (in bytes) is maximum alignment we can assume.
+ ALIGN is maximum alignment we can assume.
If PARTIAL and REG are both nonzero, then copy that many of the first
words of X into registers starting with REG, and push the rest of X.
int used = partial * UNITS_PER_WORD;
int offset = used % (PARM_BOUNDARY / BITS_PER_UNIT);
int skip;
-
+
if (size == 0)
abort ();
and if there is no difficulty with push insns that skip bytes
on the stack for alignment purposes. */
if (args_addr == 0
+ && PUSH_ARGS
&& GET_CODE (size) == CONST_INT
&& skip == 0
&& (MOVE_BY_PIECES_P ((unsigned) INTVAL (size) - used, align))
forces many pushes of a small amount of data,
and such small pushes do rounding that causes trouble. */
&& ((! SLOW_UNALIGNED_ACCESS (word_mode, align))
- || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT
+ || align >= BIGGEST_ALIGNMENT
|| PUSH_ROUNDING (align) == align)
&& PUSH_ROUNDING (INTVAL (size)) == INTVAL (size))
{
&& where_pad != none && where_pad != stack_direction)
anti_adjust_stack (GEN_INT (extra));
+ stack_pointer_delta += INTVAL (size) - used;
move_by_pieces (gen_rtx_MEM (BLKmode, gen_push_operand ()), xinner,
INTVAL (size) - used, align);
if (current_function_check_memory_usage && ! in_check_memory_usage)
{
rtx temp;
-
+
in_check_memory_usage = 1;
- temp = get_push_address (INTVAL(size) - used);
+ temp = get_push_address (INTVAL (size) - used);
if (GET_CODE (x) == MEM && type && AGGREGATE_TYPE_P (type))
- emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
- temp, Pmode,
- XEXP (xinner, 0), Pmode,
- GEN_INT (INTVAL(size) - used),
+ emit_library_call (chkr_copy_bitmap_libfunc,
+ LCT_CONST_MAKE_BLOCK, VOIDmode, 3, temp,
+ Pmode, XEXP (xinner, 0), Pmode,
+ GEN_INT (INTVAL (size) - used),
TYPE_MODE (sizetype));
else
- emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
- temp, Pmode,
- GEN_INT (INTVAL(size) - used),
+ emit_library_call (chkr_set_right_libfunc,
+ LCT_CONST_MAKE_BLOCK, VOIDmode, 3, temp,
+ Pmode, GEN_INT (INTVAL (size) - used),
TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW),
TYPE_MODE (integer_type_node));
}
}
else
-#endif /* PUSH_ROUNDING */
+#endif /* PUSH_ROUNDING */
{
+ rtx target;
+
/* Otherwise make space on the stack and copy the data
to the address of that space. */
skip));
if (current_function_check_memory_usage && ! in_check_memory_usage)
{
- rtx target;
-
in_check_memory_usage = 1;
target = copy_to_reg (temp);
if (GET_CODE (x) == MEM && type && AGGREGATE_TYPE_P (type))
- emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
+ emit_library_call (chkr_copy_bitmap_libfunc,
+ LCT_CONST_MAKE_BLOCK, VOIDmode, 3,
target, Pmode,
XEXP (xinner, 0), Pmode,
size, TYPE_MODE (sizetype));
else
- emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+ emit_library_call (chkr_set_right_libfunc,
+ LCT_CONST_MAKE_BLOCK, VOIDmode, 3,
target, Pmode,
size, TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW),
in_check_memory_usage = 0;
}
+ target = gen_rtx_MEM (BLKmode, temp);
+
+ if (type != 0)
+ {
+ set_mem_attributes (target, type, 1);
+ /* Function incoming arguments may overlap with sibling call
+ outgoing arguments and we cannot allow reordering of reads
+ from function arguments with stores to outgoing arguments
+ of sibling calls. */
+ MEM_ALIAS_SET (target) = 0;
+ }
+
/* TEMP is the address of the block. Copy the data there. */
if (GET_CODE (size) == CONST_INT
&& MOVE_BY_PIECES_P ((unsigned) INTVAL (size), align))
{
- move_by_pieces (gen_rtx_MEM (BLKmode, temp), xinner,
- INTVAL (size), align);
+ move_by_pieces (target, xinner, INTVAL (size), align);
goto ret;
}
else
{
- rtx opalign = GEN_INT (align);
+ rtx opalign = GEN_INT (align / BITS_PER_UNIT);
enum machine_mode mode;
- rtx target = gen_rtx_MEM (BLKmode, temp);
for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
mode != VOIDmode;
}
}
-#ifndef ACCUMULATE_OUTGOING_ARGS
- /* If the source is referenced relative to the stack pointer,
- copy it to another register to stabilize it. We do not need
- to do this if we know that we won't be changing sp. */
+ if (!ACCUMULATE_OUTGOING_ARGS)
+ {
+ /* If the source is referenced relative to the stack pointer,
+ copy it to another register to stabilize it. We do not need
+ to do this if we know that we won't be changing sp. */
- if (reg_mentioned_p (virtual_stack_dynamic_rtx, temp)
- || reg_mentioned_p (virtual_outgoing_args_rtx, temp))
- temp = copy_to_reg (temp);
-#endif
+ if (reg_mentioned_p (virtual_stack_dynamic_rtx, temp)
+ || reg_mentioned_p (virtual_outgoing_args_rtx, temp))
+ temp = copy_to_reg (temp);
+ }
/* Make inhibit_defer_pop nonzero around the library call
to force it to pop the bcopy-arguments right away. */
NO_DEFER_POP;
#ifdef TARGET_MEM_FUNCTIONS
- emit_library_call (memcpy_libfunc, 0,
+ emit_library_call (memcpy_libfunc, LCT_NORMAL,
VOIDmode, 3, temp, Pmode, XEXP (xinner, 0), Pmode,
convert_to_mode (TYPE_MODE (sizetype),
size, TREE_UNSIGNED (sizetype)),
TYPE_MODE (sizetype));
#else
- emit_library_call (bcopy_libfunc, 0,
+ emit_library_call (bcopy_libfunc, LCT_NORMAL,
VOIDmode, 3, XEXP (xinner, 0), Pmode, temp, Pmode,
convert_to_mode (TYPE_MODE (integer_type_node),
size,
{
rtx addr;
rtx target = NULL_RTX;
+ rtx dest;
/* Push padding now if padding above and stack grows down,
or if padding below and stack grows up.
anti_adjust_stack (GEN_INT (extra));
#ifdef PUSH_ROUNDING
- if (args_addr == 0)
- addr = gen_push_operand ();
+ if (args_addr == 0 && PUSH_ARGS)
+ {
+ addr = gen_push_operand ();
+ stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
+ }
else
#endif
{
if (GET_CODE (args_so_far) == CONST_INT)
addr
= memory_address (mode,
- plus_constant (args_addr,
+ plus_constant (args_addr,
INTVAL (args_so_far)));
- else
+ else
addr = memory_address (mode, gen_rtx_PLUS (Pmode, args_addr,
args_so_far));
target = addr;
}
- emit_move_insn (gen_rtx_MEM (mode, addr), x);
+ dest = gen_rtx_MEM (mode, addr);
+ if (type != 0)
+ {
+ set_mem_attributes (dest, type, 1);
+ /* Function incoming arguments may overlap with sibling call
+ outgoing arguments and we cannot allow reordering of reads
+ from function arguments with stores to outgoing arguments
+ of sibling calls. */
+ MEM_ALIAS_SET (dest) = 0;
+ }
+
+ emit_move_insn (dest, x);
if (current_function_check_memory_usage && ! in_check_memory_usage)
{
target = get_push_address (GET_MODE_SIZE (mode));
if (GET_CODE (x) == MEM && type && AGGREGATE_TYPE_P (type))
- emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
- target, Pmode,
- XEXP (x, 0), Pmode,
+ emit_library_call (chkr_copy_bitmap_libfunc,
+ LCT_CONST_MAKE_BLOCK, VOIDmode, 3, target,
+ Pmode, XEXP (x, 0), Pmode,
GEN_INT (GET_MODE_SIZE (mode)),
TYPE_MODE (sizetype));
else
- emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
- target, Pmode,
- GEN_INT (GET_MODE_SIZE (mode)),
+ emit_library_call (chkr_set_right_libfunc,
+ LCT_CONST_MAKE_BLOCK, VOIDmode, 3, target,
+ Pmode, GEN_INT (GET_MODE_SIZE (mode)),
TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW),
TYPE_MODE (integer_type_node));
if (extra && args_addr == 0 && where_pad == stack_direction)
anti_adjust_stack (GEN_INT (extra));
-
- if (alignment_pad)
+
+ if (alignment_pad && args_addr == 0)
anti_adjust_stack (alignment_pad);
}
\f
+/* Return X if X can be used as a subtarget in a sequence of arithmetic
+ operations. */
+
+static rtx
+get_subtarget (x)
+ rtx x;
+{
+ return ((x == 0
+ /* Only registers can be subtargets. */
+ || GET_CODE (x) != REG
+ /* If the register is readonly, it can't be set more than once. */
+ || RTX_UNCHANGING_P (x)
+ /* Don't use hard regs to avoid extending their life. */
+ || REGNO (x) < FIRST_PSEUDO_REGISTER
+ /* Avoid subtargets inside loops,
+ since they hide some invariant expressions. */
+ || preserve_subexpressions_p ())
+ ? 0 : x);
+}
+
/* Expand an assignment that stores the value of FROM into TO.
If WANT_VALUE is nonzero, return an rtx for the value of TO.
(This may contain a QUEUED rtx;
|| TREE_CODE (to) == ARRAY_REF)
{
enum machine_mode mode1;
- int bitsize;
- int bitpos;
+ HOST_WIDE_INT bitsize, bitpos;
tree offset;
int unsignedp;
int volatilep = 0;
&& GET_MODE (to_rtx) == BLKmode
&& GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
&& bitsize
- && (bitpos % bitsize) == 0
+ && (bitpos % bitsize) == 0
&& (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
- && (alignment * BITS_PER_UNIT) == GET_MODE_ALIGNMENT (mode1))
+ && alignment == GET_MODE_ALIGNMENT (mode1))
{
rtx temp = change_address (to_rtx, mode1,
plus_constant (XEXP (to_rtx, 0),
size *= GET_MODE_SIZE (best_mode);
/* Check the access right of the pointer. */
+ in_check_memory_usage = 1;
if (size)
- emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
- to_addr, Pmode,
+ emit_library_call (chkr_check_addr_libfunc, LCT_CONST_MAKE_BLOCK,
+ VOIDmode, 3, to_addr, Pmode,
GEN_INT (size), TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_WO),
TYPE_MODE (integer_type_node));
+ in_check_memory_usage = 0;
}
- result = store_field (to_rtx, bitsize, bitpos, mode1, from,
- (want_value
- /* Spurious cast makes HPUX compiler happy. */
- ? (enum machine_mode) TYPE_MODE (TREE_TYPE (to))
- : VOIDmode),
- unsignedp,
- /* Required alignment of containing datum. */
- alignment,
- int_size_in_bytes (TREE_TYPE (tem)),
- get_alias_set (to));
- preserve_temp_slots (result);
- free_temp_slots ();
- pop_temp_slots ();
+ /* If this is a varying-length object, we must get the address of
+ the source and do an explicit block move. */
+ if (bitsize < 0)
+ {
+ unsigned int from_align;
+ rtx from_rtx = expand_expr_unaligned (from, &from_align);
+ rtx inner_to_rtx
+ = change_address (to_rtx, VOIDmode,
+ plus_constant (XEXP (to_rtx, 0),
+ bitpos / BITS_PER_UNIT));
+
+ emit_block_move (inner_to_rtx, from_rtx, expr_size (from),
+ MIN (alignment, from_align));
+ free_temp_slots ();
+ pop_temp_slots ();
+ return to_rtx;
+ }
+ else
+ {
+ result = store_field (to_rtx, bitsize, bitpos, mode1, from,
+ (want_value
+ /* Spurious cast for HPUX compiler. */
+ ? ((enum machine_mode)
+ TYPE_MODE (TREE_TYPE (to)))
+ : VOIDmode),
+ unsignedp,
+ alignment,
+ int_size_in_bytes (TREE_TYPE (tem)),
+ get_alias_set (to));
+
+ preserve_temp_slots (result);
+ free_temp_slots ();
+ pop_temp_slots ();
- /* If the value is meaningful, convert RESULT to the proper mode.
- Otherwise, return nothing. */
- return (want_value ? convert_modes (TYPE_MODE (TREE_TYPE (to)),
- TYPE_MODE (TREE_TYPE (from)),
- result,
- TREE_UNSIGNED (TREE_TYPE (to)))
- : NULL_RTX);
+ /* If the value is meaningful, convert RESULT to the proper mode.
+ Otherwise, return nothing. */
+ return (want_value ? convert_modes (TYPE_MODE (TREE_TYPE (to)),
+ TYPE_MODE (TREE_TYPE (from)),
+ result,
+ TREE_UNSIGNED (TREE_TYPE (to)))
+ : NULL_RTX);
+ }
}
/* If the rhs is a function call and its value is not an aggregate,
val = setjmp (buf) on machines where reference to val
requires loading up part of an address in a separate insn.
- Don't do this if TO is a VAR_DECL whose DECL_RTL is REG since it might be
- a promoted variable where the zero- or sign- extension needs to be done.
- Handling this in the normal way is safe because no computation is done
- before the call. */
+ Don't do this if TO is a VAR_DECL or PARM_DECL whose DECL_RTL is REG
+ since it might be a promoted variable where the zero- or sign- extension
+ needs to be done. Handling this in the normal way is safe because no
+ computation is done before the call. */
if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from)
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (from))) == INTEGER_CST
- && ! (TREE_CODE (to) == VAR_DECL && GET_CODE (DECL_RTL (to)) == REG))
+ && ! ((TREE_CODE (to) == VAR_DECL || TREE_CODE (to) == PARM_DECL)
+ && GET_CODE (DECL_RTL (to)) == REG))
{
rtx value;
The Irix 6 ABI has examples of this. */
if (GET_CODE (to_rtx) == PARALLEL)
emit_group_load (to_rtx, value, int_size_in_bytes (TREE_TYPE (from)),
- TYPE_ALIGN (TREE_TYPE (from)) / BITS_PER_UNIT);
+ TYPE_ALIGN (TREE_TYPE (from)));
else if (GET_MODE (to_rtx) == BLKmode)
emit_block_move (to_rtx, value, expr_size (from),
- TYPE_ALIGN (TREE_TYPE (from)) / BITS_PER_UNIT);
+ TYPE_ALIGN (TREE_TYPE (from)));
else
{
#ifdef POINTERS_EXTEND_UNSIGNED
if (GET_CODE (to_rtx) == PARALLEL)
emit_group_load (to_rtx, temp, int_size_in_bytes (TREE_TYPE (from)),
- TYPE_ALIGN (TREE_TYPE (from)) / BITS_PER_UNIT);
+ TYPE_ALIGN (TREE_TYPE (from)));
else
emit_move_insn (to_rtx, temp);
/* Copy the rights of the bitmap. */
if (current_function_check_memory_usage)
- emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
- XEXP (to_rtx, 0), Pmode,
+ emit_library_call (chkr_copy_bitmap_libfunc, LCT_CONST_MAKE_BLOCK,
+ VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
XEXP (from_rtx, 0), Pmode,
convert_to_mode (TYPE_MODE (sizetype),
size, TREE_UNSIGNED (sizetype)),
TYPE_MODE (sizetype));
#ifdef TARGET_MEM_FUNCTIONS
- emit_library_call (memcpy_libfunc, 0,
+ emit_library_call (memcpy_libfunc, LCT_NORMAL,
VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
XEXP (from_rtx, 0), Pmode,
convert_to_mode (TYPE_MODE (sizetype),
size, TREE_UNSIGNED (sizetype)),
TYPE_MODE (sizetype));
#else
- emit_library_call (bcopy_libfunc, 0,
+ emit_library_call (bcopy_libfunc, LCT_NORMAL,
VOIDmode, 3, XEXP (from_rtx, 0), Pmode,
XEXP (to_rtx, 0), Pmode,
convert_to_mode (TYPE_MODE (integer_type_node),
SUBREG_PROMOTED_UNSIGNED_P (target)),
exp);
}
-
+
temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
/* If TEMP is a volatile MEM and we want a result value, make
&& GET_CODE (target) == MEM
&& AGGREGATE_TYPE_P (TREE_TYPE (exp)))
{
+ in_check_memory_usage = 1;
if (GET_CODE (temp) == MEM)
- emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
- XEXP (target, 0), Pmode,
+ emit_library_call (chkr_copy_bitmap_libfunc, LCT_CONST_MAKE_BLOCK,
+ VOIDmode, 3, XEXP (target, 0), Pmode,
XEXP (temp, 0), Pmode,
expr_size (exp), TYPE_MODE (sizetype));
else
- emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
- XEXP (target, 0), Pmode,
+ emit_library_call (chkr_check_addr_libfunc, LCT_CONST_MAKE_BLOCK,
+ VOIDmode, 3, XEXP (target, 0), Pmode,
expr_size (exp), TYPE_MODE (sizetype),
- GEN_INT (MEMORY_USE_WO),
+ GEN_INT (MEMORY_USE_WO),
TYPE_MODE (integer_type_node));
+ in_check_memory_usage = 0;
}
/* If value was not generated in the target, store it there.
size = expr_size (exp);
if (GET_CODE (size) == CONST_INT
&& INTVAL (size) < TREE_STRING_LENGTH (exp))
- emit_block_move (target, temp, size,
- TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
+ emit_block_move (target, temp, size, TYPE_ALIGN (TREE_TYPE (exp)));
else
{
/* Compute the size of the data to copy from the string. */
= size_binop (MIN_EXPR,
make_tree (sizetype, size),
size_int (TREE_STRING_LENGTH (exp)));
+ unsigned int align = TYPE_ALIGN (TREE_TYPE (exp));
rtx copy_size_rtx = expand_expr (copy_size, NULL_RTX,
VOIDmode, 0);
rtx label = 0;
/* Copy that much. */
emit_block_move (target, temp, copy_size_rtx,
- TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
+ TYPE_ALIGN (TREE_TYPE (exp)));
/* Figure out how much is left in TARGET that we have to clear.
Do all calculations in ptr_mode. */
if (GET_CODE (copy_size_rtx) == CONST_INT)
{
addr = plus_constant (addr, TREE_STRING_LENGTH (exp));
- size = plus_constant (size, - TREE_STRING_LENGTH (exp));
+ size = plus_constant (size, -TREE_STRING_LENGTH (exp));
+ align = MIN (align, (BITS_PER_UNIT
+ * (INTVAL (copy_size_rtx)
+ & - INTVAL (copy_size_rtx))));
}
else
{
copy_size_rtx, NULL_RTX, 0,
OPTAB_LIB_WIDEN);
+ align = BITS_PER_UNIT;
label = gen_label_rtx ();
emit_cmp_and_jump_insns (size, const0_rtx, LT, NULL_RTX,
GET_MODE (size), 0, 0, label);
}
+ align = MIN (align, expr_align (copy_size));
if (size != const0_rtx)
{
+ rtx dest = gen_rtx_MEM (BLKmode, addr);
+
+ MEM_COPY_ATTRIBUTES (dest, target);
+
/* Be sure we can write on ADDR. */
+ in_check_memory_usage = 1;
if (current_function_check_memory_usage)
- emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
+ emit_library_call (chkr_check_addr_libfunc,
+ LCT_CONST_MAKE_BLOCK, VOIDmode, 3,
addr, Pmode,
size, TYPE_MODE (sizetype),
- GEN_INT (MEMORY_USE_WO),
+ GEN_INT (MEMORY_USE_WO),
TYPE_MODE (integer_type_node));
-#ifdef TARGET_MEM_FUNCTIONS
- emit_library_call (memset_libfunc, 0, VOIDmode, 3,
- addr, ptr_mode,
- const0_rtx, TYPE_MODE (integer_type_node),
- convert_to_mode (TYPE_MODE (sizetype),
- size,
- TREE_UNSIGNED (sizetype)),
- TYPE_MODE (sizetype));
-#else
- emit_library_call (bzero_libfunc, 0, VOIDmode, 2,
- addr, ptr_mode,
- convert_to_mode (TYPE_MODE (integer_type_node),
- size,
- TREE_UNSIGNED (integer_type_node)),
- TYPE_MODE (integer_type_node));
-#endif
+ in_check_memory_usage = 0;
+ clear_storage (dest, size, align);
}
if (label)
The Irix 6 ABI has examples of this. */
else if (GET_CODE (target) == PARALLEL)
emit_group_load (target, temp, int_size_in_bytes (TREE_TYPE (exp)),
- TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
+ TYPE_ALIGN (TREE_TYPE (exp)));
else if (GET_MODE (temp) == BLKmode)
emit_block_move (target, temp, expr_size (exp),
- TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
+ TYPE_ALIGN (TREE_TYPE (exp)));
else
emit_move_insn (target, temp);
}
&& ! (GET_CODE (target) == REG
&& REGNO (target) < FIRST_PSEUDO_REGISTER))
return copy_to_reg (target);
-
+
else
return target;
}
return is_zeros_p (TREE_OPERAND (exp, 0));
case INTEGER_CST:
- return TREE_INT_CST_LOW (exp) == 0 && TREE_INT_CST_HIGH (exp) == 0;
+ return integer_zerop (exp);
case COMPLEX_CST:
return
return 0;
return 1;
-
+
default:
return 0;
}
TARGET, BITSIZE, BITPOS, MODE, EXP are as for store_field.
TYPE is the type of the CONSTRUCTOR, not the element type.
ALIGN and CLEARED are as for store_constructor.
+ ALIAS_SET is the alias set to use for any stores.
This provides a recursive shortcut back to store_constructor when it isn't
necessary to go through store_field. This is so that we can pass through
static void
store_constructor_field (target, bitsize, bitpos,
- mode, exp, type, align, cleared)
+ mode, exp, type, align, cleared, alias_set)
rtx target;
- int bitsize, bitpos;
+ unsigned HOST_WIDE_INT bitsize;
+ HOST_WIDE_INT bitpos;
enum machine_mode mode;
tree exp, type;
unsigned int align;
int cleared;
+ int alias_set;
{
if (TREE_CODE (exp) == CONSTRUCTOR
&& bitpos % BITS_PER_UNIT == 0
? BLKmode : VOIDmode,
plus_constant (XEXP (target, 0),
bitpos / BITS_PER_UNIT));
+
+ MEM_ALIAS_SET (target) = alias_set;
store_constructor (exp, target, align, cleared, bitsize / BITS_PER_UNIT);
}
else
- store_field (target, bitsize, bitpos, mode, exp, VOIDmode, 0,
- (align + BITS_PER_UNIT - 1) / BITS_PER_UNIT,
- int_size_in_bytes (type), 0);
+ store_field (target, bitsize, bitpos, mode, exp, VOIDmode, 0, align,
+ int_size_in_bytes (type), alias_set);
}
/* Store the value of constructor EXP into the rtx TARGET.
TARGET is either a REG or a MEM.
- ALIGN is the maximum known alignment for TARGET, in bits.
+ ALIGN is the maximum known alignment for TARGET.
CLEARED is true if TARGET is known to have been zero'd.
SIZE is the number of bytes of TARGET we are allowed to modify: this
may not be the same as the size of EXP if we are assigning to a field
rtx target;
unsigned int align;
int cleared;
- int size;
+ HOST_WIDE_INT size;
{
tree type = TREE_TYPE (exp);
#ifdef WORD_REGISTER_OPERATIONS
- rtx exp_size = expr_size (exp);
+ HOST_WIDE_INT exp_size = int_size_in_bytes (type);
#endif
/* We know our target cannot conflict, since safe_from_p has been called. */
/* If the constructor is empty, clear the union. */
if (! CONSTRUCTOR_ELTS (exp) && ! cleared)
- clear_storage (target, expr_size (exp),
- TYPE_ALIGN (type) / BITS_PER_UNIT);
+ clear_storage (target, expr_size (exp), TYPE_ALIGN (type));
}
/* If we are building a static constructor into a register,
/* If the constructor has fewer fields than the structure
or if we are initializing the structure to mostly zeros,
- clear the whole structure first. */
+ clear the whole structure first. Don't do this is TARGET is
+ register whose mode size isn't equal to SIZE since clear_storage
+ can't handle this case. */
else if (size > 0
&& ((list_length (CONSTRUCTOR_ELTS (exp))
- != list_length (TYPE_FIELDS (type)))
- || mostly_zeros_p (exp)))
+ != fields_length (type))
+ || mostly_zeros_p (exp))
+ && (GET_CODE (target) != REG
+ || GET_MODE_SIZE (GET_MODE (target)) == size))
{
if (! cleared)
- clear_storage (target, GEN_INT (size),
- (align + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
+ clear_storage (target, GEN_INT (size), align);
cleared = 1;
}
tree value = TREE_VALUE (elt);
#endif
register enum machine_mode mode;
- int bitsize;
- int bitpos = 0;
+ HOST_WIDE_INT bitsize;
+ HOST_WIDE_INT bitpos = 0;
int unsignedp;
- tree pos, constant = 0, offset = 0;
+ tree offset;
rtx to_rtx = target;
/* Just ignore missing fields.
if (cleared && is_zeros_p (TREE_VALUE (elt)))
continue;
- if (TREE_CODE (DECL_SIZE (field)) == INTEGER_CST)
- bitsize = TREE_INT_CST_LOW (DECL_SIZE (field));
+ if (host_integerp (DECL_SIZE (field), 1))
+ bitsize = tree_low_cst (DECL_SIZE (field), 1);
else
bitsize = -1;
if (DECL_BIT_FIELD (field))
mode = VOIDmode;
- pos = DECL_FIELD_BITPOS (field);
- if (TREE_CODE (pos) == INTEGER_CST)
- constant = pos;
- else if (TREE_CODE (pos) == PLUS_EXPR
- && TREE_CODE (TREE_OPERAND (pos, 1)) == INTEGER_CST)
- constant = TREE_OPERAND (pos, 1), offset = TREE_OPERAND (pos, 0);
+ offset = DECL_FIELD_OFFSET (field);
+ if (host_integerp (offset, 0)
+ && host_integerp (bit_position (field), 0))
+ {
+ bitpos = int_bit_position (field);
+ offset = 0;
+ }
else
- offset = pos;
-
- if (constant)
- bitpos = TREE_INT_CST_LOW (constant);
+ bitpos = tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 0);
if (offset)
{
rtx offset_rtx;
if (contains_placeholder_p (offset))
- offset = build (WITH_RECORD_EXPR, bitsizetype,
+ offset = build (WITH_RECORD_EXPR, sizetype,
offset, make_tree (TREE_TYPE (exp), target));
- offset = size_binop (EXACT_DIV_EXPR, offset,
- bitsize_int (BITS_PER_UNIT));
- offset = convert (sizetype, offset);
-
offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
if (GET_CODE (to_rtx) != MEM)
abort ();
- if (GET_MODE (offset_rtx) != ptr_mode)
- {
+ if (GET_MODE (offset_rtx) != ptr_mode)
+ {
#ifdef POINTERS_EXTEND_UNSIGNED
offset_rtx = convert_memory_address (ptr_mode, offset_rtx);
#else
gen_rtx_PLUS (ptr_mode, XEXP (to_rtx, 0),
force_reg (ptr_mode,
offset_rtx)));
+ align = DECL_OFFSET_ALIGN (field);
}
if (TREE_READONLY (field))
start of a word, try to widen it to a full word.
This special case allows us to output C++ member function
initializations in a form that the optimizers can understand. */
- if (constant
- && GET_CODE (target) == REG
+ if (GET_CODE (target) == REG
&& bitsize < BITS_PER_WORD
&& bitpos % BITS_PER_WORD == 0
&& GET_MODE_CLASS (mode) == MODE_INT
&& TREE_CODE (value) == INTEGER_CST
- && GET_CODE (exp_size) == CONST_INT
- && bitpos + BITS_PER_WORD <= INTVAL (exp_size) * BITS_PER_UNIT)
+ && exp_size >= 0
+ && bitpos + BITS_PER_WORD <= exp_size * BITS_PER_UNIT)
{
tree type = TREE_TYPE (value);
if (TYPE_PRECISION (type) < BITS_PER_WORD)
}
#endif
store_constructor_field (to_rtx, bitsize, bitpos, mode,
- TREE_VALUE (elt), type,
- MIN (align,
- DECL_ALIGN (TREE_PURPOSE (elt))),
- cleared);
+ TREE_VALUE (elt), type, align, cleared,
+ DECL_NONADDRESSABLE_P (field)
+ ? MEM_ALIAS_SET (to_rtx)
+ : get_alias_set (TREE_TYPE (field)));
}
}
else if (TREE_CODE (type) == ARRAY_TYPE)
register int i;
int need_to_clear;
tree domain = TYPE_DOMAIN (type);
- HOST_WIDE_INT minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain));
- HOST_WIDE_INT maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain));
tree elttype = TREE_TYPE (type);
+ int const_bounds_p = (host_integerp (TYPE_MIN_VALUE (domain), 0)
+ && host_integerp (TYPE_MAX_VALUE (domain), 0));
+ HOST_WIDE_INT minelt;
+ HOST_WIDE_INT maxelt;
+
+ /* If we have constant bounds for the range of the type, get them. */
+ if (const_bounds_p)
+ {
+ minelt = tree_low_cst (TYPE_MIN_VALUE (domain), 0);
+ maxelt = tree_low_cst (TYPE_MAX_VALUE (domain), 0);
+ }
/* If the constructor has fewer elements than the array,
clear the whole array first. Similarly if this is
else
{
HOST_WIDE_INT count = 0, zero_count = 0;
- need_to_clear = 0;
+ need_to_clear = ! const_bounds_p;
+
/* This loop is a more accurate version of the loop in
mostly_zeros_p (it handles RANGE_EXPR in an index).
It is also needed to check for missing elements. */
for (elt = CONSTRUCTOR_ELTS (exp);
- elt != NULL_TREE;
+ elt != NULL_TREE && ! need_to_clear;
elt = TREE_CHAIN (elt))
{
tree index = TREE_PURPOSE (elt);
HOST_WIDE_INT this_node_count;
+
if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
{
tree lo_index = TREE_OPERAND (index, 0);
tree hi_index = TREE_OPERAND (index, 1);
- if (TREE_CODE (lo_index) != INTEGER_CST
- || TREE_CODE (hi_index) != INTEGER_CST)
+
+ if (! host_integerp (lo_index, 1)
+ || ! host_integerp (hi_index, 1))
{
need_to_clear = 1;
break;
}
- this_node_count = TREE_INT_CST_LOW (hi_index)
- - TREE_INT_CST_LOW (lo_index) + 1;
+
+ this_node_count = (tree_low_cst (hi_index, 1)
+ - tree_low_cst (lo_index, 1) + 1);
}
else
this_node_count = 1;
+
count += this_node_count;
if (mostly_zeros_p (TREE_VALUE (elt)))
zero_count += this_node_count;
}
+
/* Clear the entire array first if there are any missing elements,
or if the incidence of zero elements is >= 75%. */
- if (count < maxelt - minelt + 1
- || 4 * zero_count >= 3 * count)
+ if (! need_to_clear
+ && (count < maxelt - minelt + 1 || 4 * zero_count >= 3 * count))
need_to_clear = 1;
}
+
if (need_to_clear && size > 0)
{
if (! cleared)
- clear_storage (target, GEN_INT (size),
- (align + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
+ clear_storage (target, GEN_INT (size), align);
cleared = 1;
}
else
elt = TREE_CHAIN (elt), i++)
{
register enum machine_mode mode;
- int bitsize;
- int bitpos;
+ HOST_WIDE_INT bitsize;
+ HOST_WIDE_INT bitpos;
int unsignedp;
tree value = TREE_VALUE (elt);
unsigned int align = TYPE_ALIGN (TREE_TYPE (value));
unsignedp = TREE_UNSIGNED (elttype);
mode = TYPE_MODE (elttype);
if (mode == BLKmode)
- {
- if (TREE_CODE (TYPE_SIZE (elttype)) == INTEGER_CST
- && TREE_INT_CST_HIGH (TYPE_SIZE (elttype)) == 0)
- bitsize = TREE_INT_CST_LOW (TYPE_SIZE (elttype));
- else
- bitsize = -1;
- }
+ bitsize = (host_integerp (TYPE_SIZE (elttype), 1)
+ ? tree_low_cst (TYPE_SIZE (elttype), 1)
+ : -1);
else
bitsize = GET_MODE_BITSIZE (mode);
tree position;
/* If the range is constant and "small", unroll the loop. */
- if (TREE_CODE (lo_index) == INTEGER_CST
- && TREE_CODE (hi_index) == INTEGER_CST
- && (lo = TREE_INT_CST_LOW (lo_index),
- hi = TREE_INT_CST_LOW (hi_index),
+ if (const_bounds_p
+ && host_integerp (lo_index, 0)
+ && host_integerp (hi_index, 0)
+ && (lo = tree_low_cst (lo_index, 0),
+ hi = tree_low_cst (hi_index, 0),
count = hi - lo + 1,
(GET_CODE (target) != MEM
|| count <= 2
- || (TREE_CODE (TYPE_SIZE (elttype)) == INTEGER_CST
- && TREE_INT_CST_LOW (TYPE_SIZE (elttype)) * count
- <= 40 * 8))))
+ || (host_integerp (TYPE_SIZE (elttype), 1)
+ && (tree_low_cst (TYPE_SIZE (elttype), 1) * count
+ <= 40 * 8)))))
{
lo -= minelt; hi -= minelt;
for (; lo <= hi; lo++)
{
- bitpos = lo * TREE_INT_CST_LOW (TYPE_SIZE (elttype));
- store_constructor_field (target, bitsize, bitpos, mode,
- value, type, align, cleared);
+ bitpos = lo * tree_low_cst (TYPE_SIZE (elttype), 0);
+ store_constructor_field
+ (target, bitsize, bitpos, mode, value, type, align,
+ cleared,
+ TYPE_NONALIASED_COMPONENT (type)
+ ? MEM_ALIAS_SET (target) : get_alias_set (elttype));
}
}
else
emit_label (loop_end);
}
}
- else if ((index != 0 && TREE_CODE (index) != INTEGER_CST)
- || TREE_CODE (TYPE_SIZE (elttype)) != INTEGER_CST)
+ else if ((index != 0 && ! host_integerp (index, 0))
+ || ! host_integerp (TYPE_SIZE (elttype), 1))
{
rtx pos_rtx, addr;
tree position;
index = convert (ssizetype,
fold (build (MINUS_EXPR, index,
TYPE_MIN_VALUE (domain))));
+
position = size_binop (MULT_EXPR, index,
convert (ssizetype,
TYPE_SIZE_UNIT (elttype)));
else
{
if (index != 0)
- bitpos = ((TREE_INT_CST_LOW (index) - minelt)
- * TREE_INT_CST_LOW (TYPE_SIZE (elttype)));
+ bitpos = ((tree_low_cst (index, 0) - minelt)
+ * tree_low_cst (TYPE_SIZE (elttype), 1));
else
- bitpos = (i * TREE_INT_CST_LOW (TYPE_SIZE (elttype)));
+ bitpos = (i * tree_low_cst (TYPE_SIZE (elttype), 1));
+
store_constructor_field (target, bitsize, bitpos, mode, value,
- type, align, cleared);
+ type, align, cleared,
+ TYPE_NONALIASED_COMPONENT (type)
+ ? MEM_ALIAS_SET (target) :
+ get_alias_set (elttype));
+
}
}
}
- /* set constructor assignments */
+
+ /* Set constructor assignments. */
else if (TREE_CODE (type) == SET_TYPE)
{
tree elt = CONSTRUCTOR_ELTS (exp);
- int nbytes = int_size_in_bytes (type), nbits;
+ unsigned HOST_WIDE_INT nbytes = int_size_in_bytes (type), nbits;
tree domain = TYPE_DOMAIN (type);
tree domain_min, domain_max, bitlength;
Also, if a large set has just a single range, it may also be
better to first clear all the first clear the set (using
bzero/memset), and set the bits we want. */
-
+
/* Check for all zeros. */
if (elt == NULL_TREE && size > 0)
{
if (!cleared)
- clear_storage (target, GEN_INT (size),
- TYPE_ALIGN (type) / BITS_PER_UNIT);
+ clear_storage (target, GEN_INT (size), TYPE_ALIGN (type));
return;
}
size_diffop (domain_max, domain_min),
ssize_int (1));
- if (nbytes < 0 || TREE_CODE (bitlength) != INTEGER_CST)
- abort ();
- nbits = TREE_INT_CST_LOW (bitlength);
+ nbits = tree_low_cst (bitlength, 1);
/* For "small" sets, or "medium-sized" (up to 32 bytes) sets that
are "complicated" (more than one range), initialize (the
- constant parts) by copying from a constant. */
+ constant parts) by copying from a constant. */
if (GET_MODE (target) != BLKmode || nbits <= 2 * BITS_PER_WORD
|| (nbytes <= 32 && TREE_CHAIN (elt) != NULL_TREE))
{
- int set_word_size = TYPE_ALIGN (TREE_TYPE (exp));
+ unsigned int set_word_size = TYPE_ALIGN (TREE_TYPE (exp));
enum machine_mode mode = mode_for_size (set_word_size, MODE_INT, 1);
char *bit_buffer = (char *) alloca (nbits);
HOST_WIDE_INT word = 0;
- int bit_pos = 0;
- int ibit = 0;
- int offset = 0; /* In bytes from beginning of set. */
+ unsigned int bit_pos = 0;
+ unsigned int ibit = 0;
+ unsigned int offset = 0; /* In bytes from beginning of set. */
+
elt = get_set_constructor_bits (exp, bit_buffer, nbits);
for (;;)
{
else
word |= 1 << bit_pos;
}
+
bit_pos++; ibit++;
if (bit_pos >= set_word_size || ibit == nbits)
{
{
rtx datum = GEN_INT (word);
rtx to_rtx;
+
/* The assumption here is that it is safe to use
XEXP if the set is multi-word, but not if
it's single-word. */
to_rtx = plus_constant (XEXP (target, 0), offset);
to_rtx = change_address (target, mode, to_rtx);
}
- else if (offset == 0)
+ else if (offset == 0)
to_rtx = target;
else
abort ();
emit_move_insn (to_rtx, datum);
}
+
if (ibit == nbits)
break;
word = 0;
}
}
else if (!cleared)
- {
- /* Don't bother clearing storage if the set is all ones. */
- if (TREE_CHAIN (elt) != NULL_TREE
- || (TREE_PURPOSE (elt) == NULL_TREE
- ? nbits != 1
- : (TREE_CODE (TREE_VALUE (elt)) != INTEGER_CST
- || TREE_CODE (TREE_PURPOSE (elt)) != INTEGER_CST
- || (TREE_INT_CST_LOW (TREE_VALUE (elt))
- - TREE_INT_CST_LOW (TREE_PURPOSE (elt)) + 1
- != nbits))))
- clear_storage (target, expr_size (exp),
- TYPE_ALIGN (type) / BITS_PER_UNIT);
- }
-
+ /* Don't bother clearing storage if the set is all ones. */
+ if (TREE_CHAIN (elt) != NULL_TREE
+ || (TREE_PURPOSE (elt) == NULL_TREE
+ ? nbits != 1
+ : ( ! host_integerp (TREE_VALUE (elt), 0)
+ || ! host_integerp (TREE_PURPOSE (elt), 0)
+ || (tree_low_cst (TREE_VALUE (elt), 0)
+ - tree_low_cst (TREE_PURPOSE (elt), 0) + 1
+ != (HOST_WIDE_INT) nbits))))
+ clear_storage (target, expr_size (exp), TYPE_ALIGN (type));
+
for (; elt != NULL_TREE; elt = TREE_CHAIN (elt))
{
- /* start of range of element or NULL */
+ /* Start of range of element or NULL. */
tree startbit = TREE_PURPOSE (elt);
- /* end of range of element, or element value */
+ /* End of range of element, or element value. */
tree endbit = TREE_VALUE (elt);
#ifdef TARGET_MEM_FUNCTIONS
HOST_WIDE_INT startb, endb;
#endif
- rtx bitlength_rtx, startbit_rtx, endbit_rtx, targetx;
+ rtx bitlength_rtx, startbit_rtx, endbit_rtx, targetx;
bitlength_rtx = expand_expr (bitlength,
- NULL_RTX, MEM, EXPAND_CONST_ADDRESS);
+ NULL_RTX, MEM, EXPAND_CONST_ADDRESS);
- /* handle non-range tuple element like [ expr ] */
+ /* Handle non-range tuple element like [ expr ]. */
if (startbit == NULL_TREE)
{
startbit = save_expr (endbit);
endbit = startbit;
}
+
startbit = convert (sizetype, startbit);
endbit = convert (sizetype, endbit);
if (! integer_zerop (domain_min))
startbit = size_binop (MINUS_EXPR, startbit, domain_min);
endbit = size_binop (MINUS_EXPR, endbit, domain_min);
}
- startbit_rtx = expand_expr (startbit, NULL_RTX, MEM,
+ startbit_rtx = expand_expr (startbit, NULL_RTX, MEM,
EXPAND_CONST_ADDRESS);
- endbit_rtx = expand_expr (endbit, NULL_RTX, MEM,
+ endbit_rtx = expand_expr (endbit, NULL_RTX, MEM,
EXPAND_CONST_ADDRESS);
if (REG_P (target))
0);
emit_move_insn (targetx, target);
}
+
else if (GET_CODE (target) == MEM)
targetx = target;
else
&& (startb = TREE_INT_CST_LOW (startbit)) % BITS_PER_UNIT == 0
&& (endb = TREE_INT_CST_LOW (endbit) + 1) % BITS_PER_UNIT == 0)
{
- emit_library_call (memset_libfunc, 0,
+ emit_library_call (memset_libfunc, LCT_NORMAL,
VOIDmode, 3,
plus_constant (XEXP (targetx, 0),
startb / BITS_PER_UNIT),
}
else
#endif
- {
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__setbits"),
- 0, VOIDmode, 4, XEXP (targetx, 0), Pmode,
- bitlength_rtx, TYPE_MODE (sizetype),
- startbit_rtx, TYPE_MODE (sizetype),
- endbit_rtx, TYPE_MODE (sizetype));
- }
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__setbits"),
+ LCT_NORMAL, VOIDmode, 4, XEXP (targetx, 0),
+ Pmode, bitlength_rtx, TYPE_MODE (sizetype),
+ startbit_rtx, TYPE_MODE (sizetype),
+ endbit_rtx, TYPE_MODE (sizetype));
+
if (REG_P (target))
emit_move_insn (target, targetx);
}
has mode VALUE_MODE if that is convenient to do.
In this case, UNSIGNEDP must be nonzero if the value is an unsigned type.
- ALIGN is the alignment that TARGET is known to have, measured in bytes.
- TOTAL_SIZE is the size in bytes of the structure, or -1 if varying.
+ ALIGN is the alignment that TARGET is known to have.
+ TOTAL_SIZE is the size in bytes of the structure, or -1 if varying.
ALIAS_SET is the alias set for the destination. This value will
(in general) be different from that for TARGET, since TARGET is a
store_field (target, bitsize, bitpos, mode, exp, value_mode,
unsignedp, align, total_size, alias_set)
rtx target;
- int bitsize, bitpos;
+ HOST_WIDE_INT bitsize;
+ HOST_WIDE_INT bitpos;
enum machine_mode mode;
tree exp;
enum machine_mode value_mode;
int unsignedp;
unsigned int align;
- int total_size;
+ HOST_WIDE_INT total_size;
int alias_set;
{
HOST_WIDE_INT width_mask = 0;
return blk_object;
}
+ if (GET_CODE (target) == CONCAT)
+ {
+ /* We're storing into a struct containing a single __complex. */
+
+ if (bitpos != 0)
+ abort ();
+ return store_expr (exp, target, 0);
+ }
+
/* If the structure is in a register or if the component
is a bit field, we cannot use addressing to access it.
Use bit-field techniques or SUBREG to store in it. */
/* If the field isn't aligned enough to store as an ordinary memref,
store it as a bit field. */
|| (mode != BLKmode && SLOW_UNALIGNED_ACCESS (mode, align)
- && (align * BITS_PER_UNIT < GET_MODE_ALIGNMENT (mode)
+ && (align < GET_MODE_ALIGNMENT (mode)
|| bitpos % GET_MODE_ALIGNMENT (mode)))
|| (mode == BLKmode && SLOW_UNALIGNED_ACCESS (mode, align)
- && (TYPE_ALIGN (TREE_TYPE (exp)) > align * BITS_PER_UNIT
+ && (TYPE_ALIGN (TREE_TYPE (exp)) > align
|| bitpos % TYPE_ALIGN (TREE_TYPE (exp)) != 0))
/* If the RHS and field are a constant size and the size of the
RHS isn't the same size as the bitfield, we must use bitfield
operations. */
- || ((bitsize >= 0
- && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST)
- && (TREE_INT_CST_HIGH (TYPE_SIZE (TREE_TYPE (exp))) != 0
- || TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))) != bitsize)))
+ || (bitsize >= 0
+ && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
+ && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0))
{
rtx temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
boundary. If so, we simply do a block copy. */
if (GET_MODE (target) == BLKmode && GET_MODE (temp) == BLKmode)
{
- unsigned int exp_align = expr_align (exp) / BITS_PER_UNIT;
+ unsigned int exp_align = expr_align (exp);
if (GET_CODE (target) != MEM || GET_CODE (temp) != MEM
|| bitpos % BITS_PER_UNIT != 0)
align = MIN (exp_align, align);
/* Find an alignment that is consistent with the bit position. */
- while ((bitpos % (align * BITS_PER_UNIT)) != 0)
+ while ((bitpos % align) != 0)
align >>= 1;
emit_block_move (target, temp,
- GEN_INT ((bitsize + BITS_PER_UNIT - 1)
- / BITS_PER_UNIT),
+ bitsize == -1 ? expr_size (exp)
+ : GEN_INT ((bitsize + BITS_PER_UNIT - 1)
+ / BITS_PER_UNIT),
align);
return value_mode == VOIDmode ? const0_rtx : target;
giving the variable offset (in units) in *POFFSET.
This offset is in addition to the bit position.
If the position is not variable, we store 0 in *POFFSET.
- We set *PALIGNMENT to the alignment in bytes of the address that will be
+ We set *PALIGNMENT to the alignment of the address that will be
computed. This is the alignment of the thing we return if *POFFSET
is zero, but can be more less strictly aligned if *POFFSET is nonzero.
get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
punsignedp, pvolatilep, palignment)
tree exp;
- int *pbitsize;
- int *pbitpos;
+ HOST_WIDE_INT *pbitsize;
+ HOST_WIDE_INT *pbitpos;
tree *poffset;
enum machine_mode *pmode;
int *punsignedp;
int *pvolatilep;
unsigned int *palignment;
{
- tree orig_exp = exp;
tree size_tree = 0;
enum machine_mode mode = VOIDmode;
tree offset = size_zero_node;
+ tree bit_offset = bitsize_zero_node;
unsigned int alignment = BIGGEST_ALIGNMENT;
+ tree tem;
+ /* First get the mode, signedness, and size. We do this from just the
+ 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));
+
*punsignedp = TREE_UNSIGNED (TREE_OPERAND (exp, 1));
}
else if (TREE_CODE (exp) == BIT_FIELD_REF)
else
{
mode = TYPE_MODE (TREE_TYPE (exp));
+ *punsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
+
if (mode == BLKmode)
size_tree = TYPE_SIZE (TREE_TYPE (exp));
-
- *pbitsize = GET_MODE_BITSIZE (mode);
- *punsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
+ else
+ *pbitsize = GET_MODE_BITSIZE (mode);
}
-
- if (size_tree)
+
+ if (size_tree != 0)
{
- if (TREE_CODE (size_tree) != INTEGER_CST)
+ if (! host_integerp (size_tree, 1))
mode = BLKmode, *pbitsize = -1;
else
- *pbitsize = TREE_INT_CST_LOW (size_tree);
+ *pbitsize = tree_low_cst (size_tree, 1);
}
/* Compute cumulative bit-offset for nested component-refs and array-refs,
and find the ultimate containing object. */
-
- *pbitpos = 0;
-
while (1)
{
- if (TREE_CODE (exp) == COMPONENT_REF || TREE_CODE (exp) == BIT_FIELD_REF)
+ if (TREE_CODE (exp) == BIT_FIELD_REF)
+ bit_offset = size_binop (PLUS_EXPR, bit_offset, TREE_OPERAND (exp, 2));
+ else if (TREE_CODE (exp) == COMPONENT_REF)
{
- tree pos = (TREE_CODE (exp) == COMPONENT_REF
- ? DECL_FIELD_BITPOS (TREE_OPERAND (exp, 1))
- : TREE_OPERAND (exp, 2));
- tree constant = bitsize_int (0), var = pos;
+ tree field = TREE_OPERAND (exp, 1);
+ tree this_offset = DECL_FIELD_OFFSET (field);
/* If this field hasn't been filled in yet, don't go
past it. This should only happen when folding expressions
made during type construction. */
- if (pos == 0)
+ if (this_offset == 0)
break;
+ else if (! TREE_CONSTANT (this_offset)
+ && contains_placeholder_p (this_offset))
+ this_offset = build (WITH_RECORD_EXPR, sizetype, this_offset, exp);
- /* Assume here that the offset is a multiple of a unit.
- If not, there should be an explicitly added constant. */
- if (TREE_CODE (pos) == PLUS_EXPR
- && TREE_CODE (TREE_OPERAND (pos, 1)) == INTEGER_CST)
- constant = TREE_OPERAND (pos, 1), var = TREE_OPERAND (pos, 0);
- else if (TREE_CODE (pos) == INTEGER_CST)
- constant = pos, var = bitsize_int (0);
+ offset = size_binop (PLUS_EXPR, offset, this_offset);
+ bit_offset = size_binop (PLUS_EXPR, bit_offset,
+ DECL_FIELD_BIT_OFFSET (field));
- *pbitpos += TREE_INT_CST_LOW (constant);
- offset
- = size_binop (PLUS_EXPR, offset,
- convert (sizetype,
- size_binop (EXACT_DIV_EXPR, var,
- bitsize_int (BITS_PER_UNIT))));
+ if (! host_integerp (offset, 0))
+ alignment = MIN (alignment, DECL_OFFSET_ALIGN (field));
}
else if (TREE_CODE (exp) == ARRAY_REF)
{
- /* This code is based on the code in case ARRAY_REF in expand_expr
- below. We assume here that the size of an array element is
- always an integral multiple of BITS_PER_UNIT. */
-
tree index = TREE_OPERAND (exp, 1);
tree domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
- tree low_bound
- = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
- tree index_type = TREE_TYPE (index);
- tree xindex;
-
- if (TYPE_PRECISION (index_type) != TYPE_PRECISION (sizetype))
- {
- index = convert (type_for_size (TYPE_PRECISION (sizetype), 0),
- index);
- index_type = TREE_TYPE (index);
- }
-
- /* Optimize the special-case of a zero lower bound.
-
- We convert the low_bound to sizetype to avoid some problems
- with constant folding. (E.g. suppose the lower bound is 1,
- and its mode is QI. Without the conversion, (ARRAY
- +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1))
- +INDEX), which becomes (ARRAY+255+INDEX). Oops!)
-
- But sizetype isn't quite right either (especially if
- the lowbound is negative). FIXME */
-
- if (! integer_zerop (low_bound))
- index = fold (build (MINUS_EXPR, index_type, index,
- convert (sizetype, low_bound)));
-
- if (TREE_CODE (index) == INTEGER_CST)
- {
- index = convert (sbitsizetype, index);
- index_type = TREE_TYPE (index);
- }
-
- xindex = fold (build (MULT_EXPR, sbitsizetype, index,
- convert (sbitsizetype,
- TYPE_SIZE (TREE_TYPE (exp)))));
-
- if (TREE_CODE (xindex) == INTEGER_CST
- && TREE_INT_CST_HIGH (xindex) == 0)
- *pbitpos += TREE_INT_CST_LOW (xindex);
- else
- {
- /* Either the bit offset calculated above is not constant, or
- it overflowed. In either case, redo the multiplication
- against the size in units. This is especially important
- in the non-constant case to avoid a division at runtime. */
- xindex
- = fold (build (MULT_EXPR, ssizetype, index,
- convert (ssizetype,
- TYPE_SIZE_UNIT (TREE_TYPE (exp)))));
-
- if (contains_placeholder_p (xindex))
- xindex = build (WITH_RECORD_EXPR, ssizetype, xindex, exp);
-
- offset
- = size_binop (PLUS_EXPR, offset, convert (sizetype, xindex));
- }
+ tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0);
+ tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (exp));
+
+ /* We assume all arrays have sizes that are a multiple of a byte.
+ First subtract the lower bound, if any, in the type of the
+ index, then convert to sizetype and multiply by the size of the
+ array element. */
+ if (low_bound != 0 && ! integer_zerop (low_bound))
+ index = fold (build (MINUS_EXPR, TREE_TYPE (index),
+ index, low_bound));
+
+ /* If the index has a self-referential type, pass it to a
+ WITH_RECORD_EXPR; if the component size is, pass our
+ component to one. */
+ if (! TREE_CONSTANT (index)
+ && contains_placeholder_p (index))
+ index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, exp);
+ if (! TREE_CONSTANT (unit_size)
+ && contains_placeholder_p (unit_size))
+ unit_size = build (WITH_RECORD_EXPR, sizetype, unit_size,
+ TREE_OPERAND (exp, 0));
+
+ offset = size_binop (PLUS_EXPR, offset,
+ size_binop (MULT_EXPR,
+ convert (sizetype, index),
+ unit_size));
}
+
else if (TREE_CODE (exp) != NON_LVALUE_EXPR
&& ! ((TREE_CODE (exp) == NOP_EXPR
|| TREE_CODE (exp) == CONVERT_EXPR)
/* If the offset is non-constant already, then we can't assume any
alignment more than the alignment here. */
- if (! integer_zerop (offset))
+ if (! TREE_CONSTANT (offset))
alignment = MIN (alignment, TYPE_ALIGN (TREE_TYPE (exp)));
exp = TREE_OPERAND (exp, 0);
}
- if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd')
+ if (DECL_P (exp))
alignment = MIN (alignment, DECL_ALIGN (exp));
else if (TREE_TYPE (exp) != 0)
alignment = MIN (alignment, TYPE_ALIGN (TREE_TYPE (exp)));
- if (integer_zerop (offset))
- offset = 0;
-
- if (offset != 0 && contains_placeholder_p (offset))
- offset = build (WITH_RECORD_EXPR, sizetype, offset, orig_exp);
+ /* If OFFSET is constant, see if we can return the whole thing as a
+ constant bit position. Otherwise, split it up. */
+ if (host_integerp (offset, 0)
+ && 0 != (tem = size_binop (MULT_EXPR, convert (bitsizetype, offset),
+ bitsize_unit_node))
+ && 0 != (tem = size_binop (PLUS_EXPR, tem, bit_offset))
+ && host_integerp (tem, 0))
+ *pbitpos = tree_low_cst (tem, 0), *poffset = 0;
+ else
+ *pbitpos = tree_low_cst (bit_offset, 0), *poffset = offset;
*pmode = mode;
- *poffset = offset;
- *palignment = alignment / BITS_PER_UNIT;
+ *palignment = alignment;
return exp;
}
/* Subroutine of expand_exp: compute memory_usage from modifier. */
+
static enum memory_use_mode
get_memory_usage_from_modifier (modifier)
enum expand_modifier modifier;
rtx tmp;
register rtx op2;
/* Use subtarget as the target for operand 0 of a binary operation. */
- register rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
+ register rtx subtarget = get_subtarget (target);
/* Check for a PIC address load. */
if (flag_pic
force_operand (XEXP (XEXP (value, 0), 1), 0),
target, 0, OPTAB_LIB_WIDEN);
}
-
+
tmp = force_operand (XEXP (value, 0), subtarget);
return expand_binop (GET_MODE (value), binoptab, tmp,
force_operand (op2, NULL_RTX),
It is always safe for this routine to return zero since it merely
searches for optimization opportunities. */
-static int
+int
safe_from_p (x, exp, top_p)
rtx x;
tree exp;
So we assume here that something at a higher level has prevented a
clash. This is somewhat bogus, but the best we can do. Only
do this when X is BLKmode and when we are at the top level. */
- || (top_p && TREE_TYPE (exp) != 0 && TYPE_SIZE (TREE_TYPE (exp)) != 0
+ || (top_p && TREE_TYPE (exp) != 0 && COMPLETE_TYPE_P (TREE_TYPE (exp))
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST
&& (TREE_CODE (TREE_TYPE (exp)) != ARRAY_TYPE
|| TYPE_ARRAY_MAX_SIZE (TREE_TYPE (exp)) == NULL_TREE
int rtn;
save_expr_count = 0;
- save_expr_size = sizeof (save_expr_trees) / sizeof (save_expr_trees[0]);
+ save_expr_size = ARRAY_SIZE (save_expr_trees);
save_expr_rewritten = &save_expr_trees[0];
rtn = safe_from_p (x, exp, 1);
where it is so we can turn it back in the top-level safe_from_p()
when we're done. */
- /* For now, don't bother re-sizing the array. */
+ /* For now, don't bother re-sizing the array. */
if (save_expr_count >= save_expr_size)
return 0;
save_expr_rewritten[save_expr_count++] = exp;
- nops = tree_code_length[(int) SAVE_EXPR];
+ nops = TREE_CODE_LENGTH (SAVE_EXPR);
for (i = 0; i < nops; i++)
{
tree operand = TREE_OPERAND (exp, i);
case METHOD_CALL_EXPR:
/* This takes a rtx argument, but shouldn't appear here. */
abort ();
-
+
default:
break;
}
if (exp_rtl)
break;
- nops = tree_code_length[(int) TREE_CODE (exp)];
+ nops = first_rtl_op (TREE_CODE (exp));
for (i = 0; i < nops; i++)
if (TREE_OPERAND (exp, i) != 0
&& ! safe_from_p (x, TREE_OPERAND (exp, i), 0))
return 0;
+
+ /* If this is a language-specific tree code, it may require
+ special handling. */
+ if (TREE_CODE (exp) >= LAST_AND_UNUSED_TREE_CODE
+ && lang_safe_from_p
+ && !(*lang_safe_from_p) (x, exp))
+ return 0;
}
/* If we have an rtl, find any enclosed object. Then see if we conflict
#ifdef MAX_INTEGER_COMPUTATION_MODE
void
check_max_integer_computation_mode (exp)
- tree exp;
+ tree exp;
{
enum tree_code code;
enum machine_mode mode;
&& mode > MAX_INTEGER_COMPUTATION_MODE)
fatal ("unsupported wide integer operation");
}
-
+
/* Check operands of a binary/comparison op. */
if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<')
{
}
}
#endif
-
\f
/* Utility function used by expand_expr to see if TYPE, a RECORD_TYPE,
has any readonly fields. If any of the fields have types that
tree field;
for (field = TYPE_FIELDS (type); field != 0; field = TREE_CHAIN (field))
- if (TREE_CODE (field) == FIELD_DECL
+ if (TREE_CODE (field) == FIELD_DECL
&& (TREE_READONLY (field)
|| (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
&& readonly_fields_p (TREE_TYPE (field)))))
/* Used by check-memory-usage to make modifier read only. */
enum expand_modifier ro_modifier;
- /* Handle ERROR_MARK before anybody tries to access its type. */
- if (TREE_CODE (exp) == ERROR_MARK)
+ /* Handle ERROR_MARK before anybody tries to access its type. */
+ if (TREE_CODE (exp) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
{
op0 = CONST0_RTX (tmode);
if (op0 != 0)
mode = TYPE_MODE (type);
/* Use subtarget as the target for operand 0 of a binary operation. */
- subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
+ subtarget = get_subtarget (target);
original_target = target;
ignore = (target == const0_rtx
|| ((code == NON_LVALUE_EXPR || code == NOP_EXPR
else
ro_modifier = EXPAND_NORMAL;
- /* Don't use hard regs as subtargets, because the combiner
- can only handle pseudo regs. */
- if (subtarget && REGNO (subtarget) < FIRST_PSEUDO_REGISTER)
- subtarget = 0;
- /* Avoid subtargets inside loops,
- since they hide some invariant expressions. */
- if (preserve_subexpressions_p ())
- subtarget = 0;
-
/* 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
return expand_expr (TREE_OPERAND (exp, 0), const0_rtx,
VOIDmode, ro_modifier);
else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<'
- || code == ARRAY_REF)
+ || code == ARRAY_REF)
{
expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, ro_modifier);
expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, ro_modifier);
expand_expr (TREE_OPERAND (exp, 2), const0_rtx, VOIDmode, ro_modifier);
return const0_rtx;
}
-;
+ ;
target = 0;
}
case VAR_DECL:
/* If a static var's type was incomplete when the decl was written,
but the type is complete now, lay out the decl now. */
- if (DECL_SIZE (exp) == 0 && TYPE_SIZE (TREE_TYPE (exp)) != 0
+ if (DECL_SIZE (exp) == 0 && COMPLETE_TYPE_P (TREE_TYPE (exp))
&& (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
{
push_obstacks_nochange ();
enum memory_use_mode memory_usage;
memory_usage = get_memory_usage_from_modifier (modifier);
+ in_check_memory_usage = 1;
if (memory_usage != MEMORY_USE_DONT)
- emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
+ emit_library_call (chkr_check_addr_libfunc,
+ LCT_CONST_MAKE_BLOCK, VOIDmode, 3,
XEXP (DECL_RTL (exp), 0), Pmode,
GEN_INT (int_size_in_bytes (type)),
TYPE_MODE (sizetype),
GEN_INT (memory_usage),
TYPE_MODE (integer_type_node));
+ in_check_memory_usage = 0;
}
/* ... fall through ... */
abort ();
addr = XEXP (DECL_RTL (exp), 0);
if (GET_CODE (addr) == MEM)
- addr = gen_rtx_MEM (Pmode,
- fix_lexical_addr (XEXP (addr, 0), exp));
+ addr = change_address (addr, Pmode,
+ fix_lexical_addr (XEXP (addr, 0), exp));
else
addr = fix_lexical_addr (addr, exp);
+
temp = change_address (DECL_RTL (exp), mode, addr);
}
if (temp != 0)
{
if (GET_CODE (temp) == MEM && GET_CODE (XEXP (temp, 0)) == REG)
- mark_reg_pointer (XEXP (temp, 0),
- DECL_ALIGN (exp) / BITS_PER_UNIT);
+ mark_reg_pointer (XEXP (temp, 0), DECL_ALIGN (exp));
return temp;
}
case INTEGER_CST:
return immed_double_const (TREE_INT_CST_LOW (exp),
- TREE_INT_CST_HIGH (exp),
- mode);
+ TREE_INT_CST_HIGH (exp), mode);
case CONST_DECL:
return expand_expr (DECL_INITIAL (exp), target, VOIDmode,
- EXPAND_MEMORY_USE_BAD);
+ EXPAND_MEMORY_USE_BAD);
case REAL_CST:
/* If optimized, generate immediate CONST_DOUBLE
- which will be turned into memory by reload if necessary.
-
+ which will be turned into memory by reload if necessary.
+
We used to force a register so that loop.c could see it. But
this does not allow gen_* patterns to perform optimizations with
the constants. It also produces two insns in cases like "x = 1.0;".
case EXPR_WITH_FILE_LOCATION:
{
rtx to_return;
- char *saved_input_filename = input_filename;
+ const char *saved_input_filename = input_filename;
int saved_lineno = lineno;
input_filename = EXPR_WFL_FILENAME (exp);
lineno = EXPR_WFL_LINENO (exp);
if (EXPR_WFL_EMIT_LINE_NOTE (exp))
emit_line_note (input_filename, lineno);
- /* Possibly avoid switching back and force here */
+ /* Possibly avoid switching back and force here. */
to_return = expand_expr (EXPR_WFL_NODE (exp), target, tmode, modifier);
input_filename = saved_input_filename;
lineno = saved_lineno;
tree elt;
/* Find the outermost reference that is of the type we want.
- If none, see if any object has a type that is a pointer to
+ If none, see if any object has a type that is a pointer to
the type we want. */
for (elt = TREE_PURPOSE (placeholder_expr);
elt != 0 && object == 0;
&& ((mode == BLKmode
&& ! (target != 0 && safe_from_p (target, exp, 1)))
|| TREE_ADDRESSABLE (exp)
- || (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
- && (!MOVE_BY_PIECES_P
- (TREE_INT_CST_LOW (TYPE_SIZE (type))/BITS_PER_UNIT,
- TYPE_ALIGN (type) / BITS_PER_UNIT))
+ || (host_integerp (TYPE_SIZE_UNIT (type), 1)
+ && (! MOVE_BY_PIECES_P
+ (tree_low_cst (TYPE_SIZE_UNIT (type), 1),
+ TYPE_ALIGN (type)))
&& ! mostly_zeros_p (exp))))
|| (modifier == EXPAND_INITIALIZER && TREE_CONSTANT (exp)))
{
rtx constructor = output_constant_def (exp);
+
if (modifier != EXPAND_CONST_ADDRESS
&& modifier != EXPAND_INITIALIZER
&& modifier != EXPAND_SUM
case INDIRECT_REF:
{
tree exp1 = TREE_OPERAND (exp, 0);
- tree exp2;
tree index;
- tree string = string_constant (exp1, &index);
- int i;
-
+ tree string = string_constant (exp1, &index);
+
/* Try to optimize reads from const strings. */
if (string
&& TREE_CODE (string) == STRING_CST
&& TREE_CODE (index) == INTEGER_CST
- && !TREE_INT_CST_HIGH (index)
- && (i = TREE_INT_CST_LOW (index)) < TREE_STRING_LENGTH (string)
+ && compare_tree_int (index, TREE_STRING_LENGTH (string)) < 0
&& GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == 1
&& modifier != EXPAND_MEMORY_USE_WO)
- return GEN_INT (TREE_STRING_POINTER (string)[i]);
+ return
+ GEN_INT (TREE_STRING_POINTER (string)[TREE_INT_CST_LOW (index)]);
op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
op0 = memory_address (mode, op0);
if (memory_usage != MEMORY_USE_DONT)
{
in_check_memory_usage = 1;
- emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
- op0, Pmode,
- GEN_INT (int_size_in_bytes (type)),
+ emit_library_call (chkr_check_addr_libfunc,
+ LCT_CONST_MAKE_BLOCK, VOIDmode, 3, op0,
+ Pmode, GEN_INT (int_size_in_bytes (type)),
TYPE_MODE (sizetype),
GEN_INT (memory_usage),
TYPE_MODE (integer_type_node));
}
temp = gen_rtx_MEM (mode, op0);
- /* If address was computed by addition,
- mark this as an element of an aggregate. */
- if (TREE_CODE (exp1) == PLUS_EXPR
- || (TREE_CODE (exp1) == SAVE_EXPR
- && TREE_CODE (TREE_OPERAND (exp1, 0)) == PLUS_EXPR)
- || AGGREGATE_TYPE_P (TREE_TYPE (exp))
- || (TREE_CODE (exp1) == ADDR_EXPR
- && (exp2 = TREE_OPERAND (exp1, 0))
- && AGGREGATE_TYPE_P (TREE_TYPE (exp2))))
- MEM_SET_IN_STRUCT_P (temp, 1);
-
- MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp) | flag_volatile;
- MEM_ALIAS_SET (temp) = get_alias_set (exp);
+ set_mem_attributes (temp, exp, 0);
/* It is incorrect to set RTX_UNCHANGING_P from TREE_READONLY
here, because, in C and C++, the fact that a location is accessed
if (TREE_CODE (array) == STRING_CST
&& TREE_CODE (index) == INTEGER_CST
- && !TREE_INT_CST_HIGH (index)
- && (i = TREE_INT_CST_LOW (index)) < TREE_STRING_LENGTH (array)
+ && compare_tree_int (index, TREE_STRING_LENGTH (array)) < 0
&& GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == 1)
- return GEN_INT (TREE_STRING_POINTER (array)[i]);
+ return
+ GEN_INT (TREE_STRING_POINTER (array)[TREE_INT_CST_LOW (index)]);
/* If this is a constant index into a constant array,
just get the value from the array. Handle both the cases when
we have an explicit constructor and when our operand is a variable
that was declared const. */
- if (TREE_CODE (array) == CONSTRUCTOR && ! TREE_SIDE_EFFECTS (array))
+ if (TREE_CODE (array) == CONSTRUCTOR && ! TREE_SIDE_EFFECTS (array)
+ && TREE_CODE (index) == INTEGER_CST
+ && 0 > compare_tree_int (index,
+ list_length (CONSTRUCTOR_ELTS
+ (TREE_OPERAND (exp, 0)))))
{
- if (TREE_CODE (index) == INTEGER_CST
- && TREE_INT_CST_HIGH (index) == 0)
- {
- tree elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
-
- i = TREE_INT_CST_LOW (index);
- while (elem && i--)
- elem = TREE_CHAIN (elem);
- if (elem)
- return expand_expr (fold (TREE_VALUE (elem)), target,
- tmode, ro_modifier);
- }
+ tree elem;
+
+ for (elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)),
+ i = TREE_INT_CST_LOW (index);
+ elem != 0 && i != 0; i--, elem = TREE_CHAIN (elem))
+ ;
+
+ if (elem)
+ return expand_expr (fold (TREE_VALUE (elem)), target,
+ tmode, ro_modifier);
}
-
+
else if (optimize >= 1
&& TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
&& TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
{
tree init = DECL_INITIAL (array);
- i = TREE_INT_CST_LOW (index);
if (TREE_CODE (init) == CONSTRUCTOR)
{
- tree elem = CONSTRUCTOR_ELTS (init);
+ tree elem;
+
+ for (elem = CONSTRUCTOR_ELTS (init);
+ (elem
+ && !tree_int_cst_equal (TREE_PURPOSE (elem), index));
+ elem = TREE_CHAIN (elem))
+ ;
- while (elem
- && !tree_int_cst_equal (TREE_PURPOSE (elem), index))
- elem = TREE_CHAIN (elem);
if (elem)
return expand_expr (fold (TREE_VALUE (elem)), target,
tmode, ro_modifier);
}
else if (TREE_CODE (init) == STRING_CST
- && TREE_INT_CST_HIGH (index) == 0
- && (TREE_INT_CST_LOW (index)
- < TREE_STRING_LENGTH (init)))
- return (GEN_INT
- (TREE_STRING_POINTER
- (init)[TREE_INT_CST_LOW (index)]));
+ && 0 > compare_tree_int (index,
+ TREE_STRING_LENGTH (init)))
+ {
+ tree type = TREE_TYPE (TREE_TYPE (init));
+ enum machine_mode mode = TYPE_MODE (type);
+
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && GET_MODE_SIZE (mode) == 1)
+ return (GEN_INT
+ (TREE_STRING_POINTER
+ (init)[TREE_INT_CST_LOW (index)]));
+ }
}
}
}
-
- /* ... fall through ... */
+ /* Fall through. */
case COMPONENT_REF:
case BIT_FIELD_REF:
&& (GET_MODE_BITSIZE (DECL_MODE (TREE_PURPOSE (elt)))
<= HOST_BITS_PER_WIDE_INT))))
{
- op0 = expand_expr (TREE_VALUE (elt), target, tmode, modifier);
+ op0 = expand_expr (TREE_VALUE (elt), target, tmode, modifier);
if (DECL_BIT_FIELD (TREE_PURPOSE (elt)))
{
HOST_WIDE_INT bitsize
{
enum machine_mode mode1;
- int bitsize;
- int bitpos;
+ HOST_WIDE_INT bitsize, bitpos;
tree offset;
int volatilep = 0;
unsigned int alignment;
/* If TEM's type is a union of variable size, pass TARGET to the inner
computation, since it will need a temporary and TARGET is known
to have to do. This occurs in unchecked conversion in Ada. */
-
+
op0 = expand_expr (tem,
(TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
&& (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
&& GET_MODE (op0) == BLKmode
&& GET_MODE (XEXP (op0, 0)) != VOIDmode
&& bitsize != 0
- && (bitpos % bitsize) == 0
+ && (bitpos % bitsize) == 0
&& (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
- && (alignment * BITS_PER_UNIT) == GET_MODE_ALIGNMENT (mode1))
+ && alignment == GET_MODE_ALIGNMENT (mode1))
{
rtx temp = change_address (op0, mode1,
plus_constant (XEXP (op0, 0),
bitpos = 0;
}
-
op0 = change_address (op0, VOIDmode,
gen_rtx_PLUS (ptr_mode, XEXP (op0, 0),
force_reg (ptr_mode,
}
/* Check the access. */
- if (current_function_check_memory_usage && GET_CODE (op0) == MEM)
- {
+ if (cfun != 0 && current_function_check_memory_usage
+ && GET_CODE (op0) == MEM)
+ {
enum memory_use_mode memory_usage;
memory_usage = get_memory_usage_from_modifier (modifier);
size = (bitpos % BITS_PER_UNIT) + bitsize + BITS_PER_UNIT - 1;
/* Check the access right of the pointer. */
+ in_check_memory_usage = 1;
if (size > BITS_PER_UNIT)
- emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
- to, Pmode,
- GEN_INT (size / BITS_PER_UNIT),
+ emit_library_call (chkr_check_addr_libfunc,
+ LCT_CONST_MAKE_BLOCK, VOIDmode, 3, to,
+ Pmode, GEN_INT (size / BITS_PER_UNIT),
TYPE_MODE (sizetype),
- GEN_INT (memory_usage),
+ GEN_INT (memory_usage),
TYPE_MODE (integer_type_node));
+ in_check_memory_usage = 0;
}
}
|| (mode1 != BLKmode
&& SLOW_UNALIGNED_ACCESS (mode1, alignment)
&& ((TYPE_ALIGN (TREE_TYPE (tem))
- < (unsigned int) GET_MODE_ALIGNMENT (mode))
- || (bitpos % GET_MODE_ALIGNMENT (mode) != 0)))))
+ < GET_MODE_ALIGNMENT (mode))
+ || (bitpos % GET_MODE_ALIGNMENT (mode) != 0)))
+ /* If the type and the field are a constant size and the
+ size of the type isn't the same size as the bitfield,
+ we must use bitfield operations. */
+ || ((bitsize >= 0
+ && (TREE_CODE (TYPE_SIZE (TREE_TYPE (exp)))
+ == INTEGER_CST)
+ && 0 != compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)),
+ bitsize)))))
|| (modifier != EXPAND_CONST_ADDRESS
&& modifier != EXPAND_INITIALIZER
&& mode == BLKmode
&& SLOW_UNALIGNED_ACCESS (mode, alignment)
- && (TYPE_ALIGN (type) > alignment * BITS_PER_UNIT
+ && (TYPE_ALIGN (type) > alignment
|| bitpos % TYPE_ALIGN (type) != 0)))
{
enum machine_mode ext_mode = mode;
target = assign_temp (type, 0, 1, 1);
emit_block_move (target, op0,
- GEN_INT ((bitsize + BITS_PER_UNIT - 1)
- / BITS_PER_UNIT),
- 1);
-
+ bitsize == -1 ? expr_size (exp)
+ : GEN_INT ((bitsize + BITS_PER_UNIT - 1)
+ / BITS_PER_UNIT),
+ BITS_PER_UNIT);
+
return target;
}
/* Get a reference to just this component. */
if (modifier == EXPAND_CONST_ADDRESS
|| modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
- op0 = gen_rtx_MEM (mode1, plus_constant (XEXP (op0, 0),
- (bitpos / BITS_PER_UNIT)));
+ {
+ rtx new = gen_rtx_MEM (mode1,
+ plus_constant (XEXP (op0, 0),
+ (bitpos / BITS_PER_UNIT)));
+
+ MEM_COPY_ATTRIBUTES (new, op0);
+ op0 = new;
+ }
else
op0 = change_address (op0, mode1,
plus_constant (XEXP (op0, 0),
(bitpos / BITS_PER_UNIT)));
- if (GET_CODE (op0) == MEM)
- MEM_ALIAS_SET (op0) = get_alias_set (exp);
-
+ set_mem_attributes (op0, exp, 0);
if (GET_CODE (XEXP (op0, 0)) == REG)
mark_reg_pointer (XEXP (op0, 0), alignment);
- MEM_SET_IN_STRUCT_P (op0, 1);
MEM_VOLATILE_P (op0) |= volatilep;
if (mode == mode1 || mode1 == BLKmode || mode1 == tmode
|| modifier == EXPAND_CONST_ADDRESS
of the set. */
if (GET_CODE (lo_r) == CONST_INT)
rlow = GEN_INT (INTVAL (lo_r)
- & ~ ((HOST_WIDE_INT) 1 << BITS_PER_UNIT));
+ & ~((HOST_WIDE_INT) 1 << BITS_PER_UNIT));
else
rlow = expand_binop (index_mode, and_optab, lo_r,
GEN_INT (~((HOST_WIDE_INT) 1 << BITS_PER_UNIT)),
setaddr, NULL_RTX, iunsignedp,
OPTAB_LIB_WIDEN));
- /* Extract the bit we want to examine */
+ /* Extract the bit we want to examine. */
bit = expand_shift (RSHIFT_EXPR, byte_mode,
gen_rtx_MEM (byte_mode, addr),
make_tree (TREE_TYPE (index), rem),
&& (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
== FUNCTION_DECL)
&& DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
- return expand_builtin (exp, target, subtarget, tmode, ignore);
+ {
+ if (DECL_BUILT_IN_CLASS (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
+ == BUILT_IN_FRONTEND)
+ return (*lang_expand_expr) (exp, original_target, tmode, modifier);
+ else
+ return expand_builtin (exp, target, subtarget, tmode, ignore);
+ }
/* If this call was expanded already by preexpand_calls,
just return the result we got. */
case NOP_EXPR:
case CONVERT_EXPR:
case REFERENCE_EXPR:
+ if (TREE_OPERAND (exp, 0) == error_mark_node)
+ return const0_rtx;
+
if (TREE_CODE (type) == UNION_TYPE)
{
tree valtype = TREE_TYPE (TREE_OPERAND (exp, 0));
* BITS_PER_UNIT),
GET_MODE_BITSIZE (mode)),
0, TYPE_MODE (valtype), TREE_OPERAND (exp, 0),
- VOIDmode, 0, 1, int_size_in_bytes (type), 0);
+ VOIDmode, 0, BITS_PER_UNIT,
+ int_size_in_bytes (type), 0);
else
abort ();
op0 = eliminate_constant_term (op0, &constant_term);
/* CONSTANT_TERM and XEXP (op1, 1) are known to be constant, so
- their sum should be a constant. Form it into OP1, since the
+ their sum should be a constant. Form it into OP1, since the
result we want will then be OP0 + OP1. */
temp = simplify_binary_operation (PLUS, mode, constant_term,
op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
NULL_RTX, VOIDmode, 0);
if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
- op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
- VOIDmode, 0);
+ op1 = convert_modes (innermode, mode,
+ expand_expr (TREE_OPERAND (exp, 1),
+ NULL_RTX, VOIDmode, 0),
+ unsignedp);
else
op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
NULL_RTX, VOIDmode, 0);
/* At this point, a MEM target is no longer useful; we will get better
code without it. */
-
+
if (GET_CODE (target) == MEM)
target = gen_reg_rtx (mode);
/* If we are not to produce a result, we have no target. Otherwise,
if a target was specified use it; it will not be used as an
- intermediate target unless it is safe. If no target, use a
+ intermediate target unless it is safe. If no target, use a
temporary. */
if (ignore)
TREE_OPERAND (exp, 0)
= invert_truthvalue (TREE_OPERAND (exp, 0));
}
-
+
do_pending_stack_adjust ();
NO_DEFER_POP;
op0 = gen_label_rtx ();
|| TREE_CODE (TREE_OPERAND (exp, 1)) == SAVE_EXPR)
&& safe_from_p (temp, TREE_OPERAND (exp, 2), 1))
{
- if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER)
+ if (GET_CODE (temp) == REG
+ && REGNO (temp) < FIRST_PSEUDO_REGISTER)
temp = gen_reg_rtx (mode);
store_expr (TREE_OPERAND (exp, 1), temp, 0);
jumpif (TREE_OPERAND (exp, 0), op0);
|| TREE_CODE (TREE_OPERAND (exp, 2)) == SAVE_EXPR)
&& safe_from_p (temp, TREE_OPERAND (exp, 1), 1))
{
- if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER)
+ if (GET_CODE (temp) == REG
+ && REGNO (temp) < FIRST_PSEUDO_REGISTER)
temp = gen_reg_rtx (mode);
store_expr (TREE_OPERAND (exp, 2), temp, 0);
jumpifnot (TREE_OPERAND (exp, 0), op0);
jumpifnot (TREE_OPERAND (exp, 0), op0);
start_cleanup_deferral ();
-
+
/* One branch of the cond can be void, if it never returns. For
- example A ? throw : E */
+ example A ? throw : E */
if (temp != 0
- && TREE_TYPE (TREE_OPERAND (exp, 1)) != void_type_node)
+ && TREE_TYPE (TREE_OPERAND (exp, 1)) != void_type_node)
store_expr (TREE_OPERAND (exp, 1), temp, 0);
else
expand_expr (TREE_OPERAND (exp, 1),
emit_label (op0);
start_cleanup_deferral ();
if (temp != 0
- && TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node)
+ && TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node)
store_expr (TREE_OPERAND (exp, 2), temp, 0);
else
expand_expr (TREE_OPERAND (exp, 2),
/* Set this here so that if we get a target that refers to a
register variable that's already been used, put_reg_into_stack
- knows that it should fix up those uses. */
+ knows that it should fix up those uses. */
TREE_USED (slot) = 1;
if (target == 0)
preserve_temp_slots (target);
DECL_RTL (slot) = target;
if (TREE_ADDRESSABLE (slot))
- {
- TREE_ADDRESSABLE (slot) = 0;
- mark_addressable (slot);
- }
+ put_var_into_stack (slot);
/* Since SLOT is not known to the called function
to belong to its stack frame, we must build an explicit
not target that we were passed in, as our target
parameter is only a hint. */
if (DECL_RTL (slot) != 0)
- {
- target = DECL_RTL (slot);
- /* If we have already expanded the slot, so don't do
+ {
+ target = DECL_RTL (slot);
+ /* If we have already expanded the slot, so don't do
it again. (mrs) */
- if (TREE_OPERAND (exp, 1) == NULL_TREE)
- return target;
+ if (TREE_OPERAND (exp, 1) == NULL_TREE)
+ return target;
}
else
{
/* If we must have an addressable slot, then make sure that
the RTL that we just stored in slot is OK. */
if (TREE_ADDRESSABLE (slot))
- {
- TREE_ADDRESSABLE (slot) = 0;
- mark_addressable (slot);
- }
+ put_var_into_stack (slot);
}
}
store_expr (exp1, target, 0);
expand_decl_cleanup (NULL_TREE, cleanups);
-
+
return target;
}
|| TREE_CODE (rhs) == BIT_AND_EXPR)
&& TREE_OPERAND (rhs, 0) == lhs
&& TREE_CODE (TREE_OPERAND (rhs, 1)) == COMPONENT_REF
- && TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (lhs, 1))) == 1
- && TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (TREE_OPERAND (rhs, 1), 1))) == 1)
+ && integer_onep (DECL_SIZE (TREE_OPERAND (lhs, 1)))
+ && integer_onep (DECL_SIZE (TREE_OPERAND (TREE_OPERAND (rhs, 1), 1))))
{
rtx label = gen_label_rtx ();
if (GET_CODE (op0) != MEM)
abort ();
-
+
if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
{
temp = XEXP (op0, 0);
if (GET_CODE (op0) == REG
&& ! REG_USERVAR_P (op0))
- mark_reg_pointer (op0, TYPE_ALIGN (TREE_TYPE (type)) / BITS_PER_UNIT);
+ mark_reg_pointer (op0, TYPE_ALIGN (TREE_TYPE (type)));
/* If we might have had a temp slot, add an equivalent address
for it. */
case REALPART_EXPR:
op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
return gen_realpart (mode, op0);
-
+
case IMAGPART_EXPR:
op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
return gen_imagpart (mode, op0);
enum machine_mode partmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
rtx imag_t;
rtx insns;
-
- op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
+
+ op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
if (! target)
target = gen_reg_rtx (mode);
-
+
start_sequence ();
/* Store the realpart and the negated imagpart to target. */
imag_t = gen_imagpart (partmode, target);
temp = expand_unop (partmode, neg_optab,
- gen_imagpart (partmode, op0), imag_t, 0);
+ gen_imagpart (partmode, op0), imag_t, 0);
if (temp != imag_t)
emit_move_insn (imag_t, temp);
insns = get_insns ();
end_sequence ();
- /* Conjugate should appear as a single unit
+ /* Conjugate should appear as a single unit
If TARGET is a CONCAT, we got insns like RD = RS, ID = - IS,
each with a separate pseudo as destination.
It's not correct for flow to treat them as a unit. */
return op0;
}
- case GOTO_SUBROUTINE_EXPR:
+ case GOTO_SUBROUTINE_EXPR:
{
rtx subr = (rtx) TREE_OPERAND (exp, 0);
rtx return_link = *(rtx *) &TREE_OPERAND (exp, 1);
rtx return_address = gen_label_rtx ();
- emit_move_insn (return_link, gen_rtx_LABEL_REF (Pmode, return_address));
+ emit_move_insn (return_link,
+ gen_rtx_LABEL_REF (Pmode, return_address));
emit_jump (subr);
emit_label (return_address);
return const0_rtx;
we have an explicit constructor and when our operand is a variable
that was declared const. */
- if (TREE_CODE (array) == CONSTRUCTOR && ! TREE_SIDE_EFFECTS (array))
+ if (TREE_CODE (array) == CONSTRUCTOR && ! TREE_SIDE_EFFECTS (array)
+ && 0 > compare_tree_int (index,
+ list_length (CONSTRUCTOR_ELTS
+ (TREE_OPERAND (exp, 0)))))
{
- if (TREE_CODE (index) == INTEGER_CST
- && TREE_INT_CST_HIGH (index) == 0)
- {
- tree elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
-
- i = TREE_INT_CST_LOW (index);
- while (elem && i--)
- elem = TREE_CHAIN (elem);
- if (elem)
- return expand_expr_unaligned (fold (TREE_VALUE (elem)),
- palign);
- }
+ tree elem;
+
+ for (elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)),
+ i = TREE_INT_CST_LOW (index);
+ elem != 0 && i != 0; i--, elem = TREE_CHAIN (elem))
+ ;
+
+ if (elem)
+ return expand_expr_unaligned (fold (TREE_VALUE (elem)), palign);
}
-
+
else if (optimize >= 1
&& TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
&& TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
{
tree init = DECL_INITIAL (array);
- i = TREE_INT_CST_LOW (index);
if (TREE_CODE (init) == CONSTRUCTOR)
{
- tree elem = CONSTRUCTOR_ELTS (init);
+ tree elem;
+
+ for (elem = CONSTRUCTOR_ELTS (init);
+ ! tree_int_cst_equal (TREE_PURPOSE (elem), index);
+ elem = TREE_CHAIN (elem))
+ ;
- while (elem
- && !tree_int_cst_equal (TREE_PURPOSE (elem), index))
- elem = TREE_CHAIN (elem);
if (elem)
return expand_expr_unaligned (fold (TREE_VALUE (elem)),
palign);
}
}
}
-
- /* ... fall through ... */
+ /* Fall through. */
case COMPONENT_REF:
case BIT_FIELD_REF:
{
enum machine_mode mode1;
- int bitsize;
- int bitpos;
+ HOST_WIDE_INT bitsize, bitpos;
tree offset;
int volatilep = 0;
unsigned int alignment;
/* Check the access. */
if (current_function_check_memory_usage && GET_CODE (op0) == MEM)
- {
+ {
rtx to;
int size;
size = (bitpos % BITS_PER_UNIT) + bitsize + BITS_PER_UNIT - 1;
/* Check the access right of the pointer. */
+ in_check_memory_usage = 1;
if (size > BITS_PER_UNIT)
- emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
+ emit_library_call (chkr_check_addr_libfunc,
+ LCT_CONST_MAKE_BLOCK, VOIDmode, 3,
to, ptr_mode, GEN_INT (size / BITS_PER_UNIT),
TYPE_MODE (sizetype),
- GEN_INT (MEMORY_USE_RO),
+ GEN_INT (MEMORY_USE_RO),
TYPE_MODE (integer_type_node));
+ in_check_memory_usage = 0;
}
/* In cases where an aligned union has an unaligned object
if (mode1 == VOIDmode
|| GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
|| (SLOW_UNALIGNED_ACCESS (mode1, alignment)
- && (TYPE_ALIGN (type) > alignment * BITS_PER_UNIT
+ && (TYPE_ALIGN (type) > alignment
|| bitpos % TYPE_ALIGN (type) != 0)))
{
enum machine_mode ext_mode = mode_for_size (bitsize, MODE_INT, 1);
- bitsize),
op0, 1);
-
emit_move_insn (new, op0);
op0 = copy_rtx (new);
PUT_MODE (op0, BLKmode);
else
/* Get a reference to just this component. */
op0 = change_address (op0, mode1,
- plus_constant (XEXP (op0, 0),
- (bitpos / BITS_PER_UNIT)));
+ plus_constant (XEXP (op0, 0),
+ (bitpos / BITS_PER_UNIT)));
MEM_ALIAS_SET (op0) = get_alias_set (exp);
if (this_optab == sub_optab
&& GET_CODE (op1) == CONST_INT)
{
- op1 = GEN_INT (- INTVAL (op1));
+ op1 = GEN_INT (-INTVAL (op1));
this_optab = add_optab;
}
/* Increment however we can. */
op1 = expand_binop (mode, this_optab, value, op1,
- current_function_check_memory_usage ? NULL_RTX : op0,
+ current_function_check_memory_usage ? NULL_RTX : op0,
TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
/* Make sure the value is stored into OP0. */
if (op1 != op0)
tree exp;
{
register int nops, i;
- int type = TREE_CODE_CLASS (TREE_CODE (exp));
+ int class = TREE_CODE_CLASS (TREE_CODE (exp));
if (! do_preexpand_calls)
return;
/* Only expressions and references can contain calls. */
- if (type != 'e' && type != '<' && type != '1' && type != '2' && type != 'r')
+ if (! IS_EXPR_CODE_CLASS (class) && class != 'r')
return;
switch (TREE_CODE (exp))
/* Do nothing if already expanded. */
if (CALL_EXPR_RTL (exp) != 0
/* Do nothing if the call returns a variable-sized object. */
- || TREE_CODE (TYPE_SIZE (TREE_TYPE(exp))) != INTEGER_CST
+ || (TREE_CODE (TREE_TYPE (exp)) != VOID_TYPE
+ && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST)
/* Do nothing to built-in functions. */
|| (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
&& (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
case SAVE_EXPR:
if (SAVE_EXPR_RTL (exp) != 0)
return;
-
+
default:
break;
}
- nops = tree_code_length[(int) TREE_CODE (exp)];
+ nops = TREE_CODE_LENGTH (TREE_CODE (exp));
for (i = 0; i < nops; i++)
if (TREE_OPERAND (exp, i) != 0)
{
;
else
{
- type = TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, i)));
- if (type == 'e' || type == '<' || type == '1' || type == '2'
- || type == 'r')
+ class = TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, i)));
+ if (IS_EXPR_CODE_CLASS (class) || class == 'r')
preexpand_calls (TREE_OPERAND (exp, i));
}
}
&& EXIT_IGNORE_STACK
&& ! (DECL_INLINE (current_function_decl) && ! flag_no_inline)
&& ! flag_inline_functions)
- pending_stack_adjust = 0;
+ {
+ stack_pointer_delta -= pending_stack_adjust,
+ pending_stack_adjust = 0;
+ }
#endif
}
if (! SLOW_BYTE_ACCESS
&& TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
&& TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
- && (i = floor_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))) >= 0
+ && (i = tree_floor_log2 (TREE_OPERAND (exp, 1))) >= 0
&& (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
&& (type = type_for_mode (mode, 1)) != 0
&& TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
case BIT_FIELD_REF:
case ARRAY_REF:
{
- int bitsize, bitpos, unsignedp;
+ HOST_WIDE_INT bitsize, bitpos;
+ int unsignedp;
enum machine_mode mode;
tree type;
tree offset;
/* Get description of this reference. We don't actually care
about the underlying object here. */
- get_inner_reference (exp, &bitsize, &bitpos, &offset,
- &mode, &unsignedp, &volatilep,
- &alignment);
+ get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
+ &unsignedp, &volatilep, &alignment);
type = type_for_size (bitsize, unsignedp);
if (! SLOW_BYTE_ACCESS
cmp = UNORDERED, rcmp = ORDERED;
else
cmp = ORDERED, rcmp = UNORDERED;
- mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+ mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
do_rev = 0;
if (! can_compare_p (cmp, mode, ccp_jump)
tree op1 = save_expr (TREE_OPERAND (exp, 1));
tree cmp0, cmp1;
- /* If the target doesn't support combined unordered
+ /* If the target doesn't support combined unordered
compares, decompose into UNORDERED + comparison. */
cmp0 = fold (build (UNORDERED_EXPR, TREE_TYPE (exp), op0, op1));
cmp1 = fold (build (tcode2, TREE_TYPE (exp), op0, op1));
unsignedp = 1;
}
#endif
-
+
emit_cmp_insn (op0, op1, code, size, mode, unsignedp, align);
return gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode,
((mode == BLKmode)
? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX),
- MIN (align0, align1) / BITS_PER_UNIT,
+ MIN (align0, align1),
if_false_label, if_true_label);
}
\f
if (TREE_CODE (inner) == RSHIFT_EXPR
&& TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST
&& TREE_INT_CST_HIGH (TREE_OPERAND (inner, 1)) == 0
- && (bitnum + TREE_INT_CST_LOW (TREE_OPERAND (inner, 1))
- < TYPE_PRECISION (type)))
+ && bitnum < TYPE_PRECISION (type)
+ && 0 > compare_tree_int (TREE_OPERAND (inner, 1),
+ bitnum - TYPE_PRECISION (type)))
{
bitnum += TREE_INT_CST_LOW (TREE_OPERAND (inner, 1));
inner = TREE_OPERAND (inner, 0);
#endif
);
- if (subtarget == 0 || GET_CODE (subtarget) != REG
+ if (! get_subtarget (subtarget)
|| GET_MODE (subtarget) != operand_mode
|| ! safe_from_p (subtarget, inner, 1))
subtarget = 0;
else
return 0;
}
-
+
preexpand_calls (exp);
- if (subtarget == 0 || GET_CODE (subtarget) != REG
+ if (! get_subtarget (target)
|| GET_MODE (subtarget) != operand_mode
|| ! safe_from_p (subtarget, arg1, 1))
subtarget = 0;
emit_barrier ();
}
-#endif /* HAVE_tablejump */
+#endif /* HAVE_tablejump */