]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
md.texi (setmem, movstr): Update documentation.
authorJan Hubicka <jh@suse.cz>
Sun, 17 Nov 2013 23:32:12 +0000 (00:32 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sun, 17 Nov 2013 23:32:12 +0000 (23:32 +0000)
* doc/md.texi (setmem, movstr): Update documentation.
* builtins.c (determine_block_size): New function.
(expand_builtin_memcpy): Use it and pass it to
emit_block_move_hints.
(expand_builtin_memset_args): Use it and pass it to
set_storage_via_setmem.
* expr.c (emit_block_move_via_movmem): Add min_size/max_size parameters;
update call to expander.
(emit_block_move_hints): Add min_size/max_size parameters.
(clear_storage_hints): Likewise.
(set_storage_via_setmem): Likewise.
(clear_storage): Update.
* expr.h (emit_block_move_hints, clear_storage_hints,
set_storage_via_setmem): Update prototype.
* i386.c (ix86_expand_set_or_movmem): Add bounds; export.
(ix86_expand_movmem, ix86_expand_setmem): Remove.
(ix86_expand_movmem, ix86_expand_setmem): Remove.
* i386.md (movmem, setmem): Pass parameters.

* gcc.target/i386/memcpy-2.c: New testcase.

From-SVN: r204926

gcc/ChangeLog
gcc/builtins.c
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/doc/md.texi
gcc/expr.c
gcc/expr.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/memcpy-2.c [new file with mode: 0644]

index c854ffa01eadb62cb9e1e0087eecc3f2ed4b086c..d4e0260450f7edfbe09daf244d2064d20796db3d 100644 (file)
@@ -1,3 +1,24 @@
+2013-11-17  Jan Hubicka  <jh@suse.cz>
+
+       * doc/md.texi (setmem, movstr): Update documentation.
+       * builtins.c (determine_block_size): New function.
+       (expand_builtin_memcpy): Use it and pass it to
+       emit_block_move_hints.
+       (expand_builtin_memset_args): Use it and pass it to
+       set_storage_via_setmem.
+       * expr.c (emit_block_move_via_movmem): Add min_size/max_size parameters;
+       update call to expander.
+       (emit_block_move_hints): Add min_size/max_size parameters.
+       (clear_storage_hints): Likewise.
+       (set_storage_via_setmem): Likewise.
+       (clear_storage): Update.
+       * expr.h (emit_block_move_hints, clear_storage_hints,
+       set_storage_via_setmem): Update prototype.
+       * i386.c (ix86_expand_set_or_movmem): Add bounds; export.
+       (ix86_expand_movmem, ix86_expand_setmem): Remove.
+       (ix86_expand_movmem, ix86_expand_setmem): Remove.
+       * i386.md (movmem, setmem): Pass parameters.
+
 2013-11-17  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/59153
index 7a04664c9099ced6ed1437af25047a0e05499fdf..5c8577a8e82b1f7f54251c8d8c85e1e52c164335 100644 (file)
@@ -3095,6 +3095,51 @@ builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
   return c_readstr (str + offset, mode);
 }
 
+/* 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))
+    {
+      *min_size = *max_size = UINTVAL (len_rtx);
+      return;
+    }
+  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 <=
+                      (unsigned HOST_WIDE_INT)
+                         GET_MODE_MASK (GET_MODE (len_rtx)));
+}
+
 /* Expand a call EXP to the memcpy builtin.
    Return NULL_RTX if we failed, the caller should emit a normal call,
    otherwise try to get the result in TARGET, if convenient (and in
@@ -3117,6 +3162,8 @@ expand_builtin_memcpy (tree exp, rtx target)
       rtx dest_mem, src_mem, dest_addr, len_rtx;
       HOST_WIDE_INT expected_size = -1;
       unsigned int expected_align = 0;
+      unsigned HOST_WIDE_INT min_size;
+      unsigned HOST_WIDE_INT max_size;
 
       /* If DEST is not a pointer type, call the normal function.  */
       if (dest_align == 0)
@@ -3136,6 +3183,7 @@ expand_builtin_memcpy (tree exp, rtx target)
       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
@@ -3164,7 +3212,8 @@ expand_builtin_memcpy (tree exp, rtx target)
       dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
                                         CALL_EXPR_TAILCALL (exp)
                                         ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
