This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [RFA][PATCH]Fix 59019
- From: Steven Bosscher <stevenb dot gcc at gmail dot com>
- To: Jeff Law <law at redhat dot com>
- Cc: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Sun, 17 Nov 2013 12:28:34 +0100
- Subject: Re: [RFA][PATCH]Fix 59019
- Authentication-results: sourceware.org; auth=none
- References: <528866B9 dot 3070008 at redhat dot com>
On Sun, Nov 17, 2013 at 7:48 AM, Jeff Law wrote:
>
> * combine.c (try_combine): If we have created an unconditional trap,
> make sure to fixup the insn stream & CFG appropriately.
>
> diff --git a/gcc/combine.c b/gcc/combine.c
> index 13f5e29..b3d20f2 100644
> --- a/gcc/combine.c
> +++ b/gcc/combine.c
> @@ -4348,6 +4348,37 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int
> *new_direct_jump_p,
> update_cfg_for_uncondjump (undobuf.other_insn);
> }
>
> + /* If we might have created an unconditional trap, then we have
> + cleanup work to do.
> +
> + The fundamental problem is a conditional trap is not considered
> + control flow altering, while an unconditional trap is considered
> + control flow altering.
> +
> + So while we could have a conditional trap in the middle of a block
> + we can not have an unconditional trap in the middle of a block. */
> + if (GET_CODE (i3) == INSN
> + && GET_CODE (PATTERN (i3)) == TRAP_IF
> + && XEXP (PATTERN (i3), 0) == const1_rtx)
TRAP_CONDITION (PATTERN (i3)) == const1_rtx
But shouldn't the check be on const_true_rtx? Or does combine put a
const1_rtx there?
> + {
> + basic_block bb = BLOCK_FOR_INSN (i3);
> + rtx last = get_last_bb_insn (bb);
This won't work, get_last_bb_insn() is intended to be used only in
cfgrtl mode and "combine" works in cfglayout mode. If you use it in
cfglayout mode on a block that ends in a tablejump, you get back the
JUMP_TABLE_DATA insn that is in BB_FOOTER and there is no NEXT_INSN
path from BB_END to any insns in the footer.
rtx last = BB_END (bb);
Any dead jump tables will be dealt with later.
> + /* First remove all the insns after the trap. */
> + if (i3 != last)
> + delete_insn_chain (NEXT_INSN (i3), last, true);
> +
> + /* And ensure there's no outgoing edges anymore. */
> + while (EDGE_COUNT (bb->succs) > 0)
> + remove_edge (EDGE_SUCC (bb, 0));
Alternatively, you could do "split_block (bb, i3);" and let cfgcleanup
deal with the new, unreachable basic block.
> + /* And ensure cfglayout knows this block does not fall through. */
> + emit_barrier_after_bb (bb);
Bah... Emitting the barrier is necessary here because
fixup_reorder_chain doesn't handle cases where a basic block is a dead
end. That is actually a bug in fixup_reorder_chain: Other passes could
create dead ends in the CFG in cfglayout mode and not emit a barrier
into BB_FOOTER, and fixup_reorder_chain wouldn't be able to handle
that (resulting in verify_flow_info failure).
fixup_reorder_chain should emit a BARRIER if a block has no successor edges.
(It's a general short-comming of cfglayout mode that barriers are
still there at all. Ideally all barriers would be removed going into
cfglayout mode, and fixup_reorder_chain would put them back where
necessary. That would simplify the job of updating the CFG elsewhere
in the compiler, e.g. update_cfg_for_uncondjump)
> + /* Not exactly true, but gets the effect we want. */
> + *new_direct_jump_p = 1;
> + }
> +
> /* A noop might also need cleaning up of CFG, if it comes from the
> simplification of a jump. */
> if (JUMP_P (i3)
>
Would you mind if I try spend some time making conditional traps be
control flow insns? It should make all of this a little bit less ugly.
And I have no fish to fry at all :-) Give me a week or two please, to
see if I can figure out those issues you've been running into.
Ciao!
Steven