X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fexpr.c;h=aad7b1cb5ae019bdfb404c79d04b4dfeab52213e;hb=047e31217cbb6af2c833f5dc47d96c72940eae02;hp=bf1460649f363732a22cc4f80832c1e33f59fd3c;hpb=aab2cf92f98dc58ac1bffb472b685b9b73f71529;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/expr.c b/gcc/expr.c index bf1460649f3..aad7b1cb5ae 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -47,7 +47,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "langhooks.h" #include "intl.h" #include "tm_p.h" +#include "tree-iterator.h" +#include "tree-pass.h" +#include "tree-flow.h" #include "target.h" +#include "timevar.h" /* Decide whether a function's arguments should be processed from first to last or from last to first. @@ -90,9 +94,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA the same indirect address eventually. */ int cse_not_expected; -/* Chain of pending expressions for PLACEHOLDER_EXPR to replace. */ -tree placeholder_list = 0; - /* This structure is used by move_by_pieces to describe the move to be performed. */ struct move_by_pieces @@ -146,7 +147,6 @@ static rtx clear_storage_via_libcall (rtx, rtx); static tree clear_storage_libcall_fn (int); static rtx compress_float_constant (rtx, rtx); static rtx get_subtarget (rtx); -static int is_zeros_p (tree); static void store_constructor_field (rtx, unsigned HOST_WIDE_INT, HOST_WIDE_INT, enum machine_mode, tree, tree, int, int); @@ -156,7 +156,7 @@ static rtx store_field (rtx, HOST_WIDE_INT, HOST_WIDE_INT, enum machine_mode, static rtx var_rtx (tree); static unsigned HOST_WIDE_INT highest_pow2_factor (tree); -static unsigned HOST_WIDE_INT highest_pow2_factor_for_type (tree, tree); +static unsigned HOST_WIDE_INT highest_pow2_factor_for_target (tree, tree); static int is_aligning_offset (tree, tree); static rtx expand_increment (tree, int, int); @@ -212,9 +212,6 @@ enum insn_code clrstr_optab[NUM_MACHINE_MODES]; enum insn_code cmpstr_optab[NUM_MACHINE_MODES]; enum insn_code cmpmem_optab[NUM_MACHINE_MODES]; -/* Stack of EXPR_WITH_FILE_LOCATION nested expressions. */ -struct file_stack *expr_wfl_stack; - /* SLOW_UNALIGNED_ACCESS is nonzero if unaligned accesses are very slow. */ #ifndef SLOW_UNALIGNED_ACCESS @@ -469,13 +466,30 @@ queued_subexp_p (rtx x) } } -/* Perform all the pending incrementations. */ +/* Retrieve a mark on the queue. */ + +static rtx +mark_queue (void) +{ + return pending_chain; +} -void -emit_queue (void) +/* Perform all the pending incrementations that have been enqueued + after MARK was retrieved. If MARK is null, perform all the + pending incrementations. */ + +static void +emit_insns_enqueued_after_mark (rtx mark) { rtx p; - while ((p = pending_chain)) + + /* The marked incrementation may have been emitted in the meantime + through a call to emit_queue. In this case, the mark is not valid + anymore so do nothing. */ + if (mark && ! QUEUED_BODY (mark)) + return; + + while ((p = pending_chain) != mark) { rtx body = QUEUED_BODY (p); @@ -502,9 +516,18 @@ emit_queue (void) break; } + QUEUED_BODY (p) = 0; pending_chain = QUEUED_NEXT (p); } } + +/* Perform all the pending incrementations. */ + +void +emit_queue (void) +{ + emit_insns_enqueued_after_mark (NULL_RTX); +} /* Copy data from FROM to TO, where the machine modes are not the same. Both modes may be integer, or both may be floating. @@ -531,6 +554,11 @@ convert_move (rtx to, rtx from, int unsignedp) if (to_real != from_real) abort (); + /* If the source and destination are already the same, then there's + nothing to do. */ + if (to == from) + return; + /* If FROM is a SUBREG that indicates that we have already done at least the required extension, strip it. We don't handle such SUBREGs as TO here. */ @@ -681,8 +709,12 @@ convert_move (rtx to, rtx from, int unsignedp) && ((code = can_extend_p (to_mode, word_mode, unsignedp)) != CODE_FOR_nothing)) { - if (GET_CODE (to) == REG) - emit_insn (gen_rtx_CLOBBER (VOIDmode, to)); + if (REG_P (to)) + { + if (reg_overlap_mentioned_p (to, from)) + from = force_reg (from_mode, from); + emit_insn (gen_rtx_CLOBBER (VOIDmode, to)); + } convert_move (gen_lowpart (word_mode, to), from, unsignedp); emit_unop_insn (code, to, gen_lowpart (word_mode, to), equiv_code); @@ -764,7 +796,7 @@ convert_move (rtx to, rtx from, int unsignedp) && ! MEM_VOLATILE_P (from) && direct_load[(int) to_mode] && ! mode_dependent_address_p (XEXP (from, 0))) - || GET_CODE (from) == REG + || REG_P (from) || GET_CODE (from) == SUBREG)) from = force_reg (from_mode, from); convert_move (to, gen_lowpart (word_mode, from), 0); @@ -783,10 +815,10 @@ convert_move (rtx to, rtx from, int unsignedp) && ! MEM_VOLATILE_P (from) && direct_load[(int) to_mode] && ! mode_dependent_address_p (XEXP (from, 0))) - || GET_CODE (from) == REG + || REG_P (from) || GET_CODE (from) == SUBREG)) from = force_reg (from_mode, from); - if (GET_CODE (from) == REG && REGNO (from) < FIRST_PSEUDO_REGISTER + if (REG_P (from) && REGNO (from) < FIRST_PSEUDO_REGISTER && ! HARD_REGNO_MODE_OK (REGNO (from), to_mode)) from = copy_to_reg (from); emit_move_insn (to, gen_lowpart (to_mode, from)); @@ -954,7 +986,7 @@ convert_modes (enum machine_mode mode, enum machine_mode oldmode, rtx x, int uns || (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (oldmode) && ((GET_CODE (x) == MEM && ! MEM_VOLATILE_P (x) && direct_load[(int) mode]) - || (GET_CODE (x) == REG + || (REG_P (x) && (! HARD_REGISTER_P (x) || HARD_REGNO_MODE_OK (REGNO (x), mode)) && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode), @@ -1661,8 +1693,6 @@ emit_block_move_via_loop (rtx x, rtx y, rtx size, y_addr = force_operand (XEXP (y, 0), NULL_RTX); do_pending_stack_adjust (); - emit_note (NOTE_INSN_LOOP_BEG); - emit_jump (cmp_label); emit_label (top_label); @@ -1679,13 +1709,10 @@ emit_block_move_via_loop (rtx x, rtx y, rtx size, if (tmp != iter) emit_move_insn (iter, tmp); - emit_note (NOTE_INSN_LOOP_CONT); emit_label (cmp_label); emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode, true, top_label); - - emit_note (NOTE_INSN_LOOP_END); } /* Copy all or part of a value X into registers starting at REGNO. @@ -1893,7 +1920,7 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize) to be extracted. */ tmps[i] = XEXP (src, bytepos / slen0); if (! CONSTANT_P (tmps[i]) - && (GET_CODE (tmps[i]) != REG || GET_MODE (tmps[i]) != mode)) + && (!REG_P (tmps[i]) || GET_MODE (tmps[i]) != mode)) tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT, (bytepos % slen0) * BITS_PER_UNIT, 1, NULL_RTX, mode, mode, ssize); @@ -1911,7 +1938,7 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize) SIMD register, which is currently broken. While we get GCC to emit proper RTL for these cases, let's dump to memory. */ else if (VECTOR_MODE_P (GET_MODE (dst)) - && GET_CODE (src) == REG) + && REG_P (src)) { int slen = GET_MODE_SIZE (GET_MODE (src)); rtx mem; @@ -1924,7 +1951,7 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize) && XVECLEN (dst, 0) > 1) tmps[i] = simplify_gen_subreg (mode, src, GET_MODE(dst), bytepos); else if (CONSTANT_P (src) - || (GET_CODE (src) == REG && GET_MODE (src) == mode)) + || (REG_P (src) && GET_MODE (src) == mode)) tmps[i] = src; else tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT, @@ -2124,7 +2151,7 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type) if (GET_MODE (srcreg) != BLKmode && GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD) - srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type)); + srcreg = convert_to_mode (word_mode, srcreg, TYPE_UNSIGNED (type)); /* If the structure doesn't take up a whole number of words, see whether SRCREG is padded on the left or on the right. If it's on the left, @@ -2183,7 +2210,7 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type) void use_reg (rtx *call_fusage, rtx reg) { - if (GET_CODE (reg) != REG + if (!REG_P (reg) || REGNO (reg) >= FIRST_PSEUDO_REGISTER) abort (); @@ -2223,7 +2250,7 @@ use_group_regs (rtx *call_fusage, rtx regs) /* A NULL entry means the parameter goes both on the stack and in registers. This can also be a MEM for targets that pass values partially on the stack and partially in registers. */ - if (reg != 0 && GET_CODE (reg) == REG) + if (reg != 0 && REG_P (reg)) use_reg (call_fusage, reg); } } @@ -2774,10 +2801,7 @@ emit_move_insn (rtx x, rtx y) if (mode == BLKmode || (GET_MODE (y) != mode && GET_MODE (y) != VOIDmode)) abort (); - /* Never force constant_p_rtx to memory. */ - if (GET_CODE (y) == CONSTANT_P_RTX) - ; - else if (CONSTANT_P (y)) + if (CONSTANT_P (y)) { if (optimize && SCALAR_FLOAT_MODE_P (GET_MODE (x)) @@ -2818,7 +2842,7 @@ emit_move_insn (rtx x, rtx y) last_insn = emit_move_insn_1 (x, y); - if (y_cst && GET_CODE (x) == REG + if (y_cst && REG_P (x) && (set = single_set (last_insn)) != NULL_RTX && SET_DEST (set) == x && ! rtx_equal_p (y_cst, SET_SRC (set))) @@ -2960,9 +2984,6 @@ emit_move_insn_1 (rtx x, rtx y) GET_MODE_SIZE (mode), 0); rtx cmem = adjust_address (mem, mode, 0); - cfun->cannot_inline - = N_("function using short complex types cannot be inline"); - if (packed_dest_p) { rtx sreg = gen_rtx_SUBREG (reg_mode, x, 0); @@ -3227,7 +3248,7 @@ compress_float_constant (rtx x, rtx y) emit_unop_insn (ic, x, trunc_y, UNKNOWN); last_insn = get_last_insn (); - if (GET_CODE (x) == REG) + if (REG_P (x)) set_unique_reg_note (last_insn, REG_EQUAL, y); return last_insn; @@ -3255,7 +3276,7 @@ push_block (rtx size, int extra, int below) size = convert_modes (Pmode, ptr_mode, size, 1); if (CONSTANT_P (size)) anti_adjust_stack (plus_constant (size, extra)); - else if (GET_CODE (size) == REG && extra == 0) + else if (REG_P (size) && extra == 0) anti_adjust_stack (size); else { @@ -3616,7 +3637,7 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size, /* If X is a hard register in a non-integer mode, copy it into a pseudo; SUBREGs of such registers are not allowed. */ - if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER + if ((REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER && GET_MODE_CLASS (GET_MODE (x)) != MODE_INT)) x = copy_to_reg (x); @@ -3705,7 +3726,7 @@ get_subtarget (rtx x) { return ((x == 0 /* Only registers can be subtargets. */ - || GET_CODE (x) != REG + || !REG_P (x) /* 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. */ @@ -3796,8 +3817,8 @@ expand_assignment (tree to, tree from, int want_value) } to_rtx = offset_address (to_rtx, offset_rtx, - highest_pow2_factor_for_type (TREE_TYPE (to), - offset)); + highest_pow2_factor_for_target (to, + offset)); } if (GET_CODE (to_rtx) == MEM) @@ -3854,7 +3875,7 @@ expand_assignment (tree to, tree from, int want_value) return (want_value ? convert_modes (TYPE_MODE (TREE_TYPE (to)), TYPE_MODE (TREE_TYPE (from)), result, - TREE_UNSIGNED (TREE_TYPE (to))) + TYPE_UNSIGNED (TREE_TYPE (to))) : NULL_RTX); } @@ -3871,7 +3892,7 @@ expand_assignment (tree to, tree from, int want_value) if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from, from) && TREE_CODE (TYPE_SIZE (TREE_TYPE (from))) == INTEGER_CST && ! ((TREE_CODE (to) == VAR_DECL || TREE_CODE (to) == PARM_DECL) - && GET_CODE (DECL_RTL (to)) == REG)) + && REG_P (DECL_RTL (to)))) { rtx value; @@ -3907,7 +3928,7 @@ expand_assignment (tree to, tree from, int want_value) /* Don't move directly into a return register. */ if (TREE_CODE (to) == RESULT_DECL - && (GET_CODE (to_rtx) == REG || GET_CODE (to_rtx) == PARALLEL)) + && (REG_P (to_rtx) || GET_CODE (to_rtx) == PARALLEL)) { rtx temp; @@ -3944,7 +3965,7 @@ expand_assignment (tree to, tree from, int want_value) VOIDmode, 3, XEXP (to_rtx, 0), Pmode, XEXP (from_rtx, 0), Pmode, convert_to_mode (TYPE_MODE (sizetype), - size, TREE_UNSIGNED (sizetype)), + size, TYPE_UNSIGNED (sizetype)), TYPE_MODE (sizetype)); else emit_library_call (bcopy_libfunc, LCT_NORMAL, @@ -3952,7 +3973,7 @@ expand_assignment (tree to, tree from, int want_value) XEXP (to_rtx, 0), Pmode, convert_to_mode (TYPE_MODE (integer_type_node), size, - TREE_UNSIGNED (integer_type_node)), + TYPE_UNSIGNED (integer_type_node)), TYPE_MODE (integer_type_node)); preserve_temp_slots (to_rtx); @@ -4002,6 +4023,7 @@ store_expr (tree exp, rtx target, int want_value) { rtx temp; rtx alt_rtl = NULL_RTX; + rtx mark = mark_queue (); int dont_return_target = 0; int dont_store_target = 0; @@ -4121,13 +4143,13 @@ store_expr (tree exp, rtx target, int want_value) && INTEGRAL_TYPE_P (TREE_TYPE (exp)) && TREE_TYPE (TREE_TYPE (exp)) == 0) { - if (TREE_UNSIGNED (TREE_TYPE (exp)) + if (TYPE_UNSIGNED (TREE_TYPE (exp)) != SUBREG_PROMOTED_UNSIGNED_P (target)) exp = convert - ((*lang_hooks.types.signed_or_unsigned_type) + (lang_hooks.types.signed_or_unsigned_type (SUBREG_PROMOTED_UNSIGNED_P (target), TREE_TYPE (exp)), exp); - exp = convert ((*lang_hooks.types.type_for_mode) + exp = convert (lang_hooks.types.type_for_mode (GET_MODE (SUBREG_REG (target)), SUBREG_PROMOTED_UNSIGNED_P (target)), exp); @@ -4194,7 +4216,7 @@ store_expr (tree exp, rtx target, int want_value) Otherwise, if TEMP is not TARGET, return TEMP if it is constant (for efficiency), or if we really want the correct value. */ - if (!(target && GET_CODE (target) == REG + if (!(target && REG_P (target) && REGNO (target) < FIRST_PSEUDO_REGISTER) && !(GET_CODE (target) == MEM && MEM_VOLATILE_P (target)) && ! rtx_equal_p (temp, target) @@ -4210,10 +4232,14 @@ store_expr (tree exp, rtx target, int want_value) && TREE_CODE (exp) != ERROR_MARK && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp))) temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)), - temp, TREE_UNSIGNED (TREE_TYPE (exp))); + temp, TYPE_UNSIGNED (TREE_TYPE (exp))); /* If value was not generated in the target, store it there. - Convert the value to TARGET's type first if necessary. + Convert the value to TARGET's type first if necessary and emit the + pending incrementations that have been queued when expanding EXP. + Note that we cannot emit the whole queue blindly because this will + effectively disable the POST_INC optimization later. + If TEMP and TARGET compare equal according to rtx_equal_p, but one or both of them are volatile memory refs, we have to distinguish two cases: @@ -4241,11 +4267,13 @@ store_expr (tree exp, rtx target, int want_value) bit-initialized. */ && expr_size (exp) != const0_rtx) { + emit_insns_enqueued_after_mark (mark); target = protect_from_queue (target, 1); + temp = protect_from_queue (temp, 0); if (GET_MODE (temp) != GET_MODE (target) && GET_MODE (temp) != VOIDmode) { - int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp)); + int unsignedp = TYPE_UNSIGNED (TREE_TYPE (exp)); if (dont_return_target) { /* In this case, we will return TEMP, @@ -4286,7 +4314,7 @@ store_expr (tree exp, rtx target, int want_value) /* Copy that much. */ copy_size_rtx = convert_to_mode (ptr_mode, copy_size_rtx, - TREE_UNSIGNED (sizetype)); + TYPE_UNSIGNED (sizetype)); emit_block_move (target, temp, copy_size_rtx, (want_value & 2 ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); @@ -4308,7 +4336,7 @@ store_expr (tree exp, rtx target, int want_value) #ifdef POINTERS_EXTEND_UNSIGNED if (GET_MODE (copy_size_rtx) != Pmode) copy_size_rtx = convert_to_mode (Pmode, copy_size_rtx, - TREE_UNSIGNED (sizetype)); + TYPE_UNSIGNED (sizetype)); #endif target = offset_address (target, copy_size_rtx, @@ -4354,7 +4382,7 @@ store_expr (tree exp, rtx target, int want_value) /* Return TARGET itself if it is a hard register. */ else if ((want_value & 1) != 0 && GET_MODE (target) != BLKmode - && ! (GET_CODE (target) == REG + && ! (REG_P (target) && REGNO (target) < FIRST_PSEUDO_REGISTER)) return copy_to_reg (target); @@ -4362,50 +4390,166 @@ store_expr (tree exp, rtx target, int want_value) return target; } -/* Return 1 if EXP just contains zeros. FIXME merge with initializer_zerop. */ +/* Examine CTOR. Discover how many scalar fields are set to nonzero + values and place it in *P_NZ_ELTS. Discover how many scalar fields + are set to non-constant values and place it in *P_NC_ELTS. */ -static int -is_zeros_p (tree exp) +static void +categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts, + HOST_WIDE_INT *p_nc_elts) { - tree elt; + HOST_WIDE_INT nz_elts, nc_elts; + tree list; - switch (TREE_CODE (exp)) + nz_elts = 0; + nc_elts = 0; + + for (list = CONSTRUCTOR_ELTS (ctor); list; list = TREE_CHAIN (list)) { - case CONVERT_EXPR: - case NOP_EXPR: - case NON_LVALUE_EXPR: - case VIEW_CONVERT_EXPR: - return is_zeros_p (TREE_OPERAND (exp, 0)); + tree value = TREE_VALUE (list); + tree purpose = TREE_PURPOSE (list); + HOST_WIDE_INT mult; - case INTEGER_CST: - return integer_zerop (exp); + mult = 1; + if (TREE_CODE (purpose) == RANGE_EXPR) + { + tree lo_index = TREE_OPERAND (purpose, 0); + tree hi_index = TREE_OPERAND (purpose, 1); - case COMPLEX_CST: - return - is_zeros_p (TREE_REALPART (exp)) && is_zeros_p (TREE_IMAGPART (exp)); + if (host_integerp (lo_index, 1) && host_integerp (hi_index, 1)) + mult = (tree_low_cst (hi_index, 1) + - tree_low_cst (lo_index, 1) + 1); + } - case REAL_CST: - return REAL_VALUES_IDENTICAL (TREE_REAL_CST (exp), dconst0); + switch (TREE_CODE (value)) + { + case CONSTRUCTOR: + { + HOST_WIDE_INT nz = 0, nc = 0; + categorize_ctor_elements_1 (value, &nz, &nc); + nz_elts += mult * nz; + nc_elts += mult * nc; + } + break; - case VECTOR_CST: - for (elt = TREE_VECTOR_CST_ELTS (exp); elt; - elt = TREE_CHAIN (elt)) - if (!is_zeros_p (TREE_VALUE (elt))) - return 0; + case INTEGER_CST: + case REAL_CST: + if (!initializer_zerop (value)) + nz_elts += mult; + break; + case COMPLEX_CST: + if (!initializer_zerop (TREE_REALPART (value))) + nz_elts += mult; + if (!initializer_zerop (TREE_IMAGPART (value))) + nz_elts += mult; + break; + case VECTOR_CST: + { + tree v; + for (v = TREE_VECTOR_CST_ELTS (value); v; v = TREE_CHAIN (v)) + if (!initializer_zerop (TREE_VALUE (v))) + nz_elts += mult; + } + break; - return 1; + default: + nz_elts += mult; + if (!initializer_constant_valid_p (value, TREE_TYPE (value))) + nc_elts += mult; + break; + } + } - case CONSTRUCTOR: - if (TREE_TYPE (exp) && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE) - return CONSTRUCTOR_ELTS (exp) == NULL_TREE; - for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt)) - if (! is_zeros_p (TREE_VALUE (elt))) - return 0; + *p_nz_elts += nz_elts; + *p_nc_elts += nc_elts; +} + +void +categorize_ctor_elements (tree ctor, HOST_WIDE_INT *p_nz_elts, + HOST_WIDE_INT *p_nc_elts) +{ + *p_nz_elts = 0; + *p_nc_elts = 0; + categorize_ctor_elements_1 (ctor, p_nz_elts, p_nc_elts); +} + +/* Count the number of scalars in TYPE. Return -1 on overflow or + variable-sized. */ + +HOST_WIDE_INT +count_type_elements (tree type) +{ + const HOST_WIDE_INT max = ~((HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT-1)); + switch (TREE_CODE (type)) + { + case ARRAY_TYPE: + { + tree telts = array_type_nelts (type); + if (telts && host_integerp (telts, 1)) + { + HOST_WIDE_INT n = tree_low_cst (telts, 1); + HOST_WIDE_INT m = count_type_elements (TREE_TYPE (type)); + if (n == 0) + return 0; + if (max / n < m) + return n * m; + } + return -1; + } + + case RECORD_TYPE: + { + HOST_WIDE_INT n = 0, t; + tree f; + + for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f)) + if (TREE_CODE (f) == FIELD_DECL) + { + t = count_type_elements (TREE_TYPE (f)); + if (t < 0) + return -1; + n += t; + } + + return n; + } + case UNION_TYPE: + case QUAL_UNION_TYPE: + { + /* Ho hum. How in the world do we guess here? Clearly it isn't + right to count the fields. Guess based on the number of words. */ + HOST_WIDE_INT n = int_size_in_bytes (type); + if (n < 0) + return -1; + return n / UNITS_PER_WORD; + } + + case COMPLEX_TYPE: + return 2; + + case VECTOR_TYPE: + /* ??? This is broke. We should encode the vector width in the tree. */ + return GET_MODE_NUNITS (TYPE_MODE (type)); + + case INTEGER_TYPE: + case REAL_TYPE: + case ENUMERAL_TYPE: + case BOOLEAN_TYPE: + case CHAR_TYPE: + case POINTER_TYPE: + case OFFSET_TYPE: + case REFERENCE_TYPE: return 1; + case VOID_TYPE: + case METHOD_TYPE: + case FILE_TYPE: + case SET_TYPE: + case FUNCTION_TYPE: + case LANG_TYPE: default: - return 0; + abort (); } } @@ -4415,30 +4559,21 @@ int mostly_zeros_p (tree exp) { if (TREE_CODE (exp) == CONSTRUCTOR) + { - int elts = 0, zeros = 0; - tree elt = CONSTRUCTOR_ELTS (exp); + HOST_WIDE_INT nz_elts, nc_elts, elts; + + /* If there are no ranges of true bits, it is all zero. */ if (TREE_TYPE (exp) && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE) - { - /* If there are no ranges of true bits, it is all zero. */ - return elt == NULL_TREE; - } - for (; elt; elt = TREE_CHAIN (elt)) - { - /* We do not handle the case where the index is a RANGE_EXPR, - so the statistic will be somewhat inaccurate. - We do make a more accurate count in store_constructor itself, - so since this function is only used for nested array elements, - this should be close enough. */ - if (mostly_zeros_p (TREE_VALUE (elt))) - zeros++; - elts++; - } + return CONSTRUCTOR_ELTS (exp) == NULL_TREE; - return 4 * zeros >= 3 * elts; + categorize_ctor_elements (exp, &nz_elts, &nc_elts); + elts = count_type_elements (TREE_TYPE (exp)); + + return nz_elts < elts / 4; } - return is_zeros_p (exp); + return initializer_zerop (exp); } /* Helper function for store_constructor. @@ -4458,7 +4593,10 @@ store_constructor_field (rtx target, unsigned HOST_WIDE_INT bitsize, tree exp, tree type, int cleared, int alias_set) { if (TREE_CODE (exp) == CONSTRUCTOR + /* We can only call store_constructor recursively if the size and + bit position are on a byte boundary. */ && bitpos % BITS_PER_UNIT == 0 + && (bitsize > 0 && bitsize % BITS_PER_UNIT == 0) /* If we have a nonzero bitpos for a register target, then we just let store_field do the bitfield handling. This is unlikely to generate unnecessary clear instructions anyways. */ @@ -4526,7 +4664,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) set the initial value as zero so we can fold the value into a constant. But if more than one register is involved, this probably loses. */ - else if (GET_CODE (target) == REG && TREE_STATIC (exp) + else if (REG_P (target) && TREE_STATIC (exp) && GET_MODE_SIZE (GET_MODE (target)) <= UNITS_PER_WORD) { emit_move_insn (target, CONST0_RTX (GET_MODE (target))); @@ -4538,9 +4676,10 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) clear the whole structure first. Don't do this if TARGET is a register whose mode size isn't equal to SIZE since clear_storage can't handle this case. */ - else if (((list_length (CONSTRUCTOR_ELTS (exp)) != fields_length (type)) - || mostly_zeros_p (exp)) - && (GET_CODE (target) != REG + else if (size > 0 + && ((list_length (CONSTRUCTOR_ELTS (exp)) != fields_length (type)) + || mostly_zeros_p (exp)) + && (!REG_P (target) || ((HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target)) == size))) { @@ -4578,7 +4717,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) if (field == 0) continue; - if (cleared && is_zeros_p (value)) + if (cleared && initializer_zerop (value)) continue; if (host_integerp (DECL_SIZE (field), 1)) @@ -4604,9 +4743,10 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) { rtx offset_rtx; - if (CONTAINS_PLACEHOLDER_P (offset)) - offset = build (WITH_RECORD_EXPR, sizetype, - offset, make_tree (TREE_TYPE (exp), target)); + offset + = SUBSTITUTE_PLACEHOLDER_IN_EXPR (offset, + make_tree (TREE_TYPE (exp), + target)); offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0); if (GET_CODE (to_rtx) != MEM) @@ -4637,7 +4777,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) 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 (GET_CODE (target) == REG + if (REG_P (target) && bitsize < BITS_PER_WORD && bitpos % BITS_PER_WORD == 0 && GET_MODE_CLASS (mode) == MODE_INT @@ -4649,8 +4789,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) if (TYPE_PRECISION (type) < BITS_PER_WORD) { - type = (*lang_hooks.types.type_for_size) - (BITS_PER_WORD, TREE_UNSIGNED (type)); + type = lang_hooks.types.type_for_size + (BITS_PER_WORD, TYPE_UNSIGNED (type)); value = convert (type, value); } @@ -4681,7 +4821,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) tree elt; int i; int need_to_clear; - tree domain = TYPE_DOMAIN (type); + tree domain; tree elttype = TREE_TYPE (type); int const_bounds_p; HOST_WIDE_INT minelt = 0; @@ -4691,13 +4831,14 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) int elt_size = 0; unsigned n_elts = 0; - /* Vectors are like arrays, but the domain is stored via an array - type indirectly. */ - if (TREE_CODE (type) == VECTOR_TYPE) + if (TREE_CODE (type) == ARRAY_TYPE) + domain = TYPE_DOMAIN (type); + else + /* Vectors do not have domains; look up the domain of + the array embedded in the debug representation type. + FIXME Would probably be more efficient to treat vectors + separately from arrays. */ { - /* Note that although TYPE_DEBUG_REPRESENTATION_TYPE uses - the same field as TYPE_DOMAIN, we are not guaranteed that - it always will. */ domain = TYPE_DEBUG_REPRESENTATION_TYPE (type); domain = TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (domain))); if (REG_P (target) && VECTOR_MODE_P (GET_MODE (target))) @@ -4733,7 +4874,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) /* If the constructor has fewer elements than the array, clear the whole array first. Similarly if this is static constructor of a non-BLKmode object. */ - if (cleared || (GET_CODE (target) == REG && TREE_STATIC (exp))) + if (cleared || (REG_P (target) && TREE_STATIC (exp))) need_to_clear = 1; else { @@ -4810,10 +4951,10 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) tree index = TREE_PURPOSE (elt); rtx xtarget = target; - if (cleared && is_zeros_p (value)) + if (cleared && initializer_zerop (value)) continue; - unsignedp = TREE_UNSIGNED (elttype); + unsignedp = TYPE_UNSIGNED (elttype); mode = TYPE_MODE (elttype); if (mode == BLKmode) bitsize = (host_integerp (TYPE_SIZE (elttype), 1) @@ -4826,8 +4967,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) { tree lo_index = TREE_OPERAND (index, 0); tree hi_index = TREE_OPERAND (index, 1); - rtx index_r, pos_rtx, loop_end; - struct nesting *loop; + rtx index_r, pos_rtx; HOST_WIDE_INT lo, hi, count; tree position; @@ -4868,10 +5008,12 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) } else { - expand_expr (hi_index, NULL_RTX, VOIDmode, 0); - loop_end = gen_label_rtx (); + rtx loop_start = gen_label_rtx (); + rtx loop_end = gen_label_rtx (); + tree exit_cond; - unsignedp = TREE_UNSIGNED (domain); + expand_expr (hi_index, NULL_RTX, VOIDmode, 0); + unsignedp = TYPE_UNSIGNED (domain); index = build_decl (VAR_DECL, NULL_TREE, domain); @@ -4888,7 +5030,11 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) emit_queue (); } store_expr (lo_index, index_r, 0); - loop = expand_start_loop (0); + + /* Build the head of the loop. */ + do_pending_stack_adjust (); + emit_queue (); + emit_label (loop_start); /* Assign value to element index. */ position @@ -4909,14 +5055,19 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) else store_expr (value, xtarget, 0); - expand_exit_loop_if_false (loop, - build (LT_EXPR, integer_type_node, - index, hi_index)); + /* Generate a conditional jump to exit the loop. */ + exit_cond = build (LT_EXPR, integer_type_node, + index, hi_index); + jumpif (exit_cond, loop_end); + /* Update the loop counter, and jump to the head of + the loop. */ expand_increment (build (PREINCREMENT_EXPR, TREE_TYPE (index), index, integer_one_node), 0, 0); - expand_end_loop (); + emit_jump (loop_start); + + /* Build the end of the loop. */ emit_label (loop_end); } } @@ -5046,7 +5197,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) { if (word != 0 || ! cleared) { - rtx datum = GEN_INT (word); + rtx datum = gen_int_mode (word, mode); rtx to_rtx; /* The assumption here is that it is safe to use @@ -5116,7 +5267,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) { targetx = assign_temp - ((build_qualified_type ((*lang_hooks.types.type_for_mode) + ((build_qualified_type (lang_hooks.types.type_for_mode (GET_MODE (target), 0), TYPE_QUAL_CONST)), 0, 1, 1); @@ -5209,7 +5360,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, twice, once with emit_move_insn and once via store_field. */ if (mode == BLKmode - && (GET_CODE (target) == REG || GET_CODE (target) == SUBREG)) + && (REG_P (target) || GET_CODE (target) == SUBREG)) { rtx object = assign_temp (type, 0, 1, 1); rtx blk_object = adjust_address (object, BLKmode, 0); @@ -5232,7 +5383,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, if (bitpos != 0) abort (); - return store_expr (exp, target, 0); + return store_expr (exp, target, value_mode != VOIDmode); } /* If the structure is in a register or if the component @@ -5243,7 +5394,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, || (mode != BLKmode && ! direct_store[(int) mode] && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT) - || GET_CODE (target) == REG + || REG_P (target) || GET_CODE (target) == SUBREG /* If the field isn't aligned enough to store as an ordinary memref, store it as a bit field. */ @@ -5339,7 +5490,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, /* If a value is wanted, it must be the lhs; so make the address stable for multiple use. */ - if (value_mode != VOIDmode && GET_CODE (addr) != REG + if (value_mode != VOIDmode && !REG_P (addr) && ! CONSTANT_ADDRESS_P (addr) /* A frame-pointer reference is already stable. */ && ! (GET_CODE (addr) == PLUS @@ -5395,7 +5546,6 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, enum machine_mode mode = VOIDmode; tree offset = size_zero_node; tree bit_offset = bitsize_zero_node; - tree placeholder_ptr = 0; tree tem; /* First get the mode, signedness, and size. We do this from just the @@ -5406,17 +5556,17 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, if (! DECL_BIT_FIELD (TREE_OPERAND (exp, 1))) mode = DECL_MODE (TREE_OPERAND (exp, 1)); - *punsignedp = TREE_UNSIGNED (TREE_OPERAND (exp, 1)); + *punsignedp = DECL_UNSIGNED (TREE_OPERAND (exp, 1)); } else if (TREE_CODE (exp) == BIT_FIELD_REF) { size_tree = TREE_OPERAND (exp, 1); - *punsignedp = TREE_UNSIGNED (exp); + *punsignedp = BIT_FIELD_REF_UNSIGNED (exp); } else { mode = TYPE_MODE (TREE_TYPE (exp)); - *punsignedp = TREE_UNSIGNED (TREE_TYPE (exp)); + *punsignedp = TYPE_UNSIGNED (TREE_TYPE (exp)); if (mode == BLKmode) size_tree = TYPE_SIZE (TREE_TYPE (exp)); @@ -5448,8 +5598,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, made during type construction. */ if (this_offset == 0) break; - else if (CONTAINS_PLACEHOLDER_P (this_offset)) - this_offset = build (WITH_RECORD_EXPR, sizetype, this_offset, exp); + else + this_offset = SUBSTITUTE_PLACEHOLDER_IN_EXPR (this_offset, exp); offset = size_binop (PLUS_EXPR, offset, this_offset); bit_offset = size_binop (PLUS_EXPR, bit_offset, @@ -5475,35 +5625,16 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, 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 (CONTAINS_PLACEHOLDER_P (index)) - index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, exp); - if (CONTAINS_PLACEHOLDER_P (unit_size)) - unit_size = build (WITH_RECORD_EXPR, sizetype, unit_size, array); - + /* If the index has a self-referential type, instantiate it with + the object; likewise for the component size. */ + index = SUBSTITUTE_PLACEHOLDER_IN_EXPR (index, exp); + unit_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (unit_size, array); offset = size_binop (PLUS_EXPR, offset, size_binop (MULT_EXPR, convert (sizetype, index), unit_size)); } - else if (TREE_CODE (exp) == PLACEHOLDER_EXPR) - { - tree new = find_placeholder (exp, &placeholder_ptr); - - /* If we couldn't find the replacement, return the PLACEHOLDER_EXPR. - We might have been called from tree optimization where we - haven't set up an object yet. */ - if (new == 0) - break; - else - exp = new; - - continue; - } - /* We can go inside most conversions: all NON_VALUE_EXPRs, all normal conversions that don't change the mode, and all view conversions except those that need to "step up" the alignment. */ @@ -5590,7 +5721,7 @@ force_operand (rtx value, rtx target) /* Check for subreg applied to an expression produced by loop optimizer. */ if (code == SUBREG - && GET_CODE (SUBREG_REG (value)) != REG + && !REG_P (SUBREG_REG (value)) && GET_CODE (SUBREG_REG (value)) != MEM) { value = simplify_gen_subreg (GET_MODE (value), @@ -5624,10 +5755,10 @@ force_operand (rtx value, rtx target) return target; } - if (GET_RTX_CLASS (code) == '2' || GET_RTX_CLASS (code) == 'c') + if (ARITHMETIC_P (value)) { op2 = XEXP (value, 1); - if (!CONSTANT_P (op2) && !(GET_CODE (op2) == REG && op2 != subtarget)) + if (!CONSTANT_P (op2) && !(REG_P (op2) && op2 != subtarget)) subtarget = 0; if (code == MINUS && GET_CODE (op2) == CONST_INT) { @@ -5643,7 +5774,7 @@ force_operand (rtx value, rtx target) creating another one around this addition. */ if (code == PLUS && GET_CODE (op2) == CONST_INT && GET_CODE (XEXP (value, 0)) == PLUS - && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG + && REG_P (XEXP (XEXP (value, 0), 0)) && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER) { @@ -5693,7 +5824,7 @@ force_operand (rtx value, rtx target) target, 1, OPTAB_LIB_WIDEN); } } - if (GET_RTX_CLASS (code) == '1') + if (UNARY_P (value)) { op1 = force_operand (XEXP (value, 0), NULL_RTX); return expand_simple_unop (GET_MODE (value), code, op1, target, 0); @@ -5758,7 +5889,7 @@ safe_from_p (rtx x, tree exp, int top_p) if (GET_CODE (x) == SUBREG) { x = SUBREG_REG (x); - if (GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER) + if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER) return 0; } @@ -5865,7 +5996,7 @@ safe_from_p (rtx x, tree exp, int top_p) case CALL_EXPR: /* Assume that the call will clobber all hard registers and all of memory. */ - if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER) + if ((REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER) || GET_CODE (x) == MEM) return 0; break; @@ -5931,7 +6062,7 @@ safe_from_p (rtx x, tree exp, int top_p) special handling. */ if ((unsigned int) TREE_CODE (exp) >= (unsigned int) LAST_AND_UNUSED_TREE_CODE - && !(*lang_hooks.safe_from_p) (x, exp)) + && !lang_hooks.safe_from_p (x, exp)) return 0; } @@ -5942,7 +6073,7 @@ safe_from_p (rtx x, tree exp, int top_p) if (GET_CODE (exp_rtl) == SUBREG) { exp_rtl = SUBREG_REG (exp_rtl); - if (GET_CODE (exp_rtl) == REG + if (REG_P (exp_rtl) && REGNO (exp_rtl) < FIRST_PSEUDO_REGISTER) return 0; } @@ -6027,7 +6158,7 @@ highest_pow2_factor (tree exp) break; case NON_LVALUE_EXPR: case NOP_EXPR: case CONVERT_EXPR: - case SAVE_EXPR: case WITH_RECORD_EXPR: + case SAVE_EXPR: return highest_pow2_factor (TREE_OPERAND (exp, 0)); case COMPOUND_EXPR: @@ -6045,81 +6176,86 @@ highest_pow2_factor (tree exp) return 1; } -/* Similar, except that it is known that the expression must be a multiple - of the alignment of TYPE. */ +/* Similar, except that the alignment requirements of TARGET are + taken into account. Assume it is at least as aligned as its + type, unless it is a COMPONENT_REF in which case the layout of + the structure gives the alignment. */ static unsigned HOST_WIDE_INT -highest_pow2_factor_for_type (tree type, tree exp) +highest_pow2_factor_for_target (tree target, tree exp) { - unsigned HOST_WIDE_INT type_align, factor; + unsigned HOST_WIDE_INT target_align, factor; factor = highest_pow2_factor (exp); - type_align = TYPE_ALIGN (type) / BITS_PER_UNIT; - return MAX (factor, type_align); + if (TREE_CODE (target) == COMPONENT_REF) + target_align = DECL_ALIGN (TREE_OPERAND (target, 1)) / BITS_PER_UNIT; + else + target_align = TYPE_ALIGN (TREE_TYPE (target)) / BITS_PER_UNIT; + return MAX (factor, target_align); } -/* Return an object on the placeholder list that matches EXP, a - PLACEHOLDER_EXPR. An object "matches" if it is of the type of the - PLACEHOLDER_EXPR or a pointer type to it. For further information, see - tree.def. If no such object is found, return 0. If PLIST is nonzero, it - is a location which initially points to a starting location in the - placeholder list (zero means start of the list) and where a pointer into - the placeholder list at which the object is found is placed. */ +/* Expands variable VAR. */ -tree -find_placeholder (tree exp, tree *plist) +void +expand_var (tree var) { - tree type = TREE_TYPE (exp); - tree placeholder_expr; + if (DECL_EXTERNAL (var)) + return; - for (placeholder_expr - = plist && *plist ? TREE_CHAIN (*plist) : placeholder_list; - placeholder_expr != 0; - placeholder_expr = TREE_CHAIN (placeholder_expr)) - { - tree need_type = TYPE_MAIN_VARIANT (type); - tree elt; + if (TREE_STATIC (var)) + /* If this is an inlined copy of a static local variable, + look up the original decl. */ + var = DECL_ORIGIN (var); - /* 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 the type we - want. */ - for (elt = TREE_PURPOSE (placeholder_expr); elt != 0; - elt = ((TREE_CODE (elt) == COMPOUND_EXPR - || TREE_CODE (elt) == COND_EXPR) - ? TREE_OPERAND (elt, 1) - : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r' - || TREE_CODE_CLASS (TREE_CODE (elt)) == '1' - || TREE_CODE_CLASS (TREE_CODE (elt)) == '2' - || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e') - ? TREE_OPERAND (elt, 0) : 0)) - if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type) - { - if (plist) - *plist = placeholder_expr; - return elt; - } + if (TREE_STATIC (var) + ? !TREE_ASM_WRITTEN (var) + : !DECL_RTL_SET_P (var)) + { + if (TREE_CODE (var) == VAR_DECL && DECL_DEFER_OUTPUT (var)) + { + /* Prepare a mem & address for the decl. */ + rtx x; + + if (TREE_STATIC (var)) + abort (); - for (elt = TREE_PURPOSE (placeholder_expr); elt != 0; - elt - = ((TREE_CODE (elt) == COMPOUND_EXPR - || TREE_CODE (elt) == COND_EXPR) - ? TREE_OPERAND (elt, 1) - : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r' - || TREE_CODE_CLASS (TREE_CODE (elt)) == '1' - || TREE_CODE_CLASS (TREE_CODE (elt)) == '2' - || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e') - ? TREE_OPERAND (elt, 0) : 0)) - if (POINTER_TYPE_P (TREE_TYPE (elt)) - && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt))) - == need_type)) - { - if (plist) - *plist = placeholder_expr; - return build1 (INDIRECT_REF, need_type, elt); - } + x = gen_rtx_MEM (DECL_MODE (var), + gen_reg_rtx (Pmode)); + + set_mem_attributes (x, var, 1); + SET_DECL_RTL (var, x); + } + else if (lang_hooks.expand_decl (var)) + /* OK. */; + else if (TREE_CODE (var) == VAR_DECL && !TREE_STATIC (var)) + expand_decl (var); + else if (TREE_CODE (var) == VAR_DECL && TREE_STATIC (var)) + rest_of_decl_compilation (var, NULL, 0, 0); + else if (TREE_CODE (var) == TYPE_DECL + || TREE_CODE (var) == CONST_DECL + || TREE_CODE (var) == FUNCTION_DECL + || TREE_CODE (var) == LABEL_DECL) + /* No expansion needed. */; + else + abort (); } +} - return 0; +/* Expands declarations of variables in list VARS. */ + +static void +expand_vars (tree vars) +{ + for (; vars; vars = TREE_CHAIN (vars)) + { + tree var = vars; + + if (DECL_EXTERNAL (var)) + continue; + + expand_var (var); + expand_decl_init (var); + } } /* Subroutine of expand_expr. Expand the two operands of a binary @@ -6198,13 +6334,91 @@ expand_operands (tree exp0, tree exp1, rtx target, rtx *op0, rtx *op1, COMPOUND_EXPR whose second argument is such a VAR_DECL, and so on recursively. */ +static rtx expand_expr_real_1 (tree, rtx, enum machine_mode, + enum expand_modifier, rtx *); + rtx expand_expr_real (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier modifier, rtx *alt_rtl) { + int rn = -1; + rtx ret, last = NULL; + + /* Handle ERROR_MARK before anybody tries to access its type. */ + if (TREE_CODE (exp) == ERROR_MARK + || TREE_CODE (TREE_TYPE (exp)) == ERROR_MARK) + { + ret = CONST0_RTX (tmode); + return ret ? ret : const0_rtx; + } + + if (flag_non_call_exceptions) + { + rn = lookup_stmt_eh_region (exp); + /* If rn < 0, then either (1) tree-ssa not used or (2) doesn't throw. */ + if (rn >= 0) + last = get_last_insn (); + } + + /* If this is an expression of some kind and it has an associated line + number, then emit the line number before expanding the expression. + + We need to save and restore the file and line information so that + errors discovered during expansion are emitted with the right + information. It would be better of the diagnostic routines + used the file/line information embedded in the tree nodes rather + than globals. */ + if (cfun && EXPR_HAS_LOCATION (exp)) + { + location_t saved_location = input_location; + input_location = EXPR_LOCATION (exp); + emit_line_note (input_location); + + /* Record where the insns produced belong. */ + if (cfun->dont_emit_block_notes) + record_block_change (TREE_BLOCK (exp)); + + ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl); + + input_location = saved_location; + } + else + { + ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl); + } + + /* If using non-call exceptions, mark all insns that may trap. + expand_call() will mark CALL_INSNs before we get to this code, + but it doesn't handle libcalls, and these may trap. */ + if (rn >= 0) + { + rtx insn; + for (insn = next_real_insn (last); insn; + insn = next_real_insn (insn)) + { + if (! find_reg_note (insn, REG_EH_REGION, NULL_RTX) + /* If we want exceptions for non-call insns, any + may_trap_p instruction may throw. */ + && GET_CODE (PATTERN (insn)) != CLOBBER + && GET_CODE (PATTERN (insn)) != USE + && (GET_CODE (insn) == CALL_INSN || may_trap_p (PATTERN (insn)))) + { + REG_NOTES (insn) = alloc_EXPR_LIST (REG_EH_REGION, GEN_INT (rn), + REG_NOTES (insn)); + } + } + } + + return ret; +} + +static rtx +expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, + enum expand_modifier modifier, rtx *alt_rtl) +{ rtx op0, op1, temp; tree type = TREE_TYPE (exp); - int unsignedp = TREE_UNSIGNED (type); + int unsignedp; enum machine_mode mode; enum tree_code code = TREE_CODE (exp); optab this_optab; @@ -6212,16 +6426,9 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, int ignore; tree context; - /* 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) - return op0; - return const0_rtx; - } - mode = TYPE_MODE (type); + unsignedp = TYPE_UNSIGNED (type); + /* Use subtarget as the target for operand 0 of a binary operation. */ subtarget = get_subtarget (target); original_target = target; @@ -6292,7 +6499,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, Another is a CALL_EXPR which must return in memory. */ if (! cse_not_expected && mode != BLKmode && target - && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER) + && (!REG_P (target) || REGNO (target) < FIRST_PSEUDO_REGISTER) && ! (code == CONSTRUCTOR && GET_MODE_SIZE (mode) > UNITS_PER_WORD) && ! (code == CALL_EXPR && aggregate_value_p (exp, exp))) target = 0; @@ -6302,20 +6509,15 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, case LABEL_DECL: { tree function = decl_function_context (exp); - /* Labels in containing functions, or labels used from initializers, - must be forced. */ - if (modifier == EXPAND_INITIALIZER - || (function != current_function_decl - && function != inline_function_decl - && function != 0)) - temp = force_label_rtx (exp); - else - temp = label_rtx (exp); - temp = gen_rtx_MEM (FUNCTION_MODE, gen_rtx_LABEL_REF (Pmode, temp)); + temp = label_rtx (exp); + temp = gen_rtx_LABEL_REF (Pmode, temp); + if (function != current_function_decl - && function != inline_function_decl && function != 0) - LABEL_REF_NONLOCAL_P (XEXP (temp, 0)) = 1; + && function != 0) + LABEL_REF_NONLOCAL_P (temp) = 1; + + temp = gen_rtx_MEM (FUNCTION_MODE, temp); return temp; } @@ -6358,13 +6560,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, /* Handle variables inherited from containing functions. */ context = decl_function_context (exp); - /* We treat inline_function_decl as an alias for the current function - because that is the inline function whose vars, types, etc. - are being merged into the current function. - See expand_inline_function. */ - if (context != 0 && context != current_function_decl - && context != inline_function_decl /* If var is static, we don't need a static chain to access it. */ && ! (GET_CODE (DECL_RTL (exp)) == MEM && CONSTANT_P (XEXP (DECL_RTL (exp), 0)))) @@ -6375,7 +6571,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, DECL_NONLOCAL (exp) = 1; if (DECL_NO_STATIC_CHAIN (current_function_decl)) abort (); - (*lang_hooks.mark_addressable) (exp); + lang_hooks.mark_addressable (exp); if (GET_CODE (DECL_RTL (exp)) != MEM) abort (); addr = XEXP (DECL_RTL (exp), 0); @@ -6394,7 +6590,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, See expand_decl. */ else if (GET_CODE (DECL_RTL (exp)) == MEM - && GET_CODE (XEXP (DECL_RTL (exp), 0)) == REG) + && REG_P (XEXP (DECL_RTL (exp), 0))) temp = validize_mem (DECL_RTL (exp)); /* If DECL_RTL is memory, we are in the normal case and either @@ -6408,7 +6604,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, && (! memory_address_p (DECL_MODE (exp), XEXP (DECL_RTL (exp), 0)) || (flag_force_addr - && GET_CODE (XEXP (DECL_RTL (exp), 0)) != REG))) + && !REG_P (XEXP (DECL_RTL (exp), 0))))) { if (alt_rtl) *alt_rtl = DECL_RTL (exp); @@ -6420,7 +6616,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, if the address is a register. */ if (temp != 0) { - if (GET_CODE (temp) == MEM && GET_CODE (XEXP (temp, 0)) == REG) + if (GET_CODE (temp) == MEM && REG_P (XEXP (temp, 0))) mark_reg_pointer (XEXP (temp, 0), DECL_ALIGN (exp)); return temp; @@ -6430,7 +6626,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, must be a promoted value. We return a SUBREG of the wanted mode, but mark it so that we know that it was already extended. */ - if (GET_CODE (DECL_RTL (exp)) == REG + if (REG_P (DECL_RTL (exp)) && GET_MODE (DECL_RTL (exp)) != DECL_MODE (exp)) { /* Get the signedness used for this variable. Ensure we get the @@ -6522,29 +6718,6 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, copy_rtx (XEXP (temp, 0))); return temp; - case EXPR_WITH_FILE_LOCATION: - { - rtx to_return; - struct file_stack fs; - - fs.location = input_location; - fs.next = expr_wfl_stack; - input_filename = EXPR_WFL_FILENAME (exp); - input_line = EXPR_WFL_LINENO (exp); - expr_wfl_stack = &fs; - if (EXPR_WFL_EMIT_LINE_NOTE (exp)) - emit_line_note (input_location); - /* Possibly avoid switching back and forth here. */ - to_return = expand_expr (EXPR_WFL_NODE (exp), - (ignore ? const0_rtx : target), - tmode, modifier); - if (expr_wfl_stack != &fs) - abort (); - input_location = fs.location; - expr_wfl_stack = fs.next; - return to_return; - } - case SAVE_EXPR: context = decl_function_context (exp); @@ -6553,11 +6726,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, if (context == 0) SAVE_EXPR_CONTEXT (exp) = current_function_decl; - /* We treat inline_function_decl as an alias for the current function - because that is the inline function whose vars, types, etc. - are being merged into the current function. - See expand_inline_function. */ - if (context == current_function_decl || context == inline_function_decl) + if (context == current_function_decl) context = 0; /* If this is non-local, handle it. */ @@ -6568,7 +6737,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, find_function_data (context); temp = SAVE_EXPR_RTL (exp); - if (temp && GET_CODE (temp) == REG) + if (temp && REG_P (temp)) { put_var_into_stack (exp, /*rescan=*/true); temp = SAVE_EXPR_RTL (exp); @@ -6590,7 +6759,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, 3, 0, 0); SAVE_EXPR_RTL (exp) = temp; - if (!optimize && GET_CODE (temp) == REG) + if (!optimize && REG_P (temp)) save_expr_regs = gen_rtx_EXPR_LIST (VOIDmode, temp, save_expr_regs); @@ -6599,7 +6768,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, wanted mode but mark it so that we know that it was already extended. */ - if (GET_CODE (temp) == REG && GET_MODE (temp) != mode) + if (REG_P (temp) && GET_MODE (temp) != mode) { temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp)); promote_mode (type, mode, &unsignedp, 0); @@ -6620,7 +6789,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, must be a promoted value. We return a SUBREG of the wanted mode, but mark it so that we know that it was already extended. */ - if (GET_CODE (SAVE_EXPR_RTL (exp)) == REG + if (REG_P (SAVE_EXPR_RTL (exp)) && GET_MODE (SAVE_EXPR_RTL (exp)) != mode) { /* Compute the signedness and make the proper SUBREG. */ @@ -6638,35 +6807,10 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, rtx temp; temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier); TREE_OPERAND (exp, 0) - = (*lang_hooks.unsave_expr_now) (TREE_OPERAND (exp, 0)); - return temp; - } - - case PLACEHOLDER_EXPR: - { - tree old_list = placeholder_list; - tree placeholder_expr = 0; - - exp = find_placeholder (exp, &placeholder_expr); - if (exp == 0) - abort (); - - placeholder_list = TREE_CHAIN (placeholder_expr); - temp = expand_expr (exp, original_target, tmode, modifier); - placeholder_list = old_list; + = lang_hooks.unsave_expr_now (TREE_OPERAND (exp, 0)); return temp; } - case WITH_RECORD_EXPR: - /* Put the object on the placeholder list, expand our first operand, - and pop the list. */ - placeholder_list = tree_cons (TREE_OPERAND (exp, 1), NULL_TREE, - placeholder_list); - target = expand_expr (TREE_OPERAND (exp, 0), original_target, tmode, - modifier); - placeholder_list = TREE_CHAIN (placeholder_list); - return target; - case GOTO_EXPR: if (TREE_CODE (TREE_OPERAND (exp, 0)) == LABEL_DECL) expand_goto (TREE_OPERAND (exp, 0)); @@ -6674,10 +6818,11 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, expand_computed_goto (TREE_OPERAND (exp, 0)); return const0_rtx; + /* These are lowered during gimplification, so we should never ever + see them here. */ + case LOOP_EXPR: case EXIT_EXPR: - expand_exit_loop_if_false (NULL, - invert_truthvalue (TREE_OPERAND (exp, 0))); - return const0_rtx; + abort (); case LABELED_BLOCK_EXPR: if (LABELED_BLOCK_BODY (exp)) @@ -6693,40 +6838,49 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, expand_goto (LABELED_BLOCK_LABEL (EXIT_BLOCK_LABELED_BLOCK (exp))); return const0_rtx; - case LOOP_EXPR: - push_temp_slots (); - expand_start_loop (1); - expand_expr_stmt_value (TREE_OPERAND (exp, 0), 0, 1); - expand_end_loop (); - pop_temp_slots (); - - return const0_rtx; - case BIND_EXPR: { - tree vars = TREE_OPERAND (exp, 0); + tree block = BIND_EXPR_BLOCK (exp); + int mark_ends; - /* Need to open a binding contour here because - if there are any cleanups they must be contained here. */ - expand_start_bindings (2); + if (TREE_CODE (BIND_EXPR_BODY (exp)) != RTL_EXPR) + { + /* If we're in functions-as-trees mode, this BIND_EXPR represents + the block, so we need to emit NOTE_INSN_BLOCK_* notes. */ + mark_ends = (block != NULL_TREE); + expand_start_bindings_and_block (mark_ends ? 0 : 2, block); + } + else + { + /* If we're not in functions-as-trees mode, we've already emitted + those notes into our RTL_EXPR, so we just want to splice our BLOCK + into the enclosing one. */ + mark_ends = 0; - /* Mark the corresponding BLOCK for output in its proper place. */ - if (TREE_OPERAND (exp, 2) != 0 - && ! TREE_USED (TREE_OPERAND (exp, 2))) - (*lang_hooks.decls.insert_block) (TREE_OPERAND (exp, 2)); + /* Need to open a binding contour here because + if there are any cleanups they must be contained here. */ + expand_start_bindings_and_block (2, NULL_TREE); - /* If VARS have not yet been expanded, expand them now. */ - while (vars) - { - if (!DECL_RTL_SET_P (vars)) - expand_decl (vars); - expand_decl_init (vars); - vars = TREE_CHAIN (vars); + /* Mark the corresponding BLOCK for output in its proper place. */ + if (block) + { + if (TREE_USED (block)) + abort (); + lang_hooks.decls.insert_block (block); + } } - temp = expand_expr (TREE_OPERAND (exp, 1), target, tmode, modifier); + /* If VARS have not yet been expanded, expand them now. */ + expand_vars (BIND_EXPR_VARS (exp)); + + /* TARGET was clobbered early in this function. The correct + indicator or whether or not we need the value of this + expression is the IGNORE variable. */ + temp = expand_expr (BIND_EXPR_BODY (exp), + ignore ? const0_rtx : target, + tmode, modifier); - expand_end_bindings (TREE_OPERAND (exp, 0), 0, 0); + expand_end_bindings (BIND_EXPR_VARS (exp), mark_ends, 0); return temp; } @@ -6779,9 +6933,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, && (! MOVE_BY_PIECES_P (tree_low_cst (TYPE_SIZE_UNIT (type), 1), TYPE_ALIGN (type))) - && ((TREE_CODE (type) == VECTOR_TYPE - && !is_zeros_p (exp)) - || ! mostly_zeros_p (exp))))) + && ! mostly_zeros_p (exp)))) || ((modifier == EXPAND_INITIALIZER || modifier == EXPAND_CONST_ADDRESS) && TREE_CONSTANT (exp))) @@ -6816,19 +6968,15 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, case INDIRECT_REF: { tree exp1 = TREE_OPERAND (exp, 0); - tree index; - 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 - && compare_tree_int (index, TREE_STRING_LENGTH (string)) < 0 - && GET_MODE_CLASS (mode) == MODE_INT - && GET_MODE_SIZE (mode) == 1 - && modifier != EXPAND_WRITE) - return gen_int_mode (TREE_STRING_POINTER (string) - [TREE_INT_CST_LOW (index)], mode); + if (modifier != EXPAND_WRITE) + { + tree t; + + t = fold_read_from_constant_string (exp); + if (t) + return expand_expr (t, target, tmode, modifier); + } op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM); op0 = memory_address (mode, op0); @@ -6845,8 +6993,11 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, } case ARRAY_REF: + +#ifdef ENABLE_CHECKING if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) != ARRAY_TYPE) abort (); +#endif { tree array = TREE_OPERAND (exp, 0); @@ -6873,14 +7024,13 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, if (modifier != EXPAND_CONST_ADDRESS && modifier != EXPAND_INITIALIZER - && modifier != EXPAND_MEMORY - && TREE_CODE (array) == STRING_CST - && TREE_CODE (index) == INTEGER_CST - && compare_tree_int (index, TREE_STRING_LENGTH (array)) < 0 - && GET_MODE_CLASS (mode) == MODE_INT - && GET_MODE_SIZE (mode) == 1) - return gen_int_mode (TREE_STRING_POINTER (array) - [TREE_INT_CST_LOW (index)], mode); + && modifier != EXPAND_MEMORY) + { + tree t = fold_read_from_constant_string (exp); + + if (t) + return expand_expr (t, target, tmode, modifier); + } /* If this is a constant index into a constant array, just get the value from the array. Handle both the cases when @@ -6987,7 +7137,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, enum machine_mode imode = TYPE_MODE (TREE_TYPE (TREE_PURPOSE (elt))); - if (TREE_UNSIGNED (TREE_TYPE (TREE_PURPOSE (elt)))) + if (TYPE_UNSIGNED (TREE_TYPE (TREE_PURPOSE (elt)))) { op1 = GEN_INT (((HOST_WIDE_INT) 1 << bitsize) - 1); op0 = expand_and (imode, op0, op1, target); @@ -7152,7 +7302,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, (which we know to be the width of a basic mode), then storing into memory, and changing the mode to BLKmode. */ if (mode1 == VOIDmode - || GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG + || REG_P (op0) || GET_CODE (op0) == SUBREG || (mode1 != BLKmode && ! direct_load[(int) mode1] && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT @@ -7216,7 +7366,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, op0 = validize_mem (op0); - if (GET_CODE (op0) == MEM && GET_CODE (XEXP (op0, 0)) == REG) + if (GET_CODE (op0) == MEM && REG_P (XEXP (op0, 0))) mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0)); op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp, @@ -7236,12 +7386,19 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, - bitsize), op0, 1); + /* If the result type is BLKmode, store the data into a temporary + of the appropriate type, but with the mode corresponding to the + mode for the data we have (op0's mode). It's tempting to make + this a constant type, since we know it's only being stored once, + but that can cause problems if we are taking the address of this + COMPONENT_REF because the MEM of any reference via that address + will have flags corresponding to the type, which will not + necessarily be constant. */ if (mode == BLKmode) { - rtx new = assign_temp (build_qualified_type - ((*lang_hooks.types.type_for_mode) - (ext_mode, 0), - TYPE_QUAL_CONST), 0, 1, 1); + rtx new + = assign_stack_temp_for_type + (ext_mode, GET_MODE_BITSIZE (ext_mode), 0, type); emit_move_insn (new, op0); op0 = copy_rtx (new); @@ -7268,7 +7425,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, op0 = copy_rtx (op0); set_mem_attributes (op0, exp, 0); - if (GET_CODE (XEXP (op0, 0)) == REG) + if (REG_P (XEXP (op0, 0))) mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0)); MEM_VOLATILE_P (op0) |= volatilep; @@ -7339,7 +7496,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, tree set = TREE_OPERAND (exp, 0); tree index = TREE_OPERAND (exp, 1); - int iunsignedp = TREE_UNSIGNED (TREE_TYPE (index)); + int iunsignedp = TYPE_UNSIGNED (TREE_TYPE (index)); tree set_type = TREE_TYPE (set); tree set_low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (set_type)); tree set_high_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (set_type)); @@ -7466,9 +7623,9 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, { if (DECL_BUILT_IN_CLASS (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == BUILT_IN_FRONTEND) - return (*lang_hooks.expand_expr) (exp, original_target, - tmode, modifier, - alt_rtl); + return lang_hooks.expand_expr (exp, original_target, + tmode, modifier, + alt_rtl); else return expand_builtin (exp, target, subtarget, tmode, ignore); } @@ -7512,7 +7669,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, adjust_address (target, TYPE_MODE (valtype), 0), modifier == EXPAND_STACK_PARM ? 2 : 0); - else if (GET_CODE (target) == REG) + else if (REG_P (target)) /* Store this field into a union of the proper type. */ store_field (target, MIN ((int_size_in_bytes (TREE_TYPE @@ -7536,7 +7693,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, /* If the signedness of the conversion differs and OP0 is a promoted SUBREG, clear that indication since we now have to do the proper extension. */ - if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))) != unsignedp + if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))) != unsignedp && GET_CODE (op0) == SUBREG) SUBREG_PROMOTED_VAR_P (op0) = 0; @@ -7559,7 +7716,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, inner_mode)); else return convert_modes (mode, inner_mode, op0, - TREE_UNSIGNED (inner_type)); + TYPE_UNSIGNED (inner_type)); } if (modifier == EXPAND_INITIALIZER) @@ -7568,10 +7725,10 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, if (target == 0) return convert_to_mode (mode, op0, - TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); + TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); else convert_move (target, op0, - TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); + TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); return target; case VIEW_CONVERT_EXPR: @@ -7835,9 +7992,9 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM); - if (GET_CODE (op0) != REG) + if (!REG_P (op0)) op0 = force_operand (op0, NULL_RTX); - if (GET_CODE (op0) != REG) + if (!REG_P (op0)) op0 = copy_to_mode_reg (mode, op0); return gen_rtx_MULT (mode, op0, @@ -7865,18 +8022,22 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, || exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0)) || (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR - && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0))) - == - TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))) + && (TYPE_PRECISION (TREE_TYPE + (TREE_OPERAND (TREE_OPERAND (exp, 1), 0))) + == TYPE_PRECISION (TREE_TYPE + (TREE_OPERAND + (TREE_OPERAND (exp, 0), 0)))) /* If both operands are extended, they must either both be zero-extended or both be sign-extended. */ - && (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0))) - == - TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))))))) + && (TYPE_UNSIGNED (TREE_TYPE + (TREE_OPERAND (TREE_OPERAND (exp, 1), 0))) + == TYPE_UNSIGNED (TREE_TYPE + (TREE_OPERAND + (TREE_OPERAND (exp, 0), 0))))))) { tree op0type = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)); enum machine_mode innermode = TYPE_MODE (op0type); - bool zextend_p = TREE_UNSIGNED (op0type); + bool zextend_p = TYPE_UNSIGNED (op0type); optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab; this_optab = zextend_p ? umul_widen_optab : smul_widen_optab; @@ -7985,7 +8146,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, op0 = copy_to_mode_reg (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))), op0); expand_float (target, op0, - TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); + TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); return target; case NEGATE_EXPR: @@ -8012,7 +8173,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, /* Unsigned abs is simply the operand. Testing here means we don't risk generating incorrect code below. */ - if (TREE_UNSIGNED (type)) + if (TYPE_UNSIGNED (type)) return op0; return expand_abs (mode, op0, target, unsignedp, @@ -8025,7 +8186,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, || modifier == EXPAND_STACK_PARM || (GET_CODE (target) == MEM && MEM_VOLATILE_P (target)) || GET_MODE (target) != mode - || (GET_CODE (target) == REG + || (REG_P (target) && REGNO (target) < FIRST_PSEUDO_REGISTER)) target = gen_reg_rtx (mode); expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), @@ -8034,7 +8195,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, /* First try to do it with a special MIN or MAX instruction. If that does not win, use a conditional jump to select the proper value. */ - this_optab = (TREE_UNSIGNED (type) + this_optab = (unsignedp ? (code == MIN_EXPR ? umin_optab : umax_optab) : (code == MIN_EXPR ? smin_optab : smax_optab)); @@ -8068,18 +8229,16 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, && ! can_compare_p (GE, mode, ccp_jump)) { if (code == MAX_EXPR) - do_jump_by_parts_greater_rtx (mode, TREE_UNSIGNED (type), - target, op1, NULL_RTX, op0); + do_jump_by_parts_greater_rtx (mode, unsignedp, target, op1, + NULL_RTX, op0); else - do_jump_by_parts_greater_rtx (mode, TREE_UNSIGNED (type), - op1, target, NULL_RTX, op0); + do_jump_by_parts_greater_rtx (mode, unsignedp, op1, target, + NULL_RTX, op0); } else { - int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))); do_compare_rtx_and_jump (target, op1, code == MAX_EXPR ? GE : LE, - unsignedp, mode, NULL_RTX, NULL_RTX, - op0); + unsignedp, mode, NULL_RTX, NULL_RTX, op0); } emit_move_insn (target, op1); emit_label (op0); @@ -8149,6 +8308,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, case UNGT_EXPR: case UNGE_EXPR: case UNEQ_EXPR: + case LTGT_EXPR: temp = do_store_flag (exp, modifier != EXPAND_STACK_PARM ? target : NULL_RTX, tmode != VOIDmode ? tmode : mode, 0); @@ -8158,7 +8318,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, /* For foo != 0, load foo, and if it is nonzero load 1 instead. */ if (code == NE_EXPR && integer_zerop (TREE_OPERAND (exp, 1)) && original_target - && GET_CODE (original_target) == REG + && REG_P (original_target) && (GET_MODE (original_target) == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) { @@ -8205,7 +8365,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, || ! safe_from_p (target, exp, 1) /* Make sure we don't have a hard reg (such as function's return value) live across basic blocks, if not optimizing. */ - || (!optimize && GET_CODE (target) == REG + || (!optimize && REG_P (target) && REGNO (target) < FIRST_PSEUDO_REGISTER))) target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode); @@ -8240,7 +8400,77 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, (ignore ? const0_rtx : target), VOIDmode, modifier, alt_rtl); + case STATEMENT_LIST: + { + tree_stmt_iterator iter; + + if (!ignore) + abort (); + + for (iter = tsi_start (exp); !tsi_end_p (iter); tsi_next (&iter)) + expand_expr (tsi_stmt (iter), const0_rtx, VOIDmode, modifier); + } + return const0_rtx; + case COND_EXPR: + /* If it's void, we don't need to worry about computing a value. */ + if (VOID_TYPE_P (TREE_TYPE (exp))) + { + tree pred = TREE_OPERAND (exp, 0); + tree then_ = TREE_OPERAND (exp, 1); + tree else_ = TREE_OPERAND (exp, 2); + + /* If we do not have any pending cleanups or stack_levels + to restore, and at least one arm of the COND_EXPR is a + GOTO_EXPR to a local label, then we can emit more efficient + code by using jumpif/jumpifnot instead of the 'if' machinery. */ + if (! optimize + || containing_blocks_have_cleanups_or_stack_level ()) + ; + else if (TREE_CODE (then_) == GOTO_EXPR + && TREE_CODE (GOTO_DESTINATION (then_)) == LABEL_DECL) + { + jumpif (pred, label_rtx (GOTO_DESTINATION (then_))); + return expand_expr (else_, const0_rtx, VOIDmode, 0); + } + else if (TREE_CODE (else_) == GOTO_EXPR + && TREE_CODE (GOTO_DESTINATION (else_)) == LABEL_DECL) + { + jumpifnot (pred, label_rtx (GOTO_DESTINATION (else_))); + return expand_expr (then_, const0_rtx, VOIDmode, 0); + } + + /* Just use the 'if' machinery. */ + expand_start_cond (pred, 0); + start_cleanup_deferral (); + expand_expr (then_, const0_rtx, VOIDmode, 0); + + exp = else_; + + /* Iterate over 'else if's instead of recursing. */ + for (; TREE_CODE (exp) == COND_EXPR; exp = TREE_OPERAND (exp, 2)) + { + expand_start_else (); + if (EXPR_HAS_LOCATION (exp)) + { + emit_line_note (EXPR_LOCATION (exp)); + if (cfun->dont_emit_block_notes) + record_block_change (TREE_BLOCK (exp)); + } + expand_elseif (TREE_OPERAND (exp, 0)); + expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, 0); + } + /* Don't emit the jump and label if there's no 'else' clause. */ + if (TREE_SIDE_EFFECTS (exp)) + { + expand_start_else (); + expand_expr (exp, const0_rtx, VOIDmode, 0); + } + end_cleanup_deferral (); + expand_end_cond (); + return const0_rtx; + } + /* If we would have a "singleton" (see below) were it not for a conversion in each arm, bring that conversion back out. */ if (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR @@ -8337,13 +8567,13 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, temp = assign_temp (type, 0, 0, 1); else if (original_target && (safe_from_p (original_target, TREE_OPERAND (exp, 0), 1) - || (singleton && GET_CODE (original_target) == REG + || (singleton && REG_P (original_target) && REGNO (original_target) >= FIRST_PSEUDO_REGISTER && original_target == var_rtx (singleton))) && GET_MODE (original_target) == mode #ifdef HAVE_conditional_move && (! can_conditionally_move_p (mode) - || GET_CODE (original_target) == REG + || REG_P (original_target) || TREE_ADDRESSABLE (type)) #endif && (GET_CODE (original_target) != MEM @@ -8419,7 +8649,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, might clobber it. */ if ((binary_op && ! safe_from_p (temp, TREE_OPERAND (binary_op, 1), 1)) - || (GET_CODE (temp) == REG + || (REG_P (temp) && REGNO (temp) < FIRST_PSEUDO_REGISTER)) temp = gen_reg_rtx (mode); store_expr (singleton, temp, @@ -8462,7 +8692,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, || TREE_CODE (TREE_OPERAND (exp, 1)) == SAVE_EXPR) && safe_from_p (temp, TREE_OPERAND (exp, 2), 1)) { - if (GET_CODE (temp) == REG + if (REG_P (temp) && REGNO (temp) < FIRST_PSEUDO_REGISTER) temp = gen_reg_rtx (mode); store_expr (TREE_OPERAND (exp, 1), temp, @@ -8487,7 +8717,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, || TREE_CODE (TREE_OPERAND (exp, 2)) == SAVE_EXPR) && safe_from_p (temp, TREE_OPERAND (exp, 1), 1)) { - if (GET_CODE (temp) == REG + if (REG_P (temp) && REGNO (temp) < FIRST_PSEUDO_REGISTER) temp = gen_reg_rtx (mode); store_expr (TREE_OPERAND (exp, 2), temp, @@ -8582,8 +8812,6 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, else { target = assign_temp (type, 2, 0, 1); - /* All temp slots at this level must not conflict. */ - preserve_temp_slots (target); SET_DECL_RTL (slot, target); if (TREE_ADDRESSABLE (slot)) put_var_into_stack (slot, /*rescan=*/false); @@ -8597,7 +8825,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, if (TREE_OPERAND (exp, 2) == 0) TREE_OPERAND (exp, 2) - = (*lang_hooks.maybe_build_cleanup) (slot); + = lang_hooks.maybe_build_cleanup (slot); cleanups = TREE_OPERAND (exp, 2); } } @@ -8633,7 +8861,12 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, /* Mark it as expanded. */ TREE_OPERAND (exp, 1) = NULL_TREE; - store_expr (exp1, target, modifier == EXPAND_STACK_PARM ? 2 : 0); + if (VOID_TYPE_P (TREE_TYPE (exp1))) + /* If the initializer is void, just expand it; it will initialize + the object directly. */ + expand_expr (exp1, const0_rtx, VOIDmode, 0); + else + store_expr (exp1, target, modifier == EXPAND_STACK_PARM ? 2 : 0); expand_decl_cleanup_eh (NULL_TREE, cleanups, CLEANUP_EH_ONLY (exp)); @@ -8720,18 +8953,9 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, case ADDR_EXPR: if (modifier == EXPAND_STACK_PARM) target = 0; - /* Are we taking the address of a nested function? */ - if (TREE_CODE (TREE_OPERAND (exp, 0)) == FUNCTION_DECL - && decl_function_context (TREE_OPERAND (exp, 0)) != 0 - && ! DECL_NO_STATIC_CHAIN (TREE_OPERAND (exp, 0)) - && ! TREE_STATIC (exp)) - { - op0 = trampoline_address (TREE_OPERAND (exp, 0)); - op0 = force_operand (op0, target); - } /* If we are taking the address of something erroneous, just return a zero. */ - else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK) + if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK) return const0_rtx; /* If we are taking the address of a constant and are at the top level, we have to use output_constant_def since we can't @@ -8767,7 +8991,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, if (CONSTANT_P (op0)) op0 = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))), op0); - else if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG + else if (REG_P (op0) || GET_CODE (op0) == SUBREG || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF || GET_CODE (op0) == PARALLEL || GET_CODE (op0) == LO_SUM) { @@ -8857,13 +9081,13 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, } if (flag_force_addr - && GET_CODE (op0) != REG + && !REG_P (op0) && modifier != EXPAND_CONST_ADDRESS && modifier != EXPAND_INITIALIZER && modifier != EXPAND_SUM) op0 = force_reg (Pmode, op0); - if (GET_CODE (op0) == REG + if (REG_P (op0) && ! REG_USERVAR_P (op0)) mark_reg_pointer (op0, TYPE_ALIGN (TREE_TYPE (type))); @@ -8958,25 +9182,38 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, return target; } + case RESX_EXPR: + expand_resx_expr (exp); + return const0_rtx; + case TRY_CATCH_EXPR: { tree handler = TREE_OPERAND (exp, 1); expand_eh_region_start (); - op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); - - expand_eh_region_end_cleanup (handler); + expand_eh_handler (handler); return op0; } + case CATCH_EXPR: + expand_start_catch (CATCH_TYPES (exp)); + expand_expr (CATCH_BODY (exp), const0_rtx, VOIDmode, 0); + expand_end_catch (); + return const0_rtx; + + case EH_FILTER_EXPR: + /* Should have been handled in expand_eh_handler. */ + abort (); + case TRY_FINALLY_EXPR: { tree try_block = TREE_OPERAND (exp, 0); tree finally_block = TREE_OPERAND (exp, 1); - if (!optimize || unsafe_for_reeval (finally_block) > 1) + if ((!optimize && lang_protect_cleanup_actions == NULL) + || unsafe_for_reeval (finally_block) > 1) { /* In this case, wrapping FINALLY_BLOCK in an UNSAVE_EXPR is not sufficient, so we cannot expand the block twice. @@ -9045,14 +9282,102 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, case EXC_PTR_EXPR: return get_exception_pointer (cfun); + case FILTER_EXPR: + return get_exception_filter (cfun); + case FDESC_EXPR: /* Function descriptors are not valid except for as initialization constants, and should not be expanded. */ abort (); + case SWITCH_EXPR: + expand_start_case (0, SWITCH_COND (exp), integer_type_node, + "switch"); + if (SWITCH_BODY (exp)) + expand_expr_stmt (SWITCH_BODY (exp)); + if (SWITCH_LABELS (exp)) + { + tree duplicate = 0; + tree vec = SWITCH_LABELS (exp); + size_t i, n = TREE_VEC_LENGTH (vec); + + for (i = 0; i < n; ++i) + { + tree elt = TREE_VEC_ELT (vec, i); + tree controlling_expr_type = TREE_TYPE (SWITCH_COND (exp)); + tree min_value = TYPE_MIN_VALUE (controlling_expr_type); + tree max_value = TYPE_MAX_VALUE (controlling_expr_type); + + tree case_low = CASE_LOW (elt); + tree case_high = CASE_HIGH (elt) ? CASE_HIGH (elt) : case_low; + if (case_low && case_high) + { + /* Case label is less than minimum for type. */ + if ((tree_int_cst_compare (case_low, min_value) < 0) + && (tree_int_cst_compare (case_high, min_value) < 0)) + { + warning ("case label value %d is less than minimum value for type", + TREE_INT_CST (case_low)); + continue; + } + + /* Case value is greater than maximum for type. */ + if ((tree_int_cst_compare (case_low, max_value) > 0) + && (tree_int_cst_compare (case_high, max_value) > 0)) + { + warning ("case label value %d exceeds maximum value for type", + TREE_INT_CST (case_high)); + continue; + } + + /* Saturate lower case label value to minimum. */ + if ((tree_int_cst_compare (case_high, min_value) >= 0) + && (tree_int_cst_compare (case_low, min_value) < 0)) + { + warning ("lower value %d in case label range less than minimum value for type", + TREE_INT_CST (case_low)); + case_low = min_value; + } + + /* Saturate upper case label value to maximum. */ + if ((tree_int_cst_compare (case_low, max_value) <= 0) + && (tree_int_cst_compare (case_high, max_value) > 0)) + { + warning ("upper value %d in case label range exceeds maximum value for type", + TREE_INT_CST (case_high)); + case_high = max_value; + } + } + + add_case_node (case_low, case_high, CASE_LABEL (elt), &duplicate, true); + if (duplicate) + abort (); + } + } + expand_end_case_type (SWITCH_COND (exp), TREE_TYPE (exp)); + return const0_rtx; + + case LABEL_EXPR: + expand_label (TREE_OPERAND (exp, 0)); + return const0_rtx; + + case CASE_LABEL_EXPR: + { + tree duplicate = 0; + add_case_node (CASE_LOW (exp), CASE_HIGH (exp), CASE_LABEL (exp), + &duplicate, false); + if (duplicate) + abort (); + return const0_rtx; + } + + case ASM_EXPR: + expand_asm_expr (exp); + return const0_rtx; + default: - return (*lang_hooks.expand_expr) (exp, original_target, tmode, modifier, - alt_rtl); + return lang_hooks.expand_expr (exp, original_target, tmode, + modifier, alt_rtl); } /* Here to do an ordinary binary operator, generating an instruction @@ -9077,11 +9402,10 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, static int is_aligning_offset (tree offset, tree exp) { - /* Strip off any conversions and WITH_RECORD_EXPR nodes. */ + /* Strip off any conversions. */ while (TREE_CODE (offset) == NON_LVALUE_EXPR || TREE_CODE (offset) == NOP_EXPR - || TREE_CODE (offset) == CONVERT_EXPR - || TREE_CODE (offset) == WITH_RECORD_EXPR) + || TREE_CODE (offset) == CONVERT_EXPR) offset = TREE_OPERAND (offset, 0); /* We must now have a BIT_AND_EXPR with a constant that is one less than @@ -9110,13 +9434,8 @@ is_aligning_offset (tree offset, tree exp) || TREE_CODE (offset) == CONVERT_EXPR) offset = TREE_OPERAND (offset, 0); - /* This must now be the address either of EXP or of a PLACEHOLDER_EXPR - whose type is the same as EXP. */ - return (TREE_CODE (offset) == ADDR_EXPR - && (TREE_OPERAND (offset, 0) == exp - || (TREE_CODE (TREE_OPERAND (offset, 0)) == PLACEHOLDER_EXPR - && (TREE_TYPE (TREE_OPERAND (offset, 0)) - == TREE_TYPE (exp))))); + /* This must now be the address of EXP. */ + return TREE_CODE (offset) == ADDR_EXPR && TREE_OPERAND (offset, 0) == exp; } /* Return the tree node if an ARG corresponds to a string constant or zero @@ -9135,6 +9454,13 @@ string_constant (tree arg, tree *ptr_offset) *ptr_offset = size_zero_node; return TREE_OPERAND (arg, 0); } + if (TREE_CODE (arg) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (arg, 0)) == ARRAY_REF + && TREE_CODE (TREE_OPERAND (TREE_OPERAND (arg, 0), 0)) == STRING_CST) + { + *ptr_offset = convert (sizetype, TREE_OPERAND (TREE_OPERAND (arg, 0), 1)); + return TREE_OPERAND (TREE_OPERAND (arg, 0), 0); + } else if (TREE_CODE (arg) == PLUS_EXPR) { tree arg0 = TREE_OPERAND (arg, 0); @@ -9230,7 +9556,7 @@ expand_increment (tree exp, int post, int ignore) bad_subreg = 1; } - op0_is_copy = ((GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG) + op0_is_copy = ((GET_CODE (op0) == SUBREG || REG_P (op0)) && temp != get_last_insn ()); op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); @@ -9354,7 +9680,7 @@ expand_increment (tree exp, int post, int ignore) /* Increment however we can. */ op1 = expand_binop (mode, this_optab, value, op1, op0, - TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN); + TYPE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN); /* Make sure the value is stored into OP0. */ if (op1 != op0) @@ -9414,7 +9740,7 @@ do_store_flag (tree exp, rtx target, enum machine_mode mode, int only_cheap) type = TREE_TYPE (arg0); operand_mode = TYPE_MODE (type); - unsignedp = TREE_UNSIGNED (type); + unsignedp = TYPE_UNSIGNED (type); /* We won't bother with BLKmode store-flag operations because it would mean passing a lot of information to emit_store_flag. */ @@ -9498,6 +9824,9 @@ do_store_flag (tree exp, rtx target, enum machine_mode mode, int only_cheap) case UNEQ_EXPR: code = UNEQ; break; + case LTGT_EXPR: + code = LTGT; + break; default: abort (); @@ -9523,7 +9852,7 @@ do_store_flag (tree exp, rtx target, enum machine_mode mode, int only_cheap) && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1) && integer_pow2p (TREE_OPERAND (arg0, 1))) { - tree type = (*lang_hooks.types.type_for_mode) (mode, unsignedp); + tree type = lang_hooks.types.type_for_mode (mode, unsignedp); return expand_expr (fold_single_bit_test (code == NE ? NE_EXPR : EQ_EXPR, arg0, arg1, type), target, VOIDmode, EXPAND_NORMAL); @@ -9581,7 +9910,7 @@ do_store_flag (tree exp, rtx target, enum machine_mode mode, int only_cheap) } /* If this failed, we have to do this with set/compare/jump/set code. */ - if (GET_CODE (target) != REG + if (!REG_P (target) || reg_mentioned_p (target, op0) || reg_mentioned_p (target, op1)) target = gen_reg_rtx (GET_MODE (target)); @@ -9667,7 +9996,7 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range, { if (TYPE_MODE (index_type) != index_mode) { - index_expr = convert ((*lang_hooks.types.type_for_size) + index_expr = convert (lang_hooks.types.type_for_size (index_bits, 0), index_expr); index_type = TREE_TYPE (index_expr); } @@ -9687,7 +10016,7 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range, op_mode = insn_data[(int) CODE_FOR_casesi].operand[1].mode; op1 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (minval)), - op1, TREE_UNSIGNED (TREE_TYPE (minval))); + op1, TYPE_UNSIGNED (TREE_TYPE (minval))); if (! (*insn_data[(int) CODE_FOR_casesi].operand[1].predicate) (op1, op_mode)) op1 = copy_to_mode_reg (op_mode, op1); @@ -9696,7 +10025,7 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range, op_mode = insn_data[(int) CODE_FOR_casesi].operand[2].mode; op2 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (range)), - op2, TREE_UNSIGNED (TREE_TYPE (range))); + op2, TYPE_UNSIGNED (TREE_TYPE (range))); if (! (*insn_data[(int) CODE_FOR_casesi].operand[2].predicate) (op2, op_mode)) op2 = copy_to_mode_reg (op_mode, op2); @@ -9752,7 +10081,7 @@ do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label, out of PIC_CASE_VECTOR_ADDRESS won't be a valid address, and break_out_memory_refs will go to work on it and mess it up. */ #ifdef PIC_CASE_VECTOR_ADDRESS - if (flag_pic && GET_CODE (index) != REG) + if (flag_pic && !REG_P (index)) index = copy_to_mode_reg (Pmode, index); #endif @@ -9810,7 +10139,7 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range, TYPE_MODE (TREE_TYPE (range)), expand_expr (range, NULL_RTX, VOIDmode, 0), - TREE_UNSIGNED (TREE_TYPE (range))), + TYPE_UNSIGNED (TREE_TYPE (range))), table_label, default_label); return 1; } @@ -9855,7 +10184,7 @@ const_vector_from_tree (tree exp) mode = TYPE_MODE (TREE_TYPE (exp)); - if (is_zeros_p (exp)) + if (initializer_zerop (exp)) return CONST0_RTX (mode); units = GET_MODE_NUNITS (mode); @@ -9883,5 +10212,4 @@ const_vector_from_tree (tree exp) return gen_rtx_raw_CONST_VECTOR (mode, v); } - #include "gt-expr.h"