Commit c2723bde by Bill Schmidt Committed by William Schmidt

re PR tree-optimization/52976 (Revision 186384 breaks the polyhedron tests…

re PR tree-optimization/52976 (Revision 186384 breaks the polyhedron tests aermod.f90 and doduc.f90 at -O3 -ffast-math)

gcc:

2012-04-18  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

	PR tree-optimization/52976
	* tree-ssa-reassoc.c (stmt_is_power_of_op): New function.
	(decrement_power): Likewise.
	(propagate_op_to_single_use): Likewise.
	(zero_one_operation): Handle __builtin_pow* calls in linearized
	expression trees; factor logic into propagate_op_to_single_use.
	(undistribute_ops_list): Allow operands with repeat counts > 1.


gcc/testsuite:

2012-04-18  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

	PR tree-optimization/52976
	gfortran.dg/reassoc_7.f: New test.
	gfortran.dg/reassoc_8.f: Likewise.
	gfortran.dg/reassoc_9.f: Likewise.
	gfortran.dg/reassoc_10.f: Likewise.

From-SVN: r186567
parent 03fd03d5
2012-04-18 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
PR tree-optimization/52976
* tree-ssa-reassoc.c (stmt_is_power_of_op): New function.
(decrement_power): Likewise.
(propagate_op_to_single_use): Likewise.
(zero_one_operation): Handle __builtin_pow* calls in linearized
expression trees; factor logic into propagate_op_to_single_use.
(undistribute_ops_list): Allow operands with repeat counts > 1.
2012-04-18 Richard Guenther <rguenther@suse.de> 2012-04-18 Richard Guenther <rguenther@suse.de>
PR tree-optimization/44688 PR tree-optimization/44688
......
2012-04-18 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
PR tree-optimization/52976
gfortran.dg/reassoc_7.f: New test.
gfortran.dg/reassoc_8.f: Likewise.
gfortran.dg/reassoc_9.f: Likewise.
gfortran.dg/reassoc_10.f: Likewise.
2012-04-18 Paolo Carlini <paolo.carlini@oracle.com> 2012-04-18 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/52422 PR c++/52422
......
! { dg-do compile }
! { dg-options "-O3 -ffast-math -fdump-tree-optimized" }
SUBROUTINE S55199(P,Q,Dvdph)
implicit none
real(8) :: c1,c2,c3,P,Q,Dvdph
c1=0.1d0
c2=0.2d0
c3=0.3d0
Dvdph = c1 + 2.*P*c2 + 3.*P**2*Q**3*c3
END
! There should be five multiplies following un-distribution
! and power expansion.
! { dg-final { scan-tree-dump-times " \\\* " 5 "optimized" } }
! { dg-final { cleanup-tree-dump "optimized" } }
! { dg-do compile }
! { dg-options "-O3 -ffast-math -fdump-tree-optimized" }
SUBROUTINE S55199(P,Dvdph)
implicit none
real(8) :: c1,c2,c3,P,Dvdph
c1=0.1d0
c2=0.2d0
c3=0.3d0
Dvdph = c1 + 2.*P*c2 + 3.*P**2*c3
END
! There should be two multiplies following un-distribution.
! { dg-final { scan-tree-dump-times " \\\* " 2 "optimized" } }
! { dg-final { cleanup-tree-dump "optimized" } }
! { dg-do compile }
! { dg-options "-O3 -ffast-math -fdump-tree-optimized" }
SUBROUTINE S55199(P,Dvdph)
implicit none
real(8) :: c1,c2,c3,P,Dvdph
c1=0.1d0
c2=0.2d0
c3=0.3d0
Dvdph = c1 + 2.*P**2*c2 + 3.*P**3*c3
END
! There should be three multiplies following un-distribution
! and power expansion.
! { dg-final { scan-tree-dump-times " \\\* " 3 "optimized" } }
! { dg-final { cleanup-tree-dump "optimized" } }
! { dg-do compile }
! { dg-options "-O3 -ffast-math -fdump-tree-optimized" }
SUBROUTINE S55199(P,Dvdph)
implicit none
real(8) :: c1,c2,c3,P,Dvdph
c1=0.1d0
c2=0.2d0
c3=0.3d0
Dvdph = c1 + 2.*P**2*c2 + 3.*P**4*c3
END
! There should be three multiplies following un-distribution
! and power expansion.
! { dg-final { scan-tree-dump-times " \\\* " 3 "optimized" } }
! { dg-final { cleanup-tree-dump "optimized" } }
...@@ -1020,6 +1020,98 @@ oecount_cmp (const void *p1, const void *p2) ...@@ -1020,6 +1020,98 @@ oecount_cmp (const void *p1, const void *p2)
return c1->id - c2->id; return c1->id - c2->id;
} }
/* Return TRUE iff STMT represents a builtin call that raises OP
to some exponent. */
static bool
stmt_is_power_of_op (gimple stmt, tree op)
{
tree fndecl;
if (!is_gimple_call (stmt))
return false;
fndecl = gimple_call_fndecl (stmt);
if (!fndecl
|| DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
return false;
switch (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)))
{
CASE_FLT_FN (BUILT_IN_POW):
CASE_FLT_FN (BUILT_IN_POWI):
return (operand_equal_p (gimple_call_arg (stmt, 0), op, 0));
default:
return false;
}
}
/* Given STMT which is a __builtin_pow* call, decrement its exponent
in place and return the result. Assumes that stmt_is_power_of_op
was previously called for STMT and returned TRUE. */
static HOST_WIDE_INT
decrement_power (gimple stmt)
{
REAL_VALUE_TYPE c, cint;
HOST_WIDE_INT power;
tree arg1;
switch (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)))
{
CASE_FLT_FN (BUILT_IN_POW):
arg1 = gimple_call_arg (stmt, 1);
c = TREE_REAL_CST (arg1);
power = real_to_integer (&c) - 1;
real_from_integer (&cint, VOIDmode, power, 0, 0);
gimple_call_set_arg (stmt, 1, build_real (TREE_TYPE (arg1), cint));
return power;
CASE_FLT_FN (BUILT_IN_POWI):
arg1 = gimple_call_arg (stmt, 1);
power = TREE_INT_CST_LOW (arg1) - 1;
gimple_call_set_arg (stmt, 1, build_int_cst (TREE_TYPE (arg1), power));
return power;
default:
gcc_unreachable ();
}
}
/* Find the single immediate use of STMT's LHS, and replace it
with OP. Remove STMT. If STMT's LHS is the same as *DEF,
replace *DEF with OP as well. */
static void
propagate_op_to_single_use (tree op, gimple stmt, tree *def)
{
tree lhs;
gimple use_stmt;
use_operand_p use;
gimple_stmt_iterator gsi;
if (is_gimple_call (stmt))
lhs = gimple_call_lhs (stmt);
else
lhs = gimple_assign_lhs (stmt);
gcc_assert (has_single_use (lhs));
single_imm_use (lhs, &use, &use_stmt);
if (lhs == *def)
*def = op;
SET_USE (use, op);
if (TREE_CODE (op) != SSA_NAME)
update_stmt (use_stmt);
gsi = gsi_for_stmt (stmt);
gsi_remove (&gsi, true);
release_defs (stmt);
if (is_gimple_call (stmt))
unlink_stmt_vdef (stmt);
}
/* Walks the linear chain with result *DEF searching for an operation /* Walks the linear chain with result *DEF searching for an operation
with operand OP and code OPCODE removing that from the chain. *DEF with operand OP and code OPCODE removing that from the chain. *DEF
is updated if there is only one operand but no operation left. */ is updated if there is only one operand but no operation left. */
...@@ -1031,7 +1123,17 @@ zero_one_operation (tree *def, enum tree_code opcode, tree op) ...@@ -1031,7 +1123,17 @@ zero_one_operation (tree *def, enum tree_code opcode, tree op)
do do
{ {
tree name = gimple_assign_rhs1 (stmt); tree name;
if (opcode == MULT_EXPR
&& stmt_is_power_of_op (stmt, op))
{
if (decrement_power (stmt) == 1)
propagate_op_to_single_use (op, stmt, def);
return;
}
name = gimple_assign_rhs1 (stmt);
/* If this is the operation we look for and one of the operands /* If this is the operation we look for and one of the operands
is ours simply propagate the other operand into the stmts is ours simply propagate the other operand into the stmts
...@@ -1040,24 +1142,27 @@ zero_one_operation (tree *def, enum tree_code opcode, tree op) ...@@ -1040,24 +1142,27 @@ zero_one_operation (tree *def, enum tree_code opcode, tree op)
&& (name == op && (name == op
|| gimple_assign_rhs2 (stmt) == op)) || gimple_assign_rhs2 (stmt) == op))
{ {
gimple use_stmt;
use_operand_p use;
gimple_stmt_iterator gsi;
if (name == op) if (name == op)
name = gimple_assign_rhs2 (stmt); name = gimple_assign_rhs2 (stmt);
gcc_assert (has_single_use (gimple_assign_lhs (stmt))); propagate_op_to_single_use (name, stmt, def);
single_imm_use (gimple_assign_lhs (stmt), &use, &use_stmt);
if (gimple_assign_lhs (stmt) == *def)
*def = name;
SET_USE (use, name);
if (TREE_CODE (name) != SSA_NAME)
update_stmt (use_stmt);
gsi = gsi_for_stmt (stmt);
gsi_remove (&gsi, true);
release_defs (stmt);
return; return;
} }
/* We might have a multiply of two __builtin_pow* calls, and
the operand might be hiding in the rightmost one. */
if (opcode == MULT_EXPR
&& gimple_assign_rhs_code (stmt) == opcode
&& TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME)
{
gimple stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt));
if (stmt_is_power_of_op (stmt2, op))
{
if (decrement_power (stmt2) == 1)
propagate_op_to_single_use (op, stmt2, def);
return;
}
}
/* Continue walking the chain. */ /* Continue walking the chain. */
gcc_assert (name != op gcc_assert (name != op
&& TREE_CODE (name) == SSA_NAME); && TREE_CODE (name) == SSA_NAME);
...@@ -1222,7 +1327,6 @@ undistribute_ops_list (enum tree_code opcode, ...@@ -1222,7 +1327,6 @@ undistribute_ops_list (enum tree_code opcode,
dcode = gimple_assign_rhs_code (oe1def); dcode = gimple_assign_rhs_code (oe1def);
if ((dcode != MULT_EXPR if ((dcode != MULT_EXPR
&& dcode != RDIV_EXPR) && dcode != RDIV_EXPR)
|| oe1->count != 1
|| !is_reassociable_op (oe1def, dcode, loop)) || !is_reassociable_op (oe1def, dcode, loop))
continue; continue;
...@@ -1266,8 +1370,6 @@ undistribute_ops_list (enum tree_code opcode, ...@@ -1266,8 +1370,6 @@ undistribute_ops_list (enum tree_code opcode,
oecount c; oecount c;
void **slot; void **slot;
size_t idx; size_t idx;
if (oe1->count != 1)
continue;
c.oecode = oecode; c.oecode = oecode;
c.cnt = 1; c.cnt = 1;
c.id = next_oecount_id++; c.id = next_oecount_id++;
...@@ -1336,7 +1438,7 @@ undistribute_ops_list (enum tree_code opcode, ...@@ -1336,7 +1438,7 @@ undistribute_ops_list (enum tree_code opcode,
FOR_EACH_VEC_ELT (operand_entry_t, subops[i], j, oe1) FOR_EACH_VEC_ELT (operand_entry_t, subops[i], j, oe1)
{ {
if (oe1->op == c->op && oe1->count == 1) if (oe1->op == c->op)
{ {
SET_BIT (candidates2, i); SET_BIT (candidates2, i);
++nr_candidates2; ++nr_candidates2;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment