This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA][PATCH]Fix 59019



59019 is currently latent on the trunk, but it's likely to fail again at some point.

The problem we have is combine transforms a conditional trap into an unconditional trap.

conditional traps are not considered control flow insns, but unconditional traps are.

Thus, if we turn a conditional trap in the middle of a block into an unconditional trap, we end up with a control flow insn in the middle of a block and trip a checking assert.

This is, IMHO, a bandaid. The inconsistency is amazingly annoying. But I've got bigger fish to fry and I was unhappy with the number of issues I was running into when I tried to make conditional traps control flow insns.

Basically when we see an unconditional trap after we've done combining, we remove all the insns after the trap to the end of the block, delete the block's outgoing edges and emit a barrier into the block's footer.

It's similar in spirit to the cleanups we do for other situations.

Bootstrapped on ia64 with a hack installed to make this situation more likely to arise.

Ok for the trunk if it passes a bootstrap & regression test on x86_64-unknown-linux-gnu?

Jeff

	* 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)
+    {
+      basic_block bb = BLOCK_FOR_INSN (i3);
+      rtx last = get_last_bb_insn (bb);
+
+      /* 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));
+
+      /* And ensure cfglayout knows this block does not fall through.  */
+      emit_barrier_after_bb (bb);
+
+      /* 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)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]