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

Reply via email to