diff options
author | Bernd Schmidt <bernds@codesourcery.com> | 2010-06-25 08:56:24 +0000 |
---|---|---|
committer | Bernd Schmidt <bernds@gcc.gnu.org> | 2010-06-25 08:56:24 +0000 |
commit | 0354c0c70b2a090a3705fffd6a87313233b5516d (patch) | |
tree | 5a50f0008cf354dc460d1db0b3077d133fe49dbb /gcc/gimple.c | |
parent | 38f78b0c69999b7e2eec2ce58a02d08b24be7f43 (diff) | |
download | gcc-0354c0c70b2a090a3705fffd6a87313233b5516d.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.
From-SVN: r161366
Diffstat (limited to 'gcc/gimple.c')
-rw-r--r-- | gcc/gimple.c | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/gcc/gimple.c b/gcc/gimple.c index d82a93c6c46..0a5f6fb97d1 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -305,31 +305,40 @@ gimple_build_call_from_tree (tree t) /* Extract the operands and code for expression EXPR into *SUBCODE_P, - *OP1_P and *OP2_P respectively. */ + *OP1_P, *OP2_P and *OP3_P respectively. */ void -extract_ops_from_tree (tree expr, enum tree_code *subcode_p, tree *op1_p, - tree *op2_p) +extract_ops_from_tree_1 (tree expr, enum tree_code *subcode_p, tree *op1_p, + tree *op2_p, tree *op3_p) { enum gimple_rhs_class grhs_class; *subcode_p = TREE_CODE (expr); grhs_class = get_gimple_rhs_class (*subcode_p); - if (grhs_class == GIMPLE_BINARY_RHS) + if (grhs_class == GIMPLE_TERNARY_RHS) { *op1_p = TREE_OPERAND (expr, 0); *op2_p = TREE_OPERAND (expr, 1); + *op3_p = TREE_OPERAND (expr, 2); + } + else if (grhs_class == GIMPLE_BINARY_RHS) + { + *op1_p = TREE_OPERAND (expr, 0); + *op2_p = TREE_OPERAND (expr, 1); + *op3_p = NULL_TREE; } else if (grhs_class == GIMPLE_UNARY_RHS) { *op1_p = TREE_OPERAND (expr, 0); *op2_p = NULL_TREE; + *op3_p = NULL_TREE; } else if (grhs_class == GIMPLE_SINGLE_RHS) { *op1_p = expr; *op2_p = NULL_TREE; + *op3_p = NULL_TREE; } else gcc_unreachable (); @@ -345,10 +354,10 @@ gimple gimple_build_assign_stat (tree lhs, tree rhs MEM_STAT_DECL) { enum tree_code subcode; - tree op1, op2; + tree op1, op2, op3; - extract_ops_from_tree (rhs, &subcode, &op1, &op2); - return gimple_build_assign_with_ops_stat (subcode, lhs, op1, op2 + extract_ops_from_tree_1 (rhs, &subcode, &op1, &op2, &op3); + return gimple_build_assign_with_ops_stat (subcode, lhs, op1, op2, op3 PASS_MEM_STAT); } @@ -359,7 +368,7 @@ gimple_build_assign_stat (tree lhs, tree rhs MEM_STAT_DECL) gimple gimple_build_assign_with_ops_stat (enum tree_code subcode, tree lhs, tree op1, - tree op2 MEM_STAT_DECL) + tree op2, tree op3 MEM_STAT_DECL) { unsigned num_ops; gimple p; @@ -378,6 +387,12 @@ gimple_build_assign_with_ops_stat (enum tree_code subcode, tree lhs, tree op1, gimple_assign_set_rhs2 (p, op2); } + if (op3) + { + gcc_assert (num_ops > 3); + gimple_assign_set_rhs3 (p, op3); + } + return p; } @@ -1955,22 +1970,22 @@ void gimple_assign_set_rhs_from_tree (gimple_stmt_iterator *gsi, tree expr) { enum tree_code subcode; - tree op1, op2; + tree op1, op2, op3; - extract_ops_from_tree (expr, &subcode, &op1, &op2); - gimple_assign_set_rhs_with_ops (gsi, subcode, op1, op2); + extract_ops_from_tree_1 (expr, &subcode, &op1, &op2, &op3); + gimple_assign_set_rhs_with_ops_1 (gsi, subcode, op1, op2, op3); } /* Set the RHS of assignment statement pointed-to by GSI to CODE with - operands OP1 and OP2. + operands OP1, OP2 and OP3. NOTE: The statement pointed-to by GSI may be reallocated if it did not have enough operand slots. */ void -gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *gsi, enum tree_code code, - tree op1, tree op2) +gimple_assign_set_rhs_with_ops_1 (gimple_stmt_iterator *gsi, enum tree_code code, + tree op1, tree op2, tree op3) { unsigned new_rhs_ops = get_gimple_rhs_num_ops (code); gimple stmt = gsi_stmt (*gsi); @@ -1994,6 +2009,8 @@ gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *gsi, enum tree_code code, gimple_assign_set_rhs1 (stmt, op1); if (new_rhs_ops > 1) gimple_assign_set_rhs2 (stmt, op2); + if (new_rhs_ops > 2) + gimple_assign_set_rhs3 (stmt, op3); } @@ -2473,6 +2490,8 @@ get_gimple_rhs_num_ops (enum tree_code code) return 1; else if (rhs_class == GIMPLE_BINARY_RHS) return 2; + else if (rhs_class == GIMPLE_TERNARY_RHS) + return 3; else gcc_unreachable (); } @@ -2489,6 +2508,8 @@ get_gimple_rhs_num_ops (enum tree_code code) || (SYM) == TRUTH_OR_EXPR \ || (SYM) == TRUTH_XOR_EXPR) ? GIMPLE_BINARY_RHS \ : (SYM) == TRUTH_NOT_EXPR ? GIMPLE_UNARY_RHS \ + : ((SYM) == WIDEN_MULT_PLUS_EXPR \ + || (SYM) == WIDEN_MULT_MINUS_EXPR) ? GIMPLE_TERNARY_RHS \ : ((SYM) == COND_EXPR \ || (SYM) == CONSTRUCTOR \ || (SYM) == OBJ_TYPE_REF \ |