#include "tree-pass.h"
#include "tree-ssa-propagate.h"
#include "langhooks.h"
+#include "params.h"
/* This file implements optimizations on the dominator tree. */
block_stmt_iterator bsi;
tree stmt = NULL;
tree phi;
+ int stmt_count = 0;
+ int max_stmt_count;
+
/* If E->dest does not end with a conditional, then there is
nothing to do. */
tree src = PHI_ARG_DEF_FROM_EDGE (phi, e);
tree dst = PHI_RESULT (phi);
+ /* Do not include virtual PHIs in our statement count as
+ they never generate code. */
+ if (is_gimple_reg (dst))
+ stmt_count++;
+
/* If the desired argument is not the same as this PHI's result
and it is set by a PHI in E->dest, then we can not thread
through E->dest. */
Failure to simplify into the form above merely means that the
statement provides no equivalences to help simplify later
statements. This does not prevent threading through E->dest. */
+ max_stmt_count = PARAM_VALUE (PARAM_MAX_JUMP_THREAD_DUPLICATION_STMTS);
for (bsi = bsi_start (e->dest); ! bsi_end_p (bsi); bsi_next (&bsi))
{
tree cached_lhs = NULL;
if (IS_EMPTY_STMT (stmt) || TREE_CODE (stmt) == LABEL_EXPR)
continue;
+ /* If duplicating this block is going to cause too much code
+ expansion, then do not thread through this block. */
+ stmt_count++;
+ if (stmt_count > max_stmt_count)
+ return;
+
/* Safely handle threading across loop backedges. This is
over conservative, but still allows us to capture the
majority of the cases where we can thread across a loop
{
tree last;
- /* If we are at a leaf node in the dominator tree, see if we can thread
- the edge from BB through its successor.
-
- Do this before we remove entries from our equivalence tables. */
+ /* If we have an outgoing edge to a block with multiple incoming and
+ outgoing edges, then we may be able to thread the edge. ie, we
+ may be able to statically determine which of the outgoing edges
+ will be traversed when the incoming edge from BB is traversed. */
if (single_succ_p (bb)
&& (single_succ_edge (bb)->flags & EDGE_ABNORMAL) == 0
- && (get_immediate_dominator (CDI_DOMINATORS, single_succ (bb)) != bb
- || phi_nodes (single_succ (bb))))
+ && !single_pred_p (single_succ (bb))
+ && !single_succ_p (single_succ (bb)))
{
thread_across_edge (walk_data, single_succ_edge (bb));
extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
- /* If the THEN arm is the end of a dominator tree or has PHI nodes,
- then try to thread through its edge. */
- if (get_immediate_dominator (CDI_DOMINATORS, true_edge->dest) != bb
- || phi_nodes (true_edge->dest))
+ /* Only try to thread the edge if it reaches a target block with
+ more than one predecessor and more than one successor. */
+ if (!single_pred_p (true_edge->dest) && !single_succ_p (true_edge->dest))
{
struct edge_info *edge_info;
unsigned int i;
}
/* Similarly for the ELSE arm. */
- if (get_immediate_dominator (CDI_DOMINATORS, false_edge->dest) != bb
- || phi_nodes (false_edge->dest))
+ if (!single_pred_p (false_edge->dest) && !single_succ_p (false_edge->dest))
{
struct edge_info *edge_info;
unsigned int i;
assignment. Add minus to this, as we handle it specially below. */
if ((associative_tree_code (rhs_code) || rhs_code == MINUS_EXPR)
&& TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
+ && num_imm_uses (TREE_OPERAND (rhs, 0)) == 1
&& is_gimple_min_invariant (TREE_OPERAND (rhs, 1)))
{
tree rhs_def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 0));
record ranges for enumerations. Presumably this is due to
the fact that they're rarely used directly. They are typically
cast into an integer type and used that way. */
- if (TREE_CODE (type) != INTEGER_TYPE
- /* We don't know how to deal with types with variable bounds. */
- || TREE_CODE (TYPE_MIN_VALUE (type)) != INTEGER_CST
- || TREE_CODE (TYPE_MAX_VALUE (type)) != INTEGER_CST)
+ if (TREE_CODE (type) != INTEGER_TYPE)
return 0;
switch (TREE_CODE (cond))
case GE_EXPR:
low = op1;
+
+ /* Get the highest value of the type. If not a constant, use that
+ of its base type, if it has one. */
high = TYPE_MAX_VALUE (type);
+ if (TREE_CODE (high) != INTEGER_CST && TREE_TYPE (type))
+ high = TYPE_MAX_VALUE (TREE_TYPE (type));
inverted = 0;
break;
case GT_EXPR:
high = TYPE_MAX_VALUE (type);
+ if (TREE_CODE (high) != INTEGER_CST && TREE_TYPE (type))
+ high = TYPE_MAX_VALUE (TREE_TYPE (type));
if (!tree_int_cst_lt (op1, high))
return 0;
low = int_const_binop (PLUS_EXPR, op1, integer_one_node, 1);
case LE_EXPR:
high = op1;
low = TYPE_MIN_VALUE (type);
+ if (TREE_CODE (low) != INTEGER_CST && TREE_TYPE (type))
+ low = TYPE_MIN_VALUE (TREE_TYPE (type));
inverted = 0;
break;
case LT_EXPR:
low = TYPE_MIN_VALUE (type);
+ if (TREE_CODE (low) != INTEGER_CST && TREE_TYPE (type))
+ low = TYPE_MIN_VALUE (TREE_TYPE (type));
if (!tree_int_cst_lt (low, op1))
return 0;
high = int_const_binop (MINUS_EXPR, op1, integer_one_node, 1);