From 77574c353464b38f98b7d69a5fb555b6888701a3 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 29 Jan 2014 14:45:44 +0000 Subject: [PATCH] re PR middle-end/58742 (pointer arithmetic simplification) 2014-01-29 Richard Biener 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 --- gcc/ChangeLog | 9 ++++ gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/gcc.dg/pr58742-1.c | 13 ++++++ gcc/testsuite/gcc.dg/pr58742-2.c | 13 ++++++ gcc/testsuite/gcc.dg/pr58742-3.c | 14 ++++++ gcc/tree-ssa-forwprop.c | 99 +++++++++++++++++++++++++++++++++++++++- 6 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/pr58742-1.c create mode 100644 gcc/testsuite/gcc.dg/pr58742-2.c create mode 100644 gcc/testsuite/gcc.dg/pr58742-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fc31af0..c81432d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,14 @@ 2014-01-29 Richard Biener + 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 + * lto-streamer.h (LTO_major_version): Bump to 3. (LTO_minor_version): Reset to 0. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 15ea8c7..f330ee0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2014-01-29 Richard Biener + + 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 * gcc.target/arm/ftest-armv7ve-arm.c: New. diff --git a/gcc/testsuite/gcc.dg/pr58742-1.c b/gcc/testsuite/gcc.dg/pr58742-1.c new file mode 100644 index 0000000..94f5627 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr58742-1.c @@ -0,0 +1,13 @@ +/* { 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" } } */ diff --git a/gcc/testsuite/gcc.dg/pr58742-2.c b/gcc/testsuite/gcc.dg/pr58742-2.c new file mode 100644 index 0000000..e0011e9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr58742-2.c @@ -0,0 +1,13 @@ +/* { 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" } } */ diff --git a/gcc/testsuite/gcc.dg/pr58742-3.c b/gcc/testsuite/gcc.dg/pr58742-3.c new file mode 100644 index 0000000..f4e95e6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr58742-3.c @@ -0,0 +1,14 @@ +/* { 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" } } */ diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 41285d3..ebdd8f5 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -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. */ -- 2.7.4