diff options
author | paolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-09-05 23:39:12 +0000 |
---|---|---|
committer | paolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-09-05 23:39:12 +0000 |
commit | dd8277d99b95baea264eae6dda70405f0cbe1977 (patch) | |
tree | b03be65954ece9593296959f7ff1f397f3dc89f5 /gcc/tree-tailcall.c | |
parent | 96138327a9fb924e956a0d8d4680efa043512599 (diff) | |
download | gcc-dd8277d99b95baea264eae6dda70405f0cbe1977.tar.gz |
gcc/
2010-09-05 Giuseppe Scrivano <gscrivano@gnu.org>
* tree-tailcall.c (process_assignment): Handle NEGATE_EXPR and
MINUS_EXPR.
gcc/testsuite/
2010-09-05 Giuseppe Scrivano <gscrivano@gnu.org>
* gcc.dg/tree-ssa/tailrecursion-7.c: New file.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@163888 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-tailcall.c')
-rw-r--r-- | gcc/tree-tailcall.c | 63 |
1 files changed, 44 insertions, 19 deletions
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c index 65eaa40cedb..71a273f6fe5 100644 --- a/gcc/tree-tailcall.c +++ b/gcc/tree-tailcall.c @@ -252,7 +252,7 @@ static bool process_assignment (gimple stmt, gimple_stmt_iterator call, tree *m, tree *a, tree *ass_var) { - tree op0, op1, non_ass_var; + tree op0, op1 = NULL_TREE, non_ass_var = NULL_TREE; tree dest = gimple_assign_lhs (stmt); enum tree_code code = gimple_assign_rhs_code (stmt); enum gimple_rhs_class rhs_class = get_gimple_rhs_class (code); @@ -278,8 +278,20 @@ process_assignment (gimple stmt, gimple_stmt_iterator call, tree *m, return true; } - if (rhs_class != GIMPLE_BINARY_RHS) - return false; + switch (rhs_class) + { + case GIMPLE_BINARY_RHS: + op1 = gimple_assign_rhs2 (stmt); + + /* Fall through. */ + + case GIMPLE_UNARY_RHS: + op0 = gimple_assign_rhs1 (stmt); + break; + + default: + return false; + } /* Accumulator optimizations will reverse the order of operations. We can only do that for floating-point types if we're assuming @@ -288,20 +300,9 @@ process_assignment (gimple stmt, gimple_stmt_iterator call, tree *m, if (FLOAT_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl)))) return false; - /* We only handle the code like - - x = call (); - y = m * x; - z = y + a; - return z; - - TODO -- Extend it for cases where the linear transformation of the output - is expressed in a more complicated way. */ - - op0 = gimple_assign_rhs1 (stmt); - op1 = gimple_assign_rhs2 (stmt); - - if (op0 == *ass_var + if (rhs_class == GIMPLE_UNARY_RHS) + ; + else if (op0 == *ass_var && (non_ass_var = independent_of_stmt_p (op1, stmt, call))) ; else if (op1 == *ass_var @@ -322,8 +323,32 @@ process_assignment (gimple stmt, gimple_stmt_iterator call, tree *m, *ass_var = dest; return true; - /* TODO -- Handle other codes (NEGATE_EXPR, MINUS_EXPR, - POINTER_PLUS_EXPR). */ + case NEGATE_EXPR: + if (FLOAT_TYPE_P (TREE_TYPE (op0))) + *m = build_real (TREE_TYPE (op0), dconstm1); + else + *m = build_int_cst (TREE_TYPE (op0), -1); + + *ass_var = dest; + return true; + + case MINUS_EXPR: + if (*ass_var == op0) + *a = fold_build1 (NEGATE_EXPR, TREE_TYPE (non_ass_var), non_ass_var); + else + { + if (FLOAT_TYPE_P (TREE_TYPE (non_ass_var))) + *m = build_real (TREE_TYPE (non_ass_var), dconstm1); + else + *m = build_int_cst (TREE_TYPE (non_ass_var), -1); + + *a = fold_build1 (NEGATE_EXPR, TREE_TYPE (non_ass_var), non_ass_var); + } + + *ass_var = dest; + return true; + + /* TODO -- Handle POINTER_PLUS_EXPR. */ default: return false; |