]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
i386: Fix wrong insn generated by shld/shrd ndd split [PR118510]
authorHongyu Wang <hongyu.wang@intel.com>
Fri, 17 Jan 2025 01:04:17 +0000 (09:04 +0800)
committerHongyu Wang <hongyu.wang@intel.com>
Mon, 20 Jan 2025 01:01:11 +0000 (09:01 +0800)
For shld/shrd_ndd_2 insn, the spiltter outputs wrong pattern that
mixed parallel for clobber and set. Use register_operand as dest
and ajdust output template to fix.

gcc/ChangeLog:

PR target/118510
* config/i386/i386.md (*x86_64_shld_ndd_2): Use register_operand
for operand[0] and adjust the output template to directly
generate ndd form shld pattern.
(*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
gcc/testsuite/gcc.target/i386/pr118510.c [new file with mode: 0644]

index 5fbd0848df5b43d94b3724209b7b996c7ac2a86c..c977e86b72e8aebd792d344f1f69446bd2f27642 100644 (file)
              (clobber (reg:CC FLAGS_REG))])])
 
 (define_insn_and_split "*x86_64_shld_ndd_2"
-  [(set (match_operand:DI 0 "nonimmediate_operand")
+  [(set (match_operand:DI 0 "register_operand")
        (ior:DI (ashift:DI (match_operand:DI 1 "nonimmediate_operand")
                           (match_operand:QI 3 "nonmemory_operand"))
                (lshiftrt:DI (match_operand:DI 2 "register_operand")
    && ix86_pre_reload_split ()"
   "#"
   "&& 1"
-  [(parallel [(set (match_dup 4)
+  [(parallel [(set (match_dup 0)
                   (ior:DI (ashift:DI (match_dup 1)
                                      (and:QI (match_dup 3) (const_int 63)))
                           (subreg:DI
                                 (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))])]
-{
-  operands[4] = gen_reg_rtx (DImode);
-  emit_move_insn (operands[4], operands[0]);
-})
+             (clobber (reg:CC FLAGS_REG))])])
 
 (define_insn "x86_shld<nf_name>"
   [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m")
              (clobber (reg:CC FLAGS_REG))])])
 
 (define_insn_and_split "*x86_shld_ndd_2"
-  [(set (match_operand:SI 0 "nonimmediate_operand")
+  [(set (match_operand:SI 0 "register_operand")
        (ior:SI (ashift:SI (match_operand:SI 1 "nonimmediate_operand")
                           (match_operand:QI 3 "nonmemory_operand"))
                (lshiftrt:SI (match_operand:SI 2 "register_operand")
    && ix86_pre_reload_split ()"
   "#"
   "&& 1"
-  [(parallel [(set (match_dup 4)
+  [(parallel [(set (match_dup 0)
                   (ior:SI (ashift:SI (match_dup 1)
                                      (and:QI (match_dup 3) (const_int 31)))
                           (subreg:SI
                                 (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))])]
-{
-  operands[4] = gen_reg_rtx (SImode);
-  emit_move_insn (operands[4], operands[0]);
-})
+             (clobber (reg:CC FLAGS_REG))])])
 
 (define_expand "@x86_shift<mode>_adj_1"
   [(set (reg:CCZ FLAGS_REG)
              (clobber (reg:CC FLAGS_REG))])])
 
 (define_insn_and_split "*x86_64_shrd_ndd_2"
-  [(set (match_operand:DI 0 "nonimmediate_operand")
+  [(set (match_operand:DI 0 "register_operand")
        (ior:DI (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand")
                             (match_operand:QI 3 "nonmemory_operand"))
                (ashift:DI (match_operand:DI 2 "register_operand")
   && ix86_pre_reload_split ()"
   "#"
   "&& 1"
-  [(parallel [(set (match_dup 4)
+  [(parallel [(set (match_dup 0)
                   (ior:DI (lshiftrt:DI (match_dup 1)
                                        (and:QI (match_dup 3) (const_int 63)))
                           (subreg:DI
                                 (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))])]
-{
-  operands[4] = gen_reg_rtx (DImode);
-  emit_move_insn (operands[4], operands[0]);
-})
+             (clobber (reg:CC FLAGS_REG))])])
 
 (define_insn "x86_shrd<nf_name>"
   [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m")
              (clobber (reg:CC FLAGS_REG))])])
 
 (define_insn_and_split "*x86_shrd_ndd_2"
-  [(set (match_operand:SI 0 "nonimmediate_operand")
+  [(set (match_operand:SI 0 "register_operand")
        (ior:SI (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand")
                           (match_operand:QI 3 "nonmemory_operand"))
                (ashift:SI (match_operand:SI 2 "register_operand")
    && ix86_pre_reload_split ()"
   "#"
   "&& 1"
-  [(parallel [(set (match_dup 4)
+  [(parallel [(set (match_dup 0)
                   (ior:SI (lshiftrt:SI (match_dup 1)
                                        (and:QI (match_dup 3) (const_int 31)))
                           (subreg:SI
                                 (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))])]
-{
-  operands[4] = gen_reg_rtx (SImode);
-  emit_move_insn (operands[4], operands[0]);
-})
+             (clobber (reg:CC FLAGS_REG))])])
 
 ;; Base name for insn mnemonic.
 (define_mode_attr cvt_mnemonic
diff --git a/gcc/testsuite/gcc.target/i386/pr118510.c b/gcc/testsuite/gcc.target/i386/pr118510.c
new file mode 100644 (file)
index 0000000..6cfe818
--- /dev/null
@@ -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;
+}