summaryrefslogtreecommitdiff
path: root/gcc/gimple.c
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@codesourcery.com>2010-06-25 08:56:24 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2010-06-25 08:56:24 +0000
commit0354c0c70b2a090a3705fffd6a87313233b5516d (patch)
tree5a50f0008cf354dc460d1db0b3077d133fe49dbb /gcc/gimple.c
parent38f78b0c69999b7e2eec2ce58a02d08b24be7f43 (diff)
downloadgcc-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.c49
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 \