continue;
}
- // Attempt to remove vectors moves that were inserted to zero upper bits.
+ // Look for a TESTrr+ANDrr pattern where both operands of the test are
+ // the same. Rewrite to remove the AND.
+ unsigned Opc = N->getMachineOpcode();
+ if ((Opc == X86::TEST8rr || Opc == X86::TEST16rr ||
+ Opc == X86::TEST32rr || Opc == X86::TEST64rr) &&
+ N->getOperand(0) == N->getOperand(1) &&
+ N->isOnlyUserOf(N->getOperand(0).getNode()) &&
+ N->getOperand(0).isMachineOpcode()) {
+ SDValue And = N->getOperand(0);
+ unsigned N0Opc = And.getMachineOpcode();
+ if (N0Opc == X86::AND8rr || N0Opc == X86::AND16rr ||
+ N0Opc == X86::AND32rr || N0Opc == X86::AND64rr) {
+ MachineSDNode *Test = CurDAG->getMachineNode(Opc, SDLoc(N),
+ MVT::i32,
+ And.getOperand(0),
+ And.getOperand(1));
+ ReplaceUses(N, Test);
+ MadeChange = true;
+ continue;
+ }
+ }
- if (N->getMachineOpcode() != TargetOpcode::SUBREG_TO_REG)
+ // Attempt to remove vectors moves that were inserted to zero upper bits.
+ if (Opc != TargetOpcode::SUBREG_TO_REG)
continue;
unsigned SubRegIdx = N->getConstantOperandVal(2);
let isCompare = 1 in {
let Defs = [EFLAGS] in {
let isCommutable = 1 in {
- def TEST8rr : BinOpRR_F<0x84, "test", Xi8 , X86testpat>;
- def TEST16rr : BinOpRR_F<0x84, "test", Xi16, X86testpat>;
- def TEST32rr : BinOpRR_F<0x84, "test", Xi32, X86testpat>;
- def TEST64rr : BinOpRR_F<0x84, "test", Xi64, X86testpat>;
+ // Avoid selecting these and instead use a test+and. Post processing will
+ // combine them. This gives bunch of other patterns that start with
+ // and a chance to match.
+ def TEST8rr : BinOpRR_F<0x84, "test", Xi8 , null_frag>;
+ def TEST16rr : BinOpRR_F<0x84, "test", Xi16, null_frag>;
+ def TEST32rr : BinOpRR_F<0x84, "test", Xi32, null_frag>;
+ def TEST64rr : BinOpRR_F<0x84, "test", Xi64, null_frag>;
} // isCommutable
def TEST8mr : BinOpMR_F<0x84, "test", Xi8 , X86testpat>;
define i32 @blsi32_z2(i32 %a, i32 %b, i32 %c) nounwind {
; X86-LABEL: blsi32_z2:
; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: movl %eax, %ecx
-; X86-NEXT: negl %ecx
-; X86-NEXT: testl %eax, %ecx
+; X86-NEXT: blsil {{[0-9]+}}(%esp), %eax
; X86-NEXT: leal {{[0-9]+}}(%esp), %eax
; X86-NEXT: leal {{[0-9]+}}(%esp), %ecx
; X86-NEXT: cmovel %eax, %ecx
; X64-LABEL: blsi32_z2:
; X64: # %bb.0:
; X64-NEXT: movl %esi, %eax
-; X64-NEXT: movl %edi, %ecx
-; X64-NEXT: negl %ecx
-; X64-NEXT: testl %edi, %ecx
+; X64-NEXT: blsil %edi, %ecx
; X64-NEXT: cmovnel %edx, %eax
; X64-NEXT: retq
%t0 = sub i32 0, %a
; X64-LABEL: blsi64_z2:
; X64: # %bb.0:
; X64-NEXT: movq %rsi, %rax
-; X64-NEXT: movq %rdi, %rcx
-; X64-NEXT: negq %rcx
-; X64-NEXT: testq %rdi, %rcx
+; X64-NEXT: blsiq %rdi, %rcx
; X64-NEXT: cmovneq %rdx, %rax
; X64-NEXT: retq
%t0 = sub i64 0, %a
define i32 @blsr32_z2(i32 %a, i32 %b, i32 %c) nounwind {
; X86-LABEL: blsr32_z2:
; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: leal -1(%eax), %ecx
-; X86-NEXT: testl %eax, %ecx
+; X86-NEXT: blsrl {{[0-9]+}}(%esp), %eax
; X86-NEXT: leal {{[0-9]+}}(%esp), %eax
; X86-NEXT: leal {{[0-9]+}}(%esp), %ecx
; X86-NEXT: cmovel %eax, %ecx
; X64-LABEL: blsr32_z2:
; X64: # %bb.0:
; X64-NEXT: movl %esi, %eax
-; X64-NEXT: # kill: def $edi killed $edi def $rdi
-; X64-NEXT: leal -1(%rdi), %ecx
-; X64-NEXT: testl %edi, %ecx
+; X64-NEXT: blsrl %edi, %ecx
; X64-NEXT: cmovnel %edx, %eax
; X64-NEXT: retq
%t0 = sub i32 %a, 1
; X64-LABEL: blsr64_z2:
; X64: # %bb.0:
; X64-NEXT: movq %rsi, %rax
-; X64-NEXT: leaq -1(%rdi), %rcx
-; X64-NEXT: testq %rdi, %rcx
+; X64-NEXT: blsrq %rdi, %rcx
; X64-NEXT: cmovneq %rdx, %rax
; X64-NEXT: retq
%t0 = sub i64 %a, 1
; CHECK-LABEL: test_x86_tbm_blcfill_u32_z2:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %esi, %eax
-; CHECK-NEXT: # kill: def $edi killed $edi def $rdi
-; CHECK-NEXT: leal 1(%rdi), %ecx
-; CHECK-NEXT: testl %edi, %ecx
+; CHECK-NEXT: blcfilll %edi, %ecx
; CHECK-NEXT: cmovnel %edx, %eax
; CHECK-NEXT: retq
%t0 = add i32 %a, 1
; CHECK-LABEL: test_x86_tbm_blcfill_u64_z2:
; CHECK: # %bb.0:
; CHECK-NEXT: movq %rsi, %rax
-; CHECK-NEXT: leaq 1(%rdi), %rcx
-; CHECK-NEXT: testq %rdi, %rcx
+; CHECK-NEXT: blcfillq %rdi, %rcx
; CHECK-NEXT: cmovneq %rdx, %rax
; CHECK-NEXT: retq
%t0 = add i64 %a, 1
; CHECK-LABEL: test_x86_tbm_blcic_u32_z2:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %esi, %eax
-; CHECK-NEXT: movl %edi, %ecx
-; CHECK-NEXT: notl %ecx
-; CHECK-NEXT: incl %edi
-; CHECK-NEXT: testl %ecx, %edi
+; CHECK-NEXT: blcicl %edi, %ecx
; CHECK-NEXT: cmovnel %edx, %eax
; CHECK-NEXT: retq
%t0 = xor i32 %a, -1
; CHECK-LABEL: test_x86_tbm_blcic_u64_z2:
; CHECK: # %bb.0:
; CHECK-NEXT: movq %rsi, %rax
-; CHECK-NEXT: movq %rdi, %rcx
-; CHECK-NEXT: notq %rcx
-; CHECK-NEXT: incq %rdi
-; CHECK-NEXT: testq %rcx, %rdi
+; CHECK-NEXT: blcicq %rdi, %rcx
; CHECK-NEXT: cmovneq %rdx, %rax
; CHECK-NEXT: retq
%t0 = xor i64 %a, -1
; CHECK-LABEL: test_x86_tbm_tzmsk_u32_z2:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %esi, %eax
-; CHECK-NEXT: movl %edi, %ecx
-; CHECK-NEXT: notl %ecx
-; CHECK-NEXT: decl %edi
-; CHECK-NEXT: testl %edi, %ecx
+; CHECK-NEXT: tzmskl %edi, %ecx
; CHECK-NEXT: cmovnel %edx, %eax
; CHECK-NEXT: retq
%t0 = xor i32 %a, -1
; CHECK-LABEL: test_x86_tbm_tzmsk_u64_z2:
; CHECK: # %bb.0:
; CHECK-NEXT: movq %rsi, %rax
-; CHECK-NEXT: movq %rdi, %rcx
-; CHECK-NEXT: notq %rcx
-; CHECK-NEXT: decq %rdi
-; CHECK-NEXT: testq %rdi, %rcx
+; CHECK-NEXT: tzmskq %rdi, %rcx
; CHECK-NEXT: cmovneq %rdx, %rax
; CHECK-NEXT: retq
%t0 = xor i64 %a, -1