On Feb 6, 2025, Sam James <[email protected]> wrote:
> Richard Biener <[email protected]> writes:
>> On Thu, Feb 6, 2025 at 2:41 PM Alexandre Oliva <[email protected]> wrote:
>>>
>>> On Jan 27, 2025, Richard Biener <[email protected]> wrote:
>>> > (I see the assert is no longer in the patch).
>>>
>>> That's because the assert went in as part of an earlier patch. I take
>>> it it should be backed out along with the to-be-split-out bits above,
>>> right?
>>
>> Yes.
>>
>> (IIRC there's also a PR tripping over this or a similar assert)
> Right, PR118706.
Thanks. I've added its testcase to the patch below, reverted the
assert, and dropped the other unwanted bits. Regstrapped on
x86_64-linux-gnu. Ok to install?
If decode_field_reference finds a load that accesses past the inner
object's size, bail out.
Drop the too-strict assert.
for gcc/ChangeLog
PR tree-optimization/118514
PR tree-optimization/118706
* gimple-fold.cc (decode_field_reference): Refuse to consider
merging out-of-bounds BIT_FIELD_REFs.
(make_bit_field_load): Drop too-strict assert.
* tree-eh.cc (bit_field_ref_in_bounds_p): Rename to...
(access_in_bounds_of_type_p): ... this. Change interface,
export.
(tree_could_trap_p): Adjust.
* tree-eh.h (access_in_bounds_of_type_p): Declare.
for gcc/testsuite/ChangeLog
PR tree-optimization/118514
PR tree-optimization/118706
* gcc.dg/field-merge-25.c: New.
---
gcc/gimple-fold.cc | 11 ++---------
gcc/testsuite/gcc.dg/field-merge-25.c | 15 +++++++++++++++
gcc/tree-eh.cc | 25 +++++++++++++------------
gcc/tree-eh.h | 1 +
4 files changed, 31 insertions(+), 21 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/field-merge-25.c
diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index 45485782cdf91..29191685a43c5 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -7686,10 +7686,8 @@ decode_field_reference (tree *pexp, HOST_WIDE_INT
*pbitsize,
|| bs <= shiftrt
|| offset != 0
|| TREE_CODE (inner) == PLACEHOLDER_EXPR
- /* Reject out-of-bound accesses (PR79731). */
- || (! AGGREGATE_TYPE_P (TREE_TYPE (inner))
- && compare_tree_int (TYPE_SIZE (TREE_TYPE (inner)),
- bp + bs) < 0)
+ /* Reject out-of-bound accesses (PR79731, PR118514). */
+ || !access_in_bounds_of_type_p (TREE_TYPE (inner), bs, bp)
|| (INTEGRAL_TYPE_P (TREE_TYPE (inner))
&& !type_has_mode_precision_p (TREE_TYPE (inner))))
return NULL_TREE;
@@ -7859,11 +7857,6 @@ make_bit_field_load (location_t loc, tree inner, tree
orig_inner, tree type,
gimple *new_stmt = gsi_stmt (i);
if (gimple_has_mem_ops (new_stmt))
gimple_set_vuse (new_stmt, reaching_vuse);
- gcc_checking_assert (! (gimple_assign_load_p (point)
- && gimple_assign_load_p (new_stmt))
- || (tree_could_trap_p (gimple_assign_rhs1 (point))
- == tree_could_trap_p (gimple_assign_rhs1
- (new_stmt))));
}
gimple_stmt_iterator gsi = gsi_for_stmt (point);
diff --git a/gcc/testsuite/gcc.dg/field-merge-25.c
b/gcc/testsuite/gcc.dg/field-merge-25.c
new file mode 100644
index 0000000000000..e769b0ae7b846
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/field-merge-25.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fno-tree-fre" } */
+
+/* PR tree-optimization/118706 */
+
+int a[1][1][3], b;
+int main() {
+ int c = -1;
+ while (b) {
+ if (a[c][c][6])
+ break;
+ if (a[0][0][0])
+ break;
+ }
+}
diff --git a/gcc/tree-eh.cc b/gcc/tree-eh.cc
index 7015189a2de83..a4d59954c0597 100644
--- a/gcc/tree-eh.cc
+++ b/gcc/tree-eh.cc
@@ -2646,24 +2646,22 @@ range_in_array_bounds_p (tree ref)
return true;
}
-/* Return true iff EXPR, a BIT_FIELD_REF, accesses a bit range that is known to
- be in bounds for the referred operand type. */
+/* Return true iff a BIT_FIELD_REF <(TYPE)???, SIZE, OFFSET> would access a bit
+ range that is known to be in bounds for TYPE. */
-static bool
-bit_field_ref_in_bounds_p (tree expr)
+bool
+access_in_bounds_of_type_p (tree type, poly_uint64 size, poly_uint64 offset)
{
- tree size_tree;
- poly_uint64 size_max, min, wid, max;
+ tree type_size_tree;
+ poly_uint64 type_size_max, min = offset, wid = size, max;
- size_tree = TYPE_SIZE (TREE_TYPE (TREE_OPERAND (expr, 0)));
- if (!size_tree || !poly_int_tree_p (size_tree, &size_max))
+ type_size_tree = TYPE_SIZE (type);
+ if (!type_size_tree || !poly_int_tree_p (type_size_tree, &type_size_max))
return false;
- min = bit_field_offset (expr);
- wid = bit_field_size (expr);
max = min + wid;
if (maybe_lt (max, min)
- || maybe_lt (size_max, max))
+ || maybe_lt (type_size_max, max))
return false;
return true;
@@ -2712,7 +2710,10 @@ tree_could_trap_p (tree expr)
switch (code)
{
case BIT_FIELD_REF:
- if (DECL_P (TREE_OPERAND (expr, 0)) && !bit_field_ref_in_bounds_p (expr))
+ if (DECL_P (TREE_OPERAND (expr, 0))
+ && !access_in_bounds_of_type_p (TREE_TYPE (TREE_OPERAND (expr, 0)),
+ bit_field_size (expr),
+ bit_field_offset (expr)))
return true;
/* Fall through. */
diff --git a/gcc/tree-eh.h b/gcc/tree-eh.h
index 69fe193f1b82f..1fe6de80c42e7 100644
--- a/gcc/tree-eh.h
+++ b/gcc/tree-eh.h
@@ -36,6 +36,7 @@ extern void redirect_eh_dispatch_edge (geh_dispatch *, edge,
basic_block);
extern bool operation_could_trap_helper_p (enum tree_code, bool, bool, bool,
bool, tree, bool *);
extern bool operation_could_trap_p (enum tree_code, bool, bool, tree);
+extern bool access_in_bounds_of_type_p (tree, poly_uint64, poly_uint64);
extern bool tree_could_trap_p (tree);
extern tree rewrite_to_non_trapping_overflow (tree);
extern bool stmt_could_throw_p (function *, gimple *);
--
Alexandre Oliva, happy hacker https://FSFLA.org/blogs/lxo/
Free Software Activist GNU Toolchain Engineer
More tolerance and less prejudice are key for inclusion and diversity
Excluding neuro-others for not behaving ""normal"" is *not* inclusive