[X86][SSE] Combine PTEST(AND(X,Y),AND(X,Y)) -> PTEST(X,Y) and ANDN equivalents
authorSimon Pilgrim <llvm-dev@redking.me.uk>
Wed, 8 Apr 2020 11:04:58 +0000 (12:04 +0100)
committerSimon Pilgrim <llvm-dev@redking.me.uk>
Wed, 8 Apr 2020 11:42:22 +0000 (12:42 +0100)
Tests derived from PR42035 examples

llvm/lib/Target/X86/X86ISelLowering.cpp
llvm/test/CodeGen/X86/combine-ptest.ll

index c89e4ac..175b90c 100644 (file)
@@ -39930,6 +39930,25 @@ static SDValue combinePTESTCC(SDValue EFLAGS, X86::CondCode &CC,
                          DAG.getBitcast(OpVT, NotOp1), Op0);
     }
 
+    if (Op0 == Op1) {
+      SDValue BC = peekThroughBitcasts(Op0);
+
+      // TESTZ(AND(X,Y),AND(X,Y)) == TESTZ(X,Y)
+      if (BC.getOpcode() == ISD::AND || BC.getOpcode() == X86ISD::FAND) {
+        return DAG.getNode(EFLAGS.getOpcode(), SDLoc(EFLAGS), VT,
+                           DAG.getBitcast(OpVT, BC.getOperand(0)),
+                           DAG.getBitcast(OpVT, BC.getOperand(1)));
+      }
+
+      // TESTZ(AND(~X,Y),AND(~X,Y)) == TESTC(X,Y)
+      if (BC.getOpcode() == X86ISD::ANDNP || BC.getOpcode() == X86ISD::FANDN) {
+        CC = (CC == X86::COND_E ? X86::COND_B : X86::COND_AE);
+        return DAG.getNode(EFLAGS.getOpcode(), SDLoc(EFLAGS), VT,
+                           DAG.getBitcast(OpVT, BC.getOperand(0)),
+                           DAG.getBitcast(OpVT, BC.getOperand(1)));
+      }
+    }
+
     // TESTZ(-1,X) == TESTZ(X,X)
     if (ISD::isBuildVectorAllOnes(Op0.getNode()))
       return DAG.getNode(EFLAGS.getOpcode(), SDLoc(EFLAGS), VT, Op1, Op1);
index 0ae16f1..d23277f 100644 (file)
@@ -156,8 +156,7 @@ define i32 @ptestz_128_and(<2 x i64> %c, <2 x i64> %d, i32 %a, i32 %b) {
 ; CHECK-LABEL: ptestz_128_and:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    movl %edi, %eax
-; CHECK-NEXT:    vpand %xmm1, %xmm0, %xmm0
-; CHECK-NEXT:    vptest %xmm0, %xmm0
+; CHECK-NEXT:    vptest %xmm1, %xmm0
 ; CHECK-NEXT:    cmovnel %esi, %eax
 ; CHECK-NEXT:    retq
   %t1 = and <2 x i64> %c, %d
@@ -171,8 +170,7 @@ define i32 @ptestz_256_and(<4 x i64> %c, <4 x i64> %d, i32 %a, i32 %b) {
 ; CHECK-LABEL: ptestz_256_and:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    movl %edi, %eax
-; CHECK-NEXT:    vandps %ymm1, %ymm0, %ymm0
-; CHECK-NEXT:    vptest %ymm0, %ymm0
+; CHECK-NEXT:    vptest %ymm1, %ymm0
 ; CHECK-NEXT:    cmovel %esi, %eax
 ; CHECK-NEXT:    vzeroupper
 ; CHECK-NEXT:    retq
@@ -191,9 +189,8 @@ define i32 @ptestz_128_andc(<2 x i64> %c, <2 x i64> %d, i32 %a, i32 %b) {
 ; CHECK-LABEL: ptestz_128_andc:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    movl %edi, %eax
-; CHECK-NEXT:    vpandn %xmm1, %xmm0, %xmm0
-; CHECK-NEXT:    vptest %xmm0, %xmm0
-; CHECK-NEXT:    cmovnel %esi, %eax
+; CHECK-NEXT:    vptest %xmm1, %xmm0
+; CHECK-NEXT:    cmovael %esi, %eax
 ; CHECK-NEXT:    retq
   %t1 = xor <2 x i64> %c, <i64 -1, i64 -1>
   %t2 = and <2 x i64> %t1, %d
@@ -207,9 +204,8 @@ define i32 @ptestz_256_andc(<4 x i64> %c, <4 x i64> %d, i32 %a, i32 %b) {
 ; CHECK-LABEL: ptestz_256_andc:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    movl %edi, %eax
-; CHECK-NEXT:    vandnps %ymm1, %ymm0, %ymm0
-; CHECK-NEXT:    vptest %ymm0, %ymm0
-; CHECK-NEXT:    cmovel %esi, %eax
+; CHECK-NEXT:    vptest %ymm1, %ymm0
+; CHECK-NEXT:    cmovbl %esi, %eax
 ; CHECK-NEXT:    vzeroupper
 ; CHECK-NEXT:    retq
   %t1 = xor <4 x i64> %c, <i64 -1, i64 -1, i64 -1, i64 -1>