/* Structure for recording known values of a conditional expression
at the exits from its block. */
-struct cond_equivalence
+typedef struct cond_equivalence_s
{
struct hashable_expr cond;
tree value;
-};
+} cond_equivalence;
+
+DEF_VEC_O(cond_equivalence);
+DEF_VEC_ALLOC_O(cond_equivalence,heap);
/* Structure for recording edge equivalences as well as any pending
edge redirections during the dominator optimizer.
tree rhs;
/* Traversing an edge may also indicate one or more particular conditions
- are true or false. The number of recorded conditions can vary, but
- can be determined by the condition's code. So we have an array
- and its maximum index rather than use a varray. */
- struct cond_equivalence *cond_equivalences;
- unsigned int max_cond_equivalences;
+ are true or false. */
+ VEC(cond_equivalence, heap) *cond_equivalences;
};
/* Hash table with expressions made available during the renaming process.
static hashval_t real_avail_expr_hash (const void *);
static int avail_expr_eq (const void *, const void *);
static void htab_statistics (FILE *, htab_t);
-static void record_cond (struct cond_equivalence *);
+static void record_cond (cond_equivalence *);
static void record_const_or_copy (tree, tree);
static void record_equality (tree, tree);
static void record_equivalences_from_phis (basic_block);
if (edge_info)
{
if (edge_info->cond_equivalences)
- free (edge_info->cond_equivalences);
+ VEC_free (cond_equivalence, heap, edge_info->cond_equivalences);
free (edge_info);
e->aux = NULL;
}
{
tree lhs = edge_info->lhs;
tree rhs = edge_info->rhs;
- struct cond_equivalence *cond_equivalences = edge_info->cond_equivalences;
+ cond_equivalence *eq;
if (lhs)
record_equality (lhs, rhs);
- if (cond_equivalences)
- for (i = 0; i < edge_info->max_cond_equivalences; i++)
- record_cond (&cond_equivalences[i]);
+ for (i = 0; VEC_iterate (cond_equivalence,
+ edge_info->cond_equivalences, i, eq); ++i)
+ record_cond (eq);
}
}
}
boolean value. */
static void
-record_cond (struct cond_equivalence *p)
+record_cond (cond_equivalence *p)
{
struct expr_hash_elt *element = XCNEW (struct expr_hash_elt);
void **slot;
}
/* Build a cond_equivalence record indicating that the comparison
- CODE holds between operands OP0 and OP1. */
+ CODE holds between operands OP0 and OP1 and push it to **P. */
static void
build_and_record_new_cond (enum tree_code code,
tree op0, tree op1,
- struct cond_equivalence *p)
+ VEC(cond_equivalence, heap) **p)
{
- struct hashable_expr *cond = &p->cond;
+ cond_equivalence c;
+ struct hashable_expr *cond = &c.cond;
gcc_assert (TREE_CODE_CLASS (code) == tcc_comparison);
cond->ops.binary.opnd0 = op0;
cond->ops.binary.opnd1 = op1;
- p->value = boolean_true_node;
+ c.value = boolean_true_node;
+ VEC_safe_push (cond_equivalence, heap, *p, &c);
}
/* Record that COND is true and INVERTED is false into the edge information
record_conditions (struct edge_info *edge_info, tree cond, tree inverted)
{
tree op0, op1;
+ cond_equivalence c;
if (!COMPARISON_CLASS_P (cond))
return;
case GT_EXPR:
if (FLOAT_TYPE_P (TREE_TYPE (op0)))
{
- edge_info->max_cond_equivalences = 6;
- edge_info->cond_equivalences = XNEWVEC (struct cond_equivalence, 6);
build_and_record_new_cond (ORDERED_EXPR, op0, op1,
- &edge_info->cond_equivalences[4]);
+ &edge_info->cond_equivalences);
build_and_record_new_cond (LTGT_EXPR, op0, op1,
- &edge_info->cond_equivalences[5]);
- }
- else
- {
- edge_info->max_cond_equivalences = 4;
- edge_info->cond_equivalences = XNEWVEC (struct cond_equivalence, 4);
+ &edge_info->cond_equivalences);
}
build_and_record_new_cond ((TREE_CODE (cond) == LT_EXPR
? LE_EXPR : GE_EXPR),
- op0, op1, &edge_info->cond_equivalences[2]);
+ op0, op1, &edge_info->cond_equivalences);
build_and_record_new_cond (NE_EXPR, op0, op1,
- &edge_info->cond_equivalences[3]);
+ &edge_info->cond_equivalences);
break;
case GE_EXPR:
case LE_EXPR:
if (FLOAT_TYPE_P (TREE_TYPE (op0)))
{
- edge_info->max_cond_equivalences = 3;
- edge_info->cond_equivalences = XNEWVEC (struct cond_equivalence, 3);
build_and_record_new_cond (ORDERED_EXPR, op0, op1,
- &edge_info->cond_equivalences[2]);
- }
- else
- {
- edge_info->max_cond_equivalences = 2;
- edge_info->cond_equivalences = XNEWVEC (struct cond_equivalence, 2);
+ &edge_info->cond_equivalences);
}
break;
case EQ_EXPR:
if (FLOAT_TYPE_P (TREE_TYPE (op0)))
{
- edge_info->max_cond_equivalences = 5;
- edge_info->cond_equivalences = XNEWVEC (struct cond_equivalence, 5);
build_and_record_new_cond (ORDERED_EXPR, op0, op1,
- &edge_info->cond_equivalences[4]);
- }
- else
- {
- edge_info->max_cond_equivalences = 4;
- edge_info->cond_equivalences = XNEWVEC (struct cond_equivalence, 4);
+ &edge_info->cond_equivalences);
}
build_and_record_new_cond (LE_EXPR, op0, op1,
- &edge_info->cond_equivalences[2]);
+ &edge_info->cond_equivalences);
build_and_record_new_cond (GE_EXPR, op0, op1,
- &edge_info->cond_equivalences[3]);
+ &edge_info->cond_equivalences);
break;
case UNORDERED_EXPR:
- edge_info->max_cond_equivalences = 8;
- edge_info->cond_equivalences = XNEWVEC (struct cond_equivalence, 8);
build_and_record_new_cond (NE_EXPR, op0, op1,
- &edge_info->cond_equivalences[2]);
+ &edge_info->cond_equivalences);
build_and_record_new_cond (UNLE_EXPR, op0, op1,
- &edge_info->cond_equivalences[3]);
+ &edge_info->cond_equivalences);
build_and_record_new_cond (UNGE_EXPR, op0, op1,
- &edge_info->cond_equivalences[4]);
+ &edge_info->cond_equivalences);
build_and_record_new_cond (UNEQ_EXPR, op0, op1,
- &edge_info->cond_equivalences[5]);
+ &edge_info->cond_equivalences);
build_and_record_new_cond (UNLT_EXPR, op0, op1,
- &edge_info->cond_equivalences[6]);
+ &edge_info->cond_equivalences);
build_and_record_new_cond (UNGT_EXPR, op0, op1,
- &edge_info->cond_equivalences[7]);
+ &edge_info->cond_equivalences);
break;
case UNLT_EXPR:
case UNGT_EXPR:
- edge_info->max_cond_equivalences = 4;
- edge_info->cond_equivalences = XNEWVEC (struct cond_equivalence, 4);
build_and_record_new_cond ((TREE_CODE (cond) == UNLT_EXPR
? UNLE_EXPR : UNGE_EXPR),
- op0, op1, &edge_info->cond_equivalences[2]);
+ op0, op1, &edge_info->cond_equivalences);
build_and_record_new_cond (NE_EXPR, op0, op1,
- &edge_info->cond_equivalences[3]);
+ &edge_info->cond_equivalences);
break;
case UNEQ_EXPR:
- edge_info->max_cond_equivalences = 4;
- edge_info->cond_equivalences = XNEWVEC (struct cond_equivalence, 4);
build_and_record_new_cond (UNLE_EXPR, op0, op1,
- &edge_info->cond_equivalences[2]);
+ &edge_info->cond_equivalences);
build_and_record_new_cond (UNGE_EXPR, op0, op1,
- &edge_info->cond_equivalences[3]);
+ &edge_info->cond_equivalences);
break;
case LTGT_EXPR:
- edge_info->max_cond_equivalences = 4;
- edge_info->cond_equivalences = XNEWVEC (struct cond_equivalence, 4);
build_and_record_new_cond (NE_EXPR, op0, op1,
- &edge_info->cond_equivalences[2]);
+ &edge_info->cond_equivalences);
build_and_record_new_cond (ORDERED_EXPR, op0, op1,
- &edge_info->cond_equivalences[3]);
+ &edge_info->cond_equivalences);
break;
default:
- edge_info->max_cond_equivalences = 2;
- edge_info->cond_equivalences = XNEWVEC (struct cond_equivalence, 2);
break;
}
/* Now store the original true and false conditions into the first
two slots. */
- initialize_expr_from_cond (cond, &edge_info->cond_equivalences[0].cond);
- edge_info->cond_equivalences[0].value = boolean_true_node;
+ initialize_expr_from_cond (cond, &c.cond);
+ c.value = boolean_true_node;
+ VEC_safe_push (cond_equivalence, heap, edge_info->cond_equivalences, &c);
/* It is possible for INVERTED to be the negation of a comparison,
and not a valid RHS or GIMPLE_COND condition. This happens because
invert_truthvalue may return such an expression when asked to invert
a floating-point comparison. These comparisons are not assumed to
obey the trichotomy law. */
- initialize_expr_from_cond (inverted, &edge_info->cond_equivalences[1].cond);
- edge_info->cond_equivalences[1].value = boolean_false_node;
+ initialize_expr_from_cond (inverted, &c.cond);
+ c.value = boolean_false_node;
+ VEC_safe_push (cond_equivalence, heap, edge_info->cond_equivalences, &c);
}
/* A helper function for record_const_or_copy and record_equality.
edge_info = allocate_edge_info (false_edge);
record_conditions (edge_info, inverted, cond);
- if (code == NE_EXPR)
+ if (TREE_CODE (inverted) == EQ_EXPR)
{
edge_info->lhs = op1;
edge_info->rhs = op0;
edge_info = allocate_edge_info (false_edge);
record_conditions (edge_info, inverted, cond);
- if (TREE_CODE (cond) == NE_EXPR)
+ if (TREE_CODE (inverted) == EQ_EXPR)
{
edge_info->lhs = op0;
edge_info->rhs = op1;
our equivalence tables. */
if (edge_info)
{
- struct cond_equivalence *cond_equivalences = edge_info->cond_equivalences;
+ cond_equivalence *eq;
tree lhs = edge_info->lhs;
tree rhs = edge_info->rhs;
/* If we have 0 = COND or 1 = COND equivalences, record them
into our expression hash tables. */
- if (cond_equivalences)
- for (i = 0; i < edge_info->max_cond_equivalences; i++)
- record_cond (&cond_equivalences[i]);
+ for (i = 0; VEC_iterate (cond_equivalence,
+ edge_info->cond_equivalences, i, eq); ++i)
+ record_cond (eq);
}
dom_thread_across_edge (walk_data, true_edge);
our equivalence tables. */
if (edge_info)
{
- struct cond_equivalence *cond_equivalences = edge_info->cond_equivalences;
+ cond_equivalence *eq;
tree lhs = edge_info->lhs;
tree rhs = edge_info->rhs;
/* If we have 0 = COND or 1 = COND equivalences, record them
into our expression hash tables. */
- if (cond_equivalences)
- for (i = 0; i < edge_info->max_cond_equivalences; i++)
- record_cond (&cond_equivalences[i]);
+ for (i = 0; VEC_iterate (cond_equivalence,
+ edge_info->cond_equivalences, i, eq); ++i)
+ record_cond (eq);
}
/* Now thread the edge. */
update_stmt_if_modified (stmt);
eliminate_redundant_computations (&si);
stmt = gsi_stmt (si);
+
+ /* Perform simple redundant store elimination. */
+ if (gimple_assign_single_p (stmt)
+ && TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
+ {
+ tree lhs = gimple_assign_lhs (stmt);
+ tree rhs = gimple_assign_rhs1 (stmt);
+ tree cached_lhs;
+ gimple new_stmt;
+ if (TREE_CODE (rhs) == SSA_NAME)
+ {
+ tree tem = SSA_NAME_VALUE (rhs);
+ if (tem)
+ rhs = tem;
+ }
+ /* Build a new statement with the RHS and LHS exchanged. */
+ if (TREE_CODE (rhs) == SSA_NAME)
+ {
+ gimple defstmt = SSA_NAME_DEF_STMT (rhs);
+ new_stmt = gimple_build_assign (rhs, lhs);
+ SSA_NAME_DEF_STMT (rhs) = defstmt;
+ }
+ else
+ new_stmt = gimple_build_assign (rhs, lhs);
+ gimple_set_vuse (new_stmt, gimple_vuse (stmt));
+ cached_lhs = lookup_avail_expr (new_stmt, false);
+ if (cached_lhs
+ && rhs == cached_lhs)
+ {
+ basic_block bb = gimple_bb (stmt);
+ int lp_nr = lookup_stmt_eh_lp (stmt);
+ unlink_stmt_vdef (stmt);
+ gsi_remove (&si, true);
+ if (lp_nr != 0)
+ {
+ bitmap_set_bit (need_eh_cleanup, bb->index);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " Flagged to clear EH edges.\n");
+ }
+ return;
+ }
+ }
}
/* Record any additional equivalences created by this statement. */
continue;
}
+ /* It's not ok to propagate into the definition stmt of RHS.
+ <bb 9>:
+ # prephitmp.12_36 = PHI <g_67.1_6(9)>
+ g_67.1_6 = prephitmp.12_36;
+ goto <bb 9>;
+ While this is strictly all dead code we do not want to
+ deal with this here. */
+ if (TREE_CODE (rhs) == SSA_NAME
+ && SSA_NAME_DEF_STMT (rhs) == use_stmt)
+ {
+ all = false;
+ continue;
+ }
+
/* Dump details. */
if (dump_file && (dump_flags & TDF_DETAILS))
{