+2014-11-13 Richard Biener <rguenther@suse.de>
+
+ * match.pd: Implement conditional expression patterns.
+ * tree-ssa-forwprop.c (forward_propagate_into_cond): Remove
+ them here.
+ (combine_cond_exprs): Remove.
+ (pass_forwprop::execute): Do not call combine_cond_exprs.
+ * fold-const.c (fold_ternary_loc): Remove patterns here.
+ (pedantic_omit_one_operand_loc): Remove.
+
2014-12-13 Richard Biener <rguenther@suse.de>
PR middle-end/61559
static int operand_equal_for_comparison_p (tree, tree, tree);
static int twoval_comparison_p (tree, tree *, tree *, int *);
static tree eval_subst (location_t, tree, tree, tree, tree, tree);
-static tree pedantic_omit_one_operand_loc (location_t, tree, tree, tree);
static tree distribute_bit_expr (location_t, enum tree_code, tree, tree, tree);
static tree make_bit_field_ref (location_t, tree, tree,
HOST_WIDE_INT, HOST_WIDE_INT, int);
return non_lvalue_loc (loc, t);
}
-/* Similar, but call pedantic_non_lvalue instead of non_lvalue. */
-
-static tree
-pedantic_omit_one_operand_loc (location_t loc, tree type, tree result,
- tree omitted)
-{
- tree t = fold_convert_loc (loc, type, result);
-
- /* If the resulting operand is an empty statement, just return the omitted
- statement casted to void. */
- if (IS_EMPTY_STMT (t) && TREE_SIDE_EFFECTS (omitted))
- return build1_loc (loc, NOP_EXPR, void_type_node,
- fold_ignored_result (omitted));
-
- if (TREE_SIDE_EFFECTS (omitted))
- return build2_loc (loc, COMPOUND_EXPR, type,
- fold_ignored_result (omitted), t);
-
- return pedantic_non_lvalue_loc (loc, t);
-}
-
/* Return a tree for the case when the result of an expression is RESULT
converted to TYPE and OMITTED1 and OMITTED2 were previously operands
of the expression but are now not needed.
}
else if (TREE_CODE (arg0) == VECTOR_CST)
{
- if (integer_all_onesp (arg0))
- return pedantic_omit_one_operand_loc (loc, type, arg1, arg2);
- if (integer_zerop (arg0))
- return pedantic_omit_one_operand_loc (loc, type, arg2, arg1);
-
if ((TREE_CODE (arg1) == VECTOR_CST
|| TREE_CODE (arg1) == CONSTRUCTOR)
&& (TREE_CODE (arg2) == VECTOR_CST
}
}
- if (operand_equal_p (arg1, op2, 0))
- return pedantic_omit_one_operand_loc (loc, type, arg1, arg0);
-
/* If we have A op B ? A : C, we may be able to convert this to a
simpler expression, depending on the operation and the values
of B and C. Signed zeros prevent all of these transformations,
(simplify
(bswap (bitop:c (bswap @0) @1))
(bitop @0 (bswap @1)))))
+
+
+/* Combine COND_EXPRs and VEC_COND_EXPRs. */
+
+/* Simplify constant conditions.
+ Only optimize constant conditions when the selected branch
+ has the same type as the COND_EXPR. This avoids optimizing
+ away "c ? x : throw", where the throw has a void type.
+ Note that we cannot throw away the fold-const.c variant nor
+ this one as we depend on doing this transform before possibly
+ A ? B : B -> B triggers and the fold-const.c one can optimize
+ 0 ? A : B to B even if A has side-effects. Something
+ genmatch cannot handle. */
+(simplify
+ (cond INTEGER_CST@0 @1 @2)
+ (if (integer_zerop (@0)
+ && (!VOID_TYPE_P (TREE_TYPE (@2))
+ || VOID_TYPE_P (type)))
+ @2)
+ (if (!integer_zerop (@0)
+ && (!VOID_TYPE_P (TREE_TYPE (@1))
+ || VOID_TYPE_P (type)))
+ @1))
+(simplify
+ (vec_cond VECTOR_CST@0 @1 @2)
+ (if (integer_all_onesp (@0))
+ @1)
+ (if (integer_zerop (@0))
+ @2))
+
+(for cnd (cond vec_cond)
+ /* A ? B : (A ? X : C) -> A ? B : C. */
+ (simplify
+ (cnd @0 (cnd @0 @1 @2) @3)
+ (cnd @0 @1 @3))
+ (simplify
+ (cnd @0 @1 (cnd @0 @2 @3))
+ (cnd @0 @1 @3))
+
+ /* A ? B : B -> B. */
+ (simplify
+ (cnd @0 @1 @1)
+ @1))
+
+/* !A ? B : C -> A ? C : B. */
+(simplify
+ (cond (logical_inverted_value truth_valued_p@0) @1 @2)
+ (cond @0 @2 @1))
tree tmp = NULL_TREE;
tree cond = gimple_assign_rhs1 (stmt);
enum tree_code code = gimple_assign_rhs_code (stmt);
- bool swap = false;
/* We can do tree combining on SSA_NAME and comparison expressions. */
if (COMPARISON_CLASS_P (cond))
TREE_TYPE (cond),
gimple_assign_rhs1 (def_stmt),
gimple_assign_rhs2 (def_stmt));
- else if (code == COND_EXPR
- && ((def_code == BIT_NOT_EXPR
- && TYPE_PRECISION (TREE_TYPE (cond)) == 1)
- || (def_code == BIT_XOR_EXPR
- && integer_onep (gimple_assign_rhs2 (def_stmt)))))
- {
- tmp = gimple_assign_rhs1 (def_stmt);
- swap = true;
- }
}
if (tmp
else if (integer_zerop (tmp))
gimple_assign_set_rhs_from_tree (gsi_p, gimple_assign_rhs3 (stmt));
else
- {
- gimple_assign_set_rhs1 (stmt, unshare_expr (tmp));
- if (swap)
- {
- tree t = gimple_assign_rhs2 (stmt);
- gimple_assign_set_rhs2 (stmt, gimple_assign_rhs3 (stmt));
- gimple_assign_set_rhs3 (stmt, t);
- }
- }
+ gimple_assign_set_rhs1 (stmt, unshare_expr (tmp));
stmt = gsi_stmt (*gsi_p);
update_stmt (stmt);
return 0;
}
-/* Propagate from the ssa name definition statements of COND_EXPR
- values in the rhs of statement STMT into the conditional arms
- if that simplifies it.
- Returns true if the stmt was changed. */
-
-static bool
-combine_cond_exprs (gimple_stmt_iterator *gsi_p)
-{
- gimple stmt = gsi_stmt (*gsi_p);
- tree cond, val1, val2;
- bool changed = false;
-
- cond = gimple_assign_rhs1 (stmt);
- val1 = gimple_assign_rhs2 (stmt);
- if (TREE_CODE (val1) == SSA_NAME)
- {
- gimple def_stmt = SSA_NAME_DEF_STMT (val1);
- if (is_gimple_assign (def_stmt)
- && gimple_assign_rhs_code (def_stmt) == gimple_assign_rhs_code (stmt)
- && operand_equal_p (gimple_assign_rhs1 (def_stmt), cond, 0))
- {
- val1 = unshare_expr (gimple_assign_rhs2 (def_stmt));
- gimple_assign_set_rhs2 (stmt, val1);
- changed = true;
- }
- }
- val2 = gimple_assign_rhs3 (stmt);
- if (TREE_CODE (val2) == SSA_NAME)
- {
- gimple def_stmt = SSA_NAME_DEF_STMT (val2);
- if (is_gimple_assign (def_stmt)
- && gimple_assign_rhs_code (def_stmt) == gimple_assign_rhs_code (stmt)
- && operand_equal_p (gimple_assign_rhs1 (def_stmt), cond, 0))
- {
- val2 = unshare_expr (gimple_assign_rhs3 (def_stmt));
- gimple_assign_set_rhs3 (stmt, val2);
- changed = true;
- }
- }
- if (operand_equal_p (val1, val2, 0))
- {
- gimple_assign_set_rhs_from_tree (gsi_p, val1);
- stmt = gsi_stmt (*gsi_p);
- changed = true;
- }
-
- if (changed)
- update_stmt (stmt);
-
- return changed;
-}
-
/* We've just substituted an ADDR_EXPR into stmt. Update all the
relevant data structures to match. */
|| code == VEC_COND_EXPR)
{
/* In this case the entire COND_EXPR is in rhs1. */
- if (forward_propagate_into_cond (&gsi)
- || combine_cond_exprs (&gsi))
+ if (forward_propagate_into_cond (&gsi))
{
changed = true;
stmt = gsi_stmt (gsi);