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