On Wed, Jan 29, 2025 at 03:46:46PM +0100, Richard Biener wrote: > The following guards the BIT_FIELD_REF expansion fallback for > MEM_REFs of entities expanded to register (or constant) further, > avoiding large out-of-bound offsets by, when the access does not > overlap the base object, expanding the offset as if it were zero. > > Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. > > I didn't feel lucky enough trying to simply return const0_rtx for > fully out-of-bound accesses. > > OK? > > Thanks, > Richard. > > PR middle-end/118692 > * expr.cc (expand_expr_real_1): When expanding a MEM_REF > as BIT_FIELD_REF avoid large offsets for accesses not > overlapping the base object. > > * gcc.dg/pr118692.c: New testcase. > --- > gcc/expr.cc | 8 ++++++++ > gcc/testsuite/gcc.dg/pr118692.c | 10 ++++++++++ > 2 files changed, 18 insertions(+) > create mode 100644 gcc/testsuite/gcc.dg/pr118692.c > > diff --git a/gcc/expr.cc b/gcc/expr.cc > index 7f3149b85ee..10467f82c0d 100644 > --- a/gcc/expr.cc > +++ b/gcc/expr.cc > @@ -11806,6 +11806,14 @@ expand_expr_real_1 (tree exp, rtx target, > machine_mode tmode, > set_mem_size (temp, int_size_in_bytes (type)); > return temp; > } > + /* When the access is fully outside of the underlying object > + expand the offset as zero. This avoids out-of-bound > + BIT_FIELD_REFs and generates smaller code for these cases > + with UB. */ > + type_size = tree_to_poly_uint64 (TYPE_SIZE_UNIT (type)); > + if (!ranges_maybe_overlap_p (offset, type_size, 0, > + GET_MODE_SIZE (DECL_MODE (base)))) > + offset = 0; > exp = build3 (BIT_FIELD_REF, type, base, TYPE_SIZE (type), > bitsize_int (offset * BITS_PER_UNIT)); > REF_REVERSE_STORAGE_ORDER (exp) = reverse; > diff --git a/gcc/testsuite/gcc.dg/pr118692.c b/gcc/testsuite/gcc.dg/pr118692.c > new file mode 100644 > index 00000000000..49cff35b8b7 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr118692.c > @@ -0,0 +1,10 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2" } */ > + > +_Complex cf;
Please use _Complex double here. > + > +void > +foo(char c) > +{ > + cf += *(_Complex *)__builtin_memcpy(8143523003042804629 + &c, 0, 0); Ditto here. I think it might be a good idea to use LL suffix after the constant too. Otherwise LGTM. Jakub