#include "system.h"
#include "coretypes.h"
#include "hash-table.h"
+#include "hash-map.h"
#include "tm.h"
#include "tree.h"
#include "trans-mem.h"
#include "stor-layout.h"
#include "print-tree.h"
#include "tm_p.h"
+#include "predict.h"
+#include "vec.h"
+#include "hashtab.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "hard-reg-set.h"
+#include "input.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfganal.h"
#include "basic-block.h"
#include "flags.h"
-#include "function.h"
#include "gimple-pretty-print.h"
-#include "pointer-set.h"
#include "tree-ssa-alias.h"
#include "internal-fn.h"
#include "gimple-fold.h"
#include "gimplify-me.h"
#include "gimple-walk.h"
#include "gimple-ssa.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
#include "cgraph.h"
#include "tree-cfg.h"
#include "tree-phinodes.h"
more persistent. The key is getting notification of changes to
the CFG (particularly edge removal, creation and redirection). */
-static struct pointer_map_t *edge_to_cases;
+static hash_map<edge, tree> *edge_to_cases;
/* If we record edge_to_cases, this bitmap will hold indexes
of basic blocks that end in a GIMPLE_SWITCH which we touched
return LOCATION_LINE (a->locus) == LOCATION_LINE (b->locus);
}
-static hash_table <locus_discrim_hasher> discriminator_per_locus;
+static hash_table<locus_discrim_hasher> *discriminator_per_locus;
/* Basic blocks and flowgraphs. */
static void make_blocks (gimple_seq);
static void gimple_make_forwarder_block (edge);
static gimple first_non_label_stmt (basic_block);
static bool verify_gimple_transaction (gimple);
+static bool call_can_make_abnormal_goto (gimple);
/* Flowgraph optimization and cleanup. */
static void gimple_merge_blocks (basic_block, basic_block);
group_case_labels ();
/* Create the edges of the flowgraph. */
- discriminator_per_locus.create (13);
+ discriminator_per_locus = new hash_table<locus_discrim_hasher> (13);
make_edges ();
assign_discriminators ();
cleanup_dead_labels ();
- discriminator_per_locus.dispose ();
+ delete discriminator_per_locus;
+ discriminator_per_locus = NULL;
}
+/* Look for ANNOTATE calls with loop annotation kind in BB; if found, remove
+ them and propagate the information to LOOP. We assume that the annotations
+ come immediately before the condition in BB, if any. */
+
+static void
+replace_loop_annotate_in_block (basic_block bb, struct loop *loop)
+{
+ gimple_stmt_iterator gsi = gsi_last_bb (bb);
+ gimple stmt = gsi_stmt (gsi);
+
+ if (!(stmt && gimple_code (stmt) == GIMPLE_COND))
+ return;
+
+ for (gsi_prev_nondebug (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
+ {
+ stmt = gsi_stmt (gsi);
+ if (gimple_code (stmt) != GIMPLE_CALL)
+ break;
+ if (!gimple_call_internal_p (stmt)
+ || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
+ break;
+
+ switch ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1)))
+ {
+ case annot_expr_ivdep_kind:
+ loop->safelen = INT_MAX;
+ break;
+ case annot_expr_no_vector_kind:
+ loop->dont_vectorize = true;
+ break;
+ case annot_expr_vector_kind:
+ loop->force_vectorize = true;
+ cfun->has_force_vectorize_loops = true;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ stmt = gimple_build_assign (gimple_call_lhs (stmt),
+ gimple_call_arg (stmt, 0));
+ gsi_replace (&gsi, stmt, true);
+ }
+}
/* Look for ANNOTATE calls with loop annotation kind; if found, remove
them and propagate the information to the loop. We assume that the
annotations come immediately before the condition of the loop. */
static void
-replace_loop_annotate ()
+replace_loop_annotate (void)
{
struct loop *loop;
basic_block bb;
FOR_EACH_LOOP (loop, 0)
{
- gsi = gsi_last_bb (loop->header);
- stmt = gsi_stmt (gsi);
- if (!(stmt && gimple_code (stmt) == GIMPLE_COND))
- continue;
- for (gsi_prev_nondebug (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
- {
- stmt = gsi_stmt (gsi);
- if (gimple_code (stmt) != GIMPLE_CALL)
- break;
- if (!gimple_call_internal_p (stmt)
- || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
- break;
- switch ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1)))
- {
- case annot_expr_ivdep_kind:
- loop->safelen = INT_MAX;
- break;
- case annot_expr_no_vector_kind:
- loop->dont_vectorize = true;
- break;
- case annot_expr_vector_kind:
- loop->force_vectorize = true;
- cfun->has_force_vectorize_loops = true;
- break;
- default:
- gcc_unreachable ();
- }
- stmt = gimple_build_assign (gimple_call_lhs (stmt),
- gimple_call_arg (stmt, 0));
- gsi_replace (&gsi, stmt, true);
- }
+ /* First look into the header. */
+ replace_loop_annotate_in_block (loop->header, loop);
+
+ /* Then look into the latch, if any. */
+ if (loop->latch)
+ replace_loop_annotate_in_block (loop->latch, loop);
}
/* Remove IFN_ANNOTATE. Safeguard for the case loop->latch == NULL. */
{
stmt = gsi_stmt (gsi);
if (gimple_code (stmt) != GIMPLE_CALL)
- break;
+ continue;
if (!gimple_call_internal_p (stmt)
|| gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
- break;
+ continue;
+
switch ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1)))
{
case annot_expr_ivdep_kind:
default:
gcc_unreachable ();
}
+
warning_at (gimple_location (stmt), 0, "ignoring loop annotation");
stmt = gimple_build_assign (gimple_call_lhs (stmt),
gimple_call_arg (stmt, 0));
GIMPLE_PASS, /* type */
"cfg", /* name */
OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_execute */
TV_TREE_CFG, /* tv_id */
PROP_gimple_leh, /* properties_required */
( PROP_cfg | PROP_loops ), /* properties_provided */
}
+/* Initialize GF_CALL_CTRL_ALTERING flag, which indicates the call
+ could alter control flow except via eh. We initialize the flag at
+ CFG build time and only ever clear it later. */
+
+static void
+gimple_call_initialize_ctrl_altering (gimple stmt)
+{
+ int flags = gimple_call_flags (stmt);
+
+ /* A call alters control flow if it can make an abnormal goto. */
+ if (call_can_make_abnormal_goto (stmt)
+ /* A call also alters control flow if it does not return. */
+ || flags & ECF_NORETURN
+ /* TM ending statements have backedges out of the transaction.
+ Return true so we split the basic block containing them.
+ Note that the TM_BUILTIN test is merely an optimization. */
+ || ((flags & ECF_TM_BUILTIN)
+ && is_tm_ending_fndecl (gimple_call_fndecl (stmt)))
+ /* BUILT_IN_RETURN call is same as return statement. */
+ || gimple_call_builtin_p (stmt, BUILT_IN_RETURN))
+ gimple_call_set_ctrl_altering (stmt, true);
+ else
+ gimple_call_set_ctrl_altering (stmt, false);
+}
+
+
/* Build a flowgraph for the sequence of stmts SEQ. */
static void
prev_stmt = stmt;
stmt = gsi_stmt (i);
+ if (stmt && is_gimple_call (stmt))
+ gimple_call_initialize_ctrl_altering (stmt);
+
/* If the statement starts a new basic block or if we have determined
in a previous pass that we need to create a new block for STMT, do
so now. */
fallthru = false;
break;
case GIMPLE_RETURN:
- make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
- fallthru = false;
+ {
+ edge e = make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
+ e->goto_locus = gimple_location (last);
+ fallthru = false;
+ }
break;
case GIMPLE_COND:
make_cond_expr_edges (bb);
item.locus = locus;
item.discriminator = 0;
- slot = discriminator_per_locus.find_slot_with_hash (
+ slot = discriminator_per_locus->find_slot_with_hash (
&item, LOCATION_LINE (locus), INSERT);
gcc_assert (slot);
if (*slot == HTAB_EMPTY_ENTRY)
SWITCH_EXPRs and structure sharing rules, then free the hash table
element. */
-static bool
-edge_to_cases_cleanup (const void *key ATTRIBUTE_UNUSED, void **value,
- void *data ATTRIBUTE_UNUSED)
+bool
+edge_to_cases_cleanup (edge const &, tree const &value, void *)
{
tree t, next;
- for (t = (tree) *value; t; t = next)
+ for (t = value; t; t = next)
{
next = CASE_CHAIN (t);
CASE_CHAIN (t) = NULL;
}
- *value = NULL;
return true;
}
start_recording_case_labels (void)
{
gcc_assert (edge_to_cases == NULL);
- edge_to_cases = pointer_map_create ();
+ edge_to_cases = new hash_map<edge, tree>;
touched_switch_bbs = BITMAP_ALLOC (NULL);
}
{
bitmap_iterator bi;
unsigned i;
- pointer_map_traverse (edge_to_cases, edge_to_cases_cleanup, NULL);
- pointer_map_destroy (edge_to_cases);
+ edge_to_cases->traverse<void *, edge_to_cases_cleanup> (NULL);
+ delete edge_to_cases;
edge_to_cases = NULL;
EXECUTE_IF_SET_IN_BITMAP (touched_switch_bbs, 0, i, bi)
{
static tree
get_cases_for_edge (edge e, gimple t)
{
- void **slot;
+ tree *slot;
size_t i, n;
/* If we are not recording cases, then we do not have CASE_LABEL_EXPR
if (!recording_case_labels_p ())
return NULL;
- slot = pointer_map_contains (edge_to_cases, e);
+ slot = edge_to_cases->get (e);
if (slot)
- return (tree) *slot;
+ return *slot;
/* If we did not find E in the hash table, then this must be the first
time we have been queried for information about E & T. Add all the
/* Add it to the chain of CASE_LABEL_EXPRs referencing E, or create
a new chain. */
- slot = pointer_map_insert (edge_to_cases, this_edge);
- CASE_CHAIN (elt) = (tree) *slot;
- *slot = elt;
+ tree &s = edge_to_cases->get_or_insert (this_edge);
+ CASE_CHAIN (elt) = s;
+ s = elt;
}
- return (tree) *pointer_map_contains (edge_to_cases, e);
+ return *edge_to_cases->get (e);
}
/* Create the edges for a GIMPLE_SWITCH starting at block BB. */
return false;
}
- /* Protect the loop latches. */
- if (current_loops && b->loop_father->latch == b)
+ /* Protect simple loop latches. We only want to avoid merging
+ the latch with the loop header in this case. */
+ if (current_loops
+ && b->loop_father->latch == b
+ && loops_state_satisfies_p (LOOPS_HAVE_SIMPLE_LATCHES)
+ && b->loop_father->header == a)
return false;
/* It must be possible to eliminate all phi nodes in B. If ssa form
switch (gimple_code (t))
{
case GIMPLE_CALL:
- {
- int flags = gimple_call_flags (t);
-
- /* A call alters control flow if it can make an abnormal goto. */
- if (call_can_make_abnormal_goto (t))
- return true;
-
- /* A call also alters control flow if it does not return. */
- if (flags & ECF_NORETURN)
- return true;
-
- /* TM ending statements have backedges out of the transaction.
- Return true so we split the basic block containing them.
- Note that the TM_BUILTIN test is merely an optimization. */
- if ((flags & ECF_TM_BUILTIN)
- && is_tm_ending_fndecl (gimple_call_fndecl (t)))
- return true;
-
- /* BUILT_IN_RETURN call is same as return statement. */
- if (gimple_call_builtin_p (t, BUILT_IN_RETURN))
- return true;
- }
+ /* Per stmt call flag indicates whether the call could alter
+ controlflow. */
+ if (gimple_call_ctrl_altering_p (t))
+ return true;
break;
case GIMPLE_EH_DISPATCH:
static void
reinstall_phi_args (edge new_edge, edge old_edge)
{
- edge_var_map_vector *v;
edge_var_map *vm;
int i;
gimple_stmt_iterator phis;
- v = redirect_edge_var_map_vector (old_edge);
+ vec<edge_var_map> *v = redirect_edge_var_map_vector (old_edge);
if (!v)
return;
return false;
}
-
- case VEC_UNPACK_HI_EXPR:
- case VEC_UNPACK_LO_EXPR:
case REDUC_MAX_EXPR:
case REDUC_MIN_EXPR:
case REDUC_PLUS_EXPR:
+ if (!VECTOR_TYPE_P (rhs1_type)
+ || !useless_type_conversion_p (lhs_type, TREE_TYPE (rhs1_type)))
+ {
+ error ("reduction should convert from vector to element type");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ return true;
+ }
+ return false;
+
+ case VEC_UNPACK_HI_EXPR:
+ case VEC_UNPACK_LO_EXPR:
case VEC_UNPACK_FLOAT_HI_EXPR:
case VEC_UNPACK_FLOAT_LO_EXPR:
/* FIXME. */
case ABS_EXPR:
case BIT_NOT_EXPR:
case PAREN_EXPR:
- case NON_LVALUE_EXPR:
case CONJ_EXPR:
break;
return false;
}
- case VEC_LSHIFT_EXPR:
- case VEC_RSHIFT_EXPR:
- {
- if (TREE_CODE (rhs1_type) != VECTOR_TYPE
- || !(INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
- || POINTER_TYPE_P (TREE_TYPE (rhs1_type))
- || FIXED_POINT_TYPE_P (TREE_TYPE (rhs1_type))
- || SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs1_type)))
- || (!INTEGRAL_TYPE_P (rhs2_type)
- && (TREE_CODE (rhs2_type) != VECTOR_TYPE
- || !INTEGRAL_TYPE_P (TREE_TYPE (rhs2_type))))
- || !useless_type_conversion_p (lhs_type, rhs1_type))
- {
- error ("type mismatch in vector shift expression");
- debug_generic_expr (lhs_type);
- debug_generic_expr (rhs1_type);
- debug_generic_expr (rhs2_type);
- return true;
- }
- /* For shifting a vector of non-integral components we
- only allow shifting by a constant multiple of the element size. */
- if (!INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
- && (TREE_CODE (rhs2) != INTEGER_CST
- || !div_if_zero_remainder (rhs2,
- TYPE_SIZE (TREE_TYPE (rhs1_type)))))
- {
- error ("non-element sized vector shift of floating point vector");
- return true;
- }
-
- return false;
- }
-
case WIDEN_LSHIFT_EXPR:
{
if (!INTEGRAL_TYPE_P (lhs_type)
return false;
+ case SAD_EXPR:
+ if (!useless_type_conversion_p (rhs1_type, rhs2_type)
+ || !useless_type_conversion_p (lhs_type, rhs3_type)
+ || 2 * GET_MODE_BITSIZE (GET_MODE_INNER
+ (TYPE_MODE (TREE_TYPE (rhs1_type))))
+ > GET_MODE_BITSIZE (GET_MODE_INNER
+ (TYPE_MODE (TREE_TYPE (lhs_type)))))
+ {
+ error ("type mismatch in sad expression");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ debug_generic_expr (rhs2_type);
+ debug_generic_expr (rhs3_type);
+ return true;
+ }
+
+ if (TREE_CODE (rhs1_type) != VECTOR_TYPE
+ || TREE_CODE (rhs2_type) != VECTOR_TYPE
+ || TREE_CODE (rhs3_type) != VECTOR_TYPE)
+ {
+ error ("vector types expected in sad expression");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ debug_generic_expr (rhs2_type);
+ debug_generic_expr (rhs3_type);
+ return true;
+ }
+
+ return false;
+
case DOT_PROD_EXPR:
case REALIGN_LOAD_EXPR:
/* FIXME. */
debug_generic_stmt (rhs1);
return true;
}
+ if (!is_gimple_val (elt_v))
+ {
+ error ("vector CONSTRUCTOR element is not a GIMPLE value");
+ debug_generic_stmt (rhs1);
+ return true;
+ }
}
}
+ else if (CONSTRUCTOR_NELTS (rhs1) != 0)
+ {
+ error ("non-vector CONSTRUCTOR with elements");
+ debug_generic_stmt (rhs1);
+ return true;
+ }
return res;
case OBJ_TYPE_REF:
case ASSERT_EXPR:
static tree
verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
{
- struct pointer_set_t *visited = (struct pointer_set_t *) data;
+ hash_set<void *> *visited = (hash_set<void *> *) data;
if (tree_node_can_be_shared (*tp))
{
return NULL;
}
- if (pointer_set_insert (visited, *tp))
+ if (visited->add (*tp))
return *tp;
return NULL;
}
static bool eh_error_found;
-static int
-verify_eh_throw_stmt_node (void **slot, void *data)
+bool
+verify_eh_throw_stmt_node (const gimple &stmt, const int &,
+ hash_set<gimple> *visited)
{
- struct throw_stmt_node *node = (struct throw_stmt_node *)*slot;
- struct pointer_set_t *visited = (struct pointer_set_t *) data;
-
- if (!pointer_set_contains (visited, node->stmt))
+ if (!visited->contains (stmt))
{
error ("dead STMT in EH table");
- debug_gimple_stmt (node->stmt);
+ debug_gimple_stmt (stmt);
eh_error_found = true;
}
- return 1;
+ return true;
}
/* Verify if the location LOCs block is in BLOCKS. */
static bool
-verify_location (pointer_set_t *blocks, location_t loc)
+verify_location (hash_set<tree> *blocks, location_t loc)
{
tree block = LOCATION_BLOCK (loc);
if (block != NULL_TREE
- && !pointer_set_contains (blocks, block))
+ && !blocks->contains (block))
{
error ("location references block not in block tree");
return true;
static tree
verify_expr_location_1 (tree *tp, int *walk_subtrees, void *data)
{
- struct pointer_set_t *blocks = (struct pointer_set_t *) data;
+ hash_set<tree> *blocks = (hash_set<tree> *) data;
if (TREE_CODE (*tp) == VAR_DECL
&& DECL_HAS_DEBUG_EXPR_P (*tp))
/* Insert all subblocks of BLOCK into BLOCKS and recurse. */
static void
-collect_subblocks (pointer_set_t *blocks, tree block)
+collect_subblocks (hash_set<tree> *blocks, tree block)
{
tree t;
for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
{
- pointer_set_insert (blocks, t);
+ blocks->add (t);
collect_subblocks (blocks, t);
}
}
{
basic_block bb;
bool err = false;
- struct pointer_set_t *visited, *visited_stmts, *blocks;
timevar_push (TV_TREE_STMT_VERIFY);
- visited = pointer_set_create ();
- visited_stmts = pointer_set_create ();
+ hash_set<void *> visited;
+ hash_set<gimple> visited_stmts;
/* Collect all BLOCKs referenced by the BLOCK tree of FN. */
- blocks = pointer_set_create ();
+ hash_set<tree> blocks;
if (DECL_INITIAL (fn->decl))
{
- pointer_set_insert (blocks, DECL_INITIAL (fn->decl));
- collect_subblocks (blocks, DECL_INITIAL (fn->decl));
+ blocks.add (DECL_INITIAL (fn->decl));
+ collect_subblocks (&blocks, DECL_INITIAL (fn->decl));
}
FOR_EACH_BB_FN (bb, fn)
bool err2 = false;
unsigned i;
- pointer_set_insert (visited_stmts, phi);
+ visited_stmts.add (phi);
if (gimple_bb (phi) != bb)
{
{
tree arg = gimple_phi_arg_def (phi, i);
tree addr = walk_tree (&arg, verify_node_sharing_1,
- visited, NULL);
+ &visited, NULL);
if (addr)
{
error ("incorrect sharing of tree nodes");
error ("virtual PHI with argument locations");
err2 = true;
}
- addr = walk_tree (&arg, verify_expr_location_1, blocks, NULL);
+ addr = walk_tree (&arg, verify_expr_location_1, &blocks, NULL);
if (addr)
{
debug_generic_expr (addr);
err2 = true;
}
- err2 |= verify_location (blocks, loc);
+ err2 |= verify_location (&blocks, loc);
}
if (err2)
tree addr;
int lp_nr;
- pointer_set_insert (visited_stmts, stmt);
+ visited_stmts.add (stmt);
if (gimple_bb (stmt) != bb)
{
}
err2 |= verify_gimple_stmt (stmt);
- err2 |= verify_location (blocks, gimple_location (stmt));
+ err2 |= verify_location (&blocks, gimple_location (stmt));
memset (&wi, 0, sizeof (wi));
- wi.info = (void *) visited;
+ wi.info = (void *) &visited;
addr = walk_gimple_op (stmt, verify_node_sharing, &wi);
if (addr)
{
}
memset (&wi, 0, sizeof (wi));
- wi.info = (void *) blocks;
+ wi.info = (void *) &blocks;
addr = walk_gimple_op (stmt, verify_expr_location, &wi);
if (addr)
{
}
eh_error_found = false;
- if (get_eh_throw_stmt_table (cfun))
- htab_traverse (get_eh_throw_stmt_table (cfun),
- verify_eh_throw_stmt_node,
- visited_stmts);
+ hash_map<gimple, int> *eh_table = get_eh_throw_stmt_table (cfun);
+ if (eh_table)
+ eh_table->traverse<hash_set<gimple> *, verify_eh_throw_stmt_node>
+ (&visited_stmts);
if (err || eh_error_found)
internal_error ("verify_gimple failed");
- pointer_set_destroy (visited);
- pointer_set_destroy (visited_stmts);
- pointer_set_destroy (blocks);
verify_histograms ();
timevar_pop (TV_TREE_STMT_VERIFY);
}
The duplicates are recorded in VARS_MAP. */
static void
-replace_by_duplicate_decl (tree *tp, struct pointer_map_t *vars_map,
+replace_by_duplicate_decl (tree *tp, hash_map<tree, tree> *vars_map,
tree to_context)
{
tree t = *tp, new_t;
struct function *f = DECL_STRUCT_FUNCTION (to_context);
- void **loc;
if (DECL_CONTEXT (t) == to_context)
return;
- loc = pointer_map_contains (vars_map, t);
+ bool existed;
+ tree &loc = vars_map->get_or_insert (t, &existed);
- if (!loc)
+ if (!existed)
{
- loc = pointer_map_insert (vars_map, t);
-
if (SSA_VAR_P (t))
{
new_t = copy_var_decl (t, DECL_NAME (t), TREE_TYPE (t));
}
DECL_CONTEXT (new_t) = to_context;
- *loc = new_t;
+ loc = new_t;
}
else
- new_t = (tree) *loc;
+ new_t = loc;
*tp = new_t;
}
VARS_MAP maps old ssa names and var_decls to the new ones. */
static tree
-replace_ssa_name (tree name, struct pointer_map_t *vars_map,
+replace_ssa_name (tree name, hash_map<tree, tree> *vars_map,
tree to_context)
{
- void **loc;
tree new_name;
gcc_assert (!virtual_operand_p (name));
- loc = pointer_map_contains (vars_map, name);
+ tree *loc = vars_map->get (name);
if (!loc)
{
new_name = copy_ssa_name_fn (DECL_STRUCT_FUNCTION (to_context),
name, SSA_NAME_DEF_STMT (name));
- loc = pointer_map_insert (vars_map, name);
- *loc = new_name;
+ vars_map->put (name, new_name);
}
else
- new_name = (tree) *loc;
+ new_name = *loc;
return new_name;
}
tree new_block;
tree from_context;
tree to_context;
- struct pointer_map_t *vars_map;
+ hash_map<tree, tree> *vars_map;
htab_t new_label_map;
- struct pointer_map_t *eh_map;
+ hash_map<void *, void *> *eh_map;
bool remap_decls_p;
};
move_stmt_eh_region_nr (int old_nr, struct move_stmt_d *p)
{
eh_region old_r, new_r;
- void **slot;
old_r = get_eh_region_from_number (old_nr);
- slot = pointer_map_contains (p->eh_map, old_r);
- new_r = (eh_region) *slot;
+ new_r = static_cast<eh_region> (*p->eh_map->get (old_r));
return new_r->index;
}
subblocks. */
static void
-replace_block_vars_by_duplicates (tree block, struct pointer_map_t *vars_map,
+replace_block_vars_by_duplicates (tree block, hash_map<tree, tree> *vars_map,
tree to_context)
{
tree *tp, t;
edge e;
edge_iterator ei;
htab_t new_label_map;
- struct pointer_map_t *vars_map, *eh_map;
+ hash_map<void *, void *> *eh_map;
struct loop *loop = entry_bb->loop_father;
struct loop *loop0 = get_loop (saved_cfun, 0);
struct move_stmt_d d;
if (loops_for_fn (saved_cfun)->exits)
FOR_EACH_EDGE (e, ei, bb->succs)
{
- void **slot = htab_find_slot_with_hash
- (loops_for_fn (saved_cfun)->exits, e,
- htab_hash_pointer (e), NO_INSERT);
+ struct loops *l = loops_for_fn (saved_cfun);
+ loop_exit **slot
+ = l->exits->find_slot_with_hash (e, htab_hash_pointer (e),
+ NO_INSERT);
if (slot)
- htab_clear_slot (loops_for_fn (saved_cfun)->exits, slot);
+ l->exits->clear_slot (slot);
}
}
/* Move blocks from BBS into DEST_CFUN. */
gcc_assert (bbs.length () >= 2);
after = dest_cfun->cfg->x_entry_block_ptr;
- vars_map = pointer_map_create ();
+ hash_map<tree, tree> vars_map;
memset (&d, 0, sizeof (d));
d.orig_block = orig_block;
d.new_block = DECL_INITIAL (dest_cfun->decl);
d.from_context = cfun->decl;
d.to_context = dest_cfun->decl;
- d.vars_map = vars_map;
+ d.vars_map = &vars_map;
d.new_label_map = new_label_map;
d.eh_map = eh_map;
d.remap_decls_p = true;
}
replace_block_vars_by_duplicates (DECL_INITIAL (dest_cfun->decl),
- vars_map, dest_cfun->decl);
+ &vars_map, dest_cfun->decl);
if (new_label_map)
htab_delete (new_label_map);
if (eh_map)
- pointer_map_destroy (eh_map);
- pointer_map_destroy (vars_map);
+ delete eh_map;
/* Rewire the entry and exit blocks. The successor to the entry
block turns into the successor of DEST_FN's ENTRY_BLOCK_PTR in
GIMPLE_PASS, /* type */
"crited", /* name */
OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_execute */
TV_TREE_SPLIT_EDGES, /* tv_id */
PROP_cfg, /* properties_required */
PROP_no_crit_edges, /* properties_provided */
}
+/* Insert COND expression which is GIMPLE_COND after STMT
+ in basic block BB with appropriate basic block split
+ and creation of a new conditionally executed basic block.
+ Return created basic block. */
+basic_block
+insert_cond_bb (basic_block bb, gimple stmt, gimple cond)
+{
+ edge fall = split_block (bb, stmt);
+ gimple_stmt_iterator iter = gsi_last_bb (bb);
+ basic_block new_bb;
+
+ /* Insert cond statement. */
+ gcc_assert (gimple_code (cond) == GIMPLE_COND);
+ if (gsi_end_p (iter))
+ gsi_insert_before (&iter, cond, GSI_CONTINUE_LINKING);
+ else
+ gsi_insert_after (&iter, cond, GSI_CONTINUE_LINKING);
+
+ /* Create conditionally executed block. */
+ new_bb = create_empty_bb (bb);
+ make_edge (bb, new_bb, EDGE_TRUE_VALUE);
+ make_single_succ_edge (new_bb, fall->dest, EDGE_FALLTHRU);
+
+ /* Fix edge for split bb. */
+ fall->flags = EDGE_FALSE_VALUE;
+
+ /* Update dominance info. */
+ if (dom_info_available_p (CDI_DOMINATORS))
+ {
+ set_immediate_dominator (CDI_DOMINATORS, new_bb, bb);
+ set_immediate_dominator (CDI_DOMINATORS, fall->dest, bb);
+ }
+
+ /* Update loop info. */
+ if (current_loops)
+ add_bb_to_loop (new_bb, bb->loop_father);
+
+ return new_bb;
+}
+
/* Build a ternary operation and gimplify it. Emit code before GSI.
Return the gimple_val holding the result. */
GIMPLE_PASS, /* type */
"*warn_function_return", /* name */
OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_execute */
TV_NONE, /* tv_id */
PROP_cfg, /* properties_required */
0, /* properties_provided */
GIMPLE_PASS, /* type */
"*warn_unused_result", /* name */
OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_execute */
TV_NONE, /* tv_id */
PROP_gimple_any, /* properties_required */
0, /* properties_provided */
edge_iterator ei;
count_scale
- = GCOV_COMPUTE_SCALE (cgraph_get_node (current_function_decl)->count,
+ = GCOV_COMPUTE_SCALE (cgraph_node::get (current_function_decl)->count,
ENTRY_BLOCK_PTR_FOR_FN (cfun)->count);
ENTRY_BLOCK_PTR_FOR_FN (cfun)->count =
- cgraph_get_node (current_function_decl)->count;
+ cgraph_node::get (current_function_decl)->count;
EXIT_BLOCK_PTR_FOR_FN (cfun)->count =
apply_scale (EXIT_BLOCK_PTR_FOR_FN (cfun)->count,
count_scale);
if (TREE_CODE (lhs) == VAR_DECL
&& (TREE_STATIC (lhs) || DECL_EXTERNAL (lhs))
- && varpool_get_node (lhs)->writeonly)
+ && varpool_node::get (lhs)->writeonly)
{
unlink_stmt_vdef (stmt);
gsi_remove (&gsi, true);
if (TREE_CODE (lhs) == VAR_DECL
&& (TREE_STATIC (lhs) || DECL_EXTERNAL (lhs))
- && varpool_get_node (lhs)->writeonly)
+ && varpool_node::get (lhs)->writeonly)
{
gimple_call_set_lhs (stmt, NULL);
update_stmt (stmt);
&& (!is_gimple_call (stmt)
|| (gimple_call_flags (stmt) & ECF_NORETURN) == 0)))
{
+ if (stmt && is_gimple_call (stmt))
+ gimple_call_set_ctrl_altering (stmt, false);
stmt = gimple_build_call
(builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0);
gimple_stmt_iterator gsi = gsi_last_bb (bb);
if (count_scale != REG_BR_PROB_BASE)
compute_function_frequency ();
- /* We just processed all calls. */
- if (cfun->gimple_df)
- vec_free (MODIFIED_NORETURN_CALLS (cfun));
-
/* Dump a textual representation of the flowgraph. */
if (dump_file)
gimple_dump_cfg (dump_file, dump_flags);
GIMPLE_PASS, /* type */
"*free_cfg_annotations", /* name */
OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_execute */
TV_NONE, /* tv_id */
PROP_cfg, /* properties_required */
0, /* properties_provided */
extern void gt_ggc_mx (rtx&);
extern void gt_ggc_mx (basic_block&);
+static void
+gt_ggc_mx (rtx_insn *& x)
+{
+ if (x)
+ gt_ggc_mx_rtx_def ((void *) x);
+}
+
void
gt_ggc_mx (edge_def *e)
{
extern void gt_pch_nx (rtx&);
extern void gt_pch_nx (basic_block&);
+static void
+gt_pch_nx (rtx_insn *& x)
+{
+ if (x)
+ gt_pch_nx_rtx_def ((void *) x);
+}
+
void
gt_pch_nx (edge_def *e)
{