diff options
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 441 |
1 files changed, 186 insertions, 255 deletions
diff --git a/gcc/expr.c b/gcc/expr.c index 6a300585716..633f4a75537 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -151,7 +151,6 @@ 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 int mostly_zeros_p (tree); static void store_constructor_field (rtx, unsigned HOST_WIDE_INT, HOST_WIDE_INT, enum machine_mode, tree, tree, int, int); @@ -165,6 +164,8 @@ static unsigned HOST_WIDE_INT highest_pow2_factor_for_type (tree, tree); static int is_aligning_offset (tree, tree); static rtx expand_increment (tree, int, int); +static void expand_operands (tree, tree, rtx, rtx*, rtx*, + enum expand_modifier); static rtx do_store_flag (tree, rtx, enum machine_mode, int); #ifdef PUSH_ROUNDING static void emit_single_push_insn (enum machine_mode, rtx, tree); @@ -234,6 +235,9 @@ enum insn_code movstr_optab[NUM_MACHINE_MODES]; /* This array records the insn_code of insns to perform block clears. */ enum insn_code clrstr_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 @@ -339,15 +343,7 @@ init_expr_once (void) void init_expr (void) { - cfun->expr = (struct expr_status *) ggc_alloc (sizeof (struct expr_status)); - - pending_chain = 0; - pending_stack_adjust = 0; - stack_pointer_delta = 0; - inhibit_defer_pop = 0; - saveregs_value = 0; - apply_args_value = 0; - forced_labels = 0; + cfun->expr = ggc_alloc_cleared (sizeof (struct expr_status)); } /* Small sanity check that the queue is empty at the end of a function. */ @@ -1420,6 +1416,15 @@ convert_modes (enum machine_mode mode, enum machine_mode oldmode, rtx x, int uns return gen_lowpart (mode, x); } + /* Converting from integer constant into mode is always equivalent to an + subreg operation. */ + if (VECTOR_MODE_P (mode) && GET_MODE (x) == VOIDmode) + { + if (GET_MODE_BITSIZE (mode) != GET_MODE_BITSIZE (oldmode)) + abort (); + return simplify_gen_subreg (mode, x, oldmode, 0); + } + temp = gen_reg_rtx (mode); convert_move (temp, x, unsignedp); return temp; @@ -1766,6 +1771,9 @@ emit_block_move (rtx x, rtx y, rtx size, enum block_op_methods method) can be incorrect is coming from __builtin_memcpy. */ if (GET_CODE (size) == CONST_INT) { + if (INTVAL (size) == 0) + return 0; + x = shallow_copy_rtx (x); y = shallow_copy_rtx (y); set_mem_size (x, size); @@ -1949,10 +1957,8 @@ emit_block_move_via_libcall (rtx dst, rtx src, rtx size) dst_addr = copy_to_mode_reg (Pmode, XEXP (dst, 0)); src_addr = copy_to_mode_reg (Pmode, XEXP (src, 0)); -#ifdef POINTERS_EXTEND_UNSIGNED dst_addr = convert_memory_address (ptr_mode, dst_addr); src_addr = convert_memory_address (ptr_mode, src_addr); -#endif dst_tree = make_tree (ptr_type_node, dst_addr); src_tree = make_tree (ptr_type_node, src_addr); @@ -1995,7 +2001,6 @@ emit_block_move_via_libcall (rtx dst, rtx src, rtx size) call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn); call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), call_expr, arg_list, NULL_TREE); - TREE_SIDE_EFFECTS (call_expr) = 1; retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0); @@ -2221,7 +2226,7 @@ gen_group_rtx (rtx orig) abort (); length = XVECLEN (orig, 0); - tmps = (rtx *) alloca (sizeof (rtx) * length); + tmps = alloca (sizeof (rtx) * length); /* Skip a NULL entry in first slot. */ i = XEXP (XVECEXP (orig, 0, 0), 0) ? 0 : 1; @@ -2240,18 +2245,13 @@ gen_group_rtx (rtx orig) return gen_rtx_PARALLEL (GET_MODE (orig), gen_rtvec_v (length, tmps)); } -/* 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 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 - ever changes, a new target macro along the lines of FUNCTION_ARG_PADDING - would be needed. */ +/* Emit code to move a block ORIG_SRC of type TYPE to a block DST, + where DST is non-consecutive registers represented by a PARALLEL. + SSIZE represents the total size of block ORIG_SRC in bytes, or -1 + if not known. */ void -emit_group_load (rtx dst, rtx orig_src, int ssize) +emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize) { rtx *tmps, src; int start, i; @@ -2266,7 +2266,7 @@ emit_group_load (rtx dst, rtx orig_src, int ssize) else start = 1; - tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (dst, 0)); + tmps = alloca (sizeof (rtx) * XVECLEN (dst, 0)); /* Process the pieces. */ for (i = start; i < XVECLEN (dst, 0); i++) @@ -2279,7 +2279,17 @@ emit_group_load (rtx dst, rtx orig_src, int ssize) /* Handle trailing fragments that run over the size of the struct. */ if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize) { - shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT; + /* Arrange to shift the fragment to where it belongs. + extract_bit_field loads to the lsb of the reg. */ + if ( +#ifdef BLOCK_REG_PADDING + BLOCK_REG_PADDING (GET_MODE (orig_src), type, i == start) + == (BYTES_BIG_ENDIAN ? upward : downward) +#else + BYTES_BIG_ENDIAN +#endif + ) + shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT; bytelen = ssize - bytepos; if (bytelen <= 0) abort (); @@ -2304,7 +2314,8 @@ emit_group_load (rtx dst, rtx orig_src, int ssize) /* Optimize the access just a bit. */ if (GET_CODE (src) == MEM - && MEM_ALIGN (src) >= GET_MODE_ALIGNMENT (mode) + && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (src)) + || MEM_ALIGN (src) >= GET_MODE_ALIGNMENT (mode)) && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0 && bytelen == GET_MODE_SIZE (mode)) { @@ -2360,7 +2371,7 @@ emit_group_load (rtx dst, rtx orig_src, int ssize) bytepos * BITS_PER_UNIT, 1, NULL_RTX, mode, mode, ssize); - if (BYTES_BIG_ENDIAN && shift) + if (shift) expand_binop (mode, ashl_optab, tmps[i], GEN_INT (shift), tmps[i], 0, OPTAB_WIDEN); } @@ -2391,12 +2402,13 @@ emit_group_move (rtx dst, rtx src) XEXP (XVECEXP (src, 0, i), 0)); } -/* Emit code to move a block SRC to a block DST, where SRC is non-consecutive - registers represented by a PARALLEL. SSIZE represents the total size of - block DST, or -1 if not known. */ +/* Emit code to move a block SRC to a block ORIG_DST of type TYPE, + where SRC is non-consecutive registers represented by a PARALLEL. + SSIZE represents the total size of block ORIG_DST, or -1 if not + known. */ void -emit_group_store (rtx orig_dst, rtx src, int ssize) +emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize) { rtx *tmps, dst; int start, i; @@ -2411,7 +2423,7 @@ emit_group_store (rtx orig_dst, rtx src, int ssize) else start = 1; - tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (src, 0)); + tmps = alloca (sizeof (rtx) * XVECLEN (src, 0)); /* Copy the (probable) hard regs into pseudos. */ for (i = start; i < XVECLEN (src, 0); i++) @@ -2440,8 +2452,8 @@ emit_group_store (rtx orig_dst, rtx src, int ssize) the temporary. */ temp = assign_stack_temp (GET_MODE (dst), ssize, 0); - emit_group_store (temp, src, ssize); - emit_group_load (dst, temp, ssize); + emit_group_store (temp, src, type, ssize); + emit_group_load (dst, temp, type, ssize); return; } else if (GET_CODE (dst) != MEM && GET_CODE (dst) != CONCAT) @@ -2462,7 +2474,16 @@ emit_group_store (rtx orig_dst, rtx src, int ssize) /* Handle trailing fragments that run over the size of the struct. */ if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize) { - if (BYTES_BIG_ENDIAN) + /* store_bit_field always takes its value from the lsb. + Move the fragment to the lsb if it's not already there. */ + if ( +#ifdef BLOCK_REG_PADDING + BLOCK_REG_PADDING (GET_MODE (orig_dst), type, i == start) + == (BYTES_BIG_ENDIAN ? upward : downward) +#else + BYTES_BIG_ENDIAN +#endif + ) { int shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT; expand_binop (mode, ashr_optab, tmps[i], GEN_INT (shift), @@ -2495,7 +2516,8 @@ emit_group_store (rtx orig_dst, rtx src, int ssize) /* Optimize the access just a bit. */ if (GET_CODE (dest) == MEM - && MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode) + && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (dest)) + || MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode)) && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0 && bytelen == GET_MODE_SIZE (mode)) emit_move_insn (adjust_address (dest, mode, bytepos), tmps[i]); @@ -2958,7 +2980,7 @@ clear_storage (rtx object, rtx size) object = protect_from_queue (object, 1); size = protect_from_queue (size, 0); - if (GET_CODE (size) == CONST_INT && INTVAL (size) == 0) + if (size == const0_rtx) ; else if (GET_CODE (size) == CONST_INT && CLEAR_BY_PIECES_P (INTVAL (size), align)) @@ -3092,7 +3114,6 @@ clear_storage_via_libcall (rtx object, rtx size) call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn); call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), call_expr, arg_list, NULL_TREE); - TREE_SIDE_EFFECTS (call_expr) = 1; retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0); @@ -4076,7 +4097,7 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size, /* Handle calls that pass values in multiple non-contiguous locations. The Irix 6 ABI has examples of this. */ if (GET_CODE (reg) == PARALLEL) - emit_group_load (reg, x, -1); /* ??? size? */ + emit_group_load (reg, x, type, -1); else move_block_to_reg (REGNO (reg), x, partial, mode); } @@ -4111,16 +4132,10 @@ get_subtarget (rtx x) If WANT_VALUE is nonzero, return an rtx for the value of TO. (This may contain a QUEUED rtx; if the value is constant, this rtx is a constant.) - Otherwise, the returned value is NULL_RTX. - - SUGGEST_REG is no longer actually used. - It used to mean, copy the value through a register - and return that register, if that is possible. - We now use WANT_VALUE to decide whether to do this. */ + Otherwise, the returned value is NULL_RTX. */ rtx -expand_assignment (tree to, tree from, int want_value, - int suggest_reg ATTRIBUTE_UNUSED) +expand_assignment (tree to, tree from, int want_value) { rtx to_rtx = 0; rtx result; @@ -4261,7 +4276,7 @@ expand_assignment (tree to, tree from, int want_value, since it might be a promoted variable where the zero- or sign- extension needs to be done. Handling this in the normal way is safe because no computation is done before the call. */ - if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from) + 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)) @@ -4276,16 +4291,14 @@ expand_assignment (tree to, tree from, int want_value, /* Handle calls that return values in multiple non-contiguous locations. The Irix 6 ABI has examples of this. */ if (GET_CODE (to_rtx) == PARALLEL) - emit_group_load (to_rtx, value, int_size_in_bytes (TREE_TYPE (from))); + emit_group_load (to_rtx, value, TREE_TYPE (from), + int_size_in_bytes (TREE_TYPE (from))); else if (GET_MODE (to_rtx) == BLKmode) emit_block_move (to_rtx, value, expr_size (from), BLOCK_OP_NORMAL); else { -#ifdef POINTERS_EXTEND_UNSIGNED - if (POINTER_TYPE_P (TREE_TYPE (to)) - && GET_MODE (to_rtx) != GET_MODE (value)) + if (POINTER_TYPE_P (TREE_TYPE (to))) value = convert_memory_address (GET_MODE (to_rtx), value); -#endif emit_move_insn (to_rtx, value); } preserve_temp_slots (to_rtx); @@ -4310,7 +4323,8 @@ expand_assignment (tree to, tree from, int want_value, temp = expand_expr (from, 0, GET_MODE (to_rtx), 0); if (GET_CODE (to_rtx) == PARALLEL) - emit_group_load (to_rtx, temp, int_size_in_bytes (TREE_TYPE (from))); + emit_group_load (to_rtx, temp, TREE_TYPE (from), + int_size_in_bytes (TREE_TYPE (from))); else emit_move_insn (to_rtx, temp); @@ -4720,7 +4734,8 @@ store_expr (tree exp, rtx target, int want_value) /* Handle calls that return values in multiple non-contiguous locations. The Irix 6 ABI has examples of this. */ else if (GET_CODE (target) == PARALLEL) - emit_group_load (target, temp, int_size_in_bytes (TREE_TYPE (exp))); + emit_group_load (target, temp, TREE_TYPE (exp), + int_size_in_bytes (TREE_TYPE (exp))); else if (GET_MODE (temp) == BLKmode) emit_block_move (target, temp, expr_size (exp), (want_value & 2 @@ -4749,7 +4764,7 @@ store_expr (tree exp, rtx target, int want_value) return target; } -/* Return 1 if EXP just contains zeros. */ +/* Return 1 if EXP just contains zeros. FIXME merge with initializer_zerop. */ static int is_zeros_p (tree exp) @@ -4798,7 +4813,7 @@ is_zeros_p (tree exp) /* Return 1 if EXP contains mostly (3/4) zeros. */ -static int +int mostly_zeros_p (tree exp) { if (TREE_CODE (exp) == CONSTRUCTOR) @@ -5371,7 +5386,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) { unsigned int set_word_size = TYPE_ALIGN (TREE_TYPE (exp)); enum machine_mode mode = mode_for_size (set_word_size, MODE_INT, 1); - char *bit_buffer = (char *) alloca (nbits); + char *bit_buffer = alloca (nbits); HOST_WIDE_INT word = 0; unsigned int bit_pos = 0; unsigned int ibit = 0; @@ -6246,10 +6261,6 @@ safe_from_p (rtx x, tree exp, int top_p) part of the expression. */ return safe_from_p (x, TREE_OPERAND (exp, 1), 0); - case METHOD_CALL_EXPR: - /* This takes an rtx argument, but shouldn't appear here. */ - abort (); - default: break; } @@ -6381,7 +6392,7 @@ highest_pow2_factor (tree exp) /* 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 + a MIN_EXPR, or a MAX_EXPR. If the constant overflows, we have an erroneous program, so return BIGGEST_ALIGNMENT to avoid any later ICE. */ if (TREE_CONSTANT_OVERFLOW (exp)) @@ -6512,6 +6523,30 @@ find_placeholder (tree exp, tree *plist) return 0; } + +/* Subroutine of expand_expr. Expand the two operands of a binary + expression EXP0 and EXP1 placing the results in OP0 and OP1. + The value may be stored in TARGET if TARGET is nonzero. The + MODIFIER argument is as documented by expand_expr. */ + +static void +expand_operands (tree exp0, tree exp1, rtx target, rtx *op0, rtx *op1, + enum expand_modifier modifier) +{ + if (! safe_from_p (target, exp1, 1)) + target = 0; + if (operand_equal_p (exp0, exp1, 0)) + { + *op0 = expand_expr (exp0, target, VOIDmode, modifier); + *op1 = copy_rtx (*op0); + } + else + { + *op0 = expand_expr (exp0, target, VOIDmode, modifier); + *op1 = expand_expr (exp1, NULL_RTX, VOIDmode, modifier); + } +} + /* expand_expr: generate code for computing expression EXP. An rtx for the computed value is returned. The value is never null. @@ -6556,7 +6591,8 @@ find_placeholder (tree exp, tree *plist) emit_block_move will be flagged with BLOCK_OP_CALL_PARM. */ rtx -expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier modifier) +expand_expr (tree exp, rtx target, enum machine_mode tmode, + enum expand_modifier modifier) { rtx op0, op1, temp; tree type = TREE_TYPE (exp); @@ -6693,7 +6729,7 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier if (! cse_not_expected && mode != BLKmode && target && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER) && ! (code == CONSTRUCTOR && GET_MODE_SIZE (mode) > UNITS_PER_WORD) - && ! (code == CALL_EXPR && aggregate_value_p (exp))) + && ! (code == CALL_EXPR && aggregate_value_p (exp, exp))) target = 0; switch (code) @@ -6721,7 +6757,7 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier case PARM_DECL: if (!DECL_RTL_SET_P (exp)) { - error_with_decl (exp, "prior parameter's size depends on `%s'"); + error ("%Jprior parameter's size depends on '%D'", exp, exp); return CONST0_RTX (mode); } @@ -6920,14 +6956,23 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier case EXPR_WITH_FILE_LOCATION: { rtx to_return; - location_t saved_loc = input_location; + 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), target, tmode, modifier); - input_location = saved_loc; + 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; } @@ -7440,39 +7485,41 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier op0 = validize_mem (force_const_mem (mode, op0)); } + /* Otherwise, if this object not in memory and we either have an + offset or a BLKmode result, put it there. This case can't occur in + C, but can in Ada if we have unchecked conversion of an expression + from a scalar type to an array or record type or for an + ARRAY_RANGE_REF whose type is BLKmode. */ + else if (GET_CODE (op0) != MEM + && (offset != 0 + || (code == ARRAY_RANGE_REF && mode == BLKmode))) + { + /* 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), + /*rescan=*/true); + op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0)); + } + else + { + tree nt + = build_qualified_type (TREE_TYPE (tem), + (TYPE_QUALS (TREE_TYPE (tem)) + | TYPE_QUAL_CONST)); + rtx memloc = assign_temp (nt, 1, 1, 1); + + emit_move_insn (memloc, op0); + op0 = memloc; + } + } + if (offset != 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 - unchecked conversion of an expression from a scalar type to - an array or record type. */ - if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG - || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF) - { - /* 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), - /*rescan=*/true); - op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0)); - } - else - { - tree nt - = build_qualified_type (TREE_TYPE (tem), - (TYPE_QUALS (TREE_TYPE (tem)) - | TYPE_QUAL_CONST)); - rtx memloc = assign_temp (nt, 1, 1, 1); - - emit_move_insn (memloc, op0); - op0 = memloc; - } - } - if (GET_CODE (op0) != MEM) abort (); @@ -8096,11 +8143,11 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier { op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier); - /* Don't go to both_summands if modifier - says it's not right to return a PLUS. */ - if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) - goto binop2; - goto both_summands; + /* Return a PLUS if modifier says it's OK. */ + if (modifier == EXPAND_SUM + || modifier == EXPAND_INITIALIZER) + return simplify_gen_binary (PLUS, mode, op0, op1); + goto binop2; } /* Use immed_double_const to ensure that the constant is truncated according to the mode of OP1, then sign extended @@ -8127,12 +8174,8 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) || mode != ptr_mode) { - op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); - if (! operand_equal_p (TREE_OPERAND (exp, 0), - TREE_OPERAND (exp, 1), 0)) - op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); - else - op1 = op0; + expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), + subtarget, &op0, &op1, 0); if (op0 == const0_rtx) return op1; if (op1 == const0_rtx) @@ -8140,62 +8183,9 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier goto binop2; } - op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier); - if (! operand_equal_p (TREE_OPERAND (exp, 0), - TREE_OPERAND (exp, 1), 0)) - op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, - VOIDmode, modifier); - else - op1 = op0; - - /* We come here from MINUS_EXPR when the second operand is a - constant. */ - both_summands: - /* Make sure any term that's a sum with a constant comes last. */ - if (GET_CODE (op0) == PLUS - && CONSTANT_P (XEXP (op0, 1))) - { - temp = op0; - op0 = op1; - op1 = temp; - } - /* If adding to a sum including a constant, - associate it to put the constant outside. */ - if (GET_CODE (op1) == PLUS - && CONSTANT_P (XEXP (op1, 1))) - { - rtx constant_term = const0_rtx; - - temp = simplify_binary_operation (PLUS, mode, XEXP (op1, 0), op0); - if (temp != 0) - op0 = temp; - /* Ensure that MULT comes first if there is one. */ - else if (GET_CODE (op0) == MULT) - op0 = gen_rtx_PLUS (mode, op0, XEXP (op1, 0)); - else - op0 = gen_rtx_PLUS (mode, XEXP (op1, 0), op0); - - /* Let's also eliminate constants from op0 if possible. */ - op0 = eliminate_constant_term (op0, &constant_term); - - /* CONSTANT_TERM and XEXP (op1, 1) are known to be constant, so - their sum should be a constant. Form it into OP1, since the - result we want will then be OP0 + OP1. */ - - temp = simplify_binary_operation (PLUS, mode, constant_term, - XEXP (op1, 1)); - if (temp != 0) - op1 = temp; - else - op1 = gen_rtx_PLUS (mode, constant_term, XEXP (op1, 1)); - } - - /* Put a constant term last and put a multiplication first. */ - if (CONSTANT_P (op0) || GET_CODE (op1) == MULT) - temp = op1, op1 = op0, op0 = temp; - - temp = simplify_binary_operation (PLUS, mode, op0, op1); - return temp ? temp : gen_rtx_PLUS (mode, op0, op1); + expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), + subtarget, &op0, &op1, modifier); + return simplify_gen_binary (PLUS, mode, op0, op1); case MINUS_EXPR: /* For initializers, we are allowed to return a MINUS of two @@ -8207,10 +8197,8 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_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, - modifier); - rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, - modifier); + expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), + NULL_RTX, &op0, &op1, modifier); /* If the last operand is a CONST_INT, use plus_constant of the negated constant. Else make the MINUS. */ @@ -8232,17 +8220,14 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier || mode != ptr_mode) goto binop; - if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1)) - subtarget = 0; - - op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier); - op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier); + expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), + subtarget, &op0, &op1, modifier); /* Convert A - const to A + (-const). */ if (GET_CODE (op1) == CONST_INT) { op1 = negate_rtx (mode, op1); - goto both_summands; + return simplify_gen_binary (PLUS, mode, op0, op1); } goto binop2; @@ -8331,14 +8316,14 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier { if (this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) { - op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), - NULL_RTX, VOIDmode, 0); if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST) - op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, - VOIDmode, 0); + expand_operands (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), + TREE_OPERAND (exp, 1), + NULL_RTX, &op0, &op1, 0); else - op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), - NULL_RTX, VOIDmode, 0); + expand_operands (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), + TREE_OPERAND (TREE_OPERAND (exp, 1), 0), + NULL_RTX, &op0, &op1, 0); goto binop2; } else if (other_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing @@ -8367,12 +8352,8 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier } } } - op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); - if (! operand_equal_p (TREE_OPERAND (exp, 0), - TREE_OPERAND (exp, 1), 0)) - op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); - else - op1 = op0; + expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), + subtarget, &op0, &op1, 0); return expand_mult (mode, op0, op1, target, unsignedp); case TRUNC_DIV_EXPR: @@ -8380,15 +8361,13 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier case CEIL_DIV_EXPR: case ROUND_DIV_EXPR: case EXACT_DIV_EXPR: - if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1)) - subtarget = 0; if (modifier == EXPAND_STACK_PARM) target = 0; /* Possible optimization: compute the dividend with EXPAND_SUM then if the divisor is constant can optimize the case where some terms of the dividend have coeffs divisible by it. */ - op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); - op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); + expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), + subtarget, &op0, &op1, 0); return expand_divmod (0, code, mode, op0, op1, target, unsignedp); case RDIV_EXPR: @@ -8410,12 +8389,10 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR: case ROUND_MOD_EXPR: - if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1)) - subtarget = 0; if (modifier == EXPAND_STACK_PARM) target = 0; - op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); - op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); + expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), + subtarget, &op0, &op1, 0); return expand_divmod (1, code, mode, op0, op1, target, unsignedp); case FIX_ROUND_EXPR: @@ -8460,10 +8437,10 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier if (modifier == EXPAND_STACK_PARM) target = 0; - /* Handle complex values specially. */ + /* ABS_EXPR is not valid for complex arguments. */ if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT) - return expand_complex_abs (mode, op0, target, unsignedp); + abort (); /* Unsigned abs is simply the operand. Testing here means we don't risk generating incorrect code below. */ @@ -8484,8 +8461,8 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier || (GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER)) target = gen_reg_rtx (mode); - op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); - op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0); + expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), + target, &op0, &op1, 0); /* 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 @@ -8542,43 +8519,6 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier abort (); return temp; - case FFS_EXPR: - op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); - if (modifier == EXPAND_STACK_PARM) - target = 0; - temp = expand_unop (mode, ffs_optab, op0, target, 1); - if (temp == 0) - abort (); - return temp; - - case CLZ_EXPR: - op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); - temp = expand_unop (mode, clz_optab, op0, target, 1); - if (temp == 0) - abort (); - return temp; - - case CTZ_EXPR: - op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); - temp = expand_unop (mode, ctz_optab, op0, target, 1); - if (temp == 0) - abort (); - return temp; - - case POPCOUNT_EXPR: - op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); - temp = expand_unop (mode, popcount_optab, op0, target, 1); - if (temp == 0) - abort (); - return temp; - - case PARITY_EXPR: - op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); - temp = expand_unop (mode, parity_optab, op0, target, 1); - if (temp == 0) - abort (); - return temp; - /* ??? Can optimize bitwise operations with one arg constant. Can optimize (a bitwise1 n) bitwise2 (a bitwise3 b) and (a bitwise1 b) bitwise2 b (etc) @@ -9122,7 +9062,7 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier tree lhs = TREE_OPERAND (exp, 0); tree rhs = TREE_OPERAND (exp, 1); - temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0); + temp = expand_assignment (lhs, rhs, ! ignore); return temp; } @@ -9167,13 +9107,13 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier (TREE_CODE (rhs) == BIT_IOR_EXPR ? integer_one_node : integer_zero_node)), - 0, 0); + 0); do_pending_stack_adjust (); emit_label (label); return const0_rtx; } - temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0); + temp = expand_assignment (lhs, rhs, ! ignore); return temp; } @@ -9266,7 +9206,7 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier /* Handle calls that pass values in multiple non-contiguous locations. The Irix 6 ABI has examples of this. */ - emit_group_store (memloc, op0, + emit_group_store (memloc, op0, inner_type, int_size_in_bytes (inner_type)); else emit_move_insn (memloc, op0); @@ -9282,11 +9222,8 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER) { op0 = XEXP (op0, 0); -#ifdef POINTERS_EXTEND_UNSIGNED - if (GET_MODE (op0) == Pmode && GET_MODE (op0) != mode - && mode == ptr_mode) + if (GET_MODE (op0) == Pmode && mode == ptr_mode) op0 = convert_memory_address (ptr_mode, op0); -#endif return op0; } @@ -9347,11 +9284,8 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier && ! REG_USERVAR_P (op0)) mark_reg_pointer (op0, TYPE_ALIGN (TREE_TYPE (type))); -#ifdef POINTERS_EXTEND_UNSIGNED - if (GET_MODE (op0) == Pmode && GET_MODE (op0) != mode - && mode == ptr_mode) + if (GET_MODE (op0) == Pmode && mode == ptr_mode) op0 = convert_memory_address (ptr_mode, op0); -#endif return op0; @@ -9540,10 +9474,8 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier /* Here to do an ordinary binary operator, generating an instruction from the optab already placed in `this_optab'. */ binop: - if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1)) - subtarget = 0; - op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); - op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); + expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), + subtarget, &op0, &op1, 0); binop2: if (modifier == EXPAND_STACK_PARM) target = 0; @@ -9776,7 +9708,7 @@ expand_increment (tree exp, int post, int ignore) incremented = TREE_OPERAND (incremented, 0); } - temp = expand_assignment (incremented, newexp, ! post && ! ignore , 0); + temp = expand_assignment (incremented, newexp, ! post && ! ignore); return post ? op0 : temp; } @@ -10042,8 +9974,7 @@ do_store_flag (tree exp, rtx target, enum machine_mode mode, int only_cheap) || ! safe_from_p (subtarget, arg1, 1)) subtarget = 0; - op0 = expand_expr (arg0, subtarget, VOIDmode, 0); - op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); + expand_operands (arg0, arg1, subtarget, &op0, &op1, 0); if (target == 0) target = gen_reg_rtx (mode); |