On Tue, Aug 12, 2025 at 5:14 AM H.J. Lu <hjl.to...@gmail.com> wrote: > > Since SImode MOV only supports signed 32-bit immediate, change unsigned > 32-bit immediate to signed if needed. > > gcc/ > > PR target/121497 > * config/i386/i386-features.cc (ix86_place_single_vector_set): > Change unsigned 32-bit immediate to signed if needed. > > gcc/testsuite/ > > PR target/121497 > * gcc.target/i386/pr121497.c: New test. > > Signed-off-by: H.J. Lu <hjl.to...@gmail.com> > --- > gcc/config/i386/i386-features.cc | 15 +++++++++++++-- > gcc/testsuite/gcc.target/i386/pr121497.c | 18 ++++++++++++++++++ > 2 files changed, 31 insertions(+), 2 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/i386/pr121497.c > > diff --git a/gcc/config/i386/i386-features.cc > b/gcc/config/i386/i386-features.cc > index 9941e61361c..16d1593de77 100644 > --- a/gcc/config/i386/i386-features.cc > +++ b/gcc/config/i386/i386-features.cc > @@ -3193,8 +3193,19 @@ ix86_place_single_vector_set (rtx dest, rtx src, > bitmap bbs, > rtx inner_scalar = load->val; > /* Set the source in (vec_duplicate:V4SI (reg:SI 99)). */ > rtx reg = XEXP (src, 0); > - if ((REG_P (inner_scalar) || MEM_P (inner_scalar)) > - && GET_MODE (reg) != GET_MODE (inner_scalar)) > + if (CONST_INT_P (inner_scalar)) > + { > + if (TARGET_64BIT && GET_MODE (reg) == SImode) > + { > + /* Since SImode MOV only supports signed 32-bit immediate, > + change unsigned 32-bit immediate to signed if needed. */ > + HOST_WIDE_INT val = INTVAL (inner_scalar); > + if (val > 0 && val_signbit_known_set_p (SImode, val)) > + inner_scalar = GEN_INT (val | ~GET_MODE_MASK (SImode)); > + } > + }
I think it's better to handle it in ix86_broadcast_inner like below. diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index a6b7fc96c62..2976626993d 100644 --- a/gcc/config/i386/i386-features.cc +++ b/gcc/config/i386/i386-features.cc @@ -3642,6 +3642,8 @@ ix86_broadcast_inner (rtx op, machine_mode mode, Set *INSN_P to nullptr and return SET_SRC if SET_SRC is an integer constant. */ op = src; + if (mode != GET_MODE (reg)) + op = gen_int_mode (INTVAL (src), mode); *insn_p = nullptr; } else > + else if ((REG_P (inner_scalar) || MEM_P (inner_scalar)) > + && GET_MODE (reg) != GET_MODE (inner_scalar)) > inner_scalar = gen_rtx_SUBREG (GET_MODE (reg), inner_scalar, 0); > rtx set = gen_rtx_SET (reg, inner_scalar); > insn = emit_insn_before (set, set_insn); > diff --git a/gcc/testsuite/gcc.target/i386/pr121497.c > b/gcc/testsuite/gcc.target/i386/pr121497.c > new file mode 100644 > index 00000000000..ce55f9558f0 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr121497.c > @@ -0,0 +1,18 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O3 -msse2 -w" } */ > + > +extern void a(int *); > +int q; > +void b(int c, int d, int e, int f, int g, int h) { > + int t[] = {c, d, e, f, g, h}; > + a(t); > +} > +int main() { > + int k[2], i = 0, *p(); > + if (q) { > + for (; (int)p + i < 2; i++) > + k[i] = -1294967296; > + b(k[0] + 7, k[0] + 9, k[0] + 6, k[0] + 9, k[0] + 9, k[0] + 6); > + } > + return 0; > +} > -- > 2.50.1 > -- BR, Hongtao