Commit 77574c35 by Richard Biener Committed by Richard Biener

re PR middle-end/58742 (pointer arithmetic simplification)

2014-01-29  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/58742
	* tree-ssa-forwprop.c (associate_pointerplus): Rename to
	associate_pointerplus_align.
	(associate_pointerplus_diff): New function.
	(associate_pointerplus): Likewise.  Call associate_pointerplus_align
	and associate_pointerplus_diff.

	* gcc.dg/pr58742-1.c: New testcase.
	* gcc.dg/pr58742-2.c: Likewise.
	* gcc.dg/pr58742-3.c: Likewise.

From-SVN: r207239
parent 15b25b24
2014-01-29 Richard Biener <rguenther@suse.de>
PR tree-optimization/58742
* tree-ssa-forwprop.c (associate_pointerplus): Rename to
associate_pointerplus_align.
(associate_pointerplus_diff): New function.
(associate_pointerplus): Likewise. Call associate_pointerplus_align
and associate_pointerplus_diff.
2014-01-29 Richard Biener <rguenther@suse.de>
* lto-streamer.h (LTO_major_version): Bump to 3.
(LTO_minor_version): Reset to 0.
......
2014-01-29 Richard Biener <rguenther@suse.de>
PR tree-optimization/58742
* gcc.dg/pr58742-1.c: New testcase.
* gcc.dg/pr58742-2.c: Likewise.
* gcc.dg/pr58742-3.c: Likewise.
2014-01-29 Renlin Li <Renlin.Li@arm.com>
* gcc.target/arm/ftest-armv7ve-arm.c: New.
......
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-cddce1" } */
int *
fx (int *b, int *e)
{
__SIZE_TYPE__ p = e - b;
/* The first forwprop pass should optimize this to return e; */
return b + p;
}
/* { dg-final { scan-tree-dump "return e" "cddce1" } } */
/* { dg-final { cleanup-tree-dump "cddce1" } } */
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-cddce1" } */
__SIZE_TYPE__
fx (char *a, __SIZE_TYPE__ sz)
{
char *b = a + sz;
/* The first forwprop pass should optimize this to return sz; */
return b - a;
}
/* { dg-final { scan-tree-dump "return sz" "cddce1" } } */
/* { dg-final { cleanup-tree-dump "cddce1" } } */
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-cddce1" } */
int *
fx (int *a, int sz)
{
int *b = a + sz;
b = b - sz;
/* forwprop together with FRE should optimize this to return a; */
return b;
}
/* { dg-final { scan-tree-dump "return a" "cddce1" } } */
/* { dg-final { cleanup-tree-dump "cddce1" } } */
......@@ -2802,7 +2802,7 @@ out:
true if anything changed, false otherwise. */
static bool
associate_pointerplus (gimple_stmt_iterator *gsi)
associate_pointerplus_align (gimple_stmt_iterator *gsi)
{
gimple stmt = gsi_stmt (*gsi);
gimple def_stmt;
......@@ -2850,6 +2850,103 @@ associate_pointerplus (gimple_stmt_iterator *gsi)
return true;
}
/* Associate operands of a POINTER_PLUS_EXPR assignmen at *GSI. Returns
true if anything changed, false otherwise. */
static bool
associate_pointerplus_diff (gimple_stmt_iterator *gsi)
{
gimple stmt = gsi_stmt (*gsi);
gimple def_stmt;
tree ptr1, rhs;
/* Pattern match
tem1 = (long) ptr1;
tem2 = (long) ptr2;
tem3 = tem2 - tem1;
tem4 = (unsigned long) tem3;
tem5 = ptr1 + tem4;
and produce
tem5 = ptr2; */
ptr1 = gimple_assign_rhs1 (stmt);
rhs = gimple_assign_rhs2 (stmt);
if (TREE_CODE (rhs) != SSA_NAME)
return false;
gimple minus = SSA_NAME_DEF_STMT (rhs);
/* Conditionally look through a sign-changing conversion. */
if (is_gimple_assign (minus)
&& CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (minus))
&& (TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (minus)))
== TYPE_PRECISION (TREE_TYPE (rhs)))
&& TREE_CODE (gimple_assign_rhs1 (minus)) == SSA_NAME)
minus = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (minus));
if (!is_gimple_assign (minus))
return false;
if (gimple_assign_rhs_code (minus) != MINUS_EXPR)
return false;
rhs = gimple_assign_rhs2 (minus);
if (TREE_CODE (rhs) != SSA_NAME)
return false;
def_stmt = SSA_NAME_DEF_STMT (rhs);
if (!is_gimple_assign (def_stmt)
|| ! CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))
|| gimple_assign_rhs1 (def_stmt) != ptr1)
return false;
rhs = gimple_assign_rhs1 (minus);
if (TREE_CODE (rhs) != SSA_NAME)
return false;
def_stmt = SSA_NAME_DEF_STMT (rhs);
if (!is_gimple_assign (def_stmt)
|| ! CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
return false;
rhs = gimple_assign_rhs1 (def_stmt);
if (! useless_type_conversion_p (TREE_TYPE (ptr1), TREE_TYPE (rhs)))
return false;
gimple_assign_set_rhs_with_ops (gsi, TREE_CODE (rhs), rhs, NULL_TREE);
update_stmt (stmt);
return true;
}
/* Associate operands of a POINTER_PLUS_EXPR assignmen at *GSI. Returns
true if anything changed, false otherwise. */
static bool
associate_pointerplus (gimple_stmt_iterator *gsi)
{
gimple stmt = gsi_stmt (*gsi);
gimple def_stmt;
tree ptr, off1, off2;
if (associate_pointerplus_align (gsi)
|| associate_pointerplus_diff (gsi))
return true;
/* Associate (p +p off1) +p off2 as (p +p (off1 + off2)). */
ptr = gimple_assign_rhs1 (stmt);
off1 = gimple_assign_rhs2 (stmt);
if (TREE_CODE (ptr) != SSA_NAME)
return false;
def_stmt = SSA_NAME_DEF_STMT (ptr);
if (!is_gimple_assign (def_stmt)
|| gimple_assign_rhs_code (def_stmt) != POINTER_PLUS_EXPR)
return false;
ptr = gimple_assign_rhs1 (def_stmt);
off2 = gimple_assign_rhs2 (def_stmt);
if (!types_compatible_p (TREE_TYPE (off1), TREE_TYPE (off2)))
return false;
tree off = make_ssa_name (TREE_TYPE (off1), NULL);
gimple ostmt = gimple_build_assign_with_ops (PLUS_EXPR, off, off1, off2);
gsi_insert_before (gsi, ostmt, GSI_SAME_STMT);
gimple_assign_set_rhs_with_ops (gsi, POINTER_PLUS_EXPR, ptr, off);
update_stmt (stmt);
return true;
}
/* Combine two conversions in a row for the second conversion at *GSI.
Returns 1 if there were any changes made, 2 if cfg-cleanup needs to
run. Else it returns 0. */
......
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