This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix cfgcleanup regression (PR rtl-optimization/59724)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Uros Bizjak <ubizjak at gmail dot com>, Richard Biener <rguenther at suse dot de>, Steven Bosscher <stevenb dot gcc at gmail dot com>, Eric Botcazou <ebotcazou at adacore dot com>
- Cc: gcc-patches at gcc dot gnu dot org, Jeff Law <law at redhat dot com>
- Date: Wed, 8 Jan 2014 23:42:07 +0100
- Subject: [PATCH] Fix cfgcleanup regression (PR rtl-optimization/59724)
- Authentication-results: sourceware.org; auth=none
- References: <CAFULd4bTApucqyGk1upJnFiOUSW55VNXOgPceMNWAuZuMN1xaw at mail dot gmail dot com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
On Wed, Jan 08, 2014 at 05:54:55PM +0100, Uros Bizjak wrote:
> This caused PR59724 on alpha:
>
> 20021116-1.c: In function âfooâ:
> 20021116-1.c:31:1: error: NOTE_INSN_BASIC_BLOCK is missing for block 9
> }
> ^
> 20021116-1.c:31:1: error: insn outside basic block
> (jump_insn 94 52 93 9 (return) 20021116-1.c:31 -1
> (nil)
> -> return)
Ugh, indeed. The problem is that try_head_merge_bb really wants
flow_find_head_matching_sequence to count all (non-note) insns, not
just active insns, because otherwise as in the above testcase we
can have e.g. 2 active insns followed by one non-active, all matching
(flow_find_head_matching_sequence returns 2) and on another edge
just 2 active insns and nothing else matching. 2 == 2, so the caller
thinks it doesn't matter which one is shorter, but we have the insn range
of 3 insns together.
So, this patch just reverts the try_head_merge_bb changes and makes
flow_find_head_matching_sequence behave the old way when called from
try_head_merge_bb, i.e. count all non-note insns, and only when called
from ifcvt.c count just active insns. Plus the ifcvt.c change ensures
we don't mistakenly call it with stop_after == 0 (which wouldn't actually
stop).
Bootstrapped/regtested on x86_64-linux and i686-linux, Uros is testing it
on Alpha. Ok for trunk?
2014-01-08 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/59724
* ifcvt.c (cond_exec_process_if_block): Don't call
flow_find_head_matching_sequence with 0 longest_match.
* cfgcleanup.c (flow_find_head_matching_sequence): Count even
non-active insns if !stop_after.
(try_head_merge_bb): Revert 2014-01-07 changes.
--- gcc/ifcvt.c.jj 2014-01-08 10:23:20.000000000 +0100
+++ gcc/ifcvt.c 2014-01-08 18:46:17.017715169 +0100
@@ -522,7 +522,10 @@ cond_exec_process_if_block (ce_if_block
n_insns -= 2 * n_matching;
}
- if (then_start && else_start)
+ if (then_start
+ && else_start
+ && then_n_insns > n_matching
+ && else_n_insns > n_matching)
{
int longest_match = MIN (then_n_insns - n_matching,
else_n_insns - n_matching);
--- gcc/cfgcleanup.c.jj 2014-01-07 08:54:05.772736321 +0100
+++ gcc/cfgcleanup.c 2014-01-08 18:41:14.433307914 +0100
@@ -1421,7 +1421,8 @@ flow_find_cross_jump (basic_block bb1, b
/* Like flow_find_cross_jump, except start looking for a matching sequence from
the head of the two blocks. Do not include jumps at the end.
If STOP_AFTER is nonzero, stop after finding that many matching
- instructions. */
+ instructions. If STOP_AFTER is zero, count all INSN_P insns, if it is
+ non-zero, only count active insns. */
int
flow_find_head_matching_sequence (basic_block bb1, basic_block bb2, rtx *f1,
@@ -1493,7 +1494,7 @@ flow_find_head_matching_sequence (basic_
beforelast1 = last1, beforelast2 = last2;
last1 = i1, last2 = i2;
- if (active_insn_p (i1))
+ if (!stop_after || active_insn_p (i1))
ninsns++;
}
@@ -2408,7 +2409,9 @@ try_head_merge_bb (basic_block bb)
max_match--;
if (max_match == 0)
return false;
- e0_last_head = prev_active_insn (e0_last_head);
+ do
+ e0_last_head = prev_real_insn (e0_last_head);
+ while (DEBUG_INSN_P (e0_last_head));
}
if (max_match == 0)
@@ -2428,14 +2431,16 @@ try_head_merge_bb (basic_block bb)
basic_block merge_bb = EDGE_SUCC (bb, ix)->dest;
rtx head = BB_HEAD (merge_bb);
- if (!active_insn_p (head))
- head = next_active_insn (head);
+ while (!NONDEBUG_INSN_P (head))
+ head = NEXT_INSN (head);
headptr[ix] = head;
currptr[ix] = head;
/* Compute the end point and live information */
for (j = 1; j < max_match; j++)
- head = next_active_insn (head);
+ do
+ head = NEXT_INSN (head);
+ while (!NONDEBUG_INSN_P (head));
simulate_backwards_to_point (merge_bb, live, head);
IOR_REG_SET (live_union, live);
}
Jakub