for gcc/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
PR debug/48866
* cfgexpand.c (def_expansions): New.
(def_expansion_recent_tree, def_expansion_recent_rtx): New.
(def_expansions_init, def_expansions_fini): New.
(def_has_expansion_ptr, def_get_expansion_ptr): New.
(expand_debug_expr): Use recorded expansion if available.
(expand_gimple_basic_block): Prepare to record expansion of
replaceable defs. Change return type to void.
(gimple_expand_cfg): Initialize and finalize expansions cache.
Expand dominator blocks before dominated.
* expr.c (expand_expr_real_1): Use recorded expansion of
replaceable defs.
* expr.h (def_has_expansion_ptr): Declare.
===================================================================
@@ -2337,6 +2337,55 @@ convert_debug_memory_address (enum machi
return x;
}
+/* Map replaceable SSA_NAMEs to their RTL expansions. */
+static struct pointer_map_t *def_expansions;
+
+/* Initialize the def_expansions data structure. This is to be called
+ before expansion of a function starts. */
+
+static void
+def_expansions_init (void)
+{
+ gcc_checking_assert (!def_expansions);
+ def_expansions = pointer_map_create ();
+}
+
+/* Finalize the def_expansions data structure. This is to be called
+ at the end of the expansion of a function. */
+
+static void
+def_expansions_fini (void)
+{
+ gcc_checking_assert (def_expansions);
+ pointer_map_destroy (def_expansions);
+ def_expansions = NULL;
+}
+
+/* Return NULL if no expansion is registered for EXP, or a pointer to
+ the rtx expanded from it otherwise. EXP must be a replaceable
+ SSA_NAME. */
+
+void *const *
+def_has_expansion_ptr (tree exp)
+{
+ gcc_checking_assert (def_expansions);
+ gcc_checking_assert (TREE_CODE (exp) == SSA_NAME);
+ gcc_checking_assert (bitmap_bit_p (SA.values, SSA_NAME_VERSION (exp)));
+ return pointer_map_contains (def_expansions, exp);
+}
+
+/* Return a pointer to the rtx expanded from EXP. EXP must be a
+ replaceable SSA_NAME. */
+
+static void **
+def_get_expansion_ptr (tree exp)
+{
+ gcc_checking_assert (def_expansions);
+ gcc_checking_assert (TREE_CODE (exp) == SSA_NAME);
+ gcc_checking_assert (bitmap_bit_p (SA.values, SSA_NAME_VERSION (exp)));
+ return pointer_map_insert (def_expansions, exp);
+}
+
/* Return an RTX equivalent to the value of the tree expression
EXP. */
@@ -3131,7 +3180,16 @@ expand_debug_expr (tree exp)
gimple g = get_gimple_for_ssa_name (exp);
if (g)
{
- op0 = expand_debug_expr (gimple_assign_rhs_to_tree (g));
+ void *const *xp = def_has_expansion_ptr (exp);
+
+ if (xp)
+ op0 = (rtx) *xp;
+ else
+ op0 = NULL;
+
+ if (!op0)
+ op0 = expand_debug_expr (gimple_assign_rhs_to_tree (g));
+
if (!op0)
return NULL;
}
@@ -3346,7 +3404,7 @@ expand_debug_locations (void)
/* Expand basic block BB from GIMPLE trees to RTL. */
-static basic_block
+static void
expand_gimple_basic_block (basic_block bb)
{
gimple_stmt_iterator gsi;
@@ -3539,7 +3597,7 @@ expand_gimple_basic_block (basic_block b
{
new_bb = expand_gimple_cond (bb, stmt);
if (new_bb)
- return new_bb;
+ return;
}
else if (gimple_debug_bind_p (stmt))
{
@@ -3613,25 +3671,43 @@ expand_gimple_basic_block (basic_block b
if (can_fallthru)
bb = new_bb;
else
- return new_bb;
+ return;
}
}
else
{
+ void **xp = NULL;
def_operand_p def_p;
def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF);
- if (def_p != NULL)
+ /* Ignore this stmt if it is in the list of
+ replaceable expressions. */
+ if (def_p != NULL
+ && SA.values
+ && bitmap_bit_p (SA.values,
+ SSA_NAME_VERSION (DEF_FROM_PTR (def_p))))
{
- /* Ignore this stmt if it is in the list of
- replaceable expressions. */
- if (SA.values
- && bitmap_bit_p (SA.values,
- SSA_NAME_VERSION (DEF_FROM_PTR (def_p))))
- continue;
+ tree def = DEF_FROM_PTR (def_p);
+ gimple g = get_gimple_for_ssa_name (def);
+ rtx retval;
+
+ last = get_last_insn ();
+
+ retval = expand_expr (gimple_assign_rhs_to_tree (g),
+ NULL_RTX, VOIDmode, EXPAND_SUM);
+
+ xp = def_get_expansion_ptr (def);
+ gcc_checking_assert (!*xp);
+ *xp = retval;
}
- last = expand_gimple_stmt (stmt);
+ else
+ last = expand_gimple_stmt (stmt);
maybe_dump_rtl_for_gimple_stmt (stmt, last);
+ if (xp && dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "\n=> ");
+ print_rtl (dump_file, (rtx) *xp);
+ }
}
}
}
@@ -3680,10 +3756,9 @@ expand_gimple_basic_block (basic_block b
update_bb_for_insn (bb);
- return bb;
+ return;
}
-
/* Create a basic block for initialization code. */
static basic_block
@@ -3969,6 +4044,9 @@ gimple_expand_cfg (void)
edge e;
rtx var_seq;
unsigned i;
+ VEC (basic_block, heap) *h;
+ int nblocks;
+
timevar_push (TV_OUT_OF_SSA);
rewrite_out_of_ssa (&SA);
@@ -4112,11 +4190,41 @@ gimple_expand_cfg (void)
e->flags &= ~EDGE_EXECUTABLE;
lab_rtx_for_bb = pointer_map_create ();
+ def_expansions_init ();
+
+ /* Expand dominators before dominated blocks, so that replaceable
+ DEFs are always expanded before their uses. */
+ nblocks = last_basic_block;
+ blocks = sbitmap_alloc (nblocks);
+ sbitmap_zero (blocks);
+
+ h = get_all_dominated_blocks (CDI_DOMINATORS, init_block->next_bb);
+
+ FOR_EACH_VEC_ELT (basic_block, h, i, bb)
+ {
+ gcc_checking_assert (bb->index < nblocks);
+ SET_BIT (blocks, bb->index);
+
+ start_sequence ();
+ emit_note (NOTE_INSN_DELETED);
+ expand_gimple_basic_block (bb);
+ end_sequence ();
+ }
+
+ VEC_free (basic_block, heap, h);
+
FOR_BB_BETWEEN (bb, init_block->next_bb, EXIT_BLOCK_PTR, next_bb)
- bb = expand_gimple_basic_block (bb);
+ if (bb->index >= nblocks)
+ continue;
+ else if (TEST_BIT (blocks, bb->index))
+ emit_insn (BB_HEAD (bb));
+ else
+ expand_gimple_basic_block (bb);
+ sbitmap_free (blocks);
if (MAY_HAVE_DEBUG_INSNS)
expand_debug_locations ();
+ def_expansions_fini ();
execute_free_datastructures ();
timevar_push (TV_OUT_OF_SSA);
===================================================================
@@ -8424,10 +8424,21 @@ expand_expr_real_1 (tree exp, rtx target
&& !SSA_NAME_IS_DEFAULT_DEF (exp)
&& (optimize || DECL_IGNORED_P (SSA_NAME_VAR (exp)))
&& stmt_is_replaceable_p (SSA_NAME_DEF_STMT (exp)))
- g = SSA_NAME_DEF_STMT (exp);
+ {
+ g = SSA_NAME_DEF_STMT (exp);
+ if (g)
+ return expand_expr_real (gimple_assign_rhs_to_tree (g),
+ target, tmode, modifier, NULL);
+ }
if (g)
- return expand_expr_real (gimple_assign_rhs_to_tree (g), target, tmode,
- modifier, NULL);
+ {
+ void *const *xp = def_has_expansion_ptr (exp);
+ rtx retval = (rtx) *xp;
+
+ gcc_assert (retval);
+
+ return retval;
+ }
ssa_name = exp;
decl_rtl = get_rtx_for_ssa_name (ssa_name);
===================================================================
@@ -693,4 +693,7 @@ extern tree build_libfunc_function (cons
/* Get the personality libfunc for a function decl. */
rtx get_personality_function (tree);
+/* In cfgexpand.c. */
+void *const *def_has_expansion_ptr (tree);
+
#endif /* GCC_EXPR_H */