------- 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