Hi! The force_operand on complex count expression in doloop_modify can invoke various expander routines that are assuming there is rtl unsharing after them (which is the case for expansion). When later optimizations invoke the expander (e.g. expand_mult in this case), they use unshare_all_rtl_in_chain on the sequence. The following patch does that for doloop. The count expression is already known not to be shared with anything else (we do copy_rtx on it first and then create new rtls around it if needed), so for that if it occurs just once in the sequence, we don't need to unshare it. For subexpression of condition I'm not sure, which is why I've forced unsharing even if it occurs just once and is not shareable part of the condition like REG.
Bootstrapped/regtested on powerpc64-linux, ok for trunk? 2017-01-14 Jakub Jelinek <ja...@redhat.com> PR target/79080 * loop-doloop.c (doloop_modify): Call unshare_all_rtl_in_chain on sequence. Formatting fixes. (doloop_optimize): Formatting fixes. * gcc.dg/pr79080.c: New test. --- gcc/loop-doloop.c.jj 2017-01-01 12:45:37.000000000 +0100 +++ gcc/loop-doloop.c 2017-01-13 09:55:36.918702356 +0100 @@ -479,9 +479,13 @@ doloop_modify (struct loop *loop, struct /* Insert initialization of the count register into the loop header. */ start_sequence (); + /* count has been already copied through copy_rtx. */ + reset_used_flags (count); + set_used_flags (condition); tmp = force_operand (count, counter_reg); convert_move (counter_reg, tmp, 1); sequence = get_insns (); + unshare_all_rtl_in_chain (sequence); end_sequence (); emit_insn_after (sequence, BB_END (loop_preheader_edge (loop)->src)); @@ -489,10 +493,8 @@ doloop_modify (struct loop *loop, struct { rtx ass = copy_rtx (desc->noloop_assumptions); basic_block preheader = loop_preheader_edge (loop)->src; - basic_block set_zero - = split_edge (loop_preheader_edge (loop)); - basic_block new_preheader - = split_edge (loop_preheader_edge (loop)); + basic_block set_zero = split_edge (loop_preheader_edge (loop)); + basic_block new_preheader = split_edge (loop_preheader_edge (loop)); edge te; /* Expand the condition testing the assumptions and if it does not pass, @@ -688,8 +690,7 @@ doloop_optimize (struct loop *loop) rtx_insn *doloop_seq = targetm.gen_doloop_end (doloop_reg, start_label); word_mode_size = GET_MODE_PRECISION (word_mode); - word_mode_max - = (HOST_WIDE_INT_1U << (word_mode_size - 1) << 1) - 1; + word_mode_max = (HOST_WIDE_INT_1U << (word_mode_size - 1) << 1) - 1; if (! doloop_seq && mode != word_mode /* Before trying mode different from the one in that # of iterations is --- gcc/testsuite/gcc.dg/pr79080.c.jj 2017-01-13 10:03:54.518423577 +0100 +++ gcc/testsuite/gcc.dg/pr79080.c 2017-01-13 10:07:37.610608570 +0100 @@ -0,0 +1,19 @@ +/* PR target/79080 */ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ +/* { dg-additional-options "-mcpu=8548" { target { powerpc*-*-* && ilp32 } } } */ + +int +foo (char x) +{ + int a; + + for (;;) + { + x += 59; + if (x != 0) + a = 0; + else + return 0; + } +} Jakub