-                                        expected_align, expected_size);
+                                        expected_align, expected_size,
+                                        min_size, max_size);
 
       if (dest_addr == 0)
        {
@@ -3578,6 +3627,8 @@ expand_builtin_memset_args (tree dest, tree val, tree len,
   rtx dest_mem, dest_addr, len_rtx;
   HOST_WIDE_INT expected_size = -1;
   unsigned int expected_align = 0;
+  unsigned HOST_WIDE_INT min_size;
+  unsigned HOST_WIDE_INT max_size;
 
   dest_align = get_pointer_alignment (dest);
 
@@ -3606,6 +3657,7 @@ expand_builtin_memset_args (tree dest, tree val, tree len,
   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);
 
@@ -3632,7 +3684,7 @@ expand_builtin_memset_args (tree dest, tree val, tree len,
        }
       else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
                                        dest_align, expected_align,
-                                       expected_size))
+                                       expected_size, min_size, max_size))
        goto do_libcall;
 
       dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
@@ -3654,7 +3706,7 @@ expand_builtin_memset_args (tree dest, tree val, tree len,
       else if (!set_storage_via_setmem (dest_mem, len_rtx,
                                        gen_int_mode (c, val_mode),
                                        dest_align, expected_align,
-                                       expected_size))
+                                       expected_size, min_size, max_size))
        goto do_libcall;
 
       dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
@@ -3666,7 +3718,8 @@ expand_builtin_memset_args (tree dest, tree val, tree len,
   dest_addr = clear_storage_hints (dest_mem, len_rtx,
                                   CALL_EXPR_TAILCALL (orig_exp)
                                   ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
-                                  expected_align, expected_size);
+                                  expected_align, expected_size,
+                                  min_size, max_size);
 
   if (dest_addr == 0)
     {
index fdf9d5804df1eba19a7b51fa4599634cb5adc430..85ed7a200346e35b8129d6fd782b392a6dec1fd3 100644 (file)
@@ -58,9 +58,9 @@ extern enum machine_mode ix86_cc_mode (enum rtx_code, rtx, rtx);
 extern int avx_vpermilp_parallel (rtx par, enum machine_mode mode);
 extern int avx_vperm2f128_parallel (rtx par, enum machine_mode mode);
 
-extern bool ix86_expand_movmem (rtx, rtx, rtx, rtx, rtx, rtx);
-extern bool ix86_expand_setmem (rtx, rtx, rtx, rtx, rtx, rtx);
 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);
index f7e28a570bdf64eb56ccef52773d0a61ceb722d7..565d8fa6ae653db9f70460ec83c6446d35cb94be 100644 (file)
@@ -23611,10 +23611,11 @@ promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align,
 
      3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
        with specified algorithm.  */
-static bool
+bool
 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, bool issetmem)
+                          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;
@@ -23654,6 +23655,10 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
 
   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);
 
@@ -24058,24 +24063,6 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
   return true;
 }
 
-/* Wrapper for ix86_expand_set_or_movmem for memcpy case.  */
-bool
-ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
-                   rtx expected_align_exp, rtx expected_size_exp)
-{
-  return ix86_expand_set_or_movmem (dst, src, count_exp, NULL, align_exp,
-                   expected_align_exp, expected_size_exp, false);
-}
-
-/* Wrapper for ix86_expand_set_or_movmem for memset case.  */
-bool
-ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
-                   rtx expected_align_exp, rtx expected_size_exp)
-{
-  return ix86_expand_set_or_movmem (dst, NULL, count_exp, val_exp, align_exp,
-                     expected_align_exp, expected_size_exp, true);
-}
-
 
 /* Expand the appropriate insns for doing strlen if not just doing
    repnz; scasb
index e23b3b6807e6198eba44b54837fa603a6c2a305f..223a467510809f69bb587c604a0832855fb8806f 100644 (file)
    (use (match_operand:SWI48 2 "nonmemory_operand"))
    (use (match_operand:SWI48 3 "const_int_operand"))
    (use (match_operand:SI 4 "const_int_operand"))
-   (use (match_operand:SI 5 "const_int_operand"))]
+   (use (match_operand:SI 5 "const_int_operand"))
+   (use (match_operand:SI 6 ""))
+   (use (match_operand:SI 7 ""))]
   ""
 {
- if (ix86_expand_movmem (operands[0], operands[1], operands[2], operands[3],
-                        operands[4], operands[5]))
+ 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;
     (use (match_operand:QI 2 "nonmemory_operand"))
     (use (match_operand 3 "const_int_operand"))
     (use (match_operand:SI 4 "const_int_operand"))
-    (use (match_operand:SI 5 "const_int_operand"))]
+    (use (match_operand:SI 5 "const_int_operand"))
+    (use (match_operand:SI 6 ""))
+    (use (match_operand:SI 7 ""))]
   ""
 {
- if (ix86_expand_setmem (operands[0], operands[1],
-                        operands[2], operands[3],
-                        operands[4], operands[5]))
+ if (ix86_expand_set_or_movmem (operands[0], NULL,
+                               operands[1], operands[2],
+                               operands[3], operands[4],
+                               operands[5], operands[6],
+                               operands[6], true))
    DONE;
  else
    FAIL;
index 1a06e3d6e74037f00d1fc92d4a33571762cbddbc..2054295f66be09c439c85699c869d7023dd6c728 100644 (file)
@@ -5328,6 +5328,9 @@ destination and source strings are operands 1 and 2, and both are
 the expansion of this pattern should store in operand 0 the address in
 which the @code{NUL} terminator was stored in the destination string.
 
+This patern has also several optional operands that are same as in
+@code{setmem}.
+
 @cindex @code{setmem@var{m}} instruction pattern
 @item @samp{setmem@var{m}}
 Block set instruction.  The destination string is the first operand,
@@ -5347,6 +5350,8 @@ respectively.  The expected alignment differs from alignment in operand 4
 in a way that the blocks are not required to be aligned according to it in
 all cases. This expected alignment is also in bytes, just like operand 4.
 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).
 
 The use for multiple @code{setmem@var{m}} is as for @code{movmem@var{m}}.
 
index e8c022c45eb3eb5fc7d6474ecbe55fc5ae852064..23854ccf5c780a74565420750cd203f8089035d1 100644 (file)
@@ -128,7 +128,8 @@ struct store_by_pieces_d
 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);
+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);
@@ -1119,13 +1120,18 @@ move_by_pieces_1 (insn_gen_fn genfun, machine_mode mode,
    SIZE is an rtx that says how long they are.
    ALIGN is the maximum alignment we can assume they have.
    METHOD describes what kind of copy this is, and what mechanisms may be used.
+   MIN_SIZE is the minimal size of block to move
+   MAX_SIZE is the maximal size of block to move, if it can not be represented
+   in unsigned HOST_WIDE_INT, than it is mask of all ones.
 
    Return the address of the new block, if memcpy is called and returns it,
    0 otherwise.  */
 
 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 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;
@@ -1181,7 +1187,8 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method,
   if (CONST_INT_P (size) && 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,
-                                      expected_align, expected_size))
+                                      expected_align, expected_size,
+                                      min_size, max_size))
     ;
   else if (may_use_call
           && ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x))
@@ -1211,7 +1218,13 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method,
 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);
+  unsigned HOST_WIDE_INT max, min = 0;
+  if (GET_CODE (size) == CONST_INT)
+    min = max = UINTVAL (size);
+  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
@@ -1274,13 +1287,22 @@ block_move_libcall_safe_for_call_parm (void)
 
 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 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;
 
   if (expected_align < 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 < min_size)
+       expected_size = min_size;
+    }
 
   /* Since this is a move insn, we don't care about volatility.  */
   volatile_ok = 1;
@@ -1303,9 +1325,10 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align,
          && ((CONST_INT_P (size)
               && ((unsigned HOST_WIDE_INT) INTVAL (size)
                   <= (GET_MODE_MASK (mode) >> 1)))
+             || max_size <= (GET_MODE_MASK (mode) >> 1)
              || GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode)))
        {
-         struct expand_operand ops[6];
+         struct expand_operand ops[8];
          unsigned int nops;
 
          /* ??? When called via emit_block_move_for_call, it'd be
@@ -1313,18 +1336,28 @@ 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);
+         gcc_assert (nops == 4 || nops == 6 || nops == 8);
 
          create_fixed_operand (&ops[0], x);
          create_fixed_operand (&ops[1], y);
          /* The check above guarantees that this size conversion is valid.  */
          create_convert_operand_to (&ops[2], size, mode, true);
          create_integer_operand (&ops[3], align / BITS_PER_UNIT);
-         if (nops == 6)
+         if (nops >= 6)
            {
              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,
+                make parameter NULL.  */
+             if ((HOST_WIDE_INT) max_size != -1)
+               create_integer_operand (&ops[7], max_size);
+             else
+               create_fixed_operand (&ops[7], NULL);
+           }
          if (maybe_expand_insn (code, nops, ops))
            {
              volatile_ok = save_volatile_ok;
@@ -2712,7 +2745,9 @@ store_by_pieces_2 (insn_gen_fn genfun, machine_mode mode,
 
 rtx
 clear_storage_hints (rtx object, rtx size, enum block_op_methods method,
-                    unsigned int expected_align, HOST_WIDE_INT expected_size)
+                    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;
@@ -2753,7 +2788,8 @@ clear_storage_hints (rtx object, rtx size, enum block_op_methods method,
       && 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,
-                                  expected_align, expected_size))
+                                  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,
@@ -2767,7 +2803,12 @@ clear_storage_hints (rtx object, rtx size, enum block_op_methods method,
 rtx
 clear_storage (rtx object, rtx size, enum block_op_methods method)
 {
-  return clear_storage_hints (object, size, method, 0, -1);
+  unsigned HOST_WIDE_INT max, min = 0;
+  if (GET_CODE (size) == CONST_INT)
+    min = max = UINTVAL (size);
+  else
+    max = GET_MODE_MASK (GET_MODE (size));
+  return clear_storage_hints (object, size, method, 0, -1, min, max);
 }
 
 
@@ -2864,7 +2905,9 @@ clear_storage_libcall_fn (int for_call)
 
 bool
 set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align,
-                       unsigned int expected_align, HOST_WIDE_INT expected_size)
+                       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
@@ -2874,6 +2917,13 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align,
 
   if (expected_align < 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 < min_size)
+       expected_size = min_size;
+    }
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
@@ -2889,24 +2939,35 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align,
          && ((CONST_INT_P (size)
               && ((unsigned HOST_WIDE_INT) INTVAL (size)
                   <= (GET_MODE_MASK (mode) >> 1)))
+             || max_size <= (GET_MODE_MASK (mode) >> 1)
              || GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode)))
        {
-         struct expand_operand ops[6];
+         struct expand_operand ops[8];
          unsigned int nops;
 
          nops = insn_data[(int) code].n_generator_args;
-         gcc_assert (nops == 4 || nops == 6);
+         gcc_assert (nops == 4 || nops == 6 || nops == 8);
 
          create_fixed_operand (&ops[0], object);
          /* The check above guarantees that this size conversion is valid.  */
          create_convert_operand_to (&ops[1], size, mode, true);
          create_convert_operand_from (&ops[2], val, byte_mode, true);
          create_integer_operand (&ops[3], align / BITS_PER_UNIT);
-         if (nops == 6)
+         if (nops >= 6)
            {
              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,
+                make parameter NULL.  */
+             if ((HOST_WIDE_INT) max_size != -1)
+               create_integer_operand (&ops[7], max_size);
+             else
+               create_fixed_operand (&ops[7], NULL);
+           }
          if (maybe_expand_insn (code, nops, ops))
            return true;
        }
index 2923b81b85baef397d27437eece931a3ba472561..ae7609158958494b2da0b514efb3235c1977edee 100644 (file)
@@ -300,7 +300,9 @@ extern void init_block_clear_fn (const char *);
 extern rtx emit_block_move (rtx, rtx, rtx, enum block_op_methods);
 extern rtx emit_block_move_via_libcall (rtx, rtx, rtx, bool);
 extern rtx emit_block_move_hints (rtx, rtx, rtx, enum block_op_methods,
-                                 unsigned int, HOST_WIDE_INT);
+                                 unsigned int, HOST_WIDE_INT,
+                                 unsigned HOST_WIDE_INT,
+                                 unsigned HOST_WIDE_INT);
 extern bool emit_storent_insn (rtx to, rtx from);
 
 /* Copy all or part of a value X into registers starting at REGNO.
@@ -361,13 +363,17 @@ extern void use_group_regs (rtx *, rtx);
    If OBJECT has BLKmode, SIZE is its length in bytes.  */
 extern rtx clear_storage (rtx, rtx, enum block_op_methods);
 extern rtx clear_storage_hints (rtx, rtx, enum block_op_methods,
-                               unsigned int, HOST_WIDE_INT);
+                               unsigned int, 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);
 
 /* Expand a setmem pattern; return true if successful.  */
 extern bool set_storage_via_setmem (rtx, rtx, rtx, unsigned int,
-                                   unsigned int, HOST_WIDE_INT);
+                                   unsigned int, HOST_WIDE_INT,
+                                   unsigned HOST_WIDE_INT,
+                                   unsigned HOST_WIDE_INT);
 
 extern unsigned HOST_WIDE_INT move_by_pieces_ninsns (unsigned HOST_WIDE_INT,
                                                     unsigned int,
index 564ecf065cf4e9b7fb7b7eff769f7a7d2967dd3f..4aac17c346e669c578b290f1ef24a159e2e27b5b 100644 (file)
@@ -1,3 +1,7 @@
+2013-11-17  Jan Hubicka  <jh@suse.cz>
+
+       * gcc.target/i386/memcpy-2.c: New testcase.
+
 2013-11-17  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/59153
diff --git a/gcc/testsuite/gcc.target/i386/memcpy-2.c b/gcc/testsuite/gcc.target/i386/memcpy-2.c
new file mode 100644 (file)
index 0000000..fe53f26
--- /dev/null
@@ -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(unsigned int c)
+{
+  if (c<10)
+    memcpy (a,b,c);
+}