Patchwork Fix ifcvt ICE

login
register
mail settings
Submitter Chung-Lin Tang
Date Oct. 14, 2010, 7:30 p.m.
Message ID <4CB75A6F.5030002@codesourcery.com>
Download mbox | patch
Permalink /patch/67855/
State New
Headers show

Comments

Chung-Lin Tang - Oct. 14, 2010, 7:30 p.m.
Eric Botcazou wrote:
>> So this patch is quite simple: implement two replacement functions
>> find_active_insn_before/after() that correct the above mentioned
>> behavior, and use them in ifcvt.
>
> OK on principle, but the implementation isn't fully correct because it uses
> BLOCK_FOR_INSN and this isn't defined for BARRIERs.
>
> Please add a BB parameter to both functions and test against BB_HEAD or BB_END
> to stop the iteration, like in first_active_insn/last_active_insn.
>

Here's the updated patch, tests were ran again to verify same results.
Ok for trunk now?

Thanks,
Chung-Lin
Eric Botcazou - Oct. 14, 2010, 8:07 p.m.
> Here's the updated patch, tests were ran again to verify same results.
> Ok for trunk now?

OK if you add the missing head comment for each function; no need to resubmit.

Patch

Index: ifcvt.c
===================================================================
--- ifcvt.c	(revision 165474)
+++ ifcvt.c	(working copy)
@@ -88,6 +88,8 @@ 
 static bool cheap_bb_rtx_cost_p (const_basic_block, int);
 static rtx first_active_insn (basic_block);
 static rtx last_active_insn (basic_block, int);
+static rtx find_active_insn_before (basic_block, rtx);
+static rtx find_active_insn_after (basic_block, rtx);
 static basic_block block_fallthru (basic_block);
 static int cond_exec_process_insns (ce_if_block_t *, rtx, rtx, rtx, rtx, int);
 static rtx cond_exec_get_condition (rtx);
@@ -229,6 +231,44 @@ 
   return insn;
 }
 
+static rtx
+find_active_insn_before (basic_block curr_bb, rtx insn)
+{
+  if (!insn || insn == BB_HEAD (curr_bb))
+    return NULL_RTX;
+
+  while ((insn = PREV_INSN (insn)) != NULL_RTX)
+    {
+      if (NONJUMP_INSN_P (insn) || JUMP_P (insn) || CALL_P (insn))
+        break;
+
+      /* No other active insn all the way to the start of the basic block. */
+      if (insn == BB_HEAD (curr_bb))
+        return NULL_RTX;
+    }
+
+  return insn;
+}
+
+static rtx
+find_active_insn_after (basic_block curr_bb, rtx insn)
+{
+  if (!insn || insn == BB_END (curr_bb))
+    return NULL_RTX;
+
+  while ((insn = NEXT_INSN (insn)) != NULL_RTX)
+    {
+      if (NONJUMP_INSN_P (insn) || JUMP_P (insn) || CALL_P (insn))
+        break;
+
+      /* No other active insn all the way to the end of the basic block. */
+      if (insn == BB_END (curr_bb))
+        return NULL_RTX;
+    }
+
+  return insn;
+}
+
 /* Return the basic block reached by falling though the basic block BB.  */
 
 static basic_block
@@ -447,9 +487,9 @@ 
       if (n_matching > 0)
 	{
 	  if (then_end)
-	    then_end = prev_active_insn (then_first_tail);
+	    then_end = find_active_insn_before (then_bb, then_first_tail);
 	  if (else_end)
-	    else_end = prev_active_insn (else_first_tail);
+	    else_end = find_active_insn_before (else_bb, else_first_tail);
 	  n_insns -= 2 * n_matching;
 	}
 
@@ -487,9 +527,9 @@ 
 	  if (n_matching > 0)
 	    {
 	      if (then_start)
-		then_start = next_active_insn (then_last_head);
+		then_start = find_active_insn_after (then_bb, then_last_head);
 	      if (else_start)
-		else_start = next_active_insn (else_last_head);
+		else_start = find_active_insn_after (else_bb, else_last_head);
 	      n_insns -= 2 * n_matching;
 	    }
 	}
@@ -645,7 +685,7 @@ 
     {
       rtx from = then_first_tail;
       if (!INSN_P (from))
-	from = next_active_insn (from);
+	from = find_active_insn_after (then_bb, from);
       delete_insn_chain (from, BB_END (then_bb), false);
     }
   if (else_last_head)
Index: testsuite/gcc.dg/20101010-1.c
===================================================================
--- testsuite/gcc.dg/20101010-1.c	(revision 0)
+++ testsuite/gcc.dg/20101010-1.c	(revision 0)
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-crossjumping" } */
+
+int foo (void)
+{
+  int len;
+  if (bar1 (&len))
+    {
+      char devpath [len];
+      if (bar2 (devpath) == len)
+        return len;
+    }
+  return -1;
+}