aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2020-12-06 10:43:16 -0800
committerH.J. Lu <hjl.tools@gmail.com>2020-12-06 12:56:34 -0800
commit6643ca0be6f34786b686415e457de96d0d9fbd2d (patch)
treec094b31602f3cd9454a85d2d2f6d1feca9c001df /gcc
parent8c23434fdadcf4caa1f0e966294c5f67ccf4bcf9 (diff)
downloadgcc-6643ca0be6f34786b686415e457de96d0d9fbd2d.zip
gcc-6643ca0be6f34786b686415e457de96d0d9fbd2d.tar.gz
gcc-6643ca0be6f34786b686415e457de96d0d9fbd2d.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/i386/i386-features.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/pr98161.c48
2 files changed, 50 insertions, 1 deletions
diff --git a/gcc/config/i386/i386-features.c b/gcc/config/i386/i386-features.c
index ff6676f..c61685b 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 0000000..5825b9b
--- /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;
+}