[PATCH] Fix PR48149
Richard Guenther
rguenther@suse.de
Tue Sep 6 13:33:00 GMT 2011
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.
2011-09-06 Richard Guenther <rguenther@suse.de>
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.dg/tree-ssa/ssa-fre-32.c: New testcase.
Index: trunk/gcc/tree-ssa-sccvn.c
===================================================================
*** trunk.orig/gcc/tree-ssa-sccvn.c 2011-09-06 14:58:32.000000000 +0200
--- trunk/gcc/tree-ssa-sccvn.c 2011-09-06 14:58:53.000000000 +0200
*************** vn_get_expr_for (tree name)
*** 217,222 ****
--- 217,223 ----
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;
*************** vn_get_expr_for (tree name)
*** 241,277 ****
/* 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 (!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)))
{
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),
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),
gimple_expr_type (def_stmt),
gimple_assign_rhs1 (def_stmt));
break;
case tcc_binary:
! expr = fold_build2 (gimple_assign_rhs_code (def_stmt),
gimple_expr_type (def_stmt),
gimple_assign_rhs1 (def_stmt),
gimple_assign_rhs2 (def_stmt));
--- 242,275 ----
/* Otherwise use the defining statement to build the expression. */
def_stmt = SSA_NAME_DEF_STMT (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. */
! code = gimple_assign_rhs_code (def_stmt);
! switch (TREE_CODE_CLASS (code))
{
case tcc_reference:
! 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 (code,
gimple_expr_type (def_stmt),
gimple_assign_rhs1 (def_stmt));
break;
case tcc_binary:
! expr = fold_build2 (code,
gimple_expr_type (def_stmt),
gimple_assign_rhs1 (def_stmt),
gimple_assign_rhs2 (def_stmt));
*************** stmt_has_constants (gimple stmt)
*** 2822,2827 ****
--- 2820,2838 ----
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. */
*************** valueize_expr (tree expr)
*** 2831,2851 ****
{
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:
break;
}
return expr;
}
--- 2842,2854 ----
{
switch (TREE_CODE_CLASS (TREE_CODE (expr)))
{
case tcc_binary:
! 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;
}
*************** simplify_binary_expression (gimple stmt)
*** 2859,2864 ****
--- 2862,2868 ----
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
*************** simplify_binary_expression (gimple stmt)
*** 2867,2889 ****
if (TREE_CODE (op0) == SSA_NAME)
{
if (VN_INFO (op0)->has_constants
! || TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_comparison)
op0 = valueize_expr (vn_get_expr_for (op0));
! else if (SSA_VAL (op0) != VN_TOP && SSA_VAL (op0) != op0)
! op0 = SSA_VAL (op0);
}
if (TREE_CODE (op1) == SSA_NAME)
{
! if (VN_INFO (op1)->has_constants)
op1 = valueize_expr (vn_get_expr_for (op1));
! else if (SSA_VAL (op1) != VN_TOP && SSA_VAL (op1) != op1)
! op1 = SSA_VAL (op1);
}
/* Pointer plus constant can be represented as invariant address.
Do so to allow further propatation, see also tree forwprop. */
! if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
&& host_integerp (op1, 1)
&& TREE_CODE (op0) == ADDR_EXPR
&& is_gimple_min_invariant (op0))
--- 2871,2895 ----
if (TREE_CODE (op0) == SSA_NAME)
{
if (VN_INFO (op0)->has_constants
! || TREE_CODE_CLASS (code) == tcc_comparison
! || code == COMPLEX_EXPR)
op0 = valueize_expr (vn_get_expr_for (op0));
! else
! op0 = vn_valueize (op0);
}
if (TREE_CODE (op1) == SSA_NAME)
{
! if (VN_INFO (op1)->has_constants
! || code == COMPLEX_EXPR)
op1 = valueize_expr (vn_get_expr_for (op1));
! else
! op1 = vn_valueize (op1);
}
/* Pointer plus constant can be represented as invariant address.
Do so to allow further propatation, see also tree forwprop. */
! if (code == POINTER_PLUS_EXPR
&& host_integerp (op1, 1)
&& TREE_CODE (op0) == ADDR_EXPR
&& is_gimple_min_invariant (op0))
*************** simplify_binary_expression (gimple stmt)
*** 2898,2905 ****
fold_defer_overflow_warnings ();
! result = fold_binary (gimple_assign_rhs_code (stmt),
! gimple_expr_type (stmt), op0, op1);
if (result)
STRIP_USELESS_TYPE_CONVERSION (result);
--- 2904,2910 ----
fold_defer_overflow_warnings ();
! result = fold_binary (code, gimple_expr_type (stmt), op0, op1);
if (result)
STRIP_USELESS_TYPE_CONVERSION (result);
*************** simplify_unary_expression (gimple stmt)
*** 2924,2935 ****
{
tree result = NULL_TREE;
tree orig_op0, op0 = gimple_assign_rhs1 (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)
op0 = TREE_OPERAND (op0, 0);
if (TREE_CODE (op0) != SSA_NAME)
--- 2929,2941 ----
{
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 (code == REALPART_EXPR
! || code == IMAGPART_EXPR
! || code == VIEW_CONVERT_EXPR)
op0 = TREE_OPERAND (op0, 0);
if (TREE_CODE (op0) != SSA_NAME)
*************** simplify_unary_expression (gimple stmt)
*** 2938,2947 ****
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)
{
/* We want to do tree-combining on conversion-like expressions.
Make sure we feed only SSA_NAMEs or constants to fold though. */
--- 2944,2953 ----
orig_op0 = op0;
if (VN_INFO (op0)->has_constants)
op0 = valueize_expr (vn_get_expr_for (op0));
! 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. */
*************** simplify_unary_expression (gimple stmt)
*** 2958,2965 ****
if (op0 == orig_op0)
return NULL_TREE;
! result = fold_unary_ignore_overflow (gimple_assign_rhs_code (stmt),
! gimple_expr_type (stmt), op0);
if (result)
{
STRIP_USELESS_TYPE_CONVERSION (result);
--- 2964,2970 ----
if (op0 == orig_op0)
return NULL_TREE;
! result = fold_unary_ignore_overflow (code, gimple_expr_type (stmt), op0);
if (result)
{
STRIP_USELESS_TYPE_CONVERSION (result);
*************** simplify_unary_expression (gimple stmt)
*** 2970,2988 ****
return NULL_TREE;
}
- /* 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;
- }
-
/* Try to simplify RHS using equivalences and constant folding. */
static tree
--- 2975,2980 ----
Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-32.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-32.c 2011-09-06 15:03:20.000000000 +0200
***************
*** 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" } } */
More information about the Gcc-patches
mailing list