@@ -1,5 +1,71 @@
2014-10-24 David Malcolm <dmalcolm@redhat.com>
+ Introduce gimple_cond and use it in various places
+
+ * coretypes.h (gimple_cond): New typedef.
+ (const_gimple_cond): Likewise.
+
+ * gimple.h (struct gimple_statement_cond): New subclass of
+ gimple_statement_with_ops, adding the invariant that
+ stmt->code == GIMPLE_COND.
+ (is_a_helper <gimple_statement_cond>::test): New.
+ (gimple_build_cond): Return a gimple_cond, rather than just
+ a gimple.
+ (gimple_build_cond_from_tree): Likewise.
+
+ * gdbhooks.py (build_pretty_printer): Add gimple_cond and its
+ variants, using the gimple printer.
+
+ * cfgexpand.c (expand_gimple_cond): Require a gimple_cond rather
+ than just a gimple.
+ * gimple.h (gimple_cond_set_condition_from_tree): Likewise.
+ (gimple_cond_true_p): Likewise.
+ (gimple_cond_false_p): Likewise.
+ (gimple_cond_set_condition): Likewise.
+ * gimple.c (gimple_cond_set_condition_from_tree): Likewise.
+ * gimple-fold.c (fold_gimple_cond): Likewise.
+ * gimple-pretty-print.c (dump_gimple_cond): Likewise.
+ * tree-ssa-dom.c (canonicalize_comparison): Likewise.
+ * tree-ssa-forwprop.c (forward_propagate_into_gimple_cond): Likewise.
+ * tree-ssa-ifcombine.c (recognize_single_bit_test): Likewise.
+ (recognize_bits_test): Likewise.
+ * tree-ssa-threadedge.c (simplify_control_stmt_condition): Likewise.
+ (thread_around_empty_blocks): Likewise.
+ (thread_through_normal_block): Likewise.
+ (thread_across_edge): Likewise.
+ * tree-ssa-threadedge.h (thread_across_edge): Likewise.
+ * tree-vrp.c (range_fits_type_p): Likewise.
+
+ * cfgexpand.c (expand_gimple_basic_block): Add checked cast to
+ gimple_cond in regions where a stmt is known to have code GIMPLE_COND.
+ * gimple-fold.c (fold_stmt_1): Likewise.
+ * gimple-pretty-print.c (pp_gimple_stmt_1): Likewise.
+ * tree-ssa-dom.c (optimize_stmt): Likewise.
+ * tree-ssa-forwprop.c (ssa_forward_propagate_and_combine): Likewise.
+ * tree-ssa-loop-unswitch.c (tree_unswitch_single_loop): Likewise.
+ * tree-ssa-pre.c (eliminate_dom_walker::before_dom_children):
+ Likewise.
+ * tree-vrp.c (simplify_stmt_using_ranges): Likewise.
+
+ * cfgloopmanip.c (create_empty_loop_on_edge): Update local to be a
+ gimple_cond.
+ * tree-vrp.c (identify_jump_threads): Likewise.
+
+ * gimple.c (gimple_build_cond): Return a gimple_cond, rather than
+ just a gimple.
+ (gimple_build_cond_from_tree): Likewise.
+
+ * tree-ssa-dom.c (class dom_opt_dom_walker): Strengthen type of
+ field "m_dummy_cond" from a plain gimple to a gimple_cond.
+
+ * tree-ssa-ifcombine.c (ifcombine_ifandif): Introduce locals
+ inner_stmt and outer_stmt so that inner_cond and outer_cond can be
+ of type gimple_cond once we know that we have code == GIMPLE_COND.
+ * tree-ssa-loop-unswitch.c (tree_may_unswitch_on): Introduce local
+ "last" so that stmt can be of type gimple_cond.
+
+2014-10-24 David Malcolm <dmalcolm@redhat.com>
+
Introduce gimple_bind and use it for accessors.
* coretypes.h (gimple_bind): New typedef.
@@ -2070,7 +2070,7 @@ maybe_cleanup_end_of_block (edge e, rtx_insn *last)
block and created a new one. */
static basic_block
-expand_gimple_cond (basic_block bb, gimple stmt)
+expand_gimple_cond (basic_block bb, gimple_cond stmt)
{
basic_block new_bb, dest;
edge new_edge;
@@ -5071,7 +5071,7 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
fixup the CFG accordingly. */
if (gimple_code (stmt) == GIMPLE_COND)
{
- new_bb = expand_gimple_cond (bb, stmt);
+ new_bb = expand_gimple_cond (bb, as_a <gimple_cond> (stmt));
if (new_bb)
return new_bb;
}
@@ -776,7 +776,7 @@ create_empty_loop_on_edge (edge entry_edge,
struct loop *loop;
gimple_stmt_iterator gsi;
gimple_seq stmts;
- gimple cond_expr;
+ gimple_cond cond_expr;
tree exit_test;
edge exit_e;
int prob;
@@ -90,6 +90,10 @@ struct gimple_stmt_iterator;
/* Typedefs for leaf gimple subclasses (for individual gimple codes).
Keep this in the same order as the corresponding codes in gimple.def. */
+struct gimple_statement_cond;
+typedef struct gimple_statement_cond *gimple_cond;
+typedef const struct gimple_statement_cond *const_gimple_cond;
+
struct gimple_statement_switch;
typedef struct gimple_statement_switch *gimple_switch;
typedef const struct gimple_statement_switch *const_gimple_switch;
@@ -458,6 +458,8 @@ def build_pretty_printer():
pp.add_printer_for_types(['gimple', 'gimple_statement_base *',
# Keep this in the same order as gimple.def:
+ 'gimple_cond', 'const_gimple_cond',
+ 'gimple_statement_cond *',
'gimple_switch', 'const_gimple_switch',
'gimple_statement_switch *',
'gimple_bind', 'const_gimple_bind',
@@ -547,7 +547,7 @@ fold_gimple_assign (gimple_stmt_iterator *si)
assumed that the operands have been previously folded. */
static bool
-fold_gimple_cond (gimple stmt)
+fold_gimple_cond (gimple_cond stmt)
{
tree result = fold_binary_loc (gimple_location (stmt),
gimple_cond_code (stmt),
@@ -2925,7 +2925,7 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace)
}
case GIMPLE_COND:
- changed |= fold_gimple_cond (stmt);
+ changed |= fold_gimple_cond (as_a <gimple_cond> (stmt));
break;
case GIMPLE_CALL:
@@ -819,7 +819,7 @@ dump_gimple_switch (pretty_printer *buffer, gimple_switch gs, int spc,
pp_gimple_stmt_1. */
static void
-dump_gimple_cond (pretty_printer *buffer, gimple gs, int spc, int flags)
+dump_gimple_cond (pretty_printer *buffer, gimple_cond gs, int spc, int flags)
{
if (flags & TDF_RAW)
dump_gimple_fmt (buffer, spc, flags, "%G <%s, %T, %T, %T, %T>", gs,
@@ -2101,7 +2101,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple gs, int spc, int flags)
break;
case GIMPLE_COND:
- dump_gimple_cond (buffer, gs, spc, flags);
+ dump_gimple_cond (buffer, as_a <gimple_cond> (gs), spc, flags);
break;
case GIMPLE_LABEL:
@@ -438,14 +438,14 @@ gimple_build_assign_with_ops (enum tree_code subcode, tree lhs, tree op1,
T_LABEL is the label to jump to if the condition is true.
F_LABEL is the label to jump to otherwise. */
-gimple
+gimple_cond
gimple_build_cond (enum tree_code pred_code, tree lhs, tree rhs,
tree t_label, tree f_label)
{
- gimple p;
+ gimple_cond p;
gcc_assert (TREE_CODE_CLASS (pred_code) == tcc_comparison);
- p = gimple_build_with_ops (GIMPLE_COND, pred_code, 4);
+ p = as_a <gimple_cond> (gimple_build_with_ops (GIMPLE_COND, pred_code, 4));
gimple_cond_set_lhs (p, lhs);
gimple_cond_set_rhs (p, rhs);
gimple_cond_set_true_label (p, t_label);
@@ -456,7 +456,7 @@ gimple_build_cond (enum tree_code pred_code, tree lhs, tree rhs,
/* Build a GIMPLE_COND statement from the conditional expression tree
COND. T_LABEL and F_LABEL are as in gimple_build_cond. */
-gimple
+gimple_cond
gimple_build_cond_from_tree (tree cond, tree t_label, tree f_label)
{
enum tree_code code;
@@ -470,7 +470,7 @@ gimple_build_cond_from_tree (tree cond, tree t_label, tree f_label)
boolean expression tree COND. */
void
-gimple_cond_set_condition_from_tree (gimple stmt, tree cond)
+gimple_cond_set_condition_from_tree (gimple_cond stmt, tree cond)
{
enum tree_code code;
tree lhs, rhs;
@@ -770,6 +770,16 @@ enum gimple_statement_structure_enum {
#undef DEFGSSTRUCT
/* A statement with the invariant that
+ stmt->code == GIMPLE_COND
+ i.e. a conditional jump statement. */
+
+struct GTY((tag("GSS_WITH_OPS")))
+ gimple_statement_cond : public gimple_statement_with_ops
+{
+ /* no additional fields; this uses the layout for GSS_WITH_OPS. */
+};
+
+/* A statement with the invariant that
stmt->code == GIMPLE_SWITCH
i.e. a switch statement. */
@@ -814,6 +824,14 @@ is_a_helper <gimple_statement_catch *>::test (gimple gs)
template <>
template <>
inline bool
+is_a_helper <gimple_statement_cond *>::test (gimple gs)
+{
+ return gs->code == GIMPLE_COND;
+}
+
+template <>
+template <>
+inline bool
is_a_helper <gimple_statement_resx *>::test (gimple gs)
{
return gs->code == GIMPLE_RESX;
@@ -1198,9 +1216,9 @@ gimple gimple_build_assign_with_ops (enum tree_code, tree,
tree, tree, tree CXX_MEM_STAT_INFO);
gimple gimple_build_assign_with_ops (enum tree_code, tree,
tree, tree CXX_MEM_STAT_INFO);
-gimple gimple_build_cond (enum tree_code, tree, tree, tree, tree);
-gimple gimple_build_cond_from_tree (tree, tree, tree);
-void gimple_cond_set_condition_from_tree (gimple, tree);
+gimple_cond gimple_build_cond (enum tree_code, tree, tree, tree, tree);
+gimple_cond gimple_build_cond_from_tree (tree, tree, tree);
+void gimple_cond_set_condition_from_tree (gimple_cond, tree);
gimple gimple_build_label (tree label);
gimple gimple_build_goto (tree dest);
gimple gimple_build_nop (void);
@@ -3041,7 +3059,7 @@ gimple_cond_make_true (gimple gs)
'if (0 == 0)', 'if (1 != 0)' or 'if (0 != 1)' */
static inline bool
-gimple_cond_true_p (const_gimple gs)
+gimple_cond_true_p (const_gimple_cond gs)
{
tree lhs = gimple_cond_lhs (gs);
tree rhs = gimple_cond_rhs (gs);
@@ -3066,7 +3084,7 @@ gimple_cond_true_p (const_gimple gs)
'if (0 != 0)', 'if (1 == 0)' or 'if (0 == 1)' */
static inline bool
-gimple_cond_false_p (const_gimple gs)
+gimple_cond_false_p (const_gimple_cond gs)
{
tree lhs = gimple_cond_lhs (gs);
tree rhs = gimple_cond_rhs (gs);
@@ -3090,7 +3108,8 @@ gimple_cond_false_p (const_gimple gs)
/* Set the code, LHS and RHS of GIMPLE_COND STMT from CODE, LHS and RHS. */
static inline void
-gimple_cond_set_condition (gimple stmt, enum tree_code code, tree lhs, tree rhs)
+gimple_cond_set_condition (gimple_cond stmt, enum tree_code code, tree lhs,
+ tree rhs)
{
gimple_cond_set_code (stmt, code);
gimple_cond_set_lhs (stmt, lhs);
@@ -831,7 +831,7 @@ public:
private:
void thread_across_edge (edge);
- gimple m_dummy_cond;
+ gimple_cond m_dummy_cond;
};
/* Jump threading, redundancy elimination and const/copy propagation.
@@ -1003,7 +1003,7 @@ make_pass_dominator (gcc::context *ctxt)
condition to a canonical form. */
static void
-canonicalize_comparison (gimple condstmt)
+canonicalize_comparison (gimple_cond condstmt)
{
tree op0;
tree op1;
@@ -2326,7 +2326,7 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si)
}
if (gimple_code (stmt) == GIMPLE_COND)
- canonicalize_comparison (stmt);
+ canonicalize_comparison (as_a <gimple_cond> (stmt));
update_stmt_if_modified (stmt);
opt_stats.num_stmts++;
@@ -503,7 +503,7 @@ forward_propagate_into_comparison (gimple_stmt_iterator *gsi)
This must be kept in sync with forward_propagate_into_cond. */
static int
-forward_propagate_into_gimple_cond (gimple stmt)
+forward_propagate_into_gimple_cond (gimple_cond stmt)
{
tree tmp;
enum tree_code code = gimple_cond_code (stmt);
@@ -3836,7 +3836,8 @@ pass_forwprop::execute (function *fun)
case GIMPLE_COND:
{
int did_something;
- did_something = forward_propagate_into_gimple_cond (stmt);
+ did_something =
+ forward_propagate_into_gimple_cond (as_a <gimple_cond> (stmt));
if (did_something == 2)
cfg_changed = true;
changed = did_something != 0;
@@ -202,7 +202,7 @@ get_name_for_bit_test (tree candidate)
Returns true if the pattern matched, false otherwise. */
static bool
-recognize_single_bit_test (gimple cond, tree *name, tree *bit, bool inv)
+recognize_single_bit_test (gimple_cond cond, tree *name, tree *bit, bool inv)
{
gimple stmt;
@@ -311,7 +311,7 @@ recognize_single_bit_test (gimple cond, tree *name, tree *bit, bool inv)
Returns true if the pattern matched, false otherwise. */
static bool
-recognize_bits_test (gimple cond, tree *name, tree *bits, bool inv)
+recognize_bits_test (gimple_cond cond, tree *name, tree *bits, bool inv)
{
gimple stmt;
@@ -342,18 +342,21 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
basic_block outer_cond_bb, bool outer_inv, bool result_inv)
{
gimple_stmt_iterator gsi;
- gimple inner_cond, outer_cond;
+ gimple inner_stmt, outer_stmt;
+ gimple_cond inner_cond, outer_cond;
tree name1, name2, bit1, bit2, bits1, bits2;
- inner_cond = last_stmt (inner_cond_bb);
- if (!inner_cond
- || gimple_code (inner_cond) != GIMPLE_COND)
+ inner_stmt = last_stmt (inner_cond_bb);
+ if (!inner_stmt
+ || gimple_code (inner_stmt) != GIMPLE_COND)
return false;
+ inner_cond = as_a <gimple_cond> (inner_stmt);
- outer_cond = last_stmt (outer_cond_bb);
- if (!outer_cond
- || gimple_code (outer_cond) != GIMPLE_COND)
+ outer_stmt = last_stmt (outer_cond_bb);
+ if (!outer_stmt
+ || gimple_code (outer_stmt) != GIMPLE_COND)
return false;
+ outer_cond = as_a <gimple_cond> (outer_stmt);
/* See if we test a single bit of the same name in both tests. In
that case remove the outer test, merging both else edges,
@@ -138,15 +138,17 @@ tree_ssa_unswitch_loops (void)
static tree
tree_may_unswitch_on (basic_block bb, struct loop *loop)
{
- gimple stmt, def;
+ gimple last, def;
+ gimple_cond stmt;
tree cond, use;
basic_block def_bb;
ssa_op_iter iter;
/* BB must end in a simple conditional jump. */
- stmt = last_stmt (bb);
- if (!stmt || gimple_code (stmt) != GIMPLE_COND)
+ last = last_stmt (bb);
+ if (!last || gimple_code (last) != GIMPLE_COND)
return NULL_TREE;
+ stmt = as_a <gimple_cond> (last);
/* To keep the things simple, we do not directly remove the conditions,
but just replace tests with 0 != 0 resp. 1 != 0. Prevent the infinite
@@ -248,13 +250,15 @@ tree_unswitch_single_loop (struct loop *loop, int num)
if (integer_nonzerop (cond))
{
/* Remove false path. */
- gimple_cond_set_condition_from_tree (stmt, boolean_true_node);
+ gimple_cond_set_condition_from_tree (as_a <gimple_cond> (stmt),
+ boolean_true_node);
changed = true;
}
else if (integer_zerop (cond))
{
/* Remove true path. */
- gimple_cond_set_condition_from_tree (stmt, boolean_false_node);
+ gimple_cond_set_condition_from_tree (as_a <gimple_cond> (stmt),
+ boolean_false_node);
changed = true;
}
/* Do not unswitch too much. */
@@ -316,9 +320,10 @@ tree_unswitch_single_loop (struct loop *loop, int num)
if (stmt
&& gimple_code (stmt) == GIMPLE_COND)
{
- if (gimple_cond_true_p (stmt))
+ gimple_cond cond_stmt = as_a <gimple_cond> (stmt);
+ if (gimple_cond_true_p (cond_stmt))
flags = EDGE_FALSE_VALUE;
- else if (gimple_cond_false_p (stmt))
+ else if (gimple_cond_false_p (cond_stmt))
flags = EDGE_TRUE_VALUE;
}
}
@@ -4365,8 +4365,8 @@ eliminate_dom_walker::before_dom_children (basic_block b)
fold_stmt (&gsi);
stmt = gsi_stmt (gsi);
if ((gimple_code (stmt) == GIMPLE_COND
- && (gimple_cond_true_p (stmt)
- || gimple_cond_false_p (stmt)))
+ && (gimple_cond_true_p (as_a <gimple_cond> (stmt))
+ || gimple_cond_false_p (as_a <gimple_cond> (stmt))))
|| (gimple_code (stmt) == GIMPLE_SWITCH
&& TREE_CODE (gimple_switch_index (stmt)) == INTEGER_CST))
el_todo |= TODO_cleanup_cfg;
@@ -521,7 +521,7 @@ dummy_simplify (gimple stmt1 ATTRIBUTE_UNUSED, gimple stmt2 ATTRIBUTE_UNUSED)
static tree
simplify_control_stmt_condition (edge e,
gimple stmt,
- gimple dummy_cond,
+ gimple_cond dummy_cond,
tree (*simplify) (gimple, gimple),
bool handle_dominating_asserts)
{
@@ -802,7 +802,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
try and simplify the condition at the end of TAKEN_EDGE->dest. */
static bool
thread_around_empty_blocks (edge taken_edge,
- gimple dummy_cond,
+ gimple_cond dummy_cond,
bool handle_dominating_asserts,
tree (*simplify) (gimple, gimple),
bitmap visited,
@@ -950,7 +950,7 @@ thread_around_empty_blocks (edge taken_edge,
static int
thread_through_normal_block (edge e,
- gimple dummy_cond,
+ gimple_cond dummy_cond,
bool handle_dominating_asserts,
vec<tree> *stack,
tree (*simplify) (gimple, gimple),
@@ -1078,7 +1078,7 @@ thread_through_normal_block (edge e,
SIMPLIFY is a pass-specific function used to simplify statements. */
void
-thread_across_edge (gimple dummy_cond,
+thread_across_edge (gimple_cond dummy_cond,
edge e,
bool handle_dominating_asserts,
vec<tree> *stack,
@@ -30,7 +30,7 @@ extern void threadedge_initialize_values (void);
extern void threadedge_finalize_values (void);
extern bool potentially_threadable_block (basic_block);
extern void propagate_threaded_block_debug_into (basic_block, basic_block);
-extern void thread_across_edge (gimple, edge, bool,
+extern void thread_across_edge (gimple_cond, edge, bool,
vec<tree> *, tree (*) (gimple, gimple));
#endif /* GCC_TREE_SSA_THREADEDGE_H */
@@ -9073,7 +9073,7 @@ range_fits_type_p (value_range_t *vr, unsigned dest_precision, signop dest_sgn)
the original conditional. */
static bool
-simplify_cond_using_ranges (gimple stmt)
+simplify_cond_using_ranges (gimple_cond stmt)
{
tree op0 = gimple_cond_lhs (stmt);
tree op1 = gimple_cond_rhs (stmt);
@@ -9613,7 +9613,7 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
}
}
else if (gimple_code (stmt) == GIMPLE_COND)
- return simplify_cond_using_ranges (stmt);
+ return simplify_cond_using_ranges (as_a <gimple_cond> (stmt));
else if (gimple_code (stmt) == GIMPLE_SWITCH)
return simplify_switch_using_ranges (as_a <gimple_switch> (stmt));
else if (is_gimple_call (stmt)
@@ -9757,7 +9757,7 @@ static void
identify_jump_threads (void)
{
basic_block bb;
- gimple dummy;
+ gimple_cond dummy;
int i;
edge e;