diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/sched-rgn.cc | 37 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/pr105586.c | 19 |
2 files changed, 42 insertions, 14 deletions
diff --git a/gcc/sched-rgn.cc b/gcc/sched-rgn.cc index 0dc2a8f..420c45d 100644 --- a/gcc/sched-rgn.cc +++ b/gcc/sched-rgn.cc @@ -3082,6 +3082,27 @@ free_bb_state_array (void) bb_state = NULL; } +/* If LAST_BB falls through to another block B, record that B should + start with DFA start STATE. */ + +static void +save_state_for_fallthru_edge (basic_block last_bb, state_t state) +{ + edge f = find_fallthru_edge (last_bb->succs); + if (f + && (!f->probability.initialized_p () + || (f->probability.to_reg_br_prob_base () * 100 + / REG_BR_PROB_BASE + >= param_sched_state_edge_prob_cutoff))) + { + memcpy (bb_state[f->dest->index], state, + dfa_state_size); + if (sched_verbose >= 5) + fprintf (sched_dump, "saving state for edge %d->%d\n", + f->src->index, f->dest->index); + } +} + /* Schedule a region. A region is either an inner loop, a loop-free subroutine, or a single basic block. Each bb in the region is scheduled after its flow predecessors. */ @@ -3155,6 +3176,7 @@ schedule_region (int rgn) if (no_real_insns_p (head, tail)) { gcc_assert (first_bb == last_bb); + save_state_for_fallthru_edge (last_bb, bb_state[first_bb->index]); continue; } @@ -3173,26 +3195,13 @@ schedule_region (int rgn) curr_bb = first_bb; if (dbg_cnt (sched_block)) { - edge f; int saved_last_basic_block = last_basic_block_for_fn (cfun); schedule_block (&curr_bb, bb_state[first_bb->index]); gcc_assert (EBB_FIRST_BB (bb) == first_bb); sched_rgn_n_insns += sched_n_insns; realloc_bb_state_array (saved_last_basic_block); - f = find_fallthru_edge (last_bb->succs); - if (f - && (!f->probability.initialized_p () - || (f->probability.to_reg_br_prob_base () * 100 - / REG_BR_PROB_BASE - >= param_sched_state_edge_prob_cutoff))) - { - memcpy (bb_state[f->dest->index], curr_state, - dfa_state_size); - if (sched_verbose >= 5) - fprintf (sched_dump, "saving state for edge %d->%d\n", - f->src->index, f->dest->index); - } + save_state_for_fallthru_edge (last_bb, curr_state); } else { diff --git a/gcc/testsuite/gcc.target/powerpc/pr105586.c b/gcc/testsuite/gcc.target/powerpc/pr105586.c new file mode 100644 index 0000000..bd397f5 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr105586.c @@ -0,0 +1,19 @@ +/* { dg-options "-mdejagnu-tune=power4 -O2 -fcompare-debug -fno-if-conversion -fno-guess-branch-probability" } */ + +extern int bar(int i); + +typedef unsigned long u64; +int g; + +__int128 h; + +void +foo(int a, int b) { + int i; + char u8_1 = g, u8_3 = a; + u64 u64_1 = bar(0), u64_3 = u8_3 * u64_1; + __int128 u128_1 = h ^ __builtin_expect(i, 0); + u64 u64_4 = u64_1 << ((__builtin_sub_overflow_p(0, u8_1, (u64)0) ^ u128_1) & 8); + u64 u64_r = b + u64_3 + u64_4; + bar((short)u64_r + u8_3); +} |