diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index 409da74bb74..5a57ca7646f 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -3933,7 +3933,6 @@ bool X86DAGToDAGISel::tryShrinkShlLogicImm(SDNode *N) { // Try to match two logic ops to a VPTERNLOG. // FIXME: Handle inverted inputs? // FIXME: Handle more complex patterns that use an operand more than once? -// FIXME: Support X86ISD::ANDNP bool X86DAGToDAGISel::tryVPTERNLOG(SDNode *N) { MVT NVT = N->getSimpleValueType(0); @@ -3951,7 +3950,8 @@ bool X86DAGToDAGISel::tryVPTERNLOG(SDNode *N) { SDValue N1 = N->getOperand(1); auto isLogicOp = [](unsigned Opc) { - return Opc == ISD::AND || Opc == ISD::OR || Opc == ISD::XOR; + return Opc == ISD::AND || Opc == ISD::OR || Opc == ISD::XOR || + Opc == X86ISD::ANDNP; }; SDValue A, B, C; @@ -3975,25 +3975,28 @@ bool X86DAGToDAGISel::tryVPTERNLOG(SDNode *N) { case ISD::AND: switch (Opc2) { default: llvm_unreachable("Unexpected opcode!"); - case ISD::AND: Imm = 0x80; break; - case ISD::OR: Imm = 0xe0; break; - case ISD::XOR: Imm = 0x60; break; + case ISD::AND: Imm = 0x80; break; + case ISD::OR: Imm = 0xe0; break; + case ISD::XOR: Imm = 0x60; break; + case X86ISD::ANDNP: Imm = 0x20; break; } break; case ISD::OR: switch (Opc2) { default: llvm_unreachable("Unexpected opcode!"); - case ISD::AND: Imm = 0xf8; break; - case ISD::OR: Imm = 0xfe; break; - case ISD::XOR: Imm = 0xf6; break; + case ISD::AND: Imm = 0xf8; break; + case ISD::OR: Imm = 0xfe; break; + case ISD::XOR: Imm = 0xf6; break; + case X86ISD::ANDNP: Imm = 0xf2; break; } break; case ISD::XOR: switch (Opc2) { default: llvm_unreachable("Unexpected opcode!"); - case ISD::AND: Imm = 0x78; break; - case ISD::OR: Imm = 0x1e; break; - case ISD::XOR: Imm = 0x96; break; + case ISD::AND: Imm = 0x78; break; + case ISD::OR: Imm = 0x1e; break; + case ISD::XOR: Imm = 0x96; break; + case X86ISD::ANDNP: Imm = 0xd2; break; } break; } diff --git a/test/CodeGen/X86/avx512-logic.ll b/test/CodeGen/X86/avx512-logic.ll index c7aa636bd8f..c2a4da1ba56 100644 --- a/test/CodeGen/X86/avx512-logic.ll +++ b/test/CodeGen/X86/avx512-logic.ll @@ -853,3 +853,35 @@ entry: ret <16 x float> %4 } +define <16 x i32> @ternlog_and_andn(<16 x i32> %x, <16 x i32> %y, <16 x i32> %z) { +; ALL-LABEL: ternlog_and_andn: +; ALL: ## %bb.0: +; ALL-NEXT: vpternlogd $8, %zmm1, %zmm2, %zmm0 +; ALL-NEXT: retq + %a = xor <16 x i32> %x, + %b = and <16 x i32> %y, %a + %c = and <16 x i32> %b, %z + ret <16 x i32> %c +} + +define <16 x i32> @ternlog_or_andn(<16 x i32> %x, <16 x i32> %y, <16 x i32> %z) { +; ALL-LABEL: ternlog_or_andn: +; ALL: ## %bb.0: +; ALL-NEXT: vpternlogd $206, %zmm1, %zmm2, %zmm0 +; ALL-NEXT: retq + %a = xor <16 x i32> %x, + %b = and <16 x i32> %y, %a + %c = or <16 x i32> %b, %z + ret <16 x i32> %c +} + +define <16 x i32> @ternlog_xor_andn(<16 x i32> %x, <16 x i32> %y, <16 x i32> %z) { +; ALL-LABEL: ternlog_xor_andn: +; ALL: ## %bb.0: +; ALL-NEXT: vpternlogd $198, %zmm1, %zmm2, %zmm0 +; ALL-NEXT: retq + %a = xor <16 x i32> %x, + %b = and <16 x i32> %y, %a + %c = xor <16 x i32> %b, %z + ret <16 x i32> %c +} diff --git a/test/CodeGen/X86/avx512vl-logic.ll b/test/CodeGen/X86/avx512vl-logic.ll index 52b135c7c29..0647f4e33bf 100644 --- a/test/CodeGen/X86/avx512vl-logic.ll +++ b/test/CodeGen/X86/avx512vl-logic.ll @@ -954,3 +954,36 @@ entry: %4 = select <4 x i1> %extract.i, <4 x float> %2, <4 x float> zeroinitializer ret <4 x float> %4 } + +define <4 x i32> @ternlog_and_andn(<4 x i32> %x, <4 x i32> %y, <4 x i32> %z) { +; CHECK-LABEL: ternlog_and_andn: +; CHECK: ## %bb.0: +; CHECK-NEXT: vpternlogd $8, %xmm1, %xmm2, %xmm0 +; CHECK-NEXT: retq + %a = xor <4 x i32> %x, + %b = and <4 x i32> %y, %a + %c = and <4 x i32> %b, %z + ret <4 x i32> %c +} + +define <4 x i32> @ternlog_or_andn(<4 x i32> %x, <4 x i32> %y, <4 x i32> %z) { +; CHECK-LABEL: ternlog_or_andn: +; CHECK: ## %bb.0: +; CHECK-NEXT: vpternlogd $206, %xmm1, %xmm2, %xmm0 +; CHECK-NEXT: retq + %a = xor <4 x i32> %x, + %b = and <4 x i32> %y, %a + %c = or <4 x i32> %b, %z + ret <4 x i32> %c +} + +define <4 x i32> @ternlog_xor_andn(<4 x i32> %x, <4 x i32> %y, <4 x i32> %z) { +; CHECK-LABEL: ternlog_xor_andn: +; CHECK: ## %bb.0: +; CHECK-NEXT: vpternlogd $198, %xmm1, %xmm2, %xmm0 +; CHECK-NEXT: retq + %a = xor <4 x i32> %x, + %b = and <4 x i32> %y, %a + %c = xor <4 x i32> %b, %z + ret <4 x i32> %c +}