From: hubicka Date: Sun, 25 Feb 2007 17:37:37 +0000 (+0000) Subject: PR target/30778 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1a4d0a29f33705419e2d6feefcaf68987bf9cf46;p=thirdparty%2Fgcc.git PR target/30778 * i386.c (counter_mode): New function. (expand_set_or_movmem_via_loop): Use it. (expand_movmem_epilogue): Likewise; fix pasto. (ix86_expand_movmem): Do emit guard even for constant counts. (ix86_expand_setmem): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122313 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 031c067eba92..6aa21b5c158d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2007-02-24 Uros Bizjak + Jan Hubicka + + PR target/30778 + * i386.c (counter_mode): New function. + (expand_set_or_movmem_via_loop): Use it. + (expand_movmem_epilogue): Likewise; fix pasto. + (ix86_expand_movmem): Do emit guard even for constant counts. + (ix86_expand_setmem): Likewise. + 2007-02-25 Nick Clifton * config/frv/frv.h (ASM_OUTPUT_CASE_LABEL): Delete. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index db074413086e..5a4e1d5e4c6c 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -13314,6 +13314,21 @@ scale_counter (rtx countreg, int scale) return sc; } +/* Return mode for the memcpy/memset loop counter. Preffer SImode over DImode + for constant loop counts. */ + +static enum machine_mode +counter_mode (rtx count_exp) +{ + if (GET_MODE (count_exp) != VOIDmode) + return GET_MODE (count_exp); + if (GET_CODE (count_exp) != CONST_INT) + return Pmode; + if (TARGET_64BIT && (INTVAL (count_exp) & ~0xffffffff)) + return DImode; + return SImode; +} + /* When SRCPTR is non-NULL, output simple loop to move memory pointer to SRCPTR to DESTPTR via chunks of MODE unrolled UNROLL times, overall size is COUNT specified in bytes. When SRCPTR is NULL, output the @@ -13330,7 +13345,7 @@ expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem, int expected_size) { rtx out_label, top_label, iter, tmp; - enum machine_mode iter_mode; + enum machine_mode iter_mode = counter_mode (count); rtx piece_size = GEN_INT (GET_MODE_SIZE (mode) * unroll); rtx piece_size_mask = GEN_INT (~((GET_MODE_SIZE (mode) * unroll) - 1)); rtx size; @@ -13338,10 +13353,6 @@ expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem, rtx y_addr; int i; - iter_mode = GET_MODE (count); - if (iter_mode == VOIDmode) - iter_mode = word_mode; - top_label = gen_label_rtx (); out_label = gen_label_rtx (); iter = gen_reg_rtx (iter_mode); @@ -13555,8 +13566,8 @@ expand_movmem_epilogue (rtx destmem, rtx srcmem, emit_strmov (destmem, srcmem, destptr, srcptr, DImode, offset); else { - emit_strmov (destmem, srcmem, destptr, srcptr, DImode, offset); - emit_strmov (destmem, srcmem, destptr, srcptr, DImode, offset + 4); + emit_strmov (destmem, srcmem, destptr, srcptr, SImode, offset); + emit_strmov (destmem, srcmem, destptr, srcptr, SImode, offset + 4); } offset += 8; } @@ -13673,8 +13684,8 @@ expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value, rtx count, int max_size) { count = - expand_simple_binop (GET_MODE (count), AND, count, GEN_INT (max_size - 1), - count, 1, OPTAB_DIRECT); + 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); @@ -14134,11 +14145,9 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp, gcc_assert (desired_align >= 1 && align >= 1); /* Ensure that alignment prologue won't copy past end of block. */ - if ((size_needed > 1 || (desired_align > 1 && desired_align > align)) - && !count) + if (size_needed > 1 || (desired_align > 1 && desired_align > align)) { epilogue_size_needed = MAX (size_needed - 1, desired_align - align); - /* Epilogue always copies COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes. Make sure it is power of 2. */ epilogue_size_needed = smallest_pow2_greater_than (epilogue_size_needed); @@ -14146,8 +14155,10 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp, label = gen_label_rtx (); emit_cmp_and_jump_insns (count_exp, GEN_INT (epilogue_size_needed), - LTU, 0, GET_MODE (count_exp), 1, label); - if (expected_size == -1 || expected_size < epilogue_size_needed) + LTU, 0, counter_mode (count_exp), 1, label); + if (GET_CODE (count_exp) == CONST_INT) + ; + else if (expected_size == -1 || expected_size < epilogue_size_needed) predict_jump (REG_BR_PROB_BASE * 60 / 100); else predict_jump (REG_BR_PROB_BASE * 20 / 100); @@ -14247,7 +14258,7 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp, if (size_needed < epilogue_size_needed) { tmp = - expand_simple_binop (GET_MODE (count_exp), AND, count_exp, + expand_simple_binop (counter_mode (count_exp), AND, count_exp, GEN_INT (size_needed - 1), count_exp, 1, OPTAB_DIRECT); if (tmp != count_exp) @@ -14403,7 +14414,7 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, return 0; gcc_assert (alg != no_stringop); if (!count) - count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp); + count_exp = copy_to_mode_reg (counter_mode (count_exp), count_exp); destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0)); switch (alg) { @@ -14446,11 +14457,9 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed, desired_align, align); /* Ensure that alignment prologue won't copy past end of block. */ - if ((size_needed > 1 || (desired_align > 1 && desired_align > align)) - && !count) + if (size_needed > 1 || (desired_align > 1 && desired_align > align)) { epilogue_size_needed = MAX (size_needed - 1, desired_align - align); - /* Epilogue always copies COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes. Make sure it is power of 2. */ epilogue_size_needed = smallest_pow2_greater_than (epilogue_size_needed); @@ -14464,8 +14473,10 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, label = gen_label_rtx (); emit_cmp_and_jump_insns (count_exp, GEN_INT (epilogue_size_needed), - LTU, 0, GET_MODE (count_exp), 1, label); - if (expected_size == -1 || expected_size <= epilogue_size_needed) + LTU, 0, counter_mode (count_exp), 1, label); + if (GET_CODE (count_exp) == CONST_INT) + ; + else if (expected_size == -1 || expected_size <= epilogue_size_needed) predict_jump (REG_BR_PROB_BASE * 60 / 100); else predict_jump (REG_BR_PROB_BASE * 20 / 100); @@ -14475,7 +14486,7 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, rtx hot_label = gen_label_rtx (); jump_around_label = gen_label_rtx (); emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1), - LEU, 0, GET_MODE (count_exp), 1, hot_label); + LEU, 0, counter_mode (count_exp), 1, hot_label); predict_jump (REG_BR_PROB_BASE * 90 / 100); set_storage_via_libcall (dst, count_exp, val_exp, false); emit_jump (jump_around_label); @@ -14558,7 +14569,7 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, if (size_needed < desired_align - align) { tmp = - expand_simple_binop (GET_MODE (count_exp), AND, count_exp, + 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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2e9bce6b315d..c2e1df80a567 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2007-02-24 Jan Hubicka + + * gcc.c-torture/execute/pr30778.c: New testcase. + 2007-02-24 Jerry DeLisle PR libgfortran/30918 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr30778.c b/gcc/testsuite/gcc.c-torture/execute/pr30778.c new file mode 100644 index 000000000000..1b05189f4995 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr30778.c @@ -0,0 +1,34 @@ +extern void *memset (void *, int, unsigned long); +extern void abort (void); + +struct reg_stat { + void *last_death; + void *last_set; + void *last_set_value; + int last_set_label; + char last_set_sign_bit_copies; + int last_set_mode : 8; + char last_set_invalid; + char sign_bit_copies; + long nonzero_bits; +}; + +static struct reg_stat *reg_stat; + +void __attribute__((noinline)) +init_reg_last (void) +{ + memset (reg_stat, 0, __builtin_offsetof (struct reg_stat, sign_bit_copies)); +} + +int main (void) +{ + struct reg_stat r; + + reg_stat = &r; + r.nonzero_bits = -1; + init_reg_last (); + if (r.nonzero_bits != -1) + abort (); + return 0; +}