On Mon, 18 Nov 2013, Jan Hubicka wrote: > Hi, > this patch adds support to anti-ranges to determine_block_size. > This makes it possible to bound size of block from bellow that is > useful to avoid need for small size code path and it also allows > us to inline the following: > void *a; > void *b; > t(int c) > { > if (c<10) > memcpy (a,b,c); > } > > Because C is signed, we do not really know that the block is smaller > than 10, but it is most likely the case. > > Bootstrapped/regtested x86_64-linux OK?
Ok. Thanks, Richard. > Honza > > * md.texi (setmem): Document new parameter. > * optabs.c (maybe_gen_insn): Support 9 operands. > * builtins.c (determine_block_size): Add probable_max_size; > support anti-ranges. > (expand_builtin_memcpy. expand_builtin_memset_args): Pass around > probable_max_size. > * expr.c (emit_block_move_via_movmem, emit_block_move_hints, > emit_block_move, clear_storage_hints, set_storage_via_setmem): > Likewise. > * expr.h (emit_block_move_hints, clear_storage_hints, > set_storage_via_setmem): Update prototype. > * i386.md (setmem, movmem patterns): Add 9th operand. > * i386-protos.h (ix86_expand_set_or_movmem): Update prototype. > * i386.c (ix86_expand_set_or_movmem): Take probable_max_size_exp > argument; pass it to decide_alg. > > * gcc.target/i386/memcpy-3.c: New testcase. > Index: doc/md.texi > =================================================================== > *** doc/md.texi (revision 204945) > --- doc/md.texi (working copy) > *************** all cases. This expected alignment is al > *** 5352,5357 **** > --- 5352,5359 ---- > Expected size, when unknown, is set to @code{(const_int -1)}. > Operand 7 is the minimal size of the block and operand 8 is the > maximal size of the block (NULL if it can not be represented as CONST_INT). > + Operand 9 is the probable maximal size (i.e. we can not rely on it for > correctness, > + but it can be used for choosing proper code sequence for a given size). > > The use for multiple @code{setmem@var{m}} is as for @code{movmem@var{m}}. > > Index: optabs.c > =================================================================== > *** optabs.c (revision 204945) > --- optabs.c (working copy) > *************** maybe_gen_insn (enum insn_code icode, un > *** 8229,8234 **** > --- 8229,8238 ---- > return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value, > ops[3].value, ops[4].value, ops[5].value, > ops[6].value, ops[7].value); > + case 9: > + return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value, > + ops[3].value, ops[4].value, ops[5].value, > + ops[6].value, ops[7].value, ops[8].value); > } > gcc_unreachable (); > } > Index: builtins.c > =================================================================== > *** builtins.c (revision 204945) > --- builtins.c (working copy) > *************** builtin_memcpy_read_str (void *data, HOS > *** 3096,3107 **** > } > > /* LEN specify length of the block of memcpy/memset operation. > ! Figure out its range and put it into MIN_SIZE/MAX_SIZE. */ > > static void > determine_block_size (tree len, rtx len_rtx, > unsigned HOST_WIDE_INT *min_size, > ! unsigned HOST_WIDE_INT *max_size) > { > if (CONST_INT_P (len_rtx)) > { > --- 3096,3110 ---- > } > > /* LEN specify length of the block of memcpy/memset operation. > ! Figure out its range and put it into MIN_SIZE/MAX_SIZE. > ! In some cases we can make very likely guess on max size, then we > ! set it into PROBABLE_MAX_SIZE. */ > > static void > determine_block_size (tree len, rtx len_rtx, > unsigned HOST_WIDE_INT *min_size, > ! unsigned HOST_WIDE_INT *max_size, > ! unsigned HOST_WIDE_INT *probable_max_size) > { > if (CONST_INT_P (len_rtx)) > { > *************** determine_block_size (tree len, rtx len_ > *** 3111,3138 **** > else > { > double_int min, max; > ! if (TREE_CODE (len) == SSA_NAME > ! && get_range_info (len, &min, &max) == VR_RANGE) > { > ! if (min.fits_uhwi ()) > *min_size = min.to_uhwi (); > ! else > ! *min_size = 0; > ! if (max.fits_uhwi ()) > ! *max_size = max.to_uhwi (); > ! else > ! *max_size = (HOST_WIDE_INT)-1; > } > ! else > { > ! if (host_integerp (TYPE_MIN_VALUE (TREE_TYPE (len)), 1)) > ! *min_size = tree_low_cst (TYPE_MIN_VALUE (TREE_TYPE (len)), 1); > ! else > ! *min_size = 0; > ! if (host_integerp (TYPE_MAX_VALUE (TREE_TYPE (len)), 1)) > ! *max_size = tree_low_cst (TYPE_MAX_VALUE (TREE_TYPE (len)), 1); > ! else > ! *max_size = GET_MODE_MASK (GET_MODE (len_rtx)); > } > } > gcc_checking_assert (*max_size <= > --- 3114,3160 ---- > else > { > double_int min, max; > ! enum value_range_type range_type = VR_UNDEFINED; > ! > ! /* Determine bounds from the type. */ > ! if (host_integerp (TYPE_MIN_VALUE (TREE_TYPE (len)), 1)) > ! *min_size = tree_low_cst (TYPE_MIN_VALUE (TREE_TYPE (len)), 1); > ! else > ! *min_size = 0; > ! if (host_integerp (TYPE_MAX_VALUE (TREE_TYPE (len)), 1)) > ! *probable_max_size = *max_size = tree_low_cst (TYPE_MAX_VALUE > (TREE_TYPE (len)), 1); > ! else > ! *probable_max_size = *max_size = GET_MODE_MASK (GET_MODE (len_rtx)); > ! > ! if (TREE_CODE (len) == SSA_NAME) > ! range_type = get_range_info (len, &min, &max); > ! if (range_type == VR_RANGE) > { > ! if (min.fits_uhwi () && *min_size < min.to_uhwi ()) > *min_size = min.to_uhwi (); > ! if (max.fits_uhwi () && *max_size > max.to_uhwi ()) > ! *probable_max_size = *max_size = max.to_uhwi (); > } > ! else if (range_type == VR_ANTI_RANGE) > { > ! /* Anti range 0...N lets us to determine minmal size to N+1. */ > ! if (min.is_zero ()) > ! { > ! if ((max + double_int_one).fits_uhwi ()) > ! *min_size = (max + double_int_one).to_uhwi (); > ! } > ! /* Code like > ! > ! int n; > ! if (n < 100) > ! memcpy (a,b, n) > ! > ! Produce anti range allowing negative values of N. We still > ! can use the information and make a guess that N is not negative. > ! */ > ! else if (!max.ule (double_int_one.lshift (31)) > ! && min.fits_uhwi ()) > ! *probable_max_size = min.to_uhwi () - 1; > } > } > gcc_checking_assert (*max_size <= > *************** expand_builtin_memcpy (tree exp, rtx tar > *** 3164,3169 **** > --- 3186,3192 ---- > unsigned int expected_align = 0; > unsigned HOST_WIDE_INT min_size; > unsigned HOST_WIDE_INT max_size; > + unsigned HOST_WIDE_INT probable_max_size; > > /* If DEST is not a pointer type, call the normal function. */ > if (dest_align == 0) > *************** expand_builtin_memcpy (tree exp, rtx tar > *** 3183,3189 **** > dest_mem = get_memory_rtx (dest, len); > set_mem_align (dest_mem, dest_align); > len_rtx = expand_normal (len); > ! determine_block_size (len, len_rtx, &min_size, &max_size); > src_str = c_getstr (src); > > /* If SRC is a string constant and block move would be done > --- 3206,3213 ---- > dest_mem = get_memory_rtx (dest, len); > set_mem_align (dest_mem, dest_align); > len_rtx = expand_normal (len); > ! determine_block_size (len, len_rtx, &min_size, &max_size, > ! &probable_max_size); > src_str = c_getstr (src); > > /* If SRC is a string constant and block move would be done > *************** expand_builtin_memcpy (tree exp, rtx tar > *** 3213,3219 **** > CALL_EXPR_TAILCALL (exp) > ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL, > expected_align, expected_size, > ! min_size, max_size); > > if (dest_addr == 0) > { > --- 3237,3243 ---- > CALL_EXPR_TAILCALL (exp) > ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL, > expected_align, expected_size, > ! min_size, max_size, probable_max_size); > > if (dest_addr == 0) > { > *************** expand_builtin_memset_args (tree dest, t > *** 3629,3634 **** > --- 3653,3659 ---- > unsigned int expected_align = 0; > unsigned HOST_WIDE_INT min_size; > unsigned HOST_WIDE_INT max_size; > + unsigned HOST_WIDE_INT probable_max_size; > > dest_align = get_pointer_alignment (dest); > > *************** expand_builtin_memset_args (tree dest, t > *** 3657,3663 **** > len = builtin_save_expr (len); > > len_rtx = expand_normal (len); > ! determine_block_size (len, len_rtx, &min_size, &max_size); > dest_mem = get_memory_rtx (dest, len); > val_mode = TYPE_MODE (unsigned_char_type_node); > > --- 3682,3689 ---- > len = builtin_save_expr (len); > > len_rtx = expand_normal (len); > ! determine_block_size (len, len_rtx, &min_size, &max_size, > ! &probable_max_size); > dest_mem = get_memory_rtx (dest, len); > val_mode = TYPE_MODE (unsigned_char_type_node); > > *************** expand_builtin_memset_args (tree dest, t > *** 3684,3690 **** > } > else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx, > dest_align, expected_align, > ! expected_size, min_size, max_size)) > goto do_libcall; > > dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); > --- 3710,3717 ---- > } > else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx, > dest_align, expected_align, > ! expected_size, min_size, max_size, > ! probable_max_size)) > goto do_libcall; > > dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); > *************** expand_builtin_memset_args (tree dest, t > *** 3706,3712 **** > else if (!set_storage_via_setmem (dest_mem, len_rtx, > gen_int_mode (c, val_mode), > dest_align, expected_align, > ! expected_size, min_size, max_size)) > goto do_libcall; > > dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); > --- 3733,3740 ---- > else if (!set_storage_via_setmem (dest_mem, len_rtx, > gen_int_mode (c, val_mode), > dest_align, expected_align, > ! expected_size, min_size, max_size, > ! probable_max_size)) > goto do_libcall; > > dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); > *************** expand_builtin_memset_args (tree dest, t > *** 3719,3725 **** > CALL_EXPR_TAILCALL (orig_exp) > ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL, > expected_align, expected_size, > ! min_size, max_size); > > if (dest_addr == 0) > { > --- 3747,3754 ---- > CALL_EXPR_TAILCALL (orig_exp) > ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL, > expected_align, expected_size, > ! min_size, max_size, > ! probable_max_size); > > if (dest_addr == 0) > { > Index: testsuite/gcc.target/i386/memcpy-3.c > =================================================================== > *** testsuite/gcc.target/i386/memcpy-3.c (revision 0) > --- testsuite/gcc.target/i386/memcpy-3.c (revision 0) > *************** > *** 0 **** > --- 1,11 ---- > + /* { dg-do compile } */ > + /* { dg-options "-O2" } */ > + /* Memcpy should be inlined because block size is known. */ > + /* { dg-final { scan-assembler-not "memcpy" } } */ > + void *a; > + void *b; > + t(int c) > + { > + if (c<10) > + memcpy (a,b,c); > + } > Index: expr.c > =================================================================== > *** expr.c (revision 204945) > --- expr.c (working copy) > *************** static void move_by_pieces_1 (insn_gen_f > *** 129,135 **** > 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); > 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); > --- 129,136 ---- > 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); > 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); > *************** rtx > *** 1131,1137 **** > 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) > { > bool may_use_call; > rtx retval = 0; > --- 1132,1139 ---- > 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 probable_max_size) > { > bool may_use_call; > rtx retval = 0; > *************** emit_block_move_hints (rtx x, rtx y, rtx > *** 1188,1194 **** > 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)) > ; > else if (may_use_call > && ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)) > --- 1190,1196 ---- > 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, probable_max_size)) > ; > else if (may_use_call > && ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)) > *************** emit_block_move (rtx x, rtx y, rtx size, > *** 1224,1230 **** > else > max = GET_MODE_MASK (GET_MODE (size)); > return emit_block_move_hints (x, y, size, method, 0, -1, > ! min, max); > } > > /* A subroutine of emit_block_move. Returns true if calling the > --- 1226,1232 ---- > else > max = GET_MODE_MASK (GET_MODE (size)); > return emit_block_move_hints (x, y, size, method, 0, -1, > ! min, max, max); > } > > /* A subroutine of emit_block_move. Returns true if calling the > *************** static bool > *** 1289,1295 **** > 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) > { > int save_volatile_ok = volatile_ok; > enum machine_mode mode; > --- 1291,1298 ---- > 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 probable_max_size) > { > int save_volatile_ok = volatile_ok; > enum machine_mode mode; > *************** emit_block_move_via_movmem (rtx x, rtx y > *** 1298,1305 **** > 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 < min_size) > expected_size = min_size; > } > --- 1301,1308 ---- > expected_align = align; > if (expected_size != -1) > { > ! 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; > } > *************** emit_block_move_via_movmem (rtx x, rtx y > *** 1328,1334 **** > || max_size <= (GET_MODE_MASK (mode) >> 1) > || GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode))) > { > ! struct expand_operand ops[8]; > unsigned int nops; > > /* ??? When called via emit_block_move_for_call, it'd be > --- 1331,1337 ---- > || max_size <= (GET_MODE_MASK (mode) >> 1) > || GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode))) > { > ! struct expand_operand ops[9]; > unsigned int nops; > > /* ??? When called via emit_block_move_for_call, it'd be > *************** emit_block_move_via_movmem (rtx x, rtx y > *** 1336,1342 **** > 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); > > create_fixed_operand (&ops[0], x); > create_fixed_operand (&ops[1], y); > --- 1339,1345 ---- > 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 || nops == 9); > > create_fixed_operand (&ops[0], x); > create_fixed_operand (&ops[1], y); > *************** emit_block_move_via_movmem (rtx x, rtx y > *** 1348,1354 **** > create_integer_operand (&ops[4], expected_align / BITS_PER_UNIT); > create_integer_operand (&ops[5], expected_size); > } > ! if (nops == 8) > { > create_integer_operand (&ops[6], min_size); > /* If we can not represent the maximal size, > --- 1351,1357 ---- > create_integer_operand (&ops[4], expected_align / BITS_PER_UNIT); > create_integer_operand (&ops[5], expected_size); > } > ! if (nops >= 8) > { > create_integer_operand (&ops[6], min_size); > /* If we can not represent the maximal size, > *************** emit_block_move_via_movmem (rtx x, rtx y > *** 1358,1363 **** > --- 1361,1375 ---- > 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; > *************** rtx > *** 2747,2753 **** > 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) > { > enum machine_mode mode = GET_MODE (object); > unsigned int align; > --- 2759,2766 ---- > 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 probable_max_size) > { > enum machine_mode mode = GET_MODE (object); > unsigned int align; > *************** clear_storage_hints (rtx object, rtx siz > *** 2789,2795 **** > 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)) > ; > else if (ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (object))) > return set_storage_via_libcall (object, size, const0_rtx, > --- 2802,2808 ---- > 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, probable_max_size)) > ; > else if (ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (object))) > return set_storage_via_libcall (object, size, const0_rtx, > *************** clear_storage (rtx object, rtx size, enu > *** 2808,2814 **** > min = max = UINTVAL (size); > else > max = GET_MODE_MASK (GET_MODE (size)); > ! return clear_storage_hints (object, size, method, 0, -1, min, max); > } > > > --- 2821,2827 ---- > min = max = UINTVAL (size); > else > max = GET_MODE_MASK (GET_MODE (size)); > ! return clear_storage_hints (object, size, method, 0, -1, min, max, max); > } > > > *************** bool > *** 2907,2913 **** > 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) > { > /* Try the most limited insn first, because there's no point > including more than one in the machine description unless > --- 2920,2927 ---- > 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 probable_max_size) > { > /* Try the most limited insn first, because there's no point > including more than one in the machine description unless > *************** set_storage_via_setmem (rtx object, rtx > *** 2942,2952 **** > || max_size <= (GET_MODE_MASK (mode) >> 1) > || GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode))) > { > ! struct expand_operand ops[8]; > unsigned int nops; > > nops = insn_data[(int) code].n_generator_args; > ! gcc_assert (nops == 4 || nops == 6 || nops == 8); > > create_fixed_operand (&ops[0], object); > /* The check above guarantees that this size conversion is valid. */ > --- 2956,2966 ---- > || max_size <= (GET_MODE_MASK (mode) >> 1) > || GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode))) > { > ! struct expand_operand ops[9]; > unsigned int nops; > > nops = insn_data[(int) code].n_generator_args; > ! 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. */ > *************** set_storage_via_setmem (rtx object, rtx > *** 2958,2964 **** > create_integer_operand (&ops[4], expected_align / BITS_PER_UNIT); > create_integer_operand (&ops[5], expected_size); > } > ! if (nops == 8) > { > create_integer_operand (&ops[6], min_size); > /* If we can not represent the maximal size, > --- 2972,2978 ---- > create_integer_operand (&ops[4], expected_align / BITS_PER_UNIT); > create_integer_operand (&ops[5], expected_size); > } > ! if (nops >= 8) > { > create_integer_operand (&ops[6], min_size); > /* If we can not represent the maximal size, > *************** set_storage_via_setmem (rtx object, rtx > *** 2968,2973 **** > --- 2982,2996 ---- > 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; > } > Index: expr.h > =================================================================== > *** expr.h (revision 204945) > --- expr.h (working copy) > *************** extern rtx emit_block_move_via_libcall ( > *** 302,307 **** > --- 302,308 ---- > extern rtx emit_block_move_hints (rtx, rtx, rtx, enum block_op_methods, > unsigned int, HOST_WIDE_INT, > unsigned HOST_WIDE_INT, > + unsigned HOST_WIDE_INT, > unsigned HOST_WIDE_INT); > extern bool emit_storent_insn (rtx to, rtx from); > > *************** extern rtx clear_storage (rtx, rtx, enum > *** 365,370 **** > --- 366,372 ---- > extern rtx clear_storage_hints (rtx, rtx, enum block_op_methods, > unsigned int, HOST_WIDE_INT, > unsigned HOST_WIDE_INT, > + unsigned HOST_WIDE_INT, > unsigned HOST_WIDE_INT); > /* The same, but always output an library call. */ > rtx set_storage_via_libcall (rtx, rtx, rtx, bool); > *************** rtx set_storage_via_libcall (rtx, rtx, r > *** 373,378 **** > --- 375,381 ---- > extern bool set_storage_via_setmem (rtx, rtx, rtx, unsigned int, > unsigned int, HOST_WIDE_INT, > unsigned HOST_WIDE_INT, > + unsigned HOST_WIDE_INT, > unsigned HOST_WIDE_INT); > > extern unsigned HOST_WIDE_INT move_by_pieces_ninsns (unsigned HOST_WIDE_INT, > Index: config/i386/i386.md > =================================================================== > *** config/i386/i386.md (revision 204945) > --- config/i386/i386.md (working copy) > *************** > *** 15506,15518 **** > (use (match_operand:SI 4 "const_int_operand")) > (use (match_operand:SI 5 "const_int_operand")) > (use (match_operand:SI 6 "")) > ! (use (match_operand:SI 7 ""))] > "" > { > if (ix86_expand_set_or_movmem (operands[0], operands[1], > operands[2], NULL, operands[3], > operands[4], operands[5], > ! operands[6], operands[7], false)) > DONE; > else > FAIL; > --- 15506,15520 ---- > (use (match_operand:SI 4 "const_int_operand")) > (use (match_operand:SI 5 "const_int_operand")) > (use (match_operand:SI 6 "")) > ! (use (match_operand:SI 7 "")) > ! (use (match_operand:SI 8 ""))] > "" > { > if (ix86_expand_set_or_movmem (operands[0], operands[1], > operands[2], NULL, operands[3], > operands[4], operands[5], > ! operands[6], operands[7], > ! operands[8], false)) > DONE; > else > FAIL; > *************** > *** 15702,15715 **** > (use (match_operand:SI 4 "const_int_operand")) > (use (match_operand:SI 5 "const_int_operand")) > (use (match_operand:SI 6 "")) > ! (use (match_operand:SI 7 ""))] > "" > { > if (ix86_expand_set_or_movmem (operands[0], NULL, > operands[1], operands[2], > operands[3], operands[4], > operands[5], operands[6], > ! operands[7], true)) > DONE; > else > FAIL; > --- 15704,15718 ---- > (use (match_operand:SI 4 "const_int_operand")) > (use (match_operand:SI 5 "const_int_operand")) > (use (match_operand:SI 6 "")) > ! (use (match_operand:SI 7 "")) > ! (use (match_operand:SI 8 ""))] > "" > { > if (ix86_expand_set_or_movmem (operands[0], NULL, > operands[1], operands[2], > operands[3], operands[4], > operands[5], operands[6], > ! operands[7], operands[8], true)) > DONE; > else > FAIL; > Index: config/i386/i386-protos.h > =================================================================== > *** config/i386/i386-protos.h (revision 204945) > --- config/i386/i386-protos.h (working copy) > *************** extern int avx_vperm2f128_parallel (rtx > *** 60,66 **** > > extern bool ix86_expand_strlen (rtx, rtx, rtx, rtx); > extern bool ix86_expand_set_or_movmem (rtx, rtx, rtx, rtx, rtx, rtx, > ! rtx, rtx, rtx, bool); > > extern bool constant_address_p (rtx); > extern bool legitimate_pic_operand_p (rtx); > --- 60,66 ---- > > extern bool ix86_expand_strlen (rtx, rtx, rtx, rtx); > extern bool ix86_expand_set_or_movmem (rtx, rtx, rtx, rtx, rtx, rtx, > ! rtx, rtx, rtx, rtx, bool); > > extern bool constant_address_p (rtx); > extern bool legitimate_pic_operand_p (rtx); > Index: config/i386/i386.c > =================================================================== > *** config/i386/i386.c (revision 204945) > --- config/i386/i386.c (working copy) > *************** bool > *** 23711,23717 **** > ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp, > rtx align_exp, rtx expected_align_exp, > rtx expected_size_exp, rtx min_size_exp, > ! rtx max_size_exp, bool issetmem) > { > rtx destreg; > rtx srcreg = NULL; > --- 23711,23718 ---- > ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp, > rtx align_exp, rtx expected_align_exp, > rtx expected_size_exp, rtx min_size_exp, > ! rtx max_size_exp, rtx probable_max_size_exp, > ! bool issetmem) > { > rtx destreg; > rtx srcreg = NULL; > *************** ix86_expand_set_or_movmem (rtx dst, rtx > *** 23735,23740 **** > --- 23736,23742 ---- > /* TODO: Once vlaue ranges are available, fill in proper data. */ > unsigned HOST_WIDE_INT min_size = 0; > unsigned HOST_WIDE_INT max_size = -1; > + unsigned HOST_WIDE_INT probable_max_size = -1; > bool misaligned_prologue_used = false; > > if (CONST_INT_P (align_exp)) > *************** ix86_expand_set_or_movmem (rtx dst, rtx > *** 23750,23762 **** > align = MEM_ALIGN (dst) / BITS_PER_UNIT; > > if (CONST_INT_P (count_exp)) > ! min_size = max_size = count = expected_size = INTVAL (count_exp); > ! if (min_size_exp) > ! min_size = INTVAL (min_size_exp); > ! if (max_size_exp) > ! max_size = INTVAL (max_size_exp); > ! if (CONST_INT_P (expected_size_exp) && count == 0) > ! expected_size = INTVAL (expected_size_exp); > > /* Make sure we don't need to care about overflow later on. */ > if (count > ((unsigned HOST_WIDE_INT) 1 << 30)) > --- 23752,23770 ---- > align = MEM_ALIGN (dst) / BITS_PER_UNIT; > > if (CONST_INT_P (count_exp)) > ! min_size = max_size = probable_max_size = count = expected_size > ! = INTVAL (count_exp); > ! else > ! { > ! if (min_size_exp) > ! min_size = INTVAL (min_size_exp); > ! if (max_size_exp) > ! max_size = INTVAL (max_size_exp); > ! if (probable_max_size_exp) > ! probable_max_size = INTVAL (probable_max_size_exp); > ! if (CONST_INT_P (expected_size_exp) && count == 0) > ! expected_size = INTVAL (expected_size_exp); > ! } > > /* Make sure we don't need to care about overflow later on. */ > if (count > ((unsigned HOST_WIDE_INT) 1 << 30)) > *************** ix86_expand_set_or_movmem (rtx dst, rtx > *** 23764,23770 **** > > /* Step 0: Decide on preferred algorithm, desired alignment and > size of chunks to be copied by main loop. */ > ! alg = decide_alg (count, expected_size, min_size, max_size, issetmem, > issetmem && val_exp == const0_rtx, > &dynamic_check, &noalign); > if (alg == libcall) > --- 23772,23779 ---- > > /* Step 0: Decide on preferred algorithm, desired alignment and > size of chunks to be copied by main loop. */ > ! alg = decide_alg (count, expected_size, min_size, probable_max_size, > ! issetmem, > issetmem && val_exp == const0_rtx, > &dynamic_check, &noalign); > if (alg == libcall) > > -- Richard Biener <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imend"orffer