diff options
author | bernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-06-25 08:56:24 +0000 |
---|---|---|
committer | bernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-06-25 08:56:24 +0000 |
commit | 00f4f70565fa903b89c2f1be5059898ddb069db0 (patch) | |
tree | 5a50f0008cf354dc460d1db0b3077d133fe49dbb /gcc/tree-ssa-dom.c | |
parent | 44fcaf3f4facf84f2c3d6269876bd2b80445aa32 (diff) | |
download | gcc-00f4f70565fa903b89c2f1be5059898ddb069db0.tar.gz |
With large parts from Jim Wilson:
PR target/43902
* tree-pretty-print.c (dump_generic_node, op_code_prio): Add
WIDEN_MULT_PLUS_EXPR and WIDEN_MULT_MINUS_EXPR.
* optabs.c (optab_for_tree_code): Likewise.
(expand_widen_pattern_expr): Likewise.
* tree-ssa-math-opts.c (convert_mult_to_widen): New function, broken
out of execute_optimize_widening_mul.
(convert_plusminus_to_widen): New function.
(execute_optimize_widening_mul): Use the two new functions.
* expr.c (expand_expr_real_2): Add support for GIMPLE_TERNARY_RHS.
Remove code to generate widening multiply-accumulate. Add support
for WIDEN_MULT_PLUS_EXPR and WIDEN_MULT_MINUS_EXPR.
* gimple-pretty-print.c (dump_ternary_rhs): New function.
(dump_gimple_assign): Call it when appropriate.
* tree.def (WIDEN_MULT_PLUS_EXPR, WIDEN_MULT_MINUS_EXPR): New codes.
* cfgexpand.c (gimple_assign_rhs_to_tree): Likewise.
(expand_gimple_stmt_1): Likewise.
(expand_debug_expr): Support WIDEN_MULT_PLUS_EXPR and
WIDEN_MULT_MINUS_EXPR.
* tree-ssa-operands.c (get_expr_operands): Likewise.
* tree-inline.c (estimate_operator_cost): Likewise.
* gimple.c (extract_ops_from_tree_1): Renamed from
extract_ops_from_tree. Add new arg for a third operand; fill it.
(gimple_build_assign_stat): Support operations with three operands.
(gimple_build_assign_with_ops_stat): Likewise.
(gimple_assign_set_rhs_from_tree): Likewise.
(gimple_assign_set_rhs_with_ops_1): Renamed from
gimple_assign_set_rhs_with_ops. Add new arg for a third operand.
(get_gimple_rhs_num_ops): Support GIMPLE_TERNARY_RHS.
(get_gimple_rhs_num_ops): Handle WIDEN_MULT_PLUS_EXPR and
WIDEN_MULT_MINUS_EXPR.
* gimple.h (enum gimple_rhs_class): Add GIMPLE_TERNARY_RHS.
(extract_ops_from_tree_1): Adjust declaration.
(gimple_assign_set_rhs_with_ops_1): Likewise.
(gimple_build_assign_with_ops): Pass NULL for last operand.
(gimple_build_assign_with_ops3): New macro.
(gimple_assign_rhs3, gimple_assign_rhs3_ptr, gimple_assign_set_rhs3,
gimple_assign_set_rhs_with_ops, extract_ops_from_tree): New inline
functions.
* tree-cfg.c (verify_gimple_assign_ternary): New static function.
(verify_gimple_assign): Call it.
* doc/gimple.texi (Manipulating operands): Document GIMPLE_TERNARY_RHS.
(Tuple specific accessors, subsection GIMPLE_ASSIGN): Document new
functions for dealing with three-operand statements.
* tree.c (commutative_ternary_tree_code): New function.
* tree.h (commutative_ternary_tree_code): Declare it.
* tree-vrp.c (gimple_assign_nonnegative_warnv_p): Return false for ternary
statements.
(gimple_assign_nonzero_warnv_p): Likewise.
* tree-ssa-sccvn.c (stmt_has_constants): Handle GIMPLE_TERNARY_RHS.
* tree-ssa-ccp.c (get_rhs_assign_op_for_ccp): New static function.
(ccp_fold): Use it. Handle GIMPLE_TERNARY_RHS.
* tree-ssa-dom.c (enum expr_kind): Add EXPR_TERNARY.
(struct hashtable_expr): New member ternary in the union.
(initialize_hash_element): Handle GIMPLE_TERNARY_RHS.
(hashable_expr_equal_p): Fix indentation. Handle EXPR_TERNARY.
(iterative_hash_hashable_expr): Likewise.
(print_expr_hash_elt): Handle EXPR_TERNARY.
* gimple-fold.c (fold_gimple_assign): Handle GIMPLE_TERNARY_RHS.
* tree-ssa-threadedge.c (fold_assignment_stmt): Remove useless break
statements. Handle GIMPLE_TERNARY_RHS.
testsuite/
PR target/43902
* gcc.target/mips/madd-9.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@161366 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-dom.c')
-rw-r--r-- | gcc/tree-ssa-dom.c | 114 |
1 files changed, 82 insertions, 32 deletions
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 25eb306369d..d15df31238d 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -51,6 +51,7 @@ enum expr_kind EXPR_SINGLE, EXPR_UNARY, EXPR_BINARY, + EXPR_TERNARY, EXPR_CALL }; @@ -61,7 +62,8 @@ struct hashable_expr union { struct { tree rhs; } single; struct { enum tree_code op; tree opnd; } unary; - struct { enum tree_code op; tree opnd0; tree opnd1; } binary; + struct { enum tree_code op; tree opnd0, opnd1; } binary; + struct { enum tree_code op; tree opnd0, opnd1, opnd2; } ternary; struct { tree fn; bool pure; size_t nargs; tree *args; } call; } ops; }; @@ -211,22 +213,30 @@ initialize_hash_element (gimple stmt, tree lhs, switch (get_gimple_rhs_class (subcode)) { case GIMPLE_SINGLE_RHS: - expr->kind = EXPR_SINGLE; - expr->ops.single.rhs = gimple_assign_rhs1 (stmt); - break; + expr->kind = EXPR_SINGLE; + expr->ops.single.rhs = gimple_assign_rhs1 (stmt); + break; case GIMPLE_UNARY_RHS: - expr->kind = EXPR_UNARY; + expr->kind = EXPR_UNARY; expr->type = TREE_TYPE (gimple_assign_lhs (stmt)); - expr->ops.unary.op = subcode; - expr->ops.unary.opnd = gimple_assign_rhs1 (stmt); - break; + expr->ops.unary.op = subcode; + expr->ops.unary.opnd = gimple_assign_rhs1 (stmt); + break; case GIMPLE_BINARY_RHS: - expr->kind = EXPR_BINARY; + expr->kind = EXPR_BINARY; expr->type = TREE_TYPE (gimple_assign_lhs (stmt)); - expr->ops.binary.op = subcode; - expr->ops.binary.opnd0 = gimple_assign_rhs1 (stmt); - expr->ops.binary.opnd1 = gimple_assign_rhs2 (stmt); - break; + expr->ops.binary.op = subcode; + expr->ops.binary.opnd0 = gimple_assign_rhs1 (stmt); + expr->ops.binary.opnd1 = gimple_assign_rhs2 (stmt); + break; + case GIMPLE_TERNARY_RHS: + expr->kind = EXPR_TERNARY; + expr->type = TREE_TYPE (gimple_assign_lhs (stmt)); + expr->ops.ternary.op = subcode; + expr->ops.ternary.opnd0 = gimple_assign_rhs1 (stmt); + expr->ops.ternary.opnd1 = gimple_assign_rhs2 (stmt); + expr->ops.ternary.opnd2 = gimple_assign_rhs3 (stmt); + break; default: gcc_unreachable (); } @@ -371,23 +381,40 @@ hashable_expr_equal_p (const struct hashable_expr *expr0, expr1->ops.unary.opnd, 0); case EXPR_BINARY: - { - if (expr0->ops.binary.op != expr1->ops.binary.op) - return false; - - if (operand_equal_p (expr0->ops.binary.opnd0, - expr1->ops.binary.opnd0, 0) - && operand_equal_p (expr0->ops.binary.opnd1, - expr1->ops.binary.opnd1, 0)) - return true; - - /* For commutative ops, allow the other order. */ - return (commutative_tree_code (expr0->ops.binary.op) - && operand_equal_p (expr0->ops.binary.opnd0, - expr1->ops.binary.opnd1, 0) - && operand_equal_p (expr0->ops.binary.opnd1, - expr1->ops.binary.opnd0, 0)); - } + if (expr0->ops.binary.op != expr1->ops.binary.op) + return false; + + if (operand_equal_p (expr0->ops.binary.opnd0, + expr1->ops.binary.opnd0, 0) + && operand_equal_p (expr0->ops.binary.opnd1, + expr1->ops.binary.opnd1, 0)) + return true; + + /* For commutative ops, allow the other order. */ + return (commutative_tree_code (expr0->ops.binary.op) + && operand_equal_p (expr0->ops.binary.opnd0, + expr1->ops.binary.opnd1, 0) + && operand_equal_p (expr0->ops.binary.opnd1, + expr1->ops.binary.opnd0, 0)); + + case EXPR_TERNARY: + if (expr0->ops.ternary.op != expr1->ops.ternary.op + || !operand_equal_p (expr0->ops.ternary.opnd2, + expr1->ops.ternary.opnd2, 0)) + return false; + + if (operand_equal_p (expr0->ops.ternary.opnd0, + expr1->ops.ternary.opnd0, 0) + && operand_equal_p (expr0->ops.ternary.opnd1, + expr1->ops.ternary.opnd1, 0)) + return true; + + /* For commutative ops, allow the other order. */ + return (commutative_ternary_tree_code (expr0->ops.ternary.op) + && operand_equal_p (expr0->ops.ternary.opnd0, + expr1->ops.ternary.opnd1, 0) + && operand_equal_p (expr0->ops.ternary.opnd1, + expr1->ops.ternary.opnd0, 0)); case EXPR_CALL: { @@ -450,8 +477,8 @@ iterative_hash_hashable_expr (const struct hashable_expr *expr, hashval_t val) case EXPR_BINARY: val = iterative_hash_object (expr->ops.binary.op, val); if (commutative_tree_code (expr->ops.binary.op)) - val = iterative_hash_exprs_commutative (expr->ops.binary.opnd0, - expr->ops.binary.opnd1, val); + val = iterative_hash_exprs_commutative (expr->ops.binary.opnd0, + expr->ops.binary.opnd1, val); else { val = iterative_hash_expr (expr->ops.binary.opnd0, val); @@ -459,6 +486,19 @@ iterative_hash_hashable_expr (const struct hashable_expr *expr, hashval_t val) } break; + case EXPR_TERNARY: + val = iterative_hash_object (expr->ops.ternary.op, val); + if (commutative_ternary_tree_code (expr->ops.ternary.op)) + val = iterative_hash_exprs_commutative (expr->ops.ternary.opnd0, + expr->ops.ternary.opnd1, val); + else + { + val = iterative_hash_expr (expr->ops.ternary.opnd0, val); + val = iterative_hash_expr (expr->ops.ternary.opnd1, val); + } + val = iterative_hash_expr (expr->ops.ternary.opnd2, val); + break; + case EXPR_CALL: { size_t i; @@ -511,6 +551,16 @@ print_expr_hash_elt (FILE * stream, const struct expr_hash_elt *element) print_generic_expr (stream, element->expr.ops.binary.opnd1, 0); break; + case EXPR_TERNARY: + fprintf (stream, " %s <", tree_code_name[element->expr.ops.ternary.op]); + print_generic_expr (stream, element->expr.ops.ternary.opnd0, 0); + fputs (", ", stream); + print_generic_expr (stream, element->expr.ops.ternary.opnd1, 0); + fputs (", ", stream); + print_generic_expr (stream, element->expr.ops.ternary.opnd2, 0); + fputs (">", stream); + break; + case EXPR_CALL: { size_t i; |