[backport from gcc-4.7/trunk, part 2 of PR48149 fix ] Date: Tue, 6 Sep 2011 15:33:14 +0200 (CEST) From: Richard Guenther Subject: [PATCH] Fix PR48149 List-Archive: This makes SCCVN combine COMPLEX_EXPR arguments with its operands, allowing to optimize piecewise pass-thru of a complex value. The meat of the patch is the tuplification fix ! && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME) --- ! && TREE_CODE (TREE_OPERAND (gimple_assign_rhs1 (def_stmt), ! 0)) == SSA_NAME) and special-casing of COMPLEX_EXPR in simplify_binary_expression. The rest is some TLC in the functions. Bootstrap and regtest ongoing for x86_64-unknown-linux-gnu. Richard. gcc/ 2011-09-06 Richard Guenther PR tree-optimization/48149 * tree-ssa-sccvn.c (vn_get_expr_for): Simplify. Fix tuplification bug. (vn_valueize): Move earlier. (valueize_expr): Use vn_valueize. (simplify_binary_expression): Simplify, also combine COMPLEX_EXPR operands. (simplify_unary_expression): Simplify. gcc/testsuite/ 2011-09-06 Richard Guenther PR tree-optimization/48149 * gcc.dg/tree-ssa/ssa-fre-32.c: New testcase. --- gcc-4.6.2/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-32.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.6.2/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-32.c 2011-12-10 20:48:22.000000000 +0100 @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre1-details" } */ + +_Complex float +foo (_Complex float x) +{ + float r = __real x; + float i = __imag x; + _Complex float z; + __real z = r; + __imag z = i; + return z; +} + +_Complex float +bar (_Complex float x) +{ + float r = __real x; + float i = __imag x; + _Complex float z = x; + __real z = r; + __imag z = i; + return z; +} + +/* We should CSE all the way to replace the final assignment to z with x. */ +/* { dg-final { scan-tree-dump-times "with x_1\\\(D\\\) in z" 3 "fre1" } } */ +/* { dg-final { cleanup-tree-dump "fre1" } } */ --- gcc-4.6.2/gcc/tree-ssa-sccvn.c.~1~ 2011-05-12 16:08:00.000000000 +0200 +++ gcc-4.6.2/gcc/tree-ssa-sccvn.c 2011-12-10 20:52:39.000000000 +0100 @@ -216,6 +216,7 @@ vn_get_expr_for (tree name) vn_ssa_aux_t vn = VN_INFO (name); gimple def_stmt; tree expr = NULL_TREE; + enum tree_code code; if (vn->valnum == VN_TOP) return name; @@ -240,37 +241,34 @@ vn_get_expr_for (tree name) /* Otherwise use the defining statement to build the expression. */ def_stmt = SSA_NAME_DEF_STMT (vn->valnum); - /* If the value number is a default-definition or a PHI result - use it directly. */ - if (gimple_nop_p (def_stmt) - || gimple_code (def_stmt) == GIMPLE_PHI) - return vn->valnum; - + /* If the value number is not an assignment use it directly. */ if (!is_gimple_assign (def_stmt)) return vn->valnum; /* FIXME tuples. This is incomplete and likely will miss some simplifications. */ - switch (TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt))) + code = gimple_assign_rhs_code (def_stmt); + switch (TREE_CODE_CLASS (code)) { case tcc_reference: - if ((gimple_assign_rhs_code (def_stmt) == VIEW_CONVERT_EXPR - || gimple_assign_rhs_code (def_stmt) == REALPART_EXPR - || gimple_assign_rhs_code (def_stmt) == IMAGPART_EXPR) - && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME) - expr = fold_build1 (gimple_assign_rhs_code (def_stmt), + if ((code == REALPART_EXPR + || code == IMAGPART_EXPR + || code == VIEW_CONVERT_EXPR) + && TREE_CODE (TREE_OPERAND (gimple_assign_rhs1 (def_stmt), + 0)) == SSA_NAME) + expr = fold_build1 (code, gimple_expr_type (def_stmt), TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0)); break; case tcc_unary: - expr = fold_build1 (gimple_assign_rhs_code (def_stmt), + expr = fold_build1 (code, gimple_expr_type (def_stmt), gimple_assign_rhs1 (def_stmt)); break; case tcc_binary: - expr = fold_build2 (gimple_assign_rhs_code (def_stmt), + expr = fold_build2 (code, gimple_expr_type (def_stmt), gimple_assign_rhs1 (def_stmt), gimple_assign_rhs2 (def_stmt)); @@ -2586,6 +2584,19 @@ stmt_has_constants (gimple stmt) return false; } +/* Valueize NAME if it is an SSA name, otherwise just return it. */ + +static inline tree +vn_valueize (tree name) +{ + if (TREE_CODE (name) == SSA_NAME) + { + tree tem = SSA_VAL (name); + return tem == VN_TOP ? name : tem; + } + return name; +} + /* Replace SSA_NAMES in expr with their value numbers, and return the result. This is performed in place. */ @@ -2595,21 +2606,13 @@ valueize_expr (tree expr) { switch (TREE_CODE_CLASS (TREE_CODE (expr))) { - case tcc_unary: - if (TREE_CODE (TREE_OPERAND (expr, 0)) == SSA_NAME - && SSA_VAL (TREE_OPERAND (expr, 0)) != VN_TOP) - TREE_OPERAND (expr, 0) = SSA_VAL (TREE_OPERAND (expr, 0)); - break; case tcc_binary: - if (TREE_CODE (TREE_OPERAND (expr, 0)) == SSA_NAME - && SSA_VAL (TREE_OPERAND (expr, 0)) != VN_TOP) - TREE_OPERAND (expr, 0) = SSA_VAL (TREE_OPERAND (expr, 0)); - if (TREE_CODE (TREE_OPERAND (expr, 1)) == SSA_NAME - && SSA_VAL (TREE_OPERAND (expr, 1)) != VN_TOP) - TREE_OPERAND (expr, 1) = SSA_VAL (TREE_OPERAND (expr, 1)); - break; - default: + TREE_OPERAND (expr, 1) = vn_valueize (TREE_OPERAND (expr, 1)); + /* Fallthru. */ + case tcc_unary: + TREE_OPERAND (expr, 0) = vn_valueize (TREE_OPERAND (expr, 0)); break; + default:; } return expr; } @@ -2623,6 +2626,7 @@ simplify_binary_expression (gimple stmt) tree result = NULL_TREE; tree op0 = gimple_assign_rhs1 (stmt); tree op1 = gimple_assign_rhs2 (stmt); + enum tree_code code = gimple_assign_rhs_code (stmt); /* This will not catch every single case we could combine, but will catch those with constants. The goal here is to simultaneously @@ -2631,18 +2635,20 @@ simplify_binary_expression (gimple stmt) if (TREE_CODE (op0) == SSA_NAME) { if (VN_INFO (op0)->has_constants - || TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_comparison) + || TREE_CODE_CLASS (code) == tcc_comparison + || code == COMPLEX_EXPR) op0 = valueize_expr (vn_get_expr_for (op0)); - else if (SSA_VAL (op0) != VN_TOP && SSA_VAL (op0) != op0) - op0 = SSA_VAL (op0); + else + op0 = vn_valueize (op0); } if (TREE_CODE (op1) == SSA_NAME) { - if (VN_INFO (op1)->has_constants) + if (VN_INFO (op1)->has_constants + || code == COMPLEX_EXPR) op1 = valueize_expr (vn_get_expr_for (op1)); - else if (SSA_VAL (op1) != VN_TOP && SSA_VAL (op1) != op1) - op1 = SSA_VAL (op1); + else + op1 = vn_valueize (op1); } /* Avoid folding if nothing changed. */ @@ -2652,8 +2658,7 @@ simplify_binary_expression (gimple stmt) fold_defer_overflow_warnings (); - result = fold_binary (gimple_assign_rhs_code (stmt), - gimple_expr_type (stmt), op0, op1); + result = fold_binary (code, gimple_expr_type (stmt), op0, op1); if (result) STRIP_USELESS_TYPE_CONVERSION (result); @@ -2678,12 +2683,13 @@ simplify_unary_expression (gimple stmt) { tree result = NULL_TREE; tree orig_op0, op0 = gimple_assign_rhs1 (stmt); + enum tree_code code = gimple_assign_rhs_code (stmt); /* We handle some tcc_reference codes here that are all GIMPLE_ASSIGN_SINGLE codes. */ - if (gimple_assign_rhs_code (stmt) == REALPART_EXPR - || gimple_assign_rhs_code (stmt) == IMAGPART_EXPR - || gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR) + if (code == REALPART_EXPR + || code == IMAGPART_EXPR + || code == VIEW_CONVERT_EXPR) op0 = TREE_OPERAND (op0, 0); if (TREE_CODE (op0) != SSA_NAME) @@ -2692,10 +2698,10 @@ simplify_unary_expression (gimple stmt) orig_op0 = op0; if (VN_INFO (op0)->has_constants) op0 = valueize_expr (vn_get_expr_for (op0)); - else if (gimple_assign_cast_p (stmt) - || gimple_assign_rhs_code (stmt) == REALPART_EXPR - || gimple_assign_rhs_code (stmt) == IMAGPART_EXPR - || gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR) + else if (CONVERT_EXPR_CODE_P (code) + || code == REALPART_EXPR + || code == IMAGPART_EXPR + || code == VIEW_CONVERT_EXPR) { /* We want to do tree-combining on conversion-like expressions. Make sure we feed only SSA_NAMEs or constants to fold though. */ @@ -2712,8 +2718,7 @@ simplify_unary_expression (gimple stmt) if (op0 == orig_op0) return NULL_TREE; - result = fold_unary_ignore_overflow (gimple_assign_rhs_code (stmt), - gimple_expr_type (stmt), op0); + result = fold_unary_ignore_overflow (code, gimple_expr_type (stmt), op0); if (result) { STRIP_USELESS_TYPE_CONVERSION (result);