https://gcc.gnu.org/g:46860078a0dc147b76ad0cc660b021c6e5b7bb81

commit r15-10169-g46860078a0dc147b76ad0cc660b021c6e5b7bb81
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Thu Jul 31 12:10:02 2025 +0200

    change get_best_mode args int -> HOST_WIDE_INT [PR121264]
    
    The following testcase is miscompiled, because byte 0x20000000
    is bit 0x100000000 and ifcombine incorrectly combines the two loads
    into a BIT_FIELD_REF even when they are very far away.
    The problem is that gimple-fold.cc ifcombine uses get_best_mode heavily,
    and that function has just int bitsize and int bitpos arguments, so
    when called e.g. with
      if (get_best_mode (end_bit - first_bit, first_bit, 0, ll_end_region,
                         ll_align, BITS_PER_WORD, volatilep, &lnmode))
    where end_bit - first_bit doesn't fit into int, it is silently truncated.
    If there was just a single problematic get_best_mode call, I would probably
    just check for overflows in the caller, but there are many.
    And the two arguments are used solely as arguments to
    bit_field_mode_iterator constructor which has HOST_WIDE_INT arguments,
    so I think the easiest fix is just make the get_best_mode arguments
    also HOST_WIDE_INT.
    
    2025-07-31  Jakub Jelinek  <ja...@redhat.com>
    
            PR tree-optimization/121264
            * machmode.h (get_best_mode): Change type of first 2 arguments
            from int to HOST_WIDE_INT.
            * stor-layout.cc (get_best_mode): Likewise.
    
            * gcc.dg/tree-ssa/pr121264.c: New test.
    
    (cherry picked from commit e624d5559d21992c9e5da85b4ae75629a61afc2c)

Diff:
---
 gcc/machmode.h                           |  3 ++-
 gcc/stor-layout.cc                       |  2 +-
 gcc/testsuite/gcc.dg/tree-ssa/pr121264.c | 12 ++++++++++++
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/gcc/machmode.h b/gcc/machmode.h
index 467681d9d2f3..2f2d349be29c 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -958,7 +958,8 @@ private:
 
 /* Find the best mode to use to access a bit field.  */
 
-extern bool get_best_mode (int, int, poly_uint64, poly_uint64, unsigned int,
+extern bool get_best_mode (HOST_WIDE_INT, HOST_WIDE_INT,
+                          poly_uint64, poly_uint64, unsigned int,
                           unsigned HOST_WIDE_INT, bool, scalar_int_mode *);
 
 /* Determine alignment, 1<=result<=BIGGEST_ALIGNMENT.  */
diff --git a/gcc/stor-layout.cc b/gcc/stor-layout.cc
index 18b5af56124d..a7eaf40f1d8f 100644
--- a/gcc/stor-layout.cc
+++ b/gcc/stor-layout.cc
@@ -3162,7 +3162,7 @@ bit_field_mode_iterator::prefer_smaller_modes ()
    decide which of the above modes should be used.  */
 
 bool
-get_best_mode (int bitsize, int bitpos,
+get_best_mode (HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
               poly_uint64 bitregion_start, poly_uint64 bitregion_end,
               unsigned int align,
               unsigned HOST_WIDE_INT largest_mode_bitsize, bool volatilep,
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr121264.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr121264.c
new file mode 100644
index 000000000000..bd5acc0b1ece
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr121264.c
@@ -0,0 +1,12 @@
+/* PR tree-optimization/121264 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump " \\\| " "optimized" } } */
+
+struct A { char b; char c[0x20000010]; } a;
+
+int
+foo ()
+{
+  return a.c[0x20000000] || a.c[1];
+}

Reply via email to