OSDN Git Service

PR fortran/9974
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 1 Apr 2003 22:32:37 +0000 (22:32 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 1 Apr 2003 22:32:37 +0000 (22:32 +0000)
* gcse.c (reg_killed_on_egde): New function to test whether the
given reg is overwritten by any instruction queued on an edge.
(bypass_block): Ignore substitutions killed on incoming edges.
Don't bypass outgoing edges that have queued instructions.

* gcc.c-torture/execute/20030401-1.c: New test case.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@65148 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/gcse.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20030401-1.c [new file with mode: 0644]

index 82c47e0..2fa9ef5 100644 (file)
@@ -1,3 +1,11 @@
+2003-04-01  Roger Sayle  <roger@eyesopen.com>
+
+       PR fortran/9974
+       * gcse.c (reg_killed_on_egde): New function to test whether the
+       given reg is overwritten by any instruction queued on an edge.
+       (bypass_block): Ignore substitutions killed on incoming edges.
+       Don't bypass outgoing edges that have queued instructions.
+
 2003-04-01  Alexandre Oliva  <aoliva@redhat.com>
 
        * real.h (EXP_BITS): Make room for...
index 93f656f..e7a6845 100644 (file)
@@ -624,6 +624,7 @@ static void find_implicit_sets      PARAMS ((void));
 static int one_cprop_pass      PARAMS ((int, int, int));
 static bool constprop_register PARAMS ((rtx, rtx, rtx, int));
 static struct expr *find_bypass_set PARAMS ((int, int));
+static bool reg_killed_on_edge     PARAMS ((rtx, edge));
 static int bypass_block                    PARAMS ((basic_block, rtx, rtx));
 static int bypass_conditional_jumps PARAMS ((void));
 static void alloc_pre_mem      PARAMS ((int, int));
@@ -4768,11 +4769,35 @@ find_bypass_set (regno, bb)
 }
 
 
+/* Subroutine of bypass_block that checks whether a pseudo is killed by
+   any of the instructions inserted on an edge.  Jump bypassing places
+   condition code setters on CFG edges using insert_insn_on_edge.  This
+   function is required to check that our data flow analysis is still
+   valid prior to commit_edge_insertions.  */
+
+static bool
+reg_killed_on_edge (reg, e)
+     rtx reg;
+     edge e;
+{
+  rtx insn;
+
+  for (insn = e->insns; insn; insn = NEXT_INSN (insn))
+    if (INSN_P (insn) && reg_set_p (reg, insn))
+      return true;
+
+  return false;
+}
+
 /* Subroutine of bypass_conditional_jumps that attempts to bypass the given
    basic block BB which has more than one predecessor.  If not NULL, SETCC
    is the first instruction of BB, which is immediately followed by JUMP_INSN
    JUMP.  Otherwise, SETCC is NULL, and JUMP is the first insn of BB.
-   Returns nonzero if a change was made.  */
+   Returns nonzero if a change was made.
+
+   During the jump bypassing pass, we may place copies of SETCC instuctions
+   on CFG edges.  The following routine must be careful to pay attention to
+   these inserted insns when performing its transformations.  */
 
 static int
 bypass_block (bb, setcc, jump)
@@ -4780,7 +4805,7 @@ bypass_block (bb, setcc, jump)
      rtx setcc, jump;
 {
   rtx insn, note;
-  edge e, enext;
+  edge e, enext, edest;
   int i, change;
   int may_be_loop_header;
 
@@ -4835,6 +4860,10 @@ bypass_block (bb, setcc, jump)
          if (! set)
            continue;
 
+         /* Check the data flow is valid after edge insertions.  */
+         if (e->insns && reg_killed_on_edge (reg_used->reg_rtx, e))
+           continue;
+
          src = SET_SRC (pc_set (jump));
 
          if (setcc != NULL)
@@ -4845,10 +4874,27 @@ bypass_block (bb, setcc, jump)
          new = simplify_replace_rtx (src, reg_used->reg_rtx,
                                      SET_SRC (set->expr));
 
+         /* Jump bypassing may have already placed instructions on 
+            edges of the CFG.  We can't bypass an outgoing edge that
+            has instructions associated with it, as these insns won't
+            get executed if the incoming edge is redirected.  */
+
          if (new == pc_rtx)
-           dest = FALLTHRU_EDGE (bb)->dest;
+           {
+             edest = FALLTHRU_EDGE (bb);
+             dest = edest->insns ? NULL : edest->dest;
+           }
          else if (GET_CODE (new) == LABEL_REF)
-           dest = BLOCK_FOR_INSN (XEXP (new, 0));
+           {
+             dest = BLOCK_FOR_INSN (XEXP (new, 0));
+             /* Don't bypass edges containing instructions.  */
+             for (edest = bb->succ; edest; edest = edest->succ_next)
+               if (edest->dest == dest && edest->insns)
+                 {
+                   dest = NULL;
+                   break;
+                 }
+           }
          else
            dest = NULL;
 
index c66386e..bf5d4aa 100644 (file)
@@ -1,3 +1,7 @@
+2003-04-01  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.c-torture/execute/20030401-1.c: New test case.
+
 2003-04-01  Ziemowit Laski <zlaski@apple.com>
 
        * objc.dg/defs.m: New.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20030401-1.c b/gcc/testsuite/gcc.c-torture/execute/20030401-1.c
new file mode 100644 (file)
index 0000000..0cc144a
--- /dev/null
@@ -0,0 +1,27 @@
+/* Testcase for PR fortran/9974.  This was a miscompilation of the g77
+   front-end caused by the jump bypassing optimizations not handling
+   instructions inserted on CFG edges.  */
+
+extern void abort ();
+
+int bar ()
+{
+  return 1;
+}
+
+void foo (int x)
+{
+  unsigned char error = 0;
+
+  if (! (error = ((x == 0) || bar ())))
+    bar ();
+  if (! error)
+    abort ();
+}
+
+int main()
+{
+  foo (1);
+  return 0;
+}
+