Hi,

For shld/shrd_ndd_2 insn, the spiltter outputs wrong pattern that
mixed parallel for clobber and set. Separate out the set to dest
from parallel to fix it.

Bootstrapped & regtested on x86-64-pc-linux-gnu.

Ok for trunk?

gcc/ChangeLog:

        PR target/118510
        * config/i386/i386.md (*x86_64_shld_ndd_2): Separate set to
        operand[0] from parallel in output template.
        (*x86_shld_ndd_2): Likewise.
        (*x86_64_shrd_ndd_2): Likewise.
        (*x86_shrd_ndd_2): Likewise.

gcc/testsuite/ChangeLog:

        PR target/118510
        * gcc.target/i386/pr118510.c: New test.
---
 gcc/config/i386/i386.md                  | 16 ++++++++--------
 gcc/testsuite/gcc.target/i386/pr118510.c | 14 ++++++++++++++
 2 files changed, 22 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr118510.c

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 362b0ddcf40..ebfd76593ab 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -15615,8 +15615,8 @@ (define_insn_and_split "*x86_64_shld_ndd_2"
                                 (minus:QI (const_int 64)
                                           (and:QI (match_dup 3)
                                                   (const_int 63)))) 0)))
-             (clobber (reg:CC FLAGS_REG))
-             (set (match_dup 0) (match_dup 4))])]
+             (clobber (reg:CC FLAGS_REG))])
+   (set (match_dup 0) (match_dup 4))]
 {
   operands[4] = gen_reg_rtx (DImode);
   emit_move_insn (operands[4], operands[0]);
@@ -15851,8 +15851,8 @@ (define_insn_and_split "*x86_shld_ndd_2"
                                 (minus:QI (const_int 32)
                                           (and:QI (match_dup 3)
                                                   (const_int 31)))) 0)))
-             (clobber (reg:CC FLAGS_REG))
-             (set (match_dup 0) (match_dup 4))])]
+             (clobber (reg:CC FLAGS_REG))])
+   (set (match_dup 0) (match_dup 4))]
 {
   operands[4] = gen_reg_rtx (SImode);
   emit_move_insn (operands[4], operands[0]);
@@ -17010,8 +17010,8 @@ (define_insn_and_split "*x86_64_shrd_ndd_2"
                                 (minus:QI (const_int 64)
                                           (and:QI (match_dup 3)
                                                   (const_int 63)))) 0)))
-             (clobber (reg:CC FLAGS_REG))
-             (set (match_dup 0) (match_dup 4))])]
+             (clobber (reg:CC FLAGS_REG))])
+   (set (match_dup 0) (match_dup 4))]
 {
   operands[4] = gen_reg_rtx (DImode);
   emit_move_insn (operands[4], operands[0]);
@@ -17245,8 +17245,8 @@ (define_insn_and_split "*x86_shrd_ndd_2"
                                 (minus:QI (const_int 32)
                                           (and:QI (match_dup 3)
                                                   (const_int 31)))) 0)))
-             (clobber (reg:CC FLAGS_REG))
-             (set (match_dup 0) (match_dup 4))])]
+             (clobber (reg:CC FLAGS_REG))])
+   (set (match_dup 0) (match_dup 4))]
 {
   operands[4] = gen_reg_rtx (SImode);
   emit_move_insn (operands[4], operands[0]);
diff --git a/gcc/testsuite/gcc.target/i386/pr118510.c 
b/gcc/testsuite/gcc.target/i386/pr118510.c
new file mode 100644
index 00000000000..6cfe8182b6f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118510.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mapxf" } */
+
+typedef struct cpp_num cpp_num;
+struct cpp_num {
+    int high;
+    unsigned low;
+    int overflow;
+};
+int num_rshift_n;
+cpp_num num_lshift(cpp_num num) {
+    num.low = num.low >> num_rshift_n | num.high << (32 - num_rshift_n);
+    return num;
+}
-- 
2.31.1

Reply via email to