OSDN Git Service

* sbitmap.c: Fix comment formatting.
[pf3gnuchains/gcc-fork.git] / gcc / ssa-ccp.c
index 2316824..0815f75 100644 (file)
@@ -123,41 +123,17 @@ static sbitmap ssa_edges;
 #define PHI_PARMS(x) XVEC (SET_SRC (x), 0)
 #define EIE(x,y) EDGE_INDEX (edges, x, y)
 
-rtx first_phi_node              PARAMS ((basic_block));
 static void visit_phi_node             PARAMS ((rtx, basic_block));
 static void visit_expression           PARAMS ((rtx, basic_block));
 static void defs_to_undefined          PARAMS ((rtx));
 static void defs_to_varying            PARAMS ((rtx));
 static void examine_flow_edges         PARAMS ((void));
+static int mark_references             PARAMS ((rtx *, void *));
 static void follow_def_use_chains      PARAMS ((void));
 static void optimize_unexecutable_edges PARAMS ((struct edge_list *, sbitmap));
 static void ssa_ccp_substitute_constants PARAMS ((void));
 static void ssa_ccp_df_delete_unreachable_insns PARAMS ((void));
-
-/* Return the first PHI node in a basic block.  This routine knows
-   what INSNs can start a basic block and what can validly follow
-   them up to the first PHI node.
-
-   If the INSN chain or block structures are incorrect, then the behavior
-   of this routine is undefined.  verify_flow_info will normally catch
-   these problems in a more graceful manner.  */
-rtx
-first_phi_node (block)
-     basic_block block;
-{
-  rtx insn = block->head;
-
-  /* Eat the optional CODE_LABEL at the start of the block.  */
-  if (GET_CODE (insn) == CODE_LABEL)
-    insn = NEXT_INSN (insn);
-
-  /* Eat the mandatory NOTE_INSN_BASIC_BLOCK.  */
-  if (!NOTE_INSN_BASIC_BLOCK_P (insn) || NOTE_BASIC_BLOCK (insn) != block)
-    abort ();
-
-  /* If there is a PHI node in this block, then it will be the next insn.  */
-  return NEXT_INSN (insn);
-}
+static void ssa_fast_dce PARAMS ((struct df *));
 
 /* Loop through the PHI_NODE's parameters for BLOCK and compare their
    lattice values to determine PHI_NODE's lattice value.  */
@@ -270,6 +246,30 @@ visit_expression (insn, block)
 {
   rtx src, dest, set;
 
+
+  /* Ugh.  CALL_INSNs may end a basic block and have multiple edges
+     leading out from them.
+
+     Mark all the outgoing edges as executable, then fall into the
+     normal processing below.  */
+  if (GET_CODE (insn) == CALL_INSN && block->end == insn)
+    {
+      edge curredge;
+
+      for (curredge = block->succ; curredge;
+          curredge = curredge->succ_next)
+       {
+         int index = EIE (curredge->src, curredge->dest);
+
+         if (TEST_BIT (executable_edges, index))
+           continue;
+
+         SET_BIT (executable_edges, index);
+         edge_info[index] = flow_edges;
+         flow_edges = curredge;
+       }
+    }
+
   set = single_set (insn);
   if (! set)
     {
@@ -474,7 +474,13 @@ visit_expression (insn, block)
                  defs_to_undefined (insn);
                  break;
                }
-               
+
+             /* Determine the mode for the operation before we simplify
+                our arguments to constants.  */
+             mode = GET_MODE (src0);
+             if (mode == VOIDmode)
+               mode = GET_MODE (src1);
+
              /* Simplify source operands to whatever known values they
                 may have.  */
              if (GET_CODE (src0) == REG
@@ -487,10 +493,6 @@ visit_expression (insn, block)
 
              /* See if the simplifier can determine if this operation
                 computes a constant value.  */
-             mode = GET_MODE (src0);
-             if (mode == VOIDmode)
-               mode = GET_MODE (src1);
-
              simplified = simplify_relational_operation (GET_CODE (src),
                                                          mode, src0, src1);
              break;
@@ -500,6 +502,7 @@ visit_expression (insn, block)
          case '1':
            {
              rtx src0 = XEXP (src, 0);
+             enum machine_mode mode0 = GET_MODE (src0);
 
              /* If the operand is undefined, then the result is undefined.  */
              if (GET_CODE (src0) == REG
@@ -520,7 +523,7 @@ visit_expression (insn, block)
              simplified = simplify_unary_operation (GET_CODE (src),
                                                     GET_MODE (src),
                                                     src0,
-                                                    GET_MODE (src0));
+                                                    mode0);
              break;
            }
 
@@ -638,7 +641,7 @@ examine_flow_edges (void)
 
       /* Always simulate PHI nodes, even if we have simulated this block
         before.  Note that all PHI nodes are consecutive within a block.  */
-      for (curr_phi_node = first_phi_node (succ_block);
+      for (curr_phi_node = first_insn_after_basic_block_note (succ_block);
           PHI_NODE_P (curr_phi_node);
           curr_phi_node = NEXT_INSN (curr_phi_node))
        visit_phi_node (curr_phi_node, succ_block);
@@ -670,7 +673,7 @@ examine_flow_edges (void)
          /* If we haven't looked at the next block, and it has a
             single successor, add it onto the worklist.  This is because
             if we only have one successor, we know it gets executed,
-            so we don't have to wait for cprop to tell us. */
+            so we don't have to wait for cprop to tell us.  */
          if (succ_edge != NULL
              && succ_edge->succ_next == NULL
              && !TEST_BIT (executable_edges,
@@ -751,15 +754,22 @@ optimize_unexecutable_edges (edges, executable_edges)
             the PHI nodes in the target block.  */
          if (edge->dest != EXIT_BLOCK_PTR)
            {
-             rtx insn = first_phi_node (edge->dest);
+             rtx insn = first_insn_after_basic_block_note (edge->dest);
 
              while (PHI_NODE_P (insn))
                {
                  remove_phi_alternative (PATTERN (insn), edge->src);
+                 if (rtl_dump_file)
+                   fprintf (rtl_dump_file,
+                            "Removing alternative for bb %d of phi %d\n", 
+                            edge->src->index, SSA_NAME (PATTERN (insn)));
                  insn = NEXT_INSN (insn);
                }
            }
-
+         if (rtl_dump_file)
+           fprintf (rtl_dump_file,
+                    "Removing unexecutable edge from %d to %d\n",
+                    edge->src->index, edge->dest->index);
          /* Since the edge was not executable, remove it from the CFG.  */
          remove_edge (edge);
        }
@@ -840,7 +850,7 @@ optimize_unexecutable_edges (edges, executable_edges)
 static void
 ssa_ccp_substitute_constants ()
 {
-  int i;
+  unsigned int i;
 
   for (i = FIRST_PSEUDO_REGISTER; i < VARRAY_SIZE (ssa_definition); i++)
     {
@@ -859,6 +869,10 @@ ssa_ccp_substitute_constants ()
             are consecutive at the start of the basic block.  */
          if (! PHI_NODE_P (def))
            {
+             if (rtl_dump_file)
+               fprintf (rtl_dump_file,
+                        "Register %d is now set to a constant\n",
+                        SSA_NAME (PATTERN (def)));
              SET_SRC (set) = values[i].const_value;
              INSN_CODE (def) = -1;
              df_insn_modify (df_analyzer, BLOCK_FOR_INSN (def), def);
@@ -882,15 +896,22 @@ ssa_ccp_substitute_constants ()
                  && (GET_CODE (useinsn) == INSN
                      || GET_CODE (useinsn) == JUMP_INSN))
                {
-                 validate_replace_src (regno_reg_rtx [i],
+                 
+                 if (validate_replace_src (regno_reg_rtx [i],
                                        values[i].const_value,
-                                       useinsn);
-                 INSN_CODE (useinsn) = -1;
-                 df_insn_modify (df_analyzer,
-                                 BLOCK_FOR_INSN (useinsn),
-                                 useinsn);
+                                           useinsn))
+                   {
+                     if (rtl_dump_file)
+                       fprintf (rtl_dump_file, 
+                                "Register %d in insn %d replaced with constant\n",
+                                i, INSN_UID (useinsn));
+                     INSN_CODE (useinsn) = -1;
+                     df_insn_modify (df_analyzer,
+                                     BLOCK_FOR_INSN (useinsn),
+                                     useinsn);
+                   }
+                 
                }
-
            }
        }
     }
@@ -1159,8 +1180,6 @@ ssa_fast_dce (df)
       found_use = 0;
       for (curruse = df->regs[reg].uses; curruse; curruse = curruse->next)
        {
-         rtx useinsn;
-
          if (curruse->ref
              && DF_REF_INSN (curruse->ref)
              && ! INSN_DELETED_P (DF_REF_INSN (curruse->ref))
@@ -1218,4 +1237,6 @@ ssa_fast_dce (df)
          VARRAY_RTX (ssa_definition, reg) = NULL;
        }
     }
+
+  sbitmap_free (worklist);
 }