diff mbox series

V2 [PATCH] x86: Check mode of pseudo register push

Message ID CAMe9rOqvrQ1sxxPf=gSB73t6bf_fsG0dAT85rTU3nybZTf4pBQ@mail.gmail.com
State New
Headers show
Series V2 [PATCH] x86: Check mode of pseudo register push | expand

Commit Message

H.J. Lu Dec. 6, 2020, 7:10 p.m. UTC
On Sun, Dec 6, 2020 at 10:59 AM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Sun, Dec 6, 2020 at 7:51 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > commit 266f44a91c0c9705d3d18e82d7c5bab32927a18f
> > Author: H.J. Lu <hjl.tools@gmail.com>
> > Date:   Sun May 17 10:10:34 2020 -0700
> >
> >     x86: Allow V1TI vector register pushes
> >
> >     Add V1TI vector register push and split it after reload to a sequence
> >     of:
> >
> >     (set (reg:P SP_REG) (plus:P SP_REG) (const_int -8)))
> >     (set (match_dup 0) (match_dup 1))
> >
> > added a pseudo register push check.  But
> >
> > (insn 13 12 14 3 (set (mem:SI (pre_dec:SI (reg/f:SI 7 sp)) [0  S4 A32])
> >         (reg/v:SI 87 [ srclen ])) "x.c":37:16 54 {*pushsi2}
> >      (expr_list:REG_DEAD (reg/v:SI 87 [ srclen ])
> >         (expr_list:REG_ARGS_SIZE (const_int 4 [0x4])
> >             (nil))))
> >
> > is not a pseudo register push.  In 64-bit mode, mode of pseudo register
> > push is TImode.  In 32-bit mode, it is DImode.  Add pseudo register push
> > mode check to pseudo_reg_set.
> >
> > gcc/
> >
> >         PR target/98161
> >         * config/i386/i386-features.c (pseudo_reg_set): Check mode of
> >         pseudo register push.
> >
> > gcc/testsuite/
> >
> >         * gcc.target/i386/pr98161.c: New test.
> > ---
> >  gcc/config/i386/i386-features.c         |  2 ++
> >  gcc/testsuite/gcc.target/i386/pr98161.c | 48 +++++++++++++++++++++++++
> >  2 files changed, 50 insertions(+)
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr98161.c
> >
> > diff --git a/gcc/config/i386/i386-features.c b/gcc/config/i386/i386-features.c
> > index ff6676f54f7..8ac11b13ad2 100644
> > --- a/gcc/config/i386/i386-features.c
> > +++ b/gcc/config/i386/i386-features.c
> > @@ -1266,8 +1266,10 @@ pseudo_reg_set (rtx_insn *insn)
> >      return NULL;
> >
> >    /* Check pseudo register push first. */
> > +  machine_mode mode = TARGET_64BIT ? TImode : DImode;
> >    if (REG_P (SET_SRC (set))
> >        && !HARD_REGISTER_P (SET_SRC (set))
> > +      && GET_MODE (SET_DEST (set)) == mode
> >        && push_operand (SET_DEST (set), GET_MODE (SET_DEST (set))))
>
> && push_operand (SET_DEST (set), mode)
>
> instead?
>
> push_operand checks the mode by itself:
>
> --q--
> int
> push_operand (rtx op, machine_mode mode)
> {
>   if (!MEM_P (op))
>     return 0;
>
>   if (mode != VOIDmode && GET_MODE (op) != mode)
>     return 0;
>   ...
> -/q-
>
> Uros.

Fixed.   Here is the updated patch.  OK for master?

Thanks.

Comments

Uros Bizjak Dec. 6, 2020, 7:55 p.m. UTC | #1
On Sun, Dec 6, 2020 at 8:11 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Sun, Dec 6, 2020 at 10:59 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> >
> > On Sun, Dec 6, 2020 at 7:51 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > commit 266f44a91c0c9705d3d18e82d7c5bab32927a18f
> > > Author: H.J. Lu <hjl.tools@gmail.com>
> > > Date:   Sun May 17 10:10:34 2020 -0700
> > >
> > >     x86: Allow V1TI vector register pushes
> > >
> > >     Add V1TI vector register push and split it after reload to a sequence
> > >     of:
> > >
> > >     (set (reg:P SP_REG) (plus:P SP_REG) (const_int -8)))
> > >     (set (match_dup 0) (match_dup 1))
> > >
> > > added a pseudo register push check.  But
> > >
> > > (insn 13 12 14 3 (set (mem:SI (pre_dec:SI (reg/f:SI 7 sp)) [0  S4 A32])
> > >         (reg/v:SI 87 [ srclen ])) "x.c":37:16 54 {*pushsi2}
> > >      (expr_list:REG_DEAD (reg/v:SI 87 [ srclen ])
> > >         (expr_list:REG_ARGS_SIZE (const_int 4 [0x4])
> > >             (nil))))
> > >
> > > is not a pseudo register push.  In 64-bit mode, mode of pseudo register
> > > push is TImode.  In 32-bit mode, it is DImode.  Add pseudo register push
> > > mode check to pseudo_reg_set.
> > >
> > > gcc/
> > >
> > >         PR target/98161
> > >         * config/i386/i386-features.c (pseudo_reg_set): Check mode of
> > >         pseudo register push.
> > >
> > > gcc/testsuite/
> > >
> > >         * gcc.target/i386/pr98161.c: New test.
> > > ---
> > >  gcc/config/i386/i386-features.c         |  2 ++
> > >  gcc/testsuite/gcc.target/i386/pr98161.c | 48 +++++++++++++++++++++++++
> > >  2 files changed, 50 insertions(+)
> > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr98161.c
> > >
> > > diff --git a/gcc/config/i386/i386-features.c b/gcc/config/i386/i386-features.c
> > > index ff6676f54f7..8ac11b13ad2 100644
> > > --- a/gcc/config/i386/i386-features.c
> > > +++ b/gcc/config/i386/i386-features.c
> > > @@ -1266,8 +1266,10 @@ pseudo_reg_set (rtx_insn *insn)
> > >      return NULL;
> > >
> > >    /* Check pseudo register push first. */
> > > +  machine_mode mode = TARGET_64BIT ? TImode : DImode;
> > >    if (REG_P (SET_SRC (set))
> > >        && !HARD_REGISTER_P (SET_SRC (set))
> > > +      && GET_MODE (SET_DEST (set)) == mode
> > >        && push_operand (SET_DEST (set), GET_MODE (SET_DEST (set))))
> >
> > && push_operand (SET_DEST (set), mode)
> >
> > instead?
> >
> > push_operand checks the mode by itself:
> >
> > --q--
> > int
> > push_operand (rtx op, machine_mode mode)
> > {
> >   if (!MEM_P (op))
> >     return 0;
> >
> >   if (mode != VOIDmode && GET_MODE (op) != mode)
> >     return 0;
> >   ...
> > -/q-
> >
> > Uros.
>
> Fixed.   Here is the updated patch.  OK for master?

LGTM.

Thanks,
Uros.
diff mbox series

Patch

From d44393ab8817002955ba686c1fc08afa53586da7 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Sun, 6 Dec 2020 10:43:16 -0800
Subject: [PATCH] x86: Check mode of pseudo register push

commit 266f44a91c0c9705d3d18e82d7c5bab32927a18f
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Sun May 17 10:10:34 2020 -0700

    x86: Allow V1TI vector register pushes

    Add V1TI vector register push and split it after reload to a sequence
    of:

    (set (reg:P SP_REG) (plus:P SP_REG) (const_int -8)))
    (set (match_dup 0) (match_dup 1))

