https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81763
--- Comment #35 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So, what about following?
--- gcc/config/i386/i386.md.jj 2018-01-16 09:28:19.721432394 +0100
+++ gcc/config/i386/i386.md 2018-01-25 20:58:18.382378827 +0100
@@ -9250,14 +9250,14 @@ (define_split
})
(define_insn "*andndi3_doubleword"
- [(set (match_operand:DI 0 "register_operand" "=r,&r")
+ [(set (match_operand:DI 0 "register_operand" "=r,r,&r")
(and:DI
- (not:DI (match_operand:DI 1 "register_operand" "r,0"))
- (match_operand:DI 2 "nonimmediate_operand" "rm,rm")))
+ (not:DI (match_operand:DI 1 "register_operand" "0,r,r"))
+ (match_operand:DI 2 "nonimmediate_operand" "rm,r,m")))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && TARGET_STV && TARGET_SSE2"
"#"
- [(set_attr "isa" "bmi,*")])
+ [(set_attr "isa" "*,bmi2,bmi2")])
(define_split
[(set (match_operand:DI 0 "register_operand")
@@ -9273,7 +9273,22 @@ (define_split
(parallel [(set (match_dup 3)
(and:SI (not:SI (match_dup 4)) (match_dup 5)))
(clobber (reg:CC FLAGS_REG))])]
- "split_double_mode (DImode, &operands[0], 3, &operands[0], &operands[3]);")
+{
+ split_double_mode (DImode, &operands[0], 3, &operands[0], &operands[3]);
+ /* For the =r <- (r, r) alternative of *andndi3_doubleword, there could
+ be overlap between the output and input registers. If the output
+ is equal to one of the input operands, this is fine, if there is
+ partial overlap, we can resolve it by swapping the two instructions. */
+ if (reg_overlap_mentioned_p (operands[0], operands[4])
+ || reg_overlap_mentioned_p (operands[0], operands[5]))
+ {
+ std::swap (operands[0], operands[3]);
+ std::swap (operands[1], operands[4]);
+ std::swap (operands[2], operands[5]);
+ gcc_assert (!reg_overlap_mentioned_p (operands[0], operands[4])
+ && !reg_overlap_mentioned_p (operands[0], operands[5]));
+ }
+})
(define_split
[(set (match_operand:DI 0 "register_operand")