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