X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Fexpr.c;h=ac756432f20be533d25cbf55f0973ca3fcdfc8a4;hb=e0f1be5c98090d91902b81bc6312826c7f75f1bb;hp=af36b3b5820fff038176f5c9edd0d52b42c5b6db;hpb=c24ae149dd6cec1b08f21d99c8db45fe9ba3f442;p=gcc.git diff --git a/gcc/expr.c b/gcc/expr.c index af36b3b5820..ac756432f20 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -1,6 +1,6 @@ /* Convert tree expression to rtl instructions, for GNU compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001 Free Software Foundation, Inc. + 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of GCC. @@ -81,11 +81,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA the same indirect address eventually. */ int cse_not_expected; -/* Don't check memory usage, since code is being emitted to check a memory - usage. Used when current_function_check_memory_usage is true, to avoid - infinite recursion. */ -static int in_check_memory_usage; - /* Chain of pending expressions for PLACEHOLDER_EXPR to replace. */ static tree placeholder_list = 0; @@ -124,8 +119,6 @@ struct store_by_pieces extern struct obstack permanent_obstack; -static rtx get_push_address PARAMS ((int)); - static rtx enqueue_insn PARAMS ((rtx, rtx)); static unsigned HOST_WIDE_INT move_by_pieces_ninsns PARAMS ((unsigned HOST_WIDE_INT, @@ -152,8 +145,6 @@ static rtx store_field PARAMS ((rtx, HOST_WIDE_INT, HOST_WIDE_INT, enum machine_mode, tree, enum machine_mode, int, tree, int)); -static enum memory_use_mode - get_memory_usage_from_modifier PARAMS ((enum expand_modifier)); static rtx var_rtx PARAMS ((tree)); static HOST_WIDE_INT highest_pow2_factor PARAMS ((tree)); static rtx expand_increment PARAMS ((tree, int, int)); @@ -1061,6 +1052,9 @@ convert_move (to, from, unsignedp) if ((code = can_extend_p (to_mode, from_mode, unsignedp)) != CODE_FOR_nothing) { + if (flag_force_mem) + from = force_not_mem (from); + emit_unop_insn (code, to, from, equiv_code); return; } @@ -1581,9 +1575,11 @@ move_by_pieces_1 (genfun, mode, data) from1 = adjust_address (data->from, mode, 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->to_addr, + GEN_INT (-(HOST_WIDE_INT)size))); if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0) - emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size))); + emit_insn (gen_add2_insn (data->from_addr, + GEN_INT (-(HOST_WIDE_INT)size))); if (data->to) emit_insn ((*genfun) (to1, from1)); @@ -1877,7 +1873,8 @@ move_block_from_reg (regno, x, nregs, size) /* If SIZE is that of a mode no bigger than a word, just use that mode's store operation. */ if (size <= UNITS_PER_WORD - && (mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0)) != BLKmode) + && (mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0)) != BLKmode + && !FUNCTION_ARG_REG_LITTLE_ENDIAN) { emit_move_insn (adjust_address (x, mode, 0), gen_rtx_REG (mode, regno)); return; @@ -1886,7 +1883,9 @@ move_block_from_reg (regno, x, nregs, size) /* 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). */ - if (size < UNITS_PER_WORD && BYTES_BIG_ENDIAN) + if (size < UNITS_PER_WORD + && BYTES_BIG_ENDIAN + && !FUNCTION_ARG_REG_LITTLE_ENDIAN) { rtx tem = operand_subword (x, 0, 1, BLKmode); rtx shift; @@ -1933,7 +1932,7 @@ move_block_from_reg (regno, x, nregs, size) /* Emit code to move a block SRC to a block DST, where DST is non-consecutive registers represented by a PARALLEL. SSIZE represents the total size of block SRC in bytes, or -1 if not known. */ -/* ??? If SSIZE % UNITS_PER_WORD != 0, we make the blatent assumption that +/* ??? If SSIZE % UNITS_PER_WORD != 0, we make the blatant assumption that the balance will be in what would be the low-order memory addresses, i.e. left justified for big endian, right justified for little endian. This happens to be true for the targets currently using this support. If this @@ -2169,17 +2168,28 @@ copy_blkmode_from_reg (tgtblk, srcreg, 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. */ + /* 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 FUNCTION_ARG_REG_LITTLE_ENDIAN is set and convert_to_mode does a copy, + the wrong part of the register gets copied so we fake a type conversion + in place. */ if (GET_MODE (srcreg) != BLKmode && GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD) - srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type)); + { + if (FUNCTION_ARG_REG_LITTLE_ENDIAN) + srcreg = simplify_gen_subreg (word_mode, srcreg, GET_MODE (srcreg), 0); + else + 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) + if (BYTES_BIG_ENDIAN + && !FUNCTION_ARG_REG_LITTLE_ENDIAN + && bytes % UNITS_PER_WORD) big_endian_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT)); @@ -2783,7 +2793,6 @@ emit_move_insn_1 (x, y) enum machine_mode mode = GET_MODE (x); enum machine_mode submode; enum mode_class class = GET_MODE_CLASS (mode); - unsigned int i; if ((unsigned int) mode >= (unsigned int) MAX_MACHINE_MODE) abort (); @@ -2809,10 +2818,11 @@ emit_move_insn_1 (x, y) /* In case we output to the stack, but the size is smaller machine can push exactly, we need to use move instructions. */ if (stack - && PUSH_ROUNDING (GET_MODE_SIZE (submode)) != GET_MODE_SIZE (submode)) + && (PUSH_ROUNDING (GET_MODE_SIZE (submode)) + != GET_MODE_SIZE (submode))) { rtx temp; - int offset1, offset2; + HOST_WIDE_INT offset1, offset2; /* Do not use anti_adjust_stack, since we don't want to update stack_pointer_delta. */ @@ -2824,12 +2834,13 @@ emit_move_insn_1 (x, y) #endif stack_pointer_rtx, GEN_INT - (PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))), - stack_pointer_rtx, - 0, - OPTAB_LIB_WIDEN); + (PUSH_ROUNDING + (GET_MODE_SIZE (GET_MODE (x)))), + stack_pointer_rtx, 0, OPTAB_LIB_WIDEN); + if (temp != stack_pointer_rtx) emit_move_insn (stack_pointer_rtx, temp); + #ifdef STACK_GROWS_DOWNWARD offset1 = 0; offset2 = GET_MODE_SIZE (submode); @@ -2838,6 +2849,7 @@ emit_move_insn_1 (x, y) offset2 = (-PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x))) + GET_MODE_SIZE (submode)); #endif + emit_move_insn (change_address (x, submode, gen_rtx_PLUS (Pmode, stack_pointer_rtx, @@ -2893,8 +2905,10 @@ emit_move_insn_1 (x, y) 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); - int packed_src_p = (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER); + int packed_dest_p + = (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER); + int packed_src_p + = (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER); if (packed_dest_p || packed_src_p) { @@ -2916,12 +2930,14 @@ emit_move_insn_1 (x, y) if (packed_dest_p) { rtx sreg = gen_rtx_SUBREG (reg_mode, x, 0); + emit_move_insn_1 (cmem, y); return emit_move_insn_1 (sreg, mem); } else { rtx sreg = gen_rtx_SUBREG (reg_mode, y, 0); + emit_move_insn_1 (mem, sreg); return emit_move_insn_1 (x, cmem); } @@ -2942,9 +2958,7 @@ emit_move_insn_1 (x, y) && ! (reload_in_progress || reload_completed) && (GET_CODE (realpart_x) == SUBREG || GET_CODE (imagpart_x) == SUBREG)) - { - emit_insn (gen_rtx_CLOBBER (VOIDmode, x)); - } + emit_insn (gen_rtx_CLOBBER (VOIDmode, x)); emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) (realpart_x, realpart_y)); @@ -2963,6 +2977,7 @@ emit_move_insn_1 (x, y) rtx last_insn = 0; rtx seq, inner; int need_clobber; + int i; #ifdef PUSH_ROUNDING @@ -2983,19 +2998,20 @@ emit_move_insn_1 (x, y) #endif stack_pointer_rtx, GEN_INT - (PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))), - stack_pointer_rtx, - 0, - OPTAB_LIB_WIDEN); + (PUSH_ROUNDING + (GET_MODE_SIZE (GET_MODE (x)))), + stack_pointer_rtx, 0, OPTAB_LIB_WIDEN); + if (temp != stack_pointer_rtx) emit_move_insn (stack_pointer_rtx, temp); code = GET_CODE (XEXP (x, 0)); + /* Just hope that small offsets off SP are OK. */ if (code == POST_INC) temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx, - GEN_INT (-(HOST_WIDE_INT) - GET_MODE_SIZE (GET_MODE (x)))); + GEN_INT (-((HOST_WIDE_INT) + GET_MODE_SIZE (GET_MODE (x))))); else if (code == POST_DEC) temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (GET_MODE_SIZE (GET_MODE (x)))); @@ -3054,9 +3070,7 @@ emit_move_insn_1 (x, y) if (x != y && ! (reload_in_progress || reload_completed) && need_clobber != 0) - { - emit_insn (gen_rtx_CLOBBER (VOIDmode, x)); - } + emit_insn (gen_rtx_CLOBBER (VOIDmode, x)); emit_insn (seq); @@ -3124,26 +3138,6 @@ push_block (size, extra, below) return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp); } - -/* Return an rtx for the address of the beginning of an as-if-it-was-pushed - block of SIZE bytes. */ - -static rtx -get_push_address (size) - int size; -{ - rtx temp; - - if (STACK_PUSH_CODE == POST_DEC) - temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (size)); - else if (STACK_PUSH_CODE == POST_INC) - temp = gen_rtx_MINUS (Pmode, stack_pointer_rtx, GEN_INT (size)); - else - temp = stack_pointer_rtx; - - return copy_to_reg (temp); -} - #ifdef PUSH_ROUNDING /* Emit single push insn. */ @@ -3167,7 +3161,7 @@ emit_single_push_insn (mode, x, type) if (icode != CODE_FOR_nothing) { if (((pred = insn_data[(int) icode].operand[0].predicate) - && !((*pred) (x, mode)))) + && !((*pred) (x, mode)))) x = force_reg (mode, x); emit_insn (GEN_FCN (icode) (x)); return; @@ -3178,7 +3172,7 @@ emit_single_push_insn (mode, x, type) { #ifdef STACK_GROWS_DOWNWARD dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, - GEN_INT (-(HOST_WIDE_INT)rounded_size)); + GEN_INT (-(HOST_WIDE_INT) rounded_size)); #else dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (rounded_size)); @@ -3325,28 +3319,6 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra, anti_adjust_stack (GEN_INT (extra)); move_by_pieces (NULL, 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); - if (GET_CODE (x) == MEM && type && AGGREGATE_TYPE_P (type)) - 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, - 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)); - in_check_memory_usage = 0; - } } else #endif /* PUSH_ROUNDING */ @@ -3385,26 +3357,6 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra, args_addr, args_so_far), skip)); - if (current_function_check_memory_usage && ! in_check_memory_usage) - { - 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, - LCT_CONST_MAKE_BLOCK, VOIDmode, 3, - target, Pmode, - XEXP (xinner, 0), Pmode, - size, TYPE_MODE (sizetype)); - else - emit_library_call (chkr_set_right_libfunc, - LCT_CONST_MAKE_BLOCK, VOIDmode, 3, - target, Pmode, - size, TYPE_MODE (sizetype), - GEN_INT (MEMORY_USE_RW), - TYPE_MODE (integer_type_node)); - in_check_memory_usage = 0; - } - target = gen_rtx_MEM (BLKmode, temp); if (type != 0) @@ -3605,27 +3557,6 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra, emit_move_insn (dest, x); } - if (current_function_check_memory_usage && ! in_check_memory_usage) - { - in_check_memory_usage = 1; - if (target == 0) - 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, - 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, - 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)); - in_check_memory_usage = 0; - } } ret: @@ -3724,11 +3655,11 @@ expand_assignment (to, from, want_value, suggest_reg) if (mode1 == VOIDmode && want_value) tem = stabilize_reference (tem); - orig_to_rtx = to_rtx - = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_DONT); + orig_to_rtx = to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, 0); + if (offset != 0) { - rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0); + rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM); if (GET_CODE (to_rtx) != MEM) abort (); @@ -3751,15 +3682,7 @@ expand_assignment (to, from, want_value, suggest_reg) && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1)) { - rtx temp - = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT); - - if (GET_CODE (XEXP (temp, 0)) == REG) - to_rtx = temp; - else - to_rtx = (replace_equiv_address - (to_rtx, force_reg (GET_MODE (XEXP (temp, 0)), - XEXP (temp, 0)))); + to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT); bitpos = 0; } @@ -3805,43 +3728,13 @@ expand_assignment (to, from, want_value, suggest_reg) RTX_UNCHANGING_P (to_rtx) = 1; } - if (! can_address_p (to)) + if (GET_CODE (to_rtx) == MEM && ! can_address_p (to)) { if (to_rtx == orig_to_rtx) to_rtx = copy_rtx (to_rtx); MEM_KEEP_ALIAS_SET_P (to_rtx) = 1; } - /* Check the access. */ - if (current_function_check_memory_usage && GET_CODE (to_rtx) == MEM) - { - rtx to_addr; - int size; - int best_mode_size; - enum machine_mode best_mode; - - best_mode = get_best_mode (bitsize, bitpos, - TYPE_ALIGN (TREE_TYPE (tem)), - mode1, volatilep); - if (best_mode == VOIDmode) - best_mode = QImode; - - best_mode_size = GET_MODE_BITSIZE (best_mode); - to_addr = plus_constant (XEXP (to_rtx, 0), bitpos / BITS_PER_UNIT); - size = CEIL ((bitpos % best_mode_size) + bitsize, best_mode_size); - 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, 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 for HPUX compiler. */ @@ -3883,7 +3776,7 @@ expand_assignment (to, from, want_value, suggest_reg) push_temp_slots (); value = expand_expr (from, NULL_RTX, VOIDmode, 0); if (to_rtx == 0) - to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_WO); + to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE); /* Handle calls that return values in multiple non-contiguous locations. The Irix 6 ABI has examples of this. */ @@ -3910,7 +3803,7 @@ expand_assignment (to, from, want_value, suggest_reg) Don't re-expand if it was expanded already (in COMPONENT_REF case). */ if (to_rtx == 0) - to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_WO); + to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE); /* Don't move directly into a return register. */ if (TREE_CODE (to) == RESULT_DECL @@ -3943,17 +3836,7 @@ expand_assignment (to, from, want_value, suggest_reg) push_temp_slots (); size = expr_size (from); - from_rtx = expand_expr (from, NULL_RTX, VOIDmode, - EXPAND_MEMORY_USE_DONT); - - /* Copy the rights of the bitmap. */ - if (current_function_check_memory_usage) - 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)); + from_rtx = expand_expr (from, NULL_RTX, VOIDmode, 0); #ifdef TARGET_MEM_FUNCTIONS emit_library_call (memmove_libfunc, LCT_NORMAL, @@ -4106,6 +3989,8 @@ store_expr (exp, target, want_value) and then convert to the wider mode. Our value is the computed expression. */ { + rtx inner_target = 0; + /* If we don't want a value, we can do the conversion inside EXP, which will often result in some optimizations. Do the conversion in two steps: first change the signedness, if needed, then @@ -4126,9 +4011,11 @@ store_expr (exp, target, want_value) exp = convert (type_for_mode (GET_MODE (SUBREG_REG (target)), SUBREG_PROMOTED_UNSIGNED_P (target)), exp); + + inner_target = SUBREG_REG (target); } - temp = expand_expr (exp, NULL_RTX, VOIDmode, 0); + temp = expand_expr (exp, inner_target, VOIDmode, 0); /* If TEMP is a volatile MEM and we want a result value, make the access now so it gets done only once. Likewise if @@ -4156,13 +4043,19 @@ store_expr (exp, target, want_value) target. Otherwise, the caller might get confused by a result whose mode is larger than expected. */ - if (want_value && GET_MODE (temp) != GET_MODE (target) - && GET_MODE (temp) != VOIDmode) + if (want_value && GET_MODE (temp) != GET_MODE (target)) { - temp = gen_lowpart_SUBREG (GET_MODE (target), temp); - SUBREG_PROMOTED_VAR_P (temp) = 1; - SUBREG_PROMOTED_UNSIGNED_P (temp) - = SUBREG_PROMOTED_UNSIGNED_P (target); + if (GET_MODE (temp) != VOIDmode) + { + temp = gen_lowpart_SUBREG (GET_MODE (target), temp); + SUBREG_PROMOTED_VAR_P (temp) = 1; + SUBREG_PROMOTED_UNSIGNED_SET (temp, + SUBREG_PROMOTED_UNSIGNED_P (target)); + } + else + temp = convert_modes (GET_MODE (target), + GET_MODE (SUBREG_REG (target)), + temp, SUBREG_PROMOTED_UNSIGNED_P (target)); } return want_value ? temp : NULL_RTX; @@ -4195,28 +4088,9 @@ store_expr (exp, target, want_value) temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)), temp, TREE_UNSIGNED (TREE_TYPE (exp))); - if (current_function_check_memory_usage - && 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, 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, LCT_CONST_MAKE_BLOCK, - VOIDmode, 3, XEXP (target, 0), Pmode, - expr_size (exp), TYPE_MODE (sizetype), - 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. - Convert the value to TARGET's type first if nec. */ - /* If TEMP and TARGET compare equal according to rtx_equal_p, but + Convert the value to TARGET's type first if necessary. + 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: - expand_expr has used TARGET. In this case, we must not generate @@ -4305,19 +4179,7 @@ store_expr (exp, target, want_value) } if (size != const0_rtx) - { - /* 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, - LCT_CONST_MAKE_BLOCK, VOIDmode, 3, - XEXP (target, 0), Pmode, - size, TYPE_MODE (sizetype), - GEN_INT (MEMORY_USE_WO), - TYPE_MODE (integer_type_node)); - in_check_memory_usage = 0; - clear_storage (target, size); - } + clear_storage (target, size); if (label) emit_label (label); @@ -4378,6 +4240,14 @@ is_zeros_p (exp) case REAL_CST: return REAL_VALUES_IDENTICAL (TREE_REAL_CST (exp), dconst0); + case VECTOR_CST: + for (elt = TREE_VECTOR_CST_ELTS (exp); elt; + elt = TREE_CHAIN (elt)) + if (!is_zeros_p (TREE_VALUE (elt))) + return 0; + + return 1; + case CONSTRUCTOR: if (TREE_TYPE (exp) && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE) return CONSTRUCTOR_ELTS (exp) == NULL_TREE; @@ -4662,20 +4532,34 @@ store_constructor (exp, target, cleared, size) get_alias_set (TREE_TYPE (field))); } } - else if (TREE_CODE (type) == ARRAY_TYPE) + else if (TREE_CODE (type) == ARRAY_TYPE + || TREE_CODE (type) == VECTOR_TYPE) { tree elt; int i; int need_to_clear; tree domain = TYPE_DOMAIN (type); tree elttype = TREE_TYPE (type); - int const_bounds_p = (TYPE_MIN_VALUE (domain) - && TYPE_MAX_VALUE (domain) - && host_integerp (TYPE_MIN_VALUE (domain), 0) - && host_integerp (TYPE_MAX_VALUE (domain), 0)); + int const_bounds_p; HOST_WIDE_INT minelt = 0; HOST_WIDE_INT maxelt = 0; + /* Vectors are like arrays, but the domain is stored via an array + type indirectly. */ + if (TREE_CODE (type) == VECTOR_TYPE) + { + /* 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))); + } + + const_bounds_p = (TYPE_MIN_VALUE (domain) + && TYPE_MAX_VALUE (domain) + && host_integerp (TYPE_MIN_VALUE (domain), 0) + && host_integerp (TYPE_MAX_VALUE (domain), 0)); + /* If we have constant bounds for the range of the type, get them. */ if (const_bounds_p) { @@ -4736,7 +4620,12 @@ store_constructor (exp, target, cleared, size) if (need_to_clear && size > 0) { if (! cleared) - clear_storage (target, GEN_INT (size)); + { + if (REG_P (target)) + emit_move_insn (target, CONST0_RTX (GET_MODE (target))); + else + clear_storage (target, GEN_INT (size)); + } cleared = 1; } else if (REG_P (target)) @@ -4799,6 +4688,7 @@ store_constructor (exp, target, cleared, size) if (GET_CODE (target) == MEM && !MEM_KEEP_ALIAS_SET_P (target) + && TREE_CODE (type) == ARRAY_TYPE && TYPE_NONALIASED_COMPONENT (type)) { target = copy_rtx (target); @@ -4896,6 +4786,7 @@ store_constructor (exp, target, cleared, size) bitpos = (i * tree_low_cst (TYPE_SIZE (elttype), 1)); if (GET_CODE (target) == MEM && !MEM_KEEP_ALIAS_SET_P (target) + && TREE_CODE (type) == ARRAY_TYPE && TYPE_NONALIASED_COMPONENT (type)) { target = copy_rtx (target); @@ -5152,9 +5043,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type, = assign_temp (build_qualified_type (type, TYPE_QUALS (type) | TYPE_QUAL_CONST), 0, 1, 1); - rtx blk_object = copy_rtx (object); - - PUT_MODE (blk_object, BLKmode); + rtx blk_object = adjust_address (object, BLKmode, 0); if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target))) emit_move_insn (object, target); @@ -5206,7 +5095,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type, low-order bits. However, if EXP's type is a record and this is big-endian machine, we want the upper BITSIZE bits. */ if (BYTES_BIG_ENDIAN && GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT - && bitsize < GET_MODE_BITSIZE (GET_MODE (temp)) + && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (temp)) && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE) temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp, size_int (GET_MODE_BITSIZE (GET_MODE (temp)) @@ -5250,18 +5139,16 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type, tree count; enum machine_mode tmode; - if (unsignedp) - return expand_and (temp, - GEN_INT - (trunc_int_for_mode - (width_mask, - GET_MODE (temp) == VOIDmode - ? value_mode - : GET_MODE (temp))), NULL_RTX); - tmode = GET_MODE (temp); if (tmode == VOIDmode) tmode = value_mode; + + if (unsignedp) + return expand_and (tmode, temp, + GEN_INT (trunc_int_for_mode (width_mask, + tmode)), + NULL_RTX); + count = build_int_2 (GET_MODE_BITSIZE (tmode) - bitsize, 0); temp = expand_shift (LSHIFT_EXPR, tmode, temp, count, 0, 0); return expand_shift (RSHIFT_EXPR, tmode, temp, count, 0, 0); @@ -5508,37 +5395,6 @@ handled_component_p (t) return 0; } } - -/* Subroutine of expand_exp: compute memory_usage from modifier. */ - -static enum memory_use_mode -get_memory_usage_from_modifier (modifier) - enum expand_modifier modifier; -{ - switch (modifier) - { - case EXPAND_NORMAL: - case EXPAND_SUM: - return MEMORY_USE_RO; - break; - case EXPAND_MEMORY_USE_WO: - return MEMORY_USE_WO; - break; - case EXPAND_MEMORY_USE_RW: - return MEMORY_USE_RW; - break; - case EXPAND_MEMORY_USE_DONT: - /* EXPAND_CONST_ADDRESS and EXPAND_INITIALIZER are converted into - MEMORY_USE_DONT, because they are modifiers to a call of - expand_expr in the ADDR_EXPR case of expand_expr. */ - case EXPAND_CONST_ADDRESS: - case EXPAND_INITIALIZER: - return MEMORY_USE_DONT; - case EXPAND_MEMORY_USE_BAD: - default: - abort (); - } -} /* Given an rtx VALUE that may contain additions and multiplications, return an equivalent value that just refers to a register, memory, or constant. @@ -5560,8 +5416,7 @@ force_operand (value, target) rtx subtarget = get_subtarget (target); /* Check for a PIC address load. */ - if (flag_pic - && (GET_CODE (value) == PLUS || GET_CODE (value) == MINUS) + if ((GET_CODE (value) == PLUS || GET_CODE (value) == MINUS) && XEXP (value, 0) == pic_offset_table_rtx && (GET_CODE (XEXP (value, 1)) == SYMBOL_REF || GET_CODE (XEXP (value, 1)) == LABEL_REF @@ -5879,7 +5734,7 @@ safe_from_p (x, exp, top_p) are memory and they conflict. */ return ! (rtx_equal_p (x, exp_rtl) || (GET_CODE (x) == MEM && GET_CODE (exp_rtl) == MEM - && true_dependence (exp_rtl, GET_MODE (x), x, + && true_dependence (exp_rtl, VOIDmode, x, rtx_addr_varies_p))); } @@ -5972,19 +5827,25 @@ highest_pow2_factor (exp) switch (TREE_CODE (exp)) { case INTEGER_CST: - /* If the integer is expressable in a HOST_WIDE_INT, we can find the - lowest bit that's a one. If the result is zero, pessimize by - returning 1. This is overly-conservative, but such things should not - happen in the offset expressions that we are called with. */ - if (host_integerp (exp, 0)) + /* We can find the lowest bit that's a one. If the low + HOST_BITS_PER_WIDE_INT bits are zero, return BIGGEST_ALIGNMENT. + We need to handle this case since we can find it in a COND_EXPR, + a MIN_EXPR, or a MAX_EXPR. If the constant overlows, we have an + erroneous program, so return BIGGEST_ALIGNMENT to avoid any + later ICE. */ + if (TREE_CONSTANT_OVERFLOW (exp)) + return BIGGEST_ALIGNMENT; + else { - c0 = tree_low_cst (exp, 0); - c0 = c0 < 0 ? - c0 : c0; - return c0 != 0 ? c0 & -c0 : 1; + /* Note: tree_low_cst is intentionally not used here, + we don't care about the upper bits. */ + c0 = TREE_INT_CST_LOW (exp); + c0 &= -c0; + return c0 ? c0 : BIGGEST_ALIGNMENT; } break; - case PLUS_EXPR: case MINUS_EXPR: + case PLUS_EXPR: case MINUS_EXPR: case MIN_EXPR: case MAX_EXPR: c0 = highest_pow2_factor (TREE_OPERAND (exp, 0)); c1 = highest_pow2_factor (TREE_OPERAND (exp, 1)); return MIN (c0, c1); @@ -5996,14 +5857,22 @@ highest_pow2_factor (exp) case ROUND_DIV_EXPR: case TRUNC_DIV_EXPR: case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR: - c0 = highest_pow2_factor (TREE_OPERAND (exp, 0)); - c1 = highest_pow2_factor (TREE_OPERAND (exp, 1)); - return MAX (1, c0 / c1); + if (integer_pow2p (TREE_OPERAND (exp, 1)) + && host_integerp (TREE_OPERAND (exp, 1), 1)) + { + c0 = highest_pow2_factor (TREE_OPERAND (exp, 0)); + c1 = tree_low_cst (TREE_OPERAND (exp, 1), 1); + return MAX (1, c0 / c1); + } + break; case NON_LVALUE_EXPR: case NOP_EXPR: case CONVERT_EXPR: - case COMPOUND_EXPR: case SAVE_EXPR: case WITH_RECORD_EXPR: + case SAVE_EXPR: case WITH_RECORD_EXPR: return highest_pow2_factor (TREE_OPERAND (exp, 0)); + case COMPOUND_EXPR: + return highest_pow2_factor (TREE_OPERAND (exp, 1)); + case COND_EXPR: c0 = highest_pow2_factor (TREE_OPERAND (exp, 1)); c1 = highest_pow2_factor (TREE_OPERAND (exp, 2)); @@ -6133,8 +6002,6 @@ expand_expr (exp, target, tmode, modifier) rtx subtarget, original_target; int ignore; tree context; - /* 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 || TREE_CODE (type) == ERROR_MARK) @@ -6155,13 +6022,6 @@ expand_expr (exp, target, tmode, modifier) || code == COND_EXPR || code == VIEW_CONVERT_EXPR) && TREE_CODE (type) == VOID_TYPE)); - /* Make a read-only version of the modifier. */ - if (modifier == EXPAND_NORMAL || modifier == EXPAND_SUM - || modifier == EXPAND_CONST_ADDRESS || modifier == EXPAND_INITIALIZER) - ro_modifier = modifier; - else - ro_modifier = EXPAND_NORMAL; - /* 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 @@ -6180,7 +6040,7 @@ expand_expr (exp, target, tmode, modifier) && mode != VOIDmode && mode != BLKmode && modifier != EXPAND_CONST_ADDRESS) { - temp = expand_expr (exp, NULL_RTX, VOIDmode, ro_modifier); + temp = expand_expr (exp, NULL_RTX, VOIDmode, modifier); if (GET_CODE (temp) == MEM) temp = copy_to_reg (temp); return const0_rtx; @@ -6188,34 +6048,30 @@ expand_expr (exp, target, tmode, modifier) if (TREE_CODE_CLASS (code) == '1' || code == COMPONENT_REF || code == INDIRECT_REF || code == BUFFER_REF) - return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, - VOIDmode, ro_modifier); + return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, + modifier); + else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<' || code == ARRAY_REF || code == ARRAY_RANGE_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, 0), const0_rtx, VOIDmode, modifier); + expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, modifier); return const0_rtx; } else if ((code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR) && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1))) /* If the second operand has no side effects, just evaluate the first. */ - return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, - VOIDmode, ro_modifier); + return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, + modifier); else if (code == BIT_FIELD_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); + expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier); + expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, modifier); + expand_expr (TREE_OPERAND (exp, 2), const0_rtx, VOIDmode, modifier); return const0_rtx; } - ; + target = 0; } @@ -6333,34 +6189,6 @@ expand_expr (exp, target, tmode, modifier) } } - /* Although static-storage variables start off initialized, according to - ANSI C, a memcpy could overwrite them with uninitialized values. So - we check them too. This also lets us check for read-only variables - accessed via a non-const declaration, in case it won't be detected - any other way (e.g., in an embedded system or OS kernel without - memory protection). - - Aggregates are not checked here; they're handled elsewhere. */ - if (cfun && current_function_check_memory_usage - && code == VAR_DECL - && GET_CODE (DECL_RTL (exp)) == MEM - && ! AGGREGATE_TYPE_P (TREE_TYPE (exp))) - { - 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, - 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 ... */ case FUNCTION_DECL: @@ -6452,7 +6280,7 @@ expand_expr (exp, target, tmode, modifier) but mark it so that we know that it was already extended. */ if (GET_CODE (DECL_RTL (exp)) == REG - && GET_MODE (DECL_RTL (exp)) != mode) + && GET_MODE (DECL_RTL (exp)) != DECL_MODE (exp)) { /* Get the signedness used for this variable. Ensure we get the same mode we got when the variable was declared. */ @@ -6462,7 +6290,7 @@ expand_expr (exp, target, tmode, modifier) temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp)); SUBREG_PROMOTED_VAR_P (temp) = 1; - SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp; + SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp); return temp; } @@ -6473,8 +6301,7 @@ expand_expr (exp, target, tmode, modifier) TREE_INT_CST_HIGH (exp), mode); case CONST_DECL: - return expand_expr (DECL_INITIAL (exp), target, VOIDmode, - EXPAND_MEMORY_USE_BAD); + return expand_expr (DECL_INITIAL (exp), target, VOIDmode, 0); case REAL_CST: /* If optimized, generate immediate CONST_DOUBLE @@ -6583,12 +6410,11 @@ expand_expr (exp, target, tmode, modifier) { temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp)); SUBREG_PROMOTED_VAR_P (temp) = 1; - SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp; + SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp); } if (temp == const0_rtx) - expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, - EXPAND_MEMORY_USE_BAD); + expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0); else store_expr (TREE_OPERAND (exp, 0), temp, 0); @@ -6606,7 +6432,7 @@ expand_expr (exp, target, tmode, modifier) promote_mode (type, mode, &unsignedp, 0); temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp)); SUBREG_PROMOTED_VAR_P (temp) = 1; - SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp; + SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp); return temp; } @@ -6616,7 +6442,8 @@ expand_expr (exp, target, tmode, modifier) { rtx temp; temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier); - TREE_OPERAND (exp, 0) = unsave_expr_now (TREE_OPERAND (exp, 0)); + TREE_OPERAND (exp, 0) + = (*lang_hooks.unsave_expr_now) (TREE_OPERAND (exp, 0)); return temp; } @@ -6630,7 +6457,7 @@ expand_expr (exp, target, tmode, modifier) abort (); placeholder_list = TREE_CHAIN (placeholder_expr); - temp = expand_expr (exp, original_target, tmode, ro_modifier); + temp = expand_expr (exp, original_target, tmode, modifier); placeholder_list = old_list; return temp; } @@ -6643,8 +6470,8 @@ expand_expr (exp, target, tmode, modifier) 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, ro_modifier); + target = expand_expr (TREE_OPERAND (exp, 0), original_target, tmode, + modifier); placeholder_list = TREE_CHAIN (placeholder_list); return target; @@ -6662,7 +6489,7 @@ expand_expr (exp, target, tmode, modifier) case LABELED_BLOCK_EXPR: if (LABELED_BLOCK_BODY (exp)) - expand_expr_stmt (LABELED_BLOCK_BODY (exp)); + expand_expr_stmt_value (LABELED_BLOCK_BODY (exp), 0, 1); /* Should perhaps use expand_label, but this is simpler and safer. */ do_pending_stack_adjust (); emit_label (label_rtx (LABELED_BLOCK_LABEL (exp))); @@ -6677,7 +6504,7 @@ expand_expr (exp, target, tmode, modifier) case LOOP_EXPR: push_temp_slots (); expand_start_loop (1); - expand_expr_stmt (TREE_OPERAND (exp, 0)); + expand_expr_stmt_value (TREE_OPERAND (exp, 0), 0, 1); expand_end_loop (); pop_temp_slots (); @@ -6709,7 +6536,7 @@ expand_expr (exp, target, tmode, modifier) vars = TREE_CHAIN (vars); } - temp = expand_expr (TREE_OPERAND (exp, 1), target, tmode, ro_modifier); + temp = expand_expr (TREE_OPERAND (exp, 1), target, tmode, modifier); expand_end_bindings (TREE_OPERAND (exp, 0), 0, 0); @@ -6734,9 +6561,10 @@ expand_expr (exp, target, tmode, modifier) if (ignore) { tree elt; + for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt)) - expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, - EXPAND_MEMORY_USE_BAD); + expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0); + return const0_rtx; } @@ -6798,39 +6626,19 @@ expand_expr (exp, target, tmode, modifier) && 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) + && modifier != EXPAND_WRITE) 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 (cfun && current_function_check_memory_usage - && ! AGGREGATE_TYPE_P (TREE_TYPE (exp))) - { - enum memory_use_mode memory_usage; - memory_usage = get_memory_usage_from_modifier (modifier); - - if (memory_usage != MEMORY_USE_DONT) - { - in_check_memory_usage = 1; - 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)); - in_check_memory_usage = 0; - } - } - temp = gen_rtx_MEM (mode, op0); set_mem_attributes (temp, exp, 0); /* If we are writing to this object and its type is a record with readonly fields, we must mark it as readonly so it will conflict with readonly references to those fields. */ - if (modifier == EXPAND_MEMORY_USE_WO && readonly_fields_p (type)) + if (modifier == EXPAND_WRITE && readonly_fields_p (type)) RTX_UNCHANGING_P (temp) = 1; return temp; @@ -6892,8 +6700,8 @@ expand_expr (exp, target, tmode, modifier) ; if (elem) - return expand_expr (fold (TREE_VALUE (elem)), target, - tmode, ro_modifier); + return expand_expr (fold (TREE_VALUE (elem)), target, tmode, + modifier); } else if (optimize >= 1 @@ -6919,7 +6727,7 @@ expand_expr (exp, target, tmode, modifier) if (elem && !TREE_SIDE_EFFECTS (TREE_VALUE (elem))) return expand_expr (fold (TREE_VALUE (elem)), target, - tmode, ro_modifier); + tmode, modifier); } else if (TREE_CODE (init) == STRING_CST && 0 > compare_tree_int (index, @@ -6973,16 +6781,16 @@ expand_expr (exp, target, tmode, modifier) { HOST_WIDE_INT bitsize = TREE_INT_CST_LOW (DECL_SIZE (TREE_PURPOSE (elt))); + enum machine_mode imode + = TYPE_MODE (TREE_TYPE (TREE_PURPOSE (elt))); if (TREE_UNSIGNED (TREE_TYPE (TREE_PURPOSE (elt)))) { op1 = GEN_INT (((HOST_WIDE_INT) 1 << bitsize) - 1); - op0 = expand_and (op0, op1, target); + op0 = expand_and (imode, op0, op1, target); } else { - enum machine_mode imode - = TYPE_MODE (TREE_TYPE (TREE_PURPOSE (elt))); tree count = build_int_2 (GET_MODE_BITSIZE (imode) - bitsize, 0); @@ -7042,7 +6850,7 @@ expand_expr (exp, target, tmode, modifier) if (offset != 0) { - rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0); + rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM); /* If this object is in a register, put it into memory. This case can't occur in C, but can in Ada if we have @@ -7092,15 +6900,7 @@ expand_expr (exp, target, tmode, modifier) && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 && MEM_ALIGN (op0) == GET_MODE_ALIGNMENT (mode1)) { - rtx temp = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT); - - if (GET_CODE (XEXP (temp, 0)) == REG) - op0 = temp; - else - op0 = (replace_equiv_address - (op0, - force_reg (GET_MODE (XEXP (temp, 0)), - XEXP (temp, 0)))); + op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT); bitpos = 0; } @@ -7117,34 +6917,6 @@ expand_expr (exp, target, tmode, modifier) MEM_VOLATILE_P (op0) = 1; } - /* Check the access. */ - 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); - - if (memory_usage != MEMORY_USE_DONT) - { - rtx to; - int size; - - to = plus_constant (XEXP (op0, 0), (bitpos / BITS_PER_UNIT)); - 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, - LCT_CONST_MAKE_BLOCK, VOIDmode, 3, to, - Pmode, GEN_INT (size / BITS_PER_UNIT), - TYPE_MODE (sizetype), - GEN_INT (memory_usage), - TYPE_MODE (integer_type_node)); - in_check_memory_usage = 0; - } - } - /* In cases where an aligned union has an unaligned object as a field, we might be extracting a BLKmode value from an integer-mode (e.g., SImode) object. Handle this case @@ -7216,7 +6988,7 @@ expand_expr (exp, target, tmode, modifier) machine, we must put the field into the high-order bits. */ if (TREE_CODE (type) == RECORD_TYPE && BYTES_BIG_ENDIAN && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT - && bitsize < GET_MODE_BITSIZE (GET_MODE (op0))) + && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (op0))) op0 = expand_shift (LSHIFT_EXPR, GET_MODE (op0), op0, size_int (GET_MODE_BITSIZE (GET_MODE (op0)) - bitsize), @@ -7416,7 +7188,7 @@ expand_expr (exp, target, tmode, modifier) if (WITH_CLEANUP_EXPR_RTL (exp) == 0) { WITH_CLEANUP_EXPR_RTL (exp) - = expand_expr (TREE_OPERAND (exp, 0), target, tmode, ro_modifier); + = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier); expand_decl_cleanup (NULL_TREE, TREE_OPERAND (exp, 1)); /* That's it for this cleanup. */ @@ -7432,7 +7204,7 @@ expand_expr (exp, target, tmode, modifier) target_temp_slot_level = temp_slot_level; - op0 = expand_expr (TREE_OPERAND (exp, 0), target, tmode, ro_modifier); + op0 = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier); /* If we're going to use this value, load it up now. */ if (! ignore) op0 = force_not_mem (op0); @@ -7507,7 +7279,7 @@ expand_expr (exp, target, tmode, modifier) if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) { op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, - ro_modifier); + modifier); /* If the signedness of the conversion differs and OP0 is a promoted SUBREG, clear that indication since we now @@ -7519,15 +7291,24 @@ expand_expr (exp, target, tmode, modifier) return op0; } - op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, 0); + op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, modifier); if (GET_MODE (op0) == mode) return op0; /* If OP0 is a constant, just convert it into the proper mode. */ if (CONSTANT_P (op0)) - return - convert_modes (mode, TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))), - op0, TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); + { + tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); + enum machine_mode inner_mode = TYPE_MODE (inner_type); + + if (modifier == EXPAND_INITIALIZER) + return simplify_gen_subreg (mode, op0, inner_mode, + subreg_lowpart_offset (mode, + inner_mode)); + else + return convert_modes (mode, inner_mode, op0, + TREE_UNSIGNED (inner_type)); + } if (modifier == EXPAND_INITIALIZER) return gen_rtx_fmt_e (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, mode, op0); @@ -7542,7 +7323,7 @@ expand_expr (exp, target, tmode, modifier) return target; case VIEW_CONVERT_EXPR: - op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, ro_modifier); + op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, modifier); /* If the input and output modes are both the same, we are done. Otherwise, if neither mode is BLKmode and both are within a word, we @@ -7589,16 +7370,16 @@ expand_expr (exp, target, tmode, modifier) && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (TYPE_MODE (type))) { tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); - HOST_WIDE_INT temp_size = MAX (int_size_in_bytes (inner_type), - GET_MODE_SIZE (TYPE_MODE (type))); + HOST_WIDE_INT temp_size + = MAX (int_size_in_bytes (inner_type), + (HOST_WIDE_INT) GET_MODE_SIZE (TYPE_MODE (type))); rtx new = assign_stack_temp_for_type (TYPE_MODE (type), temp_size, 0, type); - rtx new_with_op0_mode = copy_rtx (new); + rtx new_with_op0_mode = adjust_address (new, GET_MODE (op0), 0); if (TREE_ADDRESSABLE (exp)) abort (); - PUT_MODE (new_with_op0_mode, GET_MODE (op0)); if (GET_MODE (op0) == BLKmode) emit_block_move (new_with_op0_mode, op0, GEN_INT (GET_MODE_SIZE (TYPE_MODE (type)))); @@ -7608,7 +7389,7 @@ expand_expr (exp, target, tmode, modifier) op0 = new; } - PUT_MODE (op0, TYPE_MODE (type)); + op0 = adjust_address (op0, TYPE_MODE (type), 0); } return op0; @@ -7618,7 +7399,7 @@ expand_expr (exp, target, tmode, modifier) constant. */ plus_expr: this_optab = ! unsignedp && flag_trapv - && (GET_MODE_CLASS(mode) == MODE_INT) + && (GET_MODE_CLASS (mode) == MODE_INT) ? addv_optab : add_optab; /* If we are adding a constant, an RTL_EXPR that is sp, fp, or ap, and @@ -7722,8 +7503,8 @@ expand_expr (exp, target, tmode, modifier) if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1)) subtarget = 0; - op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, ro_modifier); - op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, ro_modifier); + op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier); + op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier); both_summands: /* Make sure any term that's a sum with a constant comes last. */ @@ -7782,10 +7563,10 @@ expand_expr (exp, target, tmode, modifier) && really_constant_p (TREE_OPERAND (exp, 0)) && really_constant_p (TREE_OPERAND (exp, 1))) { - rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, - VOIDmode, ro_modifier); - rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, - VOIDmode, ro_modifier); + rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, + modifier); + rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, + modifier); /* If the last operand is a CONST_INT, use plus_constant of the negated constant. Else make the MINUS. */ @@ -7831,23 +7612,20 @@ expand_expr (exp, target, tmode, modifier) indexed address, for machines that support that. */ if (modifier == EXPAND_SUM && mode == ptr_mode - && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST - && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) + && host_integerp (TREE_OPERAND (exp, 1), 0)) { op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM); - /* Apply distributive law if OP0 is x+c. */ - if (GET_CODE (op0) == PLUS - && GET_CODE (XEXP (op0, 1)) == CONST_INT) - return - gen_rtx_PLUS - (mode, - gen_rtx_MULT - (mode, XEXP (op0, 0), - GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))), - GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) - * INTVAL (XEXP (op0, 1)))); + /* If we knew for certain that this is arithmetic for an array + reference, and we knew the bounds of the array, then we could + apply the distributive law across (PLUS X C) for constant C. + Without such knowledge, we risk overflowing the computation + when both X and C are large, but X+C isn't. */ + /* ??? Could perhaps special-case EXP being unsigned and C being + positive. In that case we are certain that X+C is no smaller + than X and so the transformed expression will overflow iff the + original would have. */ if (GET_CODE (op0) != REG) op0 = force_operand (op0, NULL_RTX); @@ -7856,7 +7634,7 @@ expand_expr (exp, target, tmode, modifier) return gen_rtx_MULT (mode, op0, - GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))); + GEN_INT (tree_low_cst (TREE_OPERAND (exp, 1), 0))); } if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1)) @@ -8267,11 +8045,11 @@ expand_expr (exp, target, tmode, modifier) if (ignore) { expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, - ro_modifier); + modifier); return const0_rtx; } - op0 = expand_expr (TREE_OPERAND (exp, 0), target, mode, ro_modifier); + op0 = expand_expr (TREE_OPERAND (exp, 0), target, mode, modifier); if (GET_MODE (op0) == mode) return op0; @@ -8737,21 +8515,30 @@ expand_expr (exp, target, tmode, modifier) || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF || GET_CODE (op0) == PARALLEL) { - /* If this object is in a register, it must can't be BLKmode. */ - tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); - tree nt = build_qualified_type (inner_type, - (TYPE_QUALS (inner_type) - | TYPE_QUAL_CONST)); - rtx memloc = assign_temp (nt, 1, 1, 1); - - if (GET_CODE (op0) == PARALLEL) - /* Handle calls that pass values in multiple non-contiguous - locations. The Irix 6 ABI has examples of this. */ - emit_group_store (memloc, op0, int_size_in_bytes (inner_type)); + /* If the operand is a SAVE_EXPR, we can deal with this by + forcing the SAVE_EXPR into memory. */ + if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR) + { + put_var_into_stack (TREE_OPERAND (exp, 0)); + op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0)); + } else - emit_move_insn (memloc, op0); - - op0 = memloc; + { + /* If this object is in a register, it can't be BLKmode. */ + tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); + rtx memloc = assign_temp (inner_type, 1, 1, 1); + + if (GET_CODE (op0) == PARALLEL) + /* Handle calls that pass values in multiple + non-contiguous locations. The Irix 6 ABI has examples + of this. */ + emit_group_store (memloc, op0, + int_size_in_bytes (inner_type)); + else + emit_move_insn (memloc, op0); + + op0 = memloc; + } } if (GET_CODE (op0) != MEM) @@ -8804,7 +8591,11 @@ expand_expr (exp, target, tmode, modifier) op0 = force_operand (XEXP (op0, 0), target); } - if (flag_force_addr && GET_CODE (op0) != REG) + if (flag_force_addr + && GET_CODE (op0) != REG + && modifier != EXPAND_CONST_ADDRESS + && modifier != EXPAND_INITIALIZER + && modifier != EXPAND_SUM) op0 = force_reg (Pmode, op0); if (GET_CODE (op0) == REG @@ -9076,7 +8867,7 @@ expand_increment (exp, post, ignore) and insns were generated in computing it. */ temp = get_last_insn (); - op0 = expand_expr (incremented, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_RW); + op0 = expand_expr (incremented, NULL_RTX, VOIDmode, 0); /* If OP0 is a SUBREG made for a promoted variable, we cannot increment in place but instead must do sign- or zero-extension during assignment, @@ -9107,8 +8898,7 @@ expand_increment (exp, post, ignore) op0_is_copy = ((GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG) && temp != get_last_insn ()); - op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, - EXPAND_MEMORY_USE_BAD); + op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); /* Decide whether incrementing or decrementing. */ if (TREE_CODE (exp) == POSTDECREMENT_EXPR @@ -9124,7 +8914,7 @@ expand_increment (exp, post, ignore) } if (TYPE_TRAP_SIGNED (TREE_TYPE (exp))) - this_optab = this_optab == add_optab ? addv_optab : subv_optab; + this_optab = this_optab == add_optab ? addv_optab : subv_optab; /* For a preincrement, see if we can do this with a single instruction. */ if (!post) @@ -9229,9 +9019,9 @@ expand_increment (exp, post, ignore) temp = copy_rtx (value = op0); /* Increment however we can. */ - op1 = expand_binop (mode, this_optab, value, op1, - current_function_check_memory_usage ? NULL_RTX : op0, + op1 = expand_binop (mode, this_optab, value, op1, op0, TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN); + /* Make sure the value is stored into OP0. */ if (op1 != op0) emit_move_insn (op0, op1); @@ -10417,7 +10207,7 @@ do_store_flag (exp, target, mode, only_cheap) /* Put the AND last so it can combine with more things. */ if (bitnum != TYPE_PRECISION (type) - 1) - op0 = expand_and (op0, const1_rtx, subtarget); + op0 = expand_and (mode, op0, const1_rtx, subtarget); return op0; } @@ -10488,6 +10278,14 @@ do_store_flag (exp, target, mode, only_cheap) || (result != const0_rtx && invert)) ? const0_rtx : const1_rtx); + /* The code of RESULT may not match CODE if compare_from_rtx + decided to swap its operands and reverse the original code. + + We know that compare_from_rtx returns either a CONST_INT or + a new comparison code, so it is safe to just extract the + code from RESULT. */ + code = GET_CODE (result); + label = gen_label_rtx (); if (bcc_gen_fctn[(int) code] == 0) abort ();