diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-01-29 14:45:44 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-01-29 14:45:44 +0000 |
commit | b904104cb8c81fcd196aa64cde69663157de4be0 (patch) | |
tree | 0b29ae9817e081fdd5d933b5bcbf8bebda1d3615 /gcc/tree-ssa-forwprop.c | |
parent | 3dbd6a28ad910ef80a90038f6f24c14727566fd7 (diff) | |
download | gcc-b904104cb8c81fcd196aa64cde69663157de4be0.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@207239 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-forwprop.c')
-rw-r--r-- | gcc/tree-ssa-forwprop.c | 99 |
1 files changed, 98 insertions, 1 deletions
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 41285d3a19f..ebdd8f546f2 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. */ |