------- Comment #3 from hjl dot tools at gmail dot com  2009-01-02 22:01 -------
i386.c has

/* Output code to set at most count & (max_size - 1) bytes starting by DEST. 
*/static void
expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value,
                                 rtx count, int max_size)
{
  count =
    expand_simple_binop (counter_mode (count), AND, count,
                         GEN_INT (max_size - 1), count, 1, OPTAB_DIRECT);
  expand_set_or_movmem_via_loop (destmem, NULL, destptr, NULL,
                                 gen_lowpart (QImode, value), count, QImode,
                                 1, max_size / 2); 
}

It seems to assume that max_size is power of 2. But there may not be
the case:

#0  expand_set_or_movmem_via_loop (destmem=0x7ffff30f17e0, srcmem=0x0, 
    destptr=0x7ffff30f1560, srcptr=0x0, value=0x7ffff30f1500, 
    count=0x7ffff30f1520, mode=QImode, unroll=1, expected_size=3)
    at /export/gnu/src/gcc-work/gcc/gcc/config/i386/i386.c:16484
#1  0x0000000000b6e7d1 in expand_setmem_epilogue_via_loop (
    destmem=0x7ffff30f17e0, destptr=0x7ffff30f1560, value=0x7ffff30f1500, 
    count=0x7ffff30f1520, max_size=7)
    at /export/gnu/src/gcc-work/gcc/gcc/config/i386/i386.c:16850
#2  0x0000000000b71af6 in ix86_expand_setmem (dst=0x7ffff30f17e0, 
    count_exp=0x7ffff30f1520, val_exp=0x7ffff30f1500, 
    align_exp=0x7ffff31f4470, expected_align_exp=0x7ffff31f4470, 
    expected_size_exp=0x7ffff31f4440)
    at /export/gnu/src/gcc-work/gcc/gcc/config/i386/i386.c:18031
#3  0x0000000000ce16cc in gen_setmemsi (operand0=0x7ffff30f1440, 
    operand1=0x7ffff30f1340, operand2=0x7ffff30f1500, operand3=0x7ffff31f4470, 
    operand4=0x7ffff31f4470, operand5=0x7ffff31f4440)
    at /export/gnu/src/gcc-work/gcc/gcc/config/i386/i386.md:19126
#4  0x000000000061478b in set_storage_via_setmem (object=0x7ffff30f1440, 
    size=0x7ffff30f1340, val=0x7ffff30f1500, align=16, expected_align=16, 
    expected_size=-1) at /export/gnu/src/gcc-work/gcc/gcc/expr.c:2807

The problem comes from

 if (label)
    {
      /* When the main loop is done, COUNT_EXP might hold original count,
         while we want to copy only COUNT_EXP & SIZE_NEEDED bytes.
         Epilogue code will actually copy COUNT_EXP & EPILOGUE_SIZE_NEEDED
         bytes. Compensate if needed.  */

      if (size_needed < desired_align - align)
        {     
          tmp = 
            expand_simple_binop (counter_mode (count_exp), AND, count_exp,
                                 GEN_INT (size_needed - 1), count_exp, 1,
                                 OPTAB_DIRECT);
          size_needed = desired_align - align + 1;
          if (tmp != count_exp)
            emit_move_insn (count_exp, tmp); 
        }     
      emit_label (label);
      LABEL_NUSES (label) = 1;
    }

size_needed won't be power of 2. If we add

--- ./i386.c.align      2008-12-23 09:34:11.000000000 -0800
+++ ./i386.c    2009-01-02 14:00:33.000000000 -0800
@@ -16751,6 +16751,7 @@ expand_movmem_epilogue (rtx destmem, rtx
     }
   if (max_size > 8)
     {
+      gcc_assert (max_size == (max_size & -max_size));
       count = expand_simple_binop (GET_MODE (count), AND, count, GEN_INT
(max_size - 1),
                                    count, 1, OPTAB_DIRECT);
       expand_set_or_movmem_via_loop (destmem, srcmem, destptr, srcptr, NULL,
@@ -16844,6 +16845,7 @@ static void
 expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value,
                                 rtx count, int max_size)
 {
+  gcc_assert (max_size == (max_size & -max_size));
   count =
     expand_simple_binop (counter_mode (count), AND, count,
                         GEN_INT (max_size - 1), count, 1, OPTAB_DIRECT);

we will get an error.


-- 

hjl dot tools at gmail dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jh at suse dot cz


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38708

Reply via email to