Fix order of eval problem from when I refactored this into a function.
[oota-llvm.git] / lib / CodeGen / IntrinsicLowering.cpp
index 49dd809193c8199c4ff156bc33e83a95985e0e96..b2dd57b50c2c33b963b3db11d0d4808a58b42b1a 100644 (file)
@@ -127,6 +127,63 @@ void DefaultIntrinsicLowering::AddPrototypes(Module &M) {
       }
 }
 
+/// LowerCTPOP - Emit the code to lower ctpop of V before the specified
+/// instruction.
+static Value *LowerCTPOP(Value *V, Instruction *IP) {
+  assert(V->getType()->isInteger() && "Can't ctpop a non-integer type!");
+
+  static const uint64_t MaskValues[6] = {
+    0x5555555555555555ULL, 0x3333333333333333ULL,
+    0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,
+    0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL
+  };
+
+  const Type *DestTy = V->getType();
+
+  // Force to unsigned so that the shift rights are logical.
+  if (DestTy->isSigned())
+    V = new CastInst(V, DestTy->getUnsignedVersion(), V->getName(), IP);
+
+  unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
+  for (unsigned i = 1, ct = 0; i != BitSize; i <<= 1, ++ct) {
+    Value *MaskCst =
+      ConstantExpr::getCast(ConstantUInt::get(Type::ULongTy,
+                                              MaskValues[ct]), V->getType());
+    Value *LHS = BinaryOperator::createAnd(V, MaskCst, "cppop.and1", IP);
+    Value *VShift = new ShiftInst(Instruction::Shr, V,
+                      ConstantInt::get(Type::UByteTy, i), "ctpop.sh", IP);
+    Value *RHS = BinaryOperator::createAnd(VShift, MaskCst, "cppop.and2", IP);
+    V = BinaryOperator::createAdd(LHS, RHS, "ctpop.step", IP);
+  }
+
+  if (V->getType() != DestTy)
+    V = new CastInst(V, DestTy, V->getName(), IP);
+  return V;
+}
+
+/// LowerCTLZ - Emit the code to lower ctlz of V before the specified
+/// instruction.
+static Value *LowerCTLZ(Value *V, Instruction *IP) {
+  const Type *DestTy = V->getType();
+
+  // Force to unsigned so that the shift rights are logical.
+  if (DestTy->isSigned())
+    V = new CastInst(V, DestTy->getUnsignedVersion(), V->getName(), IP);
+
+  unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
+  for (unsigned i = 1; i != BitSize; i <<= 1) {
+    Value *ShVal = ConstantInt::get(Type::UByteTy, i);
+    ShVal = new ShiftInst(Instruction::Shr, V, ShVal, "ctlz.sh", IP);
+    V = BinaryOperator::createOr(V, ShVal, "ctlz.step", IP);
+  }
+
+  if (V->getType() != DestTy)
+    V = new CastInst(V, DestTy, V->getName(), IP);
+
+  V = BinaryOperator::createNot(V, "", IP);
+  return LowerCTPOP(V, IP);
+}
+
 void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
   Function *Callee = CI->getCalledFunction();
   assert(Callee && "Cannot lower an indirect call!");
@@ -172,198 +229,20 @@ void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
                     AbortFCache);
     break;
   }
-  case Intrinsic::ctpop: {
-    Value *Src = CI->getOperand(1);
-    switch (CI->getOperand(0)->getType()->getTypeID())
-    {
-    case Type::SByteTyID:
-    case Type::UByteTyID:
-      {
-        Value* SA = ConstantUInt::get(Type::UByteTy, 1);
-        Value* MA = ConstantUInt::get(Type::UIntTy, 0x55);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA));
-        SA = ConstantUInt::get(Type::UByteTy, 2);
-        MA = ConstantUInt::get(Type::UIntTy, 0x33);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And,
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA));
-        SA = ConstantUInt::get(Type::UByteTy, 4);
-        MA = ConstantUInt::get(Type::UIntTy, 0x0F);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA), "ctpop");
-      }
-      break;
-    case Type::ShortTyID:
-    case Type::UShortTyID:
-      {
-        Value* SA = ConstantUInt::get(Type::UByteTy, 1);
-        Value* MA = ConstantUInt::get(Type::UIntTy, 0x5555);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA));
-        SA = ConstantUInt::get(Type::UByteTy, 2);
-        MA = ConstantUInt::get(Type::UIntTy, 0x3333);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA));
-        SA = ConstantUInt::get(Type::UByteTy, 4);
-        MA = ConstantUInt::get(Type::UIntTy, 0x0F0F);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA));
-        SA = ConstantUInt::get(Type::UByteTy, 8);
-        MA = ConstantUInt::get(Type::UIntTy, 0x00FF);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA), "ctpop");
-
-      }
-      break;
-    case Type::IntTyID:
-    case Type::UIntTyID:
-      {
-        Value* SA = ConstantUInt::get(Type::UByteTy, 1);
-        Value* MA = ConstantUInt::get(Type::UIntTy, 0x55555555);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA));
-        SA = ConstantUInt::get(Type::UByteTy, 2);
-        MA = ConstantUInt::get(Type::UIntTy, 0x33333333);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA));
-        SA = ConstantUInt::get(Type::UByteTy, 4);
-        MA = ConstantUInt::get(Type::UIntTy, 0x0F0F0F0F);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA));
-        SA = ConstantUInt::get(Type::UByteTy, 8);
-        MA = ConstantUInt::get(Type::UIntTy, 0x00FF00FF);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA));
-        SA = ConstantUInt::get(Type::UByteTy, 8);
-        MA = ConstantUInt::get(Type::UIntTy, 0x0000FFFF);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA), "ctpop");
-      }
-      break;
-    case Type::LongTyID:
-    case Type::ULongTyID:
-      {
-        Value* SA = ConstantUInt::get(Type::UByteTy, 1);
-        Value* MA = ConstantUInt::get(Type::ULongTy, 0x5555555555555555ULL);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA));
-        SA = ConstantUInt::get(Type::UByteTy, 2);
-        MA = ConstantUInt::get(Type::ULongTy, 0x3333333333333333ULL);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA));
-        SA = ConstantUInt::get(Type::UByteTy, 4);
-        MA = ConstantUInt::get(Type::ULongTy, 0x0F0F0F0F0F0F0F0FULL);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA));
-        SA = ConstantUInt::get(Type::UByteTy, 8);
-        MA = ConstantUInt::get(Type::ULongTy, 0x00FF00FF00FF00FFULL);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA));
-        SA = ConstantUInt::get(Type::UByteTy, 16);
-        MA = ConstantUInt::get(Type::ULongTy, 0x00000000FFFFFFFFULL);
-        Src = BinaryOperator::create(Instruction::Add,
-                BinaryOperator::create(Instruction::And, Src, MA),
-                BinaryOperator::create(Instruction::And, 
-                                       new ShiftInst(Instruction::Shr, Src, SA),
-                                       MA), "ctpop");
-      }
-      break;
-    default:
-      abort();
-    }
-        
-    CI->replaceAllUsesWith(Src);
+  case Intrinsic::ctpop:
+    CI->replaceAllUsesWith(LowerCTPOP(CI->getOperand(1), CI));
     break;
-  }
-  case Intrinsic::ctlz: {
-    Value *Src = CI->getOperand(1);
-    Value* SA;
-    switch (CI->getOperand(0)->getType()->getTypeID())
-    {
-    case Type::LongTyID:
-    case Type::ULongTyID:
-      SA = ConstantUInt::get(Type::UByteTy, 32);
-      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
-    case Type::IntTyID:
-    case Type::UIntTyID:
-      SA = ConstantUInt::get(Type::UByteTy, 16);
-      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
-    case Type::ShortTyID:
-    case Type::UShortTyID:
-      SA = ConstantUInt::get(Type::UByteTy, 8);
-      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
-    default:
-      SA = ConstantUInt::get(Type::UByteTy, 1);
-      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
-      SA = ConstantUInt::get(Type::UByteTy, 2);
-      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
-      SA = ConstantUInt::get(Type::UByteTy, 4);
-      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
-    };
-    Src = BinaryOperator::createNot(Src);
 
-    Src = new CallInst(new Function(CI->getCalledFunction()->getFunctionType(),
-                                    CI->getCalledFunction()->getLinkage(),
-                                    "llvm.ctpop"), Src);
-    CI->replaceAllUsesWith(Src);
+  case Intrinsic::ctlz:
+    CI->replaceAllUsesWith(LowerCTLZ(CI->getOperand(1), CI));
     break;
-  }
   case Intrinsic::cttz: {
+    // cttz(x) -> ctpop(~X & (X-1))
     Value *Src = CI->getOperand(1);
-    Src = BinaryOperator::create(Instruction::And, BinaryOperator::createNot(Src),
-            BinaryOperator::create(Instruction::Sub, Src, 
-                            ConstantUInt::get(CI->getOperand(0)->getType(), 1)));
-    Src = new CallInst(new Function(CI->getCalledFunction()->getFunctionType(),
-                                    CI->getCalledFunction()->getLinkage(),
-                                    "llvm.ctpop"), Src);
+    Value *NotSrc = BinaryOperator::createNot(Src, Src->getName()+".not", CI);
+    Value *SrcM1  = ConstantInt::get(Src->getType(), 1);
+    SrcM1 = BinaryOperator::createSub(Src, SrcM1, "", CI);
+    Src = LowerCTPOP(BinaryOperator::createAnd(NotSrc, SrcM1, "", CI), CI);
     CI->replaceAllUsesWith(Src);
     break;
   }
@@ -442,5 +321,5 @@ void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
 
   assert(CI->use_empty() &&
          "Lowering should have eliminated any uses of the intrinsic call!");
-  CI->getParent()->getInstList().erase(CI);
+  CI->eraseFromParent();
 }