#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. */
{
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)
{
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
/* 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;
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
simplified = simplify_unary_operation (GET_CODE (src),
GET_MODE (src),
src0,
- GET_MODE (src0));
+ mode0);
break;
}
/* 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);
/* 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,
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);
}
static void
ssa_ccp_substitute_constants ()
{
- int i;
+ unsigned int i;
for (i = FIRST_PSEUDO_REGISTER; i < VARRAY_SIZE (ssa_definition); i++)
{
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);
&& (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);
+ }
+
}
-
}
}
}
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))
VARRAY_RTX (ssa_definition, reg) = NULL;
}
}
+
+ sbitmap_free (worklist);
}