[InstCombine] allow icmp (bit-manipulation-intrinsic(), C) folds for vectors
authorSanjay Patel <spatel@rotateright.com>
Sat, 23 Jul 2016 13:06:49 +0000 (13:06 +0000)
committerSanjay Patel <spatel@rotateright.com>
Sat, 23 Jul 2016 13:06:49 +0000 (13:06 +0000)
llvm-svn: 276523

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/lib/Transforms/InstCombine/InstCombineInternal.h
llvm/test/Transforms/InstCombine/intrinsics.ll

index f5514a8..4004200 100644 (file)
@@ -2355,37 +2355,35 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI,
   return nullptr;
 }
 
-Instruction *InstCombiner::foldICmpIntrinsicWithConstant(ICmpInst &ICI,
-                                                         Instruction *LHSI,
-                                                         ConstantInt *RHS) {
-  IntrinsicInst *II = dyn_cast<IntrinsicInst>(LHSI);
-  if (!II || !ICI.isEquality())
+Instruction *InstCombiner::foldICmpIntrinsicWithConstant(ICmpInst &ICI) {
+  IntrinsicInst *II = dyn_cast<IntrinsicInst>(ICI.getOperand(0));
+  const APInt *Op1C;
+  if (!II || !ICI.isEquality() || !match(ICI.getOperand(1), m_APInt(Op1C)))
     return nullptr;
 
   // Handle icmp {eq|ne} <intrinsic>, intcst.
-  const APInt &RHSV = RHS->getValue();
   switch (II->getIntrinsicID()) {
   case Intrinsic::bswap:
     Worklist.Add(II);
     ICI.setOperand(0, II->getArgOperand(0));
-    ICI.setOperand(1, Builder->getInt(RHSV.byteSwap()));
+    ICI.setOperand(1, Builder->getInt(Op1C->byteSwap()));
     return &ICI;
   case Intrinsic::ctlz:
   case Intrinsic::cttz:
     // ctz(A) == bitwidth(a)  ->  A == 0 and likewise for !=
-    if (RHSV == RHS->getType()->getBitWidth()) {
+    if (*Op1C == Op1C->getBitWidth()) {
       Worklist.Add(II);
       ICI.setOperand(0, II->getArgOperand(0));
-      ICI.setOperand(1, ConstantInt::get(RHS->getType(), 0));
+      ICI.setOperand(1, ConstantInt::getNullValue(II->getType()));
       return &ICI;
     }
     break;
   case Intrinsic::ctpop:
     // popcount(A) == 0  ->  A == 0 and likewise for !=
-    if (RHS->isZero()) {
+    if (*Op1C == 0) {
       Worklist.Add(II);
       ICI.setOperand(0, II->getArgOperand(0));
-      ICI.setOperand(1, RHS);
+      ICI.setOperand(1, ConstantInt::getNullValue(II->getType()));
       return &ICI;
     }
     break;
@@ -3641,6 +3639,10 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
 
   // See if we are doing a comparison between a constant and an instruction that
   // can be folded into the comparison.
+
+  // FIXME: Use m_APInt instead of dyn_cast<ConstantInt> to allow these
+  // transforms for vectors.
+
   if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
     // Since the RHS is a ConstantInt (CI), if the left hand side is an
     // instruction, see if that instruction also has constants so that the
@@ -3650,11 +3652,12 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
         return Res;
       if (Instruction *Res = foldICmpEqualityWithConstant(I, LHSI, CI))
         return Res;
-      if (Instruction *Res = foldICmpIntrinsicWithConstant(I, LHSI, CI))
-        return Res;
     }
   }
 
+  if (Instruction *Res = foldICmpIntrinsicWithConstant(I))
+    return Res;
+
   // Handle icmp with constant (but not simple integer constant) RHS
   if (Constant *RHSC = dyn_cast<Constant>(Op1)) {
     if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
index 61dbd31..894e9a0 100644 (file)
@@ -585,8 +585,7 @@ private:
                                     ConstantInt *RHS);
   Instruction *foldICmpEqualityWithConstant(ICmpInst &ICI, Instruction *LHS,
                                             ConstantInt *RHS);
-  Instruction *foldICmpIntrinsicWithConstant(ICmpInst &ICI, Instruction *LHS,
-                                             ConstantInt *RHS);
+  Instruction *foldICmpIntrinsicWithConstant(ICmpInst &ICI);
 
   Instruction *OptAndOp(Instruction *Op, ConstantInt *OpRHS,
                         ConstantInt *AndRHS, BinaryOperator &TheAnd);
index 1d49a0c..f384583 100644 (file)
@@ -316,12 +316,9 @@ entry:
 ; CHECK-NEXT: store volatile i1 %pop.cmp, i1* %c
 }
 
-; FIXME: Vectors should get the same folds as scalars.
-
 define <2 x i1> @ctlz_cmp_vec(<2 x i32> %a) {
 ; CHECK-LABEL: @ctlz_cmp_vec(
-; CHECK-NEXT:    [[X:%.*]] = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %a, i1 false) #0
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i32> [[X]], <i32 32, i32 32>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i32> %a, zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
   %x = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %a, i1 false) nounwind readnone
@@ -331,8 +328,7 @@ define <2 x i1> @ctlz_cmp_vec(<2 x i32> %a) {
 
 define <2 x i1> @cttz_cmp_vec(<2 x i32> %a) {
 ; CHECK-LABEL: @cttz_cmp_vec(
-; CHECK-NEXT:    [[X:%.*]] = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %a, i1 false) #0
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <2 x i32> [[X]], <i32 32, i32 32>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <2 x i32> %a, zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
   %x = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %a, i1 false) nounwind readnone
@@ -342,8 +338,7 @@ define <2 x i1> @cttz_cmp_vec(<2 x i32> %a) {
 
 define <2 x i1> @ctpop_cmp_vec(<2 x i32> %a) {
 ; CHECK-LABEL: @ctpop_cmp_vec(
-; CHECK-NEXT:    [[X:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %a) #0
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i32> [[X]], zeroinitializer
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i32> %a, zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
   %x = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %a) nounwind readnone