if (!single_succ_p (a))
return false;
- if (single_succ_edge (a)->flags & EDGE_ABNORMAL)
+ if (single_succ_edge (a)->flags & (EDGE_ABNORMAL | EDGE_EH))
return false;
if (single_succ (a) != b)
remove_useless_stmts_1 (&gsi, &data);
}
while (data.repeat);
+
+#ifdef ENABLE_TYPES_CHECKING
+ verify_types_in_gimple_seq (gimple_body (current_function_decl));
+#endif
+
return 0;
}
return false;
}
-/* Verify if EXPR is a valid GIMPLE reference expression. Returns true
+/* Verify if EXPR is a valid GIMPLE reference expression. If
+ REQUIRE_LVALUE is true verifies it is an lvalue. Returns true
if there is an error, otherwise false. */
static bool
-verify_types_in_gimple_reference (tree expr)
+verify_types_in_gimple_reference (tree expr, bool require_lvalue)
{
while (handled_component_p (expr))
{
expr = op;
}
- return verify_types_in_gimple_min_lval (expr);
+ return ((require_lvalue || !is_gimple_min_invariant (expr))
+ && verify_types_in_gimple_min_lval (expr));
}
/* Returns true if there is one pointer type in TYPE_POINTER_TO (SRC_OBJ)
{
if (TREE_CODE (rhs1_type) != VECTOR_TYPE
|| !(INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
- || FIXED_POINT_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))))
debug_generic_expr (rhs2_type);
return true;
}
+ /* For shifting a vector of floating point components we
+ only allow shifting by a constant multiple of the element size. */
+ if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs1_type))
+ && (TREE_CODE (rhs2) != INTEGER_CST
+ || !div_if_zero_remainder (EXACT_DIV_EXPR, rhs2,
+ TYPE_SIZE (TREE_TYPE (rhs1_type)))))
+ {
+ error ("non-element sized vector shift of floating point vector");
+ return true;
+ }
return false;
}
}
if (handled_component_p (lhs))
- res |= verify_types_in_gimple_reference (lhs);
+ res |= verify_types_in_gimple_reference (lhs, true);
/* Special codes we cannot handle via their class. */
switch (rhs_code)
return true;
}
- return verify_types_in_gimple_reference (op);
+ return verify_types_in_gimple_reference (op, true);
}
/* tcc_reference */
debug_generic_stmt (rhs1);
return true;
}
- return res || verify_types_in_gimple_reference (rhs1);
+ return res || verify_types_in_gimple_reference (rhs1, false);
/* tcc_constant */
case SSA_NAME:
to match. */
if (lookup_stmt_eh_region (stmt) >= 0)
{
- if (!stmt_could_throw_p (stmt))
+ /* During IPA passes, ipa-pure-const sets nothrow flags on calls
+ and they are updated on statements only after fixup_cfg
+ is executed at beggining of expansion stage. */
+ if (!stmt_could_throw_p (stmt) && cgraph_state != CGRAPH_STATE_IPA_SSA)
{
error ("statement marked for throw, but doesn%'t");
goto fail;
err |= true;
}
}
+
+#ifdef ENABLE_TYPES_CHECKING
+ if (verify_gimple_phi (phi))
+ {
+ debug_gimple_stmt (phi);
+ err |= true;
+ }
+#endif
}
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
}
err |= verify_stmt (&gsi);
+
+#ifdef ENABLE_TYPES_CHECKING
+ if (verify_types_in_gimple_stmt (gsi_stmt (gsi)))
+ {
+ debug_gimple_stmt (stmt);
+ err |= true;
+ }
+#endif
addr = walk_gimple_op (gsi_stmt (gsi), verify_node_sharing, &wi);
if (addr)
{
if (e->dest == dest)
return NULL;
+ if (e->flags & EDGE_EH)
+ return redirect_eh_edge (e, dest);
+
gsi = gsi_last_bb (bb);
stmt = gsi_end_p (gsi) ? NULL : gsi_stmt (gsi);
static bool
gimple_can_remove_branch_p (const_edge e)
{
- if (e->flags & EDGE_ABNORMAL)
+ if (e->flags & (EDGE_ABNORMAL | EDGE_EH))
return false;
return true;
return changed;
}
-/* Stores all basic blocks dominated by BB to DOM_BBS. */
-
-static void
-get_all_dominated_blocks (basic_block bb, VEC (basic_block, heap) **dom_bbs)
-{
- basic_block son;
-
- VEC_safe_push (basic_block, heap, *dom_bbs, bb);
- for (son = first_dom_son (CDI_DOMINATORS, bb);
- son;
- son = next_dom_son (CDI_DOMINATORS, son))
- get_all_dominated_blocks (son, dom_bbs);
-}
-
/* Removes edge E and all the blocks dominated by it, and updates dominance
information. The IL in E->src needs to be updated separately.
If dominance info is not available, only the edge E is removed.*/
get_immediate_dominator (CDI_DOMINATORS, e->dest)->index);
else
{
- get_all_dominated_blocks (e->dest, &bbs_to_remove);
+ bbs_to_remove = get_all_dominated_blocks (CDI_DOMINATORS, e->dest);
for (i = 0; VEC_iterate (basic_block, bbs_to_remove, i, bb); i++)
{
FOR_EACH_EDGE (f, ei, bb->succs)
FOR_ALL_BB (bb)
{
FOR_EACH_EDGE (e, ei, bb->succs)
- if (EDGE_CRITICAL_P (e) && !(e->flags & EDGE_ABNORMAL))
- {
+ {
+ if (EDGE_CRITICAL_P (e) && !(e->flags & EDGE_ABNORMAL))
split_edge (e);
- }
+ /* PRE inserts statements to edges and expects that
+ since split_critical_edges was done beforehand, committing edge
+ insertions will not split more edges. In addition to critical
+ edges we must split edges that have multiple successors and
+ end by control flow statements, such as RESX.
+ Go ahead and split them too. This matches the logic in
+ gimple_find_edge_insert_loc. */
+ else if ((!single_pred_p (e->dest)
+ || phi_nodes (e->dest)
+ || e->dest == EXIT_BLOCK_PTR)
+ && e->src != ENTRY_BLOCK_PTR
+ && !(e->flags & EDGE_ABNORMAL))
+ {
+ gimple_stmt_iterator gsi;
+
+ gsi = gsi_last_bb (e->src);
+ if (!gsi_end_p (gsi)
+ && stmt_ends_bb_p (gsi_stmt (gsi))
+ && gimple_code (gsi_stmt (gsi)) != GIMPLE_RETURN)
+ split_edge (e);
+ }
+ }
}
end_recording_case_labels ();
return 0;