diff options
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 61 |
1 files changed, 44 insertions, 17 deletions
diff --git a/gcc/expr.c b/gcc/expr.c index a7ad8561e10..cdc1baff5af 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -24,6 +24,10 @@ along with GCC; see the file COPYING3. If not see #include "machmode.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "stor-layout.h" +#include "attribs.h" +#include "varasm.h" #include "flags.h" #include "regs.h" #include "hard-reg-set.h" @@ -129,7 +133,8 @@ static void move_by_pieces_1 (insn_gen_fn, machine_mode, struct move_by_pieces_d *); static bool block_move_libcall_safe_for_call_parm (void); static bool emit_block_move_via_movmem (rtx, rtx, rtx, unsigned, unsigned, HOST_WIDE_INT, - unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT); + unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, + 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); @@ -1100,7 +1105,8 @@ rtx emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method, unsigned int expected_align, HOST_WIDE_INT expected_size, unsigned HOST_WIDE_INT min_size, - unsigned HOST_WIDE_INT max_size) + unsigned HOST_WIDE_INT max_size, + unsigned HOST_WIDE_INT probable_max_size) { bool may_use_call; rtx retval = 0; @@ -1157,7 +1163,7 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method, move_by_pieces (x, y, INTVAL (size), align, 0); else if (emit_block_move_via_movmem (x, y, size, align, expected_align, expected_size, - min_size, max_size)) + min_size, max_size, probable_max_size)) ; else if (may_use_call && ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)) @@ -1193,7 +1199,7 @@ emit_block_move (rtx x, rtx y, rtx size, enum block_op_methods method) else max = GET_MODE_MASK (GET_MODE (size)); return emit_block_move_hints (x, y, size, method, 0, -1, - min, max); + min, max, max); } /* A subroutine of emit_block_move. Returns true if calling the @@ -1258,7 +1264,8 @@ static bool emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align, unsigned int expected_align, HOST_WIDE_INT expected_size, unsigned HOST_WIDE_INT min_size, - unsigned HOST_WIDE_INT max_size) + unsigned HOST_WIDE_INT max_size, + unsigned HOST_WIDE_INT probable_max_size) { int save_volatile_ok = volatile_ok; enum machine_mode mode; @@ -1267,8 +1274,8 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align, expected_align = align; if (expected_size != -1) { - if ((unsigned HOST_WIDE_INT)expected_size > max_size) - expected_size = max_size; + if ((unsigned HOST_WIDE_INT)expected_size > probable_max_size) + expected_size = probable_max_size; if ((unsigned HOST_WIDE_INT)expected_size < min_size) expected_size = min_size; } @@ -1297,7 +1304,7 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align, || max_size <= (GET_MODE_MASK (mode) >> 1) || GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode))) { - struct expand_operand ops[8]; + struct expand_operand ops[9]; unsigned int nops; /* ??? When called via emit_block_move_for_call, it'd be @@ -1305,7 +1312,7 @@ 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. */ nops = insn_data[(int) code].n_generator_args; - gcc_assert (nops == 4 || nops == 6 || nops == 8); + gcc_assert (nops == 4 || nops == 6 || nops == 8 || nops == 9); create_fixed_operand (&ops[0], x); create_fixed_operand (&ops[1], y); @@ -1317,7 +1324,7 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align, create_integer_operand (&ops[4], expected_align / BITS_PER_UNIT); create_integer_operand (&ops[5], expected_size); } - if (nops == 8) + if (nops >= 8) { create_integer_operand (&ops[6], min_size); /* If we can not represent the maximal size, @@ -1327,6 +1334,15 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align, else create_fixed_operand (&ops[7], NULL); } + if (nops == 9) + { + /* If we can not represent the maximal size, + make parameter NULL. */ + if ((HOST_WIDE_INT) probable_max_size != -1) + create_integer_operand (&ops[8], probable_max_size); + else + create_fixed_operand (&ops[8], NULL); + } if (maybe_expand_insn (code, nops, ops)) { volatile_ok = save_volatile_ok; @@ -2717,7 +2733,8 @@ rtx clear_storage_hints (rtx object, rtx size, enum block_op_methods method, unsigned int expected_align, HOST_WIDE_INT expected_size, unsigned HOST_WIDE_INT min_size, - unsigned HOST_WIDE_INT max_size) + unsigned HOST_WIDE_INT max_size, + unsigned HOST_WIDE_INT probable_max_size) { enum machine_mode mode = GET_MODE (object); unsigned int align; @@ -2759,7 +2776,7 @@ clear_storage_hints (rtx object, rtx size, enum block_op_methods method, clear_by_pieces (object, INTVAL (size), align); else if (set_storage_via_setmem (object, size, const0_rtx, align, expected_align, expected_size, - min_size, max_size)) + min_size, max_size, probable_max_size)) ; else if (ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (object))) return set_storage_via_libcall (object, size, const0_rtx, @@ -2778,7 +2795,7 @@ clear_storage (rtx object, rtx size, enum block_op_methods method) min = max = UINTVAL (size); else max = GET_MODE_MASK (GET_MODE (size)); - return clear_storage_hints (object, size, method, 0, -1, min, max); + return clear_storage_hints (object, size, method, 0, -1, min, max, max); } @@ -2877,7 +2894,8 @@ bool set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align, unsigned int expected_align, HOST_WIDE_INT expected_size, unsigned HOST_WIDE_INT min_size, - unsigned HOST_WIDE_INT max_size) + unsigned HOST_WIDE_INT max_size, + unsigned HOST_WIDE_INT probable_max_size) { /* Try the most limited insn first, because there's no point including more than one in the machine description unless @@ -2912,11 +2930,11 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align, || max_size <= (GET_MODE_MASK (mode) >> 1) || GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode))) { - struct expand_operand ops[8]; + struct expand_operand ops[9]; unsigned int nops; nops = insn_data[(int) code].n_generator_args; - gcc_assert (nops == 4 || nops == 6 || nops == 8); + gcc_assert (nops == 4 || nops == 6 || nops == 8 || nops == 9); create_fixed_operand (&ops[0], object); /* The check above guarantees that this size conversion is valid. */ @@ -2928,7 +2946,7 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align, create_integer_operand (&ops[4], expected_align / BITS_PER_UNIT); create_integer_operand (&ops[5], expected_size); } - if (nops == 8) + if (nops >= 8) { create_integer_operand (&ops[6], min_size); /* If we can not represent the maximal size, @@ -2938,6 +2956,15 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align, else create_fixed_operand (&ops[7], NULL); } + if (nops == 9) + { + /* If we can not represent the maximal size, + make parameter NULL. */ + if ((HOST_WIDE_INT) probable_max_size != -1) + create_integer_operand (&ops[8], probable_max_size); + else + create_fixed_operand (&ops[8], NULL); + } if (maybe_expand_insn (code, nops, ops)) return true; } |