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

Reply via email to