added a pseudo register push check.  But

(insn 13 12 14 3 (set (mem:SI (pre_dec:SI (reg/f:SI 7 sp)) [0  S4 A32])
        (reg/v:SI 87 [ srclen ])) "x.c":37:16 54 {*pushsi2}
     (expr_list:REG_DEAD (reg/v:SI 87 [ srclen ])
        (expr_list:REG_ARGS_SIZE (const_int 4 [0x4])
            (nil))))

is not a pseudo register push.  In 64-bit mode, mode of pseudo register
push is TImode.  In 32-bit mode, it is DImode.  Add pseudo register push
mode check to pseudo_reg_set.

gcc/

	PR target/98161
	* config/i386/i386-features.c (pseudo_reg_set): Check mode of
	pseudo register push.

gcc/testsuite/

	* gcc.target/i386/pr98161.c: New test.
---
 gcc/config/i386/i386-features.c         |  3 +-
 gcc/testsuite/gcc.target/i386/pr98161.c | 48 +++++++++++++++++++++++++
 2 files changed, 50 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr98161.c

diff --git a/gcc/config/i386/i386-features.c b/gcc/config/i386/i386-features.c
index ff6676f54f7..c61685bd2f5 100644
--- a/gcc/config/i386/i386-features.c
+++ b/gcc/config/i386/i386-features.c
@@ -1266,9 +1266,10 @@  pseudo_reg_set (rtx_insn *insn)
     return NULL;
 
   /* Check pseudo register push first. */
+  machine_mode mode = TARGET_64BIT ? TImode : DImode;
   if (REG_P (SET_SRC (set))
       && !HARD_REGISTER_P (SET_SRC (set))
-      && push_operand (SET_DEST (set), GET_MODE (SET_DEST (set))))
+      && push_operand (SET_DEST (set), mode))
     return set;
 
   df_ref ref;
diff --git a/gcc/testsuite/gcc.target/i386/pr98161.c b/gcc/testsuite/gcc.target/i386/pr98161.c
new file mode 100644
index 00000000000..5825b9bd1db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr98161.c
@@ -0,0 +1,48 @@ 
+/* { dg-do run } */
+/* { dg-options "-O2 -msse4" } */
+/* { dg-require-effective-target sse4} */
+
+typedef unsigned short u16;
+typedef unsigned int   u32;
+typedef unsigned char  u8;
+
+u32
+__attribute__((__force_align_arg_pointer__))
+unreach(const u16 * pu16, u16 *dst, u32 dstlen, const u8 *src, u32 srclen)
+{
+  for (u32 i = dstlen; srclen && i; i--, srclen--, src++, dst++)
+    {
+      u16 off = pu16[*src];
+      if (off)
+	{
+	  src++; srclen--;
+	  *dst = pu16[off + *src];
+	}
+    }
+  return 56;
+}
+
+u32
+__attribute__((__force_align_arg_pointer__))
+__attribute__((noipa))
+bug(const u16 * pu16, u16 *dst, u32 dstlen, const u8 *src, u32 srclen)
+{
+  if (pu16)
+    /* Branch should not execute, but stack realignment
+     * reads wrong 'pu16' value from stack. */
+    return unreach(pu16, dst, dstlen, src, srclen);
+
+  return (srclen < dstlen) ? srclen : dstlen;
+}
+
+int
+main()
+{
+  if (__builtin_cpu_supports ("sse4.1"))
+    {
+      /* Should return 12 */
+      if (bug(0, 0, 12, 0, 34) != 12)
+	__builtin_abort ();
+    }
+  return 0;
+}
-- 
2.28.0