On Linux/x86, r206213 gave [hjl@gnu-18 gcc]$ cat bad.c #define BUFFER_SIZE (16*1024*1024 + AVG_SIZE*2) /*#define MEMORY_COPIES (1024*1024*64*(long long)10)*/ char t[BUFFER_SIZE]; main() { unsigned int i; for (i=0;i<((long long)MEMORY_COPIES + AVG_SIZE * 2 - 1)/AVG_SIZE*2;i++) #ifdef test_memset __builtin_memset (t+(i*1024*1024+i*1)%(BUFFER_SIZE - AVG_SIZE*2), i, (AVG_SIZE + i) % (AVG_SIZE * 2 + 0)); #else __builtin_memcpy (t+(i*1024*1024+i*1)%(BUFFER_SIZE - AVG_SIZE*2), t+((i+1)*1024*1024*4+i*1)%(BUFFER_SIZE - AVG_SIZE *2), (AVG_SIZE + i) % (AVG_SIZE * 2 + 0)); #endif return 0; } [hjl@gnu-18 gcc]$ ./xgcc -B ./ -x c -O3 -minline-stringops-dynamically -DAVG_SIZE=8192000 -DMEMORY_COPIES=640000000 bad.c bad.c: In function ‘main’: bad.c:14:1: error: wrong number of branch edges after unconditional jump in bb 11 } ^ bad.c:14:1: error: wrong number of branch edges after unconditional jump in bb 7 bad.c:14:1: internal compiler error: verify_flow_info failed 0x666c23 verify_flow_info() /export/gnu/import/git/gcc/gcc/cfghooks.c:260 0xe25a53 try_optimize_cfg /export/gnu/import/git/gcc/gcc/cfgcleanup.c:2857 0xe25a53 cleanup_cfg(int) /export/gnu/import/git/gcc/gcc/cfgcleanup.c:3022 0x665412 gimple_expand_cfg /export/gnu/import/git/gcc/gcc/cfgexpand.c:5837 0x665412 execute /export/gnu/import/git/gcc/gcc/cfgexpand.c:5932 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <http://gcc.gnu.org/bugs.html> for instructions. [hjl@gnu-18 gcc]$
It is caused by r203937.
ix86_expand_set_or_movmem has rtx jump_around_label = NULL; /* Misaligned move sequences handles both prologues and epilogues at once. Default code generation results in smaller code for large alignments and also avoids redundant job when sizes are known precisely. */ if (misaligned_prologue_used) { /* Misaligned move prologue handled small blocks by itself. */ expand_set_or_movmem_prologue_epilogue_by_misaligned_moves (dst, src, &destreg, &srcreg, move_mode, promoted_val, vec_promoted_val, &count_exp, &jump_around_label, desired_align < align ? MAX (desired_align, epilogue_size_needed) : epilogue_size_needed, desired_align, align, &min_size, dynamic_check, issetmem); if (!issetmem) src = change_address (src, BLKmode, srcreg); ... else { rtx hot_label = gen_label_rtx (); jump_around_label = gen_label_rtx (); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ When jump_around_label != NULL, the previous jump_around_label is lost. emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1), LEU, 0, GET_MODE (count_exp), 1, hot_label); predict_jump (REG_BR_PROB_BASE * 90 / 100); if (issetmem) set_storage_via_libcall (dst, count_exp, val_exp, false); else emit_block_move_via_libcall (dst, src, count_exp, false); emit_jump (jump_around_label); emit_label (hot_label); }
Does this --- diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 0cf0a9d..07f9a86 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -24015,7 +24015,8 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp, else { rtx hot_label = gen_label_rtx (); - jump_around_label = gen_label_rtx (); + if (jump_around_label == NULL_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); predict_jump (REG_BR_PROB_BASE * 90 / 100); --- make any senses?
A patch is posted at http://gcc.gnu.org/ml/gcc-patches/2013-12/msg01907.html
Author: jakub Date: Mon Dec 30 08:48:25 2013 New Revision: 206242 URL: http://gcc.gnu.org/viewcvs?rev=206242&root=gcc&view=rev Log: PR target/59605 * config/i386/i386.c (ix86_expand_set_or_movmem): Create jump_around_label only if it doesn't exist. * gcc.dg/pr59605.c: New test. Added: trunk/gcc/testsuite/gcc.dg/pr59605.c Modified: trunk/gcc/ChangeLog trunk/gcc/config/i386/i386.c trunk/gcc/testsuite/ChangeLog
Fixed.