Propogate constant additions and subtractions to an offset when
computing an estimate for a PHI of constants.
gcc/ChangeLog:
PR tree-optimization/PR116556
* tree-object-size.cc (try_collapsing_offset): New parameters
CST and CODE. Use them to propagate PLUS_EXPR and MINUS_EXPR
through recursively calling TRY_COLLAPSE_OFFSET.
(plus_stmt_object_size): Adjust call to TRY_COLLAPSE_OFFSET.
* testsuite/gcc.dg/builtin-object-size-1.c (test13): Test
constant addition and subtraction.
* testsuite/gcc.dg/builtin-object-size-3.c (test13): Likewise.
Signed-off-by: Siddhesh Poyarekar <[email protected]>
---
gcc/testsuite/gcc.dg/builtin-object-size-1.c | 20 +++++++
gcc/testsuite/gcc.dg/builtin-object-size-3.c | 20 +++++++
gcc/tree-object-size.cc | 58 ++++++++++++++++----
3 files changed, 86 insertions(+), 12 deletions(-)
diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-1.c
b/gcc/testsuite/gcc.dg/builtin-object-size-1.c
index 1f5cd5d99a1..6ffe12be683 100644
--- a/gcc/testsuite/gcc.dg/builtin-object-size-1.c
+++ b/gcc/testsuite/gcc.dg/builtin-object-size-1.c
@@ -769,6 +769,26 @@ test13 (unsigned cond)
if (__builtin_object_size (&p[t], 0) != 9)
FAIL ();
#endif
+
+ t += 4;
+
+#ifdef __builtin_object_size
+ if (__builtin_object_size (&p[t], 0) != (cond ? 1 : 5))
+ FAIL ();
+#else
+ if (__builtin_object_size (&p[t], 0) != 5)
+ FAIL ();
+#endif
+
+ t -= 5;
+
+#ifdef __builtin_object_size
+ if (__builtin_object_size (&p[t], 0) != (cond ? 6 : 10))
+ FAIL ();
+#else
+ if (__builtin_object_size (&p[t], 0) != 10)
+ FAIL ();
+#endif
}
int
diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-3.c
b/gcc/testsuite/gcc.dg/builtin-object-size-3.c
index 7fad106fc27..c51cb69c01b 100644
--- a/gcc/testsuite/gcc.dg/builtin-object-size-3.c
+++ b/gcc/testsuite/gcc.dg/builtin-object-size-3.c
@@ -777,6 +777,26 @@ test13 (unsigned cond)
if (__builtin_object_size (&p[t], 2) != 5)
FAIL ();
#endif
+
+ t += 4;
+
+#ifdef __builtin_object_size
+ if (__builtin_object_size (&p[t], 2) != (cond ? 1 : 5))
+ FAIL ();
+#else
+ if (__builtin_object_size (&p[t], 2) != 1)
+ FAIL ();
+#endif
+
+ t -= 5;
+
+#ifdef __builtin_object_size
+ if (__builtin_object_size (&p[t], 2) != (cond ? 6 : 10))
+ FAIL ();
+#else
+ if (__builtin_object_size (&p[t], 2) != 6)
+ FAIL ();
+#endif
}
int
diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc
index 2dfc28407ab..1b569c3d12b 100644
--- a/gcc/tree-object-size.cc
+++ b/gcc/tree-object-size.cc
@@ -1473,7 +1473,7 @@ merge_object_sizes (struct object_size_info *osi, tree
dest, tree orig)
with all of its targets are constants. */
static tree
-try_collapsing_offset (tree op, int object_size_type)
+try_collapsing_offset (tree op, tree cst, tree_code code, int object_size_type)
{
gcc_assert (!(object_size_type & OST_DYNAMIC));
@@ -1485,13 +1485,41 @@ try_collapsing_offset (tree op, int object_size_type)
switch (gimple_code (stmt))
{
case GIMPLE_ASSIGN:
- /* Peek through casts. */
- if (gimple_assign_rhs_code (stmt) == NOP_EXPR)
+ switch (gimple_assign_rhs_code (stmt))
{
- tree ret = try_collapsing_offset (gimple_assign_rhs1 (stmt),
- object_size_type);
- if (TREE_CODE (ret) == INTEGER_CST)
- return ret;
+ /* Peek through casts. */
+ case NOP_EXPR:
+ {
+ tree ret = try_collapsing_offset (gimple_assign_rhs1 (stmt),
+ NULL_TREE, NOP_EXPR,
+ object_size_type);
+ if (TREE_CODE (ret) == INTEGER_CST)
+ return ret;
+ break;
+ }
+ /* Propagate constant offsets to PHI expressions. */
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ {
+ tree rhs1 = gimple_assign_rhs1 (stmt);
+ tree rhs2 = gimple_assign_rhs2 (stmt);
+ tree ret = NULL_TREE;
+
+ if (TREE_CODE (rhs1) == INTEGER_CST)
+ ret = try_collapsing_offset (rhs2, rhs1,
+ gimple_assign_rhs_code (stmt),
+ object_size_type);
+ else if (TREE_CODE (rhs2) == INTEGER_CST)
+ ret = try_collapsing_offset (rhs1, rhs2,
+ gimple_assign_rhs_code (stmt),
+ object_size_type);
+
+ if (ret && TREE_CODE (ret) == INTEGER_CST)
+ return ret;
+ break;
+ }
+ default:
+ break;
}
break;
case GIMPLE_PHI:
@@ -1507,14 +1535,20 @@ try_collapsing_offset (tree op, int object_size_type)
if (TREE_CODE (rhs) != INTEGER_CST)
return op;
+ if (cst)
+ rhs = fold_build2 (code, sizetype,
+ fold_convert (ptrdiff_type_node, rhs),
+ fold_convert (ptrdiff_type_node, cst));
+ else
+ rhs = fold_convert (ptrdiff_type_node, rhs);
+
/* Note that this is the *opposite* of what we usually do with
sizes, because the maximum offset estimate here will give us a
minimum size estimate and vice versa. */
- enum tree_code code = (object_size_type & OST_MINIMUM
- ? MAX_EXPR : MIN_EXPR);
+ enum tree_code selection_code = (object_size_type & OST_MINIMUM
+ ? MAX_EXPR : MIN_EXPR);
- off = fold_build2 (code, ptrdiff_type_node, off,
- fold_convert (ptrdiff_type_node, rhs));
+ off = fold_build2 (selection_code, ptrdiff_type_node, off, rhs);
}
return fold_convert (sizetype, off);
}
@@ -1558,7 +1592,7 @@ plus_stmt_object_size (struct object_size_info *osi, tree
var, gimple *stmt)
return false;
if (!(object_size_type & OST_DYNAMIC) && TREE_CODE (op1) != INTEGER_CST)
- op1 = try_collapsing_offset (op1, object_size_type);
+ op1 = try_collapsing_offset (op1, NULL_TREE, NOP_EXPR, object_size_type);
/* Handle PTR + OFFSET here. */
if (size_valid_p (op1, object_size_type)
--
2.45.1