diff options
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 53 |
1 files changed, 44 insertions, 9 deletions
@@ -126,7 +126,7 @@ static unsigned HOST_WIDE_INT move_by_pieces_ninsns (unsigned HOST_WIDE_INT, static void move_by_pieces_1 (rtx (*) (rtx, ...), enum machine_mode, struct move_by_pieces *); static bool block_move_libcall_safe_for_call_parm (void); -static bool emit_block_move_via_movmem (rtx, rtx, rtx, unsigned); +static bool emit_block_move_via_movmem (rtx, rtx, rtx, unsigned, unsigned, HOST_WIDE_INT); static tree emit_block_move_libcall_fn (int); static void emit_block_move_via_loop (rtx, rtx, rtx, unsigned); static rtx clear_by_pieces_1 (void *, HOST_WIDE_INT, enum machine_mode); @@ -1147,7 +1147,8 @@ move_by_pieces_1 (rtx (*genfun) (rtx, ...), enum machine_mode mode, 0 otherwise. */ rtx -emit_block_move (rtx x, rtx y, rtx size, enum block_op_methods method) +emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method, + unsigned int expected_align, HOST_WIDE_INT expected_size) { bool may_use_call; rtx retval = 0; @@ -1202,7 +1203,8 @@ emit_block_move (rtx x, rtx y, rtx size, enum block_op_methods method) if (GET_CODE (size) == CONST_INT && MOVE_BY_PIECES_P (INTVAL (size), align)) move_by_pieces (x, y, INTVAL (size), align, 0); - else if (emit_block_move_via_movmem (x, y, size, align)) + else if (emit_block_move_via_movmem (x, y, size, align, + expected_align, expected_size)) ; else if (may_use_call) retval = emit_block_move_via_libcall (x, y, size, @@ -1216,6 +1218,12 @@ emit_block_move (rtx x, rtx y, rtx size, enum block_op_methods method) return retval; } +rtx +emit_block_move (rtx x, rtx y, rtx size, enum block_op_methods method) +{ + return emit_block_move_hints (x, y, size, method, 0, -1); +} + /* A subroutine of emit_block_move. Returns true if calling the block move libcall will not clobber any parameters which may have already been placed on the stack. */ @@ -1266,12 +1274,16 @@ block_move_libcall_safe_for_call_parm (void) return true if successful. */ static bool -emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align) +emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align, + unsigned int expected_align, HOST_WIDE_INT expected_size) { rtx opalign = GEN_INT (align / BITS_PER_UNIT); int save_volatile_ok = volatile_ok; enum machine_mode mode; + if (expected_align < align) + expected_align = align; + /* Since this is a move insn, we don't care about volatility. */ volatile_ok = 1; @@ -1315,7 +1327,12 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align) that it doesn't fail the expansion because it thinks emitting the libcall would be more efficient. */ - pat = GEN_FCN ((int) code) (x, y, op2, opalign); + if (insn_data[(int) code].n_operands == 4) + pat = GEN_FCN ((int) code) (x, y, op2, opalign); + else + pat = GEN_FCN ((int) code) (x, y, op2, opalign, + GEN_INT (expected_align), + GEN_INT (expected_size)); if (pat) { emit_insn (pat); @@ -2495,7 +2512,8 @@ store_by_pieces_2 (rtx (*genfun) (rtx, ...), enum machine_mode mode, its length in bytes. */ rtx -clear_storage (rtx object, rtx size, enum block_op_methods method) +clear_storage_hints (rtx object, rtx size, enum block_op_methods method, + unsigned int expected_align, HOST_WIDE_INT expected_size) { enum machine_mode mode = GET_MODE (object); unsigned int align; @@ -2535,7 +2553,8 @@ clear_storage (rtx object, rtx size, enum block_op_methods method) if (GET_CODE (size) == CONST_INT && CLEAR_BY_PIECES_P (INTVAL (size), align)) clear_by_pieces (object, INTVAL (size), align); - else if (set_storage_via_setmem (object, size, const0_rtx, align)) + else if (set_storage_via_setmem (object, size, const0_rtx, align, + expected_align, expected_size)) ; else return set_storage_via_libcall (object, size, const0_rtx, @@ -2544,6 +2563,13 @@ clear_storage (rtx object, rtx size, enum block_op_methods method) return NULL; } +rtx +clear_storage (rtx object, rtx size, enum block_op_methods method) +{ + return clear_storage_hints (object, size, method, 0, -1); +} + + /* A subroutine of clear_storage. Expand a call to memset. Return the return value of memset, 0 otherwise. */ @@ -2645,7 +2671,8 @@ clear_storage_libcall_fn (int for_call) /* Expand a setmem pattern; return true if successful. */ bool -set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align) +set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align, + unsigned int expected_align, HOST_WIDE_INT expected_size) { /* Try the most limited insn first, because there's no point including more than one in the machine description unless @@ -2654,6 +2681,9 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align) rtx opalign = GEN_INT (align / BITS_PER_UNIT); enum machine_mode mode; + if (expected_align < align) + expected_align = align; + for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) { @@ -2694,7 +2724,12 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align) opchar = copy_to_mode_reg (char_mode, opchar); } - pat = GEN_FCN ((int) code) (object, opsize, opchar, opalign); + if (insn_data[(int) code].n_operands == 4) + pat = GEN_FCN ((int) code) (object, opsize, opchar, opalign); + else + pat = GEN_FCN ((int) code) (object, opsize, opchar, opalign, + GEN_INT (expected_align), + GEN_INT (expected_size)); if (pat) { emit_insn (pat); |