#include "config.h"
#include "system.h"
#include "rtl.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "ssa.h"
#include "insn-config.h"
#include "recog.h"
#include "output.h"
#include "errors.h"
#include "ggc.h"
#include "df.h"
#include "function.h"
typedef enum
{
UNDEFINED,
CONSTANT,
VARYING
} latticevalue;
typedef struct
{
latticevalue lattice_val;
rtx const_value;
} value;
static value *values;
static sbitmap executable_blocks;
static sbitmap executable_edges;
static edge *edge_info;
static struct edge_list *edges;
static struct df *df_analyzer;
static edge flow_edges;
static sbitmap ssa_edges;
#define SSA_NAME(x) REGNO (SET_DEST (x))
#define EIE(x,y) EDGE_INDEX (edges, x, y)
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));
static void ssa_fast_dce PARAMS ((struct df *));
static void
visit_phi_node (phi_node, block)
rtx phi_node;
basic_block block;
{
unsigned int i;
rtx phi_node_expr = NULL;
unsigned int phi_node_name = SSA_NAME (PATTERN (phi_node));
latticevalue phi_node_lattice_val = UNDEFINED;
rtx pat = PATTERN (phi_node);
rtvec phi_vec = XVEC (SET_SRC (pat), 0);
unsigned int num_elem = GET_NUM_ELEM (phi_vec);
for (i = 0; i < num_elem; i += 2)
{
if (TEST_BIT (executable_edges,
EIE (BASIC_BLOCK (INTVAL (RTVEC_ELT (phi_vec, i + 1))),
block)))
{
unsigned int current_parm
= REGNO (RTVEC_ELT (phi_vec, i));
latticevalue current_parm_lattice_val
= values[current_parm].lattice_val;
if (current_parm_lattice_val == VARYING)
{
phi_node_lattice_val = VARYING;
phi_node_expr = NULL;
break;
}
if (current_parm_lattice_val == CONSTANT
&& phi_node_lattice_val == CONSTANT
&& values[current_parm].const_value != phi_node_expr)
{
phi_node_lattice_val = VARYING;
phi_node_expr = NULL;
break;
}
if (phi_node_lattice_val == UNDEFINED
&& phi_node_expr == NULL
&& current_parm_lattice_val == CONSTANT)
{
phi_node_expr = values[current_parm].const_value;
phi_node_lattice_val = CONSTANT;
continue;
}
}
}
if (phi_node_lattice_val != values[phi_node_name].lattice_val)
{
values[phi_node_name].lattice_val = phi_node_lattice_val;
values[phi_node_name].const_value = phi_node_expr;
SET_BIT (ssa_edges, phi_node_name);
}
}
static void
defs_to_undefined (insn)
rtx insn;
{
struct df_link *currdef;
for (currdef = DF_INSN_DEFS (df_analyzer, insn); currdef;
currdef = currdef->next)
{
if (values[DF_REF_REGNO (currdef->ref)].lattice_val != UNDEFINED)
SET_BIT (ssa_edges, DF_REF_REGNO (currdef->ref));
values[DF_REF_REGNO (currdef->ref)].lattice_val = UNDEFINED;
}
}
static void
defs_to_varying (insn)
rtx insn;
{
struct df_link *currdef;
for (currdef = DF_INSN_DEFS (df_analyzer, insn); currdef;
currdef = currdef->next)
{
if (values[DF_REF_REGNO (currdef->ref)].lattice_val != VARYING)
SET_BIT (ssa_edges, DF_REF_REGNO (currdef->ref));
values[DF_REF_REGNO (currdef->ref)].lattice_val = VARYING;
}
}
static void
visit_expression (insn, block)
rtx insn;
basic_block block;
{
rtx src, dest, set;
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_varying (insn);
return;
}
src = SET_SRC (set);
dest = SET_DEST (set);
if (GET_CODE (dest) != REG && dest != pc_rtx)
{
defs_to_varying (insn);
return;
}
if (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER)
{
defs_to_varying (insn);
return;
}
if (GET_CODE (src) == CONST_INT && GET_CODE (insn) == INSN)
{
unsigned int resultreg = REGNO (dest);
values[resultreg].lattice_val = CONSTANT;
values[resultreg].const_value = SET_SRC (PATTERN (insn));
SET_BIT (ssa_edges, resultreg);
}
else if (GET_CODE (src) == REG && GET_CODE (dest) == REG)
{
unsigned int old_value = REGNO (src);
latticevalue old_lattice_value = values[old_value].lattice_val;
unsigned int new_value = REGNO (dest);
if (values[new_value].lattice_val != old_lattice_value
|| values[new_value].const_value != values[old_value].const_value)
SET_BIT (ssa_edges, new_value);
values[new_value].lattice_val = old_lattice_value;
values[new_value].const_value = values[old_value].const_value;
}
else if (GET_CODE (insn) == JUMP_INSN)
{
rtx x = pc_set (insn);
if (GET_CODE (src) != IF_THEN_ELSE)
{
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;
}
}
else
{
edge curredge;
enum rtx_code comparison_code;
rtx comparison_src0;
rtx comparison_src1;
comparison_code = GET_CODE (XEXP (src, 0));
comparison_src0 = XEXP (XEXP (src, 0), 0);
comparison_src1 = XEXP (XEXP (src, 0), 1);
if ((GET_CODE (comparison_src0) == REG
&& values[REGNO (comparison_src0)].lattice_val == UNDEFINED)
|| (GET_CODE (comparison_src1) == REG
&& values[REGNO (comparison_src1)].lattice_val == UNDEFINED))
return;
if ((GET_CODE (comparison_src0) == REG
&& values[REGNO (comparison_src0)].lattice_val == VARYING)
|| (GET_CODE (comparison_src1) == REG
&& values[REGNO (comparison_src1)].lattice_val == VARYING))
{
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;
}
return;
}
if (GET_CODE (comparison_src0) == REG
&& values[REGNO (comparison_src0)].lattice_val == CONSTANT)
comparison_src0 = values[REGNO (comparison_src0)].const_value;
if (GET_CODE (comparison_src1) == REG
&& values[REGNO (comparison_src1)].lattice_val == CONSTANT)
comparison_src1 = values[REGNO (comparison_src1)].const_value;
x = simplify_ternary_operation (IF_THEN_ELSE,
VOIDmode,
GET_MODE (XEXP (src, 0)),
gen_rtx (comparison_code,
GET_MODE (XEXP (src, 0)),
comparison_src0,
comparison_src1),
XEXP (src, 1),
XEXP (src, 2));
for (curredge = block->succ; curredge;
curredge = curredge->succ_next)
{
int index = EIE (curredge->src, curredge->dest);
if (TEST_BIT (executable_edges, index))
continue;
if (!x
|| (x == pc_rtx
&& (curredge->flags & EDGE_FALLTHRU))
|| (GET_CODE (x) == LABEL_REF
&& ! (curredge->flags & EDGE_FALLTHRU)))
{
SET_BIT (executable_edges, index);
edge_info[index] = flow_edges;
flow_edges = curredge;
}
}
}
}
else if (!PHI_NODE_P (insn))
{
rtx simplified = NULL;
switch (GET_RTX_CLASS (GET_CODE (src)))
{
case '<':
{
rtx src0 = XEXP (src, 0);
rtx src1 = XEXP (src, 1);
enum machine_mode mode;
if ((GET_CODE (src0) == REG
&& values[REGNO (src0)].lattice_val == UNDEFINED)
|| (GET_CODE (src1) == REG
&& values[REGNO (src1)].lattice_val == UNDEFINED))
{
defs_to_undefined (insn);
break;
}
mode = GET_MODE (src0);
if (mode == VOIDmode)
mode = GET_MODE (src1);
if (GET_CODE (src0) == REG
&& values[REGNO (src0)].lattice_val == CONSTANT)
src0 = values[REGNO (src0)].const_value;
if (GET_CODE (src1) == REG
&& values[REGNO (src1)].lattice_val == CONSTANT)
src1 = values[REGNO (src1)].const_value;
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 (GET_CODE (src0) == REG
&& values[REGNO (src0)].lattice_val == UNDEFINED)
{
defs_to_undefined (insn);
break;
}
if (GET_CODE (src0) == REG
&& values[REGNO (src0)].lattice_val == CONSTANT)
src0 = values[REGNO (src0)].const_value;
simplified = simplify_unary_operation (GET_CODE (src),
GET_MODE (src),
src0,
mode0);
break;
}
case '2':
case 'c':
{
rtx src0 = XEXP (src, 0);
rtx src1 = XEXP (src, 1);
if ((GET_CODE (src0) == REG
&& values[REGNO (src0)].lattice_val == UNDEFINED)
|| (GET_CODE (src1) == REG
&& values[REGNO (src1)].lattice_val == UNDEFINED))
{
defs_to_undefined (insn);
break;
}
if (GET_CODE (src0) == REG
&& values[REGNO (src0)].lattice_val == CONSTANT)
src0 = values[REGNO (src0)].const_value;
if (GET_CODE (src1) == REG
&& values[REGNO (src1)].lattice_val == CONSTANT)
src1 = values[REGNO (src1)].const_value;
simplified = simplify_binary_operation (GET_CODE (src),
GET_MODE (src),
src0, src1);
break;
}
case '3':
case 'b':
{
rtx src0 = XEXP (src, 0);
rtx src1 = XEXP (src, 1);
rtx src2 = XEXP (src, 2);
if ((GET_CODE (src0) == REG
&& values[REGNO (src0)].lattice_val == UNDEFINED)
|| (GET_CODE (src1) == REG
&& values[REGNO (src1)].lattice_val == UNDEFINED)
|| (GET_CODE (src2) == REG
&& values[REGNO (src2)].lattice_val == UNDEFINED))
{
defs_to_undefined (insn);
break;
}
if (GET_CODE (src0) == REG
&& values[REGNO (src0)].lattice_val == CONSTANT)
src0 = values[REGNO (src0)].const_value;
if (GET_CODE (src1) == REG
&& values[REGNO (src1)].lattice_val == CONSTANT)
src1 = values[REGNO (src1)].const_value;
if (GET_CODE (src2) == REG
&& values[REGNO (src2)].lattice_val == CONSTANT)
src2 = values[REGNO (src2)].const_value;
simplified = simplify_ternary_operation (GET_CODE (src),
GET_MODE (src),
GET_MODE (src),
src0, src1, src2);
break;
}
default:
defs_to_varying (insn);
}
if (simplified && GET_CODE (simplified) == CONST_INT)
{
if (values[REGNO (dest)].lattice_val != CONSTANT
|| values[REGNO (dest)].const_value != simplified)
SET_BIT (ssa_edges, REGNO (dest));
values[REGNO (dest)].lattice_val = CONSTANT;
values[REGNO (dest)].const_value = simplified;
}
else
defs_to_varying (insn);
}
}
static void
examine_flow_edges ()
{
while (flow_edges != NULL)
{
basic_block succ_block;
rtx curr_phi_node;
succ_block = flow_edges->dest;
flow_edges = edge_info[EIE (flow_edges->src, flow_edges->dest)];
if (succ_block == EXIT_BLOCK_PTR)
continue;
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 (!TEST_BIT (executable_blocks, succ_block->index))
{
rtx currinsn;
edge succ_edge = succ_block->succ;
SET_BIT (executable_blocks, succ_block->index);
currinsn = succ_block->head;
while (currinsn != succ_block->end)
{
if (INSN_P (currinsn))
visit_expression (currinsn, succ_block);
currinsn = NEXT_INSN (currinsn);
}
if (INSN_P (currinsn))
visit_expression (currinsn, succ_block);
if (succ_edge != NULL
&& succ_edge->succ_next == NULL
&& !TEST_BIT (executable_edges,
EIE (succ_edge->src, succ_edge->dest)))
{
SET_BIT (executable_edges,
EIE (succ_edge->src, succ_edge->dest));
edge_info[EIE (succ_edge->src, succ_edge->dest)] = flow_edges;
flow_edges = succ_edge;
}
}
}
}
static void
follow_def_use_chains ()
{
while (sbitmap_first_set_bit (ssa_edges) >= 0)
{
int member;
struct df_link *curruse;
member = sbitmap_first_set_bit (ssa_edges);
RESET_BIT (ssa_edges, member);
for (curruse = df_analyzer->regs[member].uses; curruse;
curruse = curruse->next)
{
rtx useinsn;
useinsn = DF_REF_INSN (curruse->ref);
if (PHI_NODE_P (useinsn))
{
if (TEST_BIT (executable_blocks, BLOCK_NUM (useinsn)))
visit_phi_node (useinsn, BLOCK_FOR_INSN (useinsn));
}
else
{
if (TEST_BIT (executable_blocks, BLOCK_NUM (useinsn)))
visit_expression (useinsn, BLOCK_FOR_INSN (useinsn));
}
}
}
}
static void
optimize_unexecutable_edges (edges, executable_edges)
struct edge_list *edges;
sbitmap executable_edges;
{
int i;
basic_block bb;
for (i = 0; i < NUM_EDGES (edges); i++)
{
if (!TEST_BIT (executable_edges, i))
{
edge edge = INDEX_EDGE (edges, i);
if (edge->flags & EDGE_ABNORMAL)
continue;
if (edge->dest != EXIT_BLOCK_PTR)
{
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);
remove_edge (edge);
}
}
FOR_EACH_BB (bb)
{
rtx insn = bb->end;
edge edge = bb->succ;
if (bb->pred == NULL || GET_CODE (insn) != JUMP_INSN)
continue;
if (condjump_p (insn) && ! simplejump_p (insn)
&& bb->succ && bb->succ->succ_next == NULL)
{
if (edge->flags & EDGE_FALLTHRU)
{
PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
}
else
{
SET_SRC (PATTERN (insn)) = gen_rtx_LABEL_REF (Pmode,
JUMP_LABEL (insn));
emit_barrier_after (insn);
INSN_CODE (insn) = -1;
}
df_insn_modify (df_analyzer, BLOCK_FOR_INSN (insn), insn);
}
}
}
static void
ssa_ccp_substitute_constants ()
{
unsigned int i;
for (i = FIRST_PSEUDO_REGISTER; i < VARRAY_SIZE (ssa_definition); i++)
{
if (values[i].lattice_val == CONSTANT)
{
rtx def = VARRAY_RTX (ssa_definition, i);
rtx set = single_set (def);
struct df_link *curruse;
if (! set)
continue;
if (! PHI_NODE_P (def)
&& ! ((GET_CODE (def) == INSN
&& GET_CODE (SET_SRC (set)) == CONST_INT)))
{
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);
}
for (curruse = df_analyzer->regs[i].uses;
curruse;
curruse = curruse->next)
{
rtx useinsn;
useinsn = DF_REF_INSN (curruse->ref);
if (!INSN_DELETED_P (useinsn)
&& ! (GET_CODE (useinsn) == NOTE
&& NOTE_LINE_NUMBER (useinsn) == NOTE_INSN_DELETED)
&& (GET_CODE (useinsn) == INSN
|| GET_CODE (useinsn) == JUMP_INSN))
{
if (validate_replace_src (regno_reg_rtx [i],
values[i].const_value,
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);
}
}
}
}
}
}
static void
ssa_ccp_df_delete_unreachable_insns ()
{
basic_block b;
find_unreachable_blocks ();
FOR_EACH_BB_REVERSE (b)
{
if (!(b->flags & BB_REACHABLE))
{
rtx start = b->head;
rtx end = b->end;
rtx tmp;
end = b->end;
if (GET_CODE (end) == JUMP_INSN
&& (tmp = JUMP_LABEL (end)) != NULL_RTX
&& (tmp = NEXT_INSN (tmp)) != NULL_RTX
&& GET_CODE (tmp) == JUMP_INSN
&& (GET_CODE (PATTERN (tmp)) == ADDR_VEC
|| GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC))
end = tmp;
while (1)
{
rtx next = NEXT_INSN (start);
if (GET_CODE (start) == INSN
|| GET_CODE (start) == CALL_INSN
|| GET_CODE (start) == JUMP_INSN)
df_insn_delete (df_analyzer, BLOCK_FOR_INSN (start), start);
if (start == end)
break;
start = next;
}
}
}
}
void
ssa_const_prop ()
{
unsigned int i;
edge curredge;
init_alias_analysis ();
df_analyzer = df_init ();
df_analyse (df_analyzer, 0,
DF_RD_CHAIN | DF_RU_CHAIN | DF_REG_INFO | DF_HARD_REGS);
ssa_fast_dce (df_analyzer);
edges = create_edge_list ();
values = (value *) xmalloc (VARRAY_SIZE (ssa_definition) * sizeof (value));
for (i = 0; i < VARRAY_SIZE (ssa_definition); i++)
{
if (i < FIRST_PSEUDO_REGISTER)
values[i].lattice_val = VARYING;
else
values[i].lattice_val = UNDEFINED;
values[i].const_value = NULL;
}
ssa_edges = sbitmap_alloc (VARRAY_SIZE (ssa_definition));
sbitmap_zero (ssa_edges);
executable_blocks = sbitmap_alloc (last_basic_block);
sbitmap_zero (executable_blocks);
executable_edges = sbitmap_alloc (NUM_EDGES (edges));
sbitmap_zero (executable_edges);
edge_info = (edge *) xmalloc (NUM_EDGES (edges) * sizeof (edge));
flow_edges = ENTRY_BLOCK_PTR->succ;
for (curredge = ENTRY_BLOCK_PTR->succ; curredge;
curredge = curredge->succ_next)
{
int index = EIE (curredge->src, curredge->dest);
SET_BIT (executable_edges, index);
edge_info[index] = curredge->succ_next;
}
do
{
examine_flow_edges ();
follow_def_use_chains ();
}
while (flow_edges != NULL);
ssa_ccp_substitute_constants ();
optimize_unexecutable_edges (edges, executable_edges);
ssa_ccp_df_delete_unreachable_insns ();
#if 0
df_analyse (df_analyzer, 0,
DF_RD_CHAIN | DF_RU_CHAIN | DF_REG_INFO | DF_HARD_REGS);
#endif
ssa_fast_dce (df_analyzer);
free (values);
values = NULL;
free (edge_info);
edge_info = NULL;
sbitmap_free (executable_blocks);
executable_blocks = NULL;
sbitmap_free (ssa_edges);
ssa_edges = NULL;
free_edge_list (edges);
edges = NULL;
sbitmap_free (executable_edges);
executable_edges = NULL;
df_finish (df_analyzer);
end_alias_analysis ();
}
static int
mark_references (current_rtx, data)
rtx *current_rtx;
void *data;
{
rtx x = *current_rtx;
sbitmap worklist = (sbitmap) data;
if (x == NULL_RTX)
return 0;
if (GET_CODE (x) == SET)
{
rtx dest = SET_DEST (x);
if (GET_CODE (dest) == STRICT_LOW_PART
|| GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == ZERO_EXTRACT)
{
rtx reg;
reg = dest;
while (GET_CODE (reg) == STRICT_LOW_PART
|| GET_CODE (reg) == SUBREG
|| GET_CODE (reg) == SIGN_EXTRACT
|| GET_CODE (reg) == ZERO_EXTRACT)
reg = XEXP (reg, 0);
if (GET_CODE (reg) == REG)
SET_BIT (worklist, REGNO (reg));
}
if (GET_CODE (dest) == REG)
{
for_each_rtx (&SET_SRC (x), mark_references, data);
return -1;
}
return 0;
}
else if (GET_CODE (x) == REG)
{
SET_BIT (worklist, REGNO (x));
return -1;
}
else if (GET_CODE (x) == CLOBBER)
return -1;
else
return 0;
}
static void
ssa_fast_dce (df)
struct df *df;
{
sbitmap worklist = sbitmap_alloc (VARRAY_SIZE (ssa_definition));
sbitmap_ones (worklist);
while (sbitmap_first_set_bit (worklist) >= 0)
{
struct df_link *curruse;
int reg, found_use;
reg = sbitmap_first_set_bit (worklist);
RESET_BIT (worklist, reg);
if (reg < FIRST_PSEUDO_REGISTER
|| ! VARRAY_RTX (ssa_definition, reg)
|| INSN_DELETED_P (VARRAY_RTX (ssa_definition, reg))
|| (GET_CODE (VARRAY_RTX (ssa_definition, reg)) == NOTE
&& (NOTE_LINE_NUMBER (VARRAY_RTX (ssa_definition, reg))
== NOTE_INSN_DELETED))
|| side_effects_p (PATTERN (VARRAY_RTX (ssa_definition, reg))))
continue;
found_use = 0;
for (curruse = df->regs[reg].uses; curruse; curruse = curruse->next)
{
if (curruse->ref
&& DF_REF_INSN (curruse->ref)
&& ! INSN_DELETED_P (DF_REF_INSN (curruse->ref))
&& ! (GET_CODE (DF_REF_INSN (curruse->ref)) == NOTE
&& (NOTE_LINE_NUMBER (DF_REF_INSN (curruse->ref))
== NOTE_INSN_DELETED))
&& DF_REF_INSN (curruse->ref) != VARRAY_RTX (ssa_definition, reg))
{
found_use = 1;
break;
}
}
if (! found_use)
{
rtx def = VARRAY_RTX (ssa_definition, reg);
for_each_rtx (&PATTERN (def), mark_references, worklist);
df_insn_delete (df, BLOCK_FOR_INSN (def), def);
VARRAY_RTX (ssa_definition, reg) = NULL;
}
}
sbitmap_free (worklist);
df_analyse (df_analyzer, 0,
DF_RD_CHAIN | DF_RU_CHAIN | DF_REG_INFO | DF_HARD_REGS);
}