AVX-512: Fixed the "test" operation for i1 type
authorElena Demikhovsky <elena.demikhovsky@intel.com>
Thu, 12 Feb 2015 08:40:34 +0000 (08:40 +0000)
committerElena Demikhovsky <elena.demikhovsky@intel.com>
Thu, 12 Feb 2015 08:40:34 +0000 (08:40 +0000)
Using KORTESTW for comparison i1 value with zero was wrong since the instruction tests 16 bits.
KORTESTW may be used with KSHIFTL+KSHIFTR that clean the 15 upper bits.
I removed (X86cmp i1, 0) pattern and zero-extend i1 to i8 and then use TESTB.

There are some cases where i1 is in the mask register and the upper bits are already zeroed.
Then KORTESTW is the better solution, but it is subject for optimization.
Meanwhile, I'm fixing the correctness issue.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228916 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86ISelDAGToDAG.cpp
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86InstrAVX512.td
test/CodeGen/X86/avx512-i1test.ll
test/CodeGen/X86/avx512-insert-extract.ll

index abde9f1ceae9c9fecf778e6c205c283db1679b81..f143b200ec4ebc57ba412cf90c9d097a29b599c6 100644 (file)
@@ -2610,26 +2610,9 @@ SDNode *X86DAGToDAGISel::Select(SDNode *Node) {
     SDValue N1 = Node->getOperand(1);
 
     if (N0.getOpcode() == ISD::TRUNCATE && N0.hasOneUse() &&
-        HasNoSignedComparisonUses(Node)) {
-      // Look for (X86cmp (truncate $op, i1), 0) and try to convert to a
-      // smaller encoding
-      if (Opcode == X86ISD::CMP && N0.getValueType() == MVT::i1 &&
-          X86::isZeroNode(N1)) {
-        SDValue Reg = N0.getOperand(0);
-        SDValue Imm = CurDAG->getTargetConstant(1, MVT::i8);
-
-        // Emit testb
-        if (Reg.getScalarValueSizeInBits() > 8)
-          Reg = CurDAG->getTargetExtractSubreg(X86::sub_8bit, dl, MVT::i8, Reg);
-        // Emit a testb.
-        SDNode *NewNode = CurDAG->getMachineNode(X86::TEST8ri, dl, MVT::i32,
-                                                Reg, Imm);
-        ReplaceUses(SDValue(Node, 0), SDValue(NewNode, 0));
-        return nullptr;
-      }
-
+        HasNoSignedComparisonUses(Node))
       N0 = N0.getOperand(0);
-    }
+
     // Look for (X86cmp (and $op, $imm), 0) and see if we can convert it to
     // use a smaller encoding.
     // Look past the truncate if CMP is the only use of it.
index c36db5a4931b6a995f90d1cf72c011ff6bda4b9a..8cec2e3978271722f7254bfb19acd4761d2e1725 100644 (file)
@@ -15045,11 +15045,11 @@ static bool hasNonFlagsUse(SDValue Op) {
 /// equivalent.
 SDValue X86TargetLowering::EmitTest(SDValue Op, unsigned X86CC, SDLoc dl,
                                     SelectionDAG &DAG) const {
-  if (Op.getValueType() == MVT::i1)
-    // KORTEST instruction should be selected
-    return DAG.getNode(X86ISD::CMP, dl, MVT::i32, Op,
-                       DAG.getConstant(0, Op.getValueType()));
-
+  if (Op.getValueType() == MVT::i1) {
+    SDValue ExtOp = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i8, Op);
+    return DAG.getNode(X86ISD::CMP, dl, MVT::i32, ExtOp,
+                       DAG.getConstant(0, MVT::i8));
+  }
   // CF and OF aren't always set the way we want. Determine which
   // of these we need.
   bool NeedCF = false;
index ee63271632e699013d9bd7dcb470b59c7ec92d48..dec5ba01542a861e492bf67daf9a3e6abf8e03b0 100644 (file)
@@ -1813,7 +1813,7 @@ let Predicates = [HasBWI] in
 def : Pat<(xor VK64:$src1, (v64i1 immAllOnesV)), (KNOTQrr VK64:$src1)>;
 
 // KNL does not support KMOVB, 8-bit mask is promoted to 16-bit
-let Predicates = [HasAVX512] in {
+let Predicates = [HasAVX512, NoDQI] in {
 def : Pat<(xor VK8:$src1,  (v8i1 immAllOnesV)),
           (COPY_TO_REGCLASS (KNOTWrr (COPY_TO_REGCLASS VK8:$src1, VK16)), VK8)>;
 
@@ -1955,14 +1955,6 @@ multiclass avx512_mask_testop_w<bits<8> opc, string OpcodeStr, SDNode OpNode> {
 
 defm KORTEST : avx512_mask_testop_w<0x98, "kortest", X86kortest>;
 
-def : Pat<(X86cmp VK1:$src1, (i1 0)),
-          (KORTESTWrr (COPY_TO_REGCLASS VK1:$src1, VK16),
-           (COPY_TO_REGCLASS VK1:$src1, VK16))>, Requires<[HasAVX512, NoDQI]>;
-
-def : Pat<(X86cmp VK1:$src1, (i1 0)),
-          (KORTESTBrr (COPY_TO_REGCLASS VK1:$src1, VK8),
-           (COPY_TO_REGCLASS VK1:$src1, VK8))>, Requires<[HasDQI]>;
-
 // Mask shift
 multiclass avx512_mask_shiftop<bits<8> opc, string OpcodeStr, RegisterClass KRC,
                              SDNode OpNode> {
index 4814314a64429be9dd6756e815fdb78e721c2580..a2377380f0d54cd95fc7b1031640a421d9a50922 100755 (executable)
@@ -5,8 +5,8 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 
 ; CHECK-LABEL: func
-; CHECK: kortestw
-; CHECK: kortestw
+; CHECK: testb
+; CHECK: testb
 define void @func() {
 bb1:
   br i1 undef, label %L_10, label %L_10
index 3d263df03dcaff0b997e8b8fcb4cdde02d475c3a..d6b887e4c5cd1c493eb775ae3de511331c0b822a 100644 (file)
@@ -106,8 +106,7 @@ define i32 @test10(<16 x i32> %x, i32 %ind) nounwind {
 ;CHECK: vpcmpltud
 ;CHECK: kshiftlw $11
 ;CHECK: kshiftrw $15
-;KNL: kortestw
-;SKX: kortestb
+;CHECK: testb
 ;CHECK: je
 ;CHECK: ret
 ;CHECK: ret
@@ -126,8 +125,7 @@ define <16 x i32> @test11(<16 x i32>%a, <16 x i32>%b) {
 ;CHECK: vpcmpgtq
 ;CHECK: kshiftlw $15
 ;CHECK: kshiftrw $15
-;KNL: kortestw
-;SKX: kortestb
+;CHECK: testb
 ;CHECK: ret
 
 define i64 @test12(<16 x i64>%a, <16 x i64>%b, i64 %a1, i64 %b1) {
@@ -154,10 +152,10 @@ define i16 @test13(i32 %a, i32 %b) {
 ;CHECK: vpcmpgtq
 ;KNL: kshiftlw $11
 ;KNL: kshiftrw $15
-;KNL: kortestw
+;KNL: testb
 ;SKX: kshiftlb $3
 ;SKX: kshiftrb $7
-;SKX: kortestb
+;SKX: testb
 ;CHECK: ret
 
 define i64 @test14(<8 x i64>%a, <8 x i64>%b, i64 %a1, i64 %b1) {