When a function takes a variable number of pointer arguments, with a zero
[oota-llvm.git] / lib / CodeGen / IntrinsicLowering.cpp
index 1817ade1cdb66955febf7a4bb60c8b0485ba9498..a570ef54c4582a1e26f088d52cc1f6d64746efcc 100644 (file)
@@ -110,7 +110,8 @@ void DefaultIntrinsicLowering::AddPrototypes(Module &M) {
       case Intrinsic::memset:
         M.getOrInsertFunction("memset", PointerType::get(Type::SByteTy),
                               PointerType::get(Type::SByteTy),
-                              Type::IntTy, (--(--I->arg_end()))->getType(), 0);
+                              Type::IntTy, (--(--I->arg_end()))->getType(),
+                              (Type *)0);
         break;
       case Intrinsic::isunordered:
         EnsureFunctionExists(M, "isunordered", I->arg_begin(), I->arg_end(),
@@ -131,7 +132,6 @@ void DefaultIntrinsicLowering::AddPrototypes(Module &M) {
 /// instruction.
 static Value *LowerCTPOP(Value *V, Instruction *IP) {
   assert(V->getType()->isInteger() && "Can't ctpop a non-integer type!");
-  unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
 
   static const uint64_t MaskValues[6] = {
     0x5555555555555555ULL, 0x3333333333333333ULL,
@@ -145,12 +145,13 @@ static Value *LowerCTPOP(Value *V, Instruction *IP) {
   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, 
+    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);
@@ -161,6 +162,29 @@ static Value *LowerCTPOP(Value *V, Instruction *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!");
@@ -210,54 +234,16 @@ void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
     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::createOr(Src, new ShiftInst(Instruction::Shr, Src,
-                                                        SA, "", CI), "", CI);
-    case Type::IntTyID:
-    case Type::UIntTyID:
-      SA = ConstantUInt::get(Type::UByteTy, 16);
-      Src = BinaryOperator::createOr(Src, new ShiftInst(Instruction::Shr,
-                                                        Src, SA, "", CI),
-                                     "", CI);
-    case Type::ShortTyID:
-    case Type::UShortTyID:
-      SA = ConstantUInt::get(Type::UByteTy, 8);
-      Src = BinaryOperator::createOr(Src, new ShiftInst(Instruction::Shr,
-                                                        Src, SA, "", CI),
-                                     "", CI);
-    default:
-      SA = ConstantUInt::get(Type::UByteTy, 1);
-      Src = BinaryOperator::createOr(Src, new ShiftInst(Instruction::Shr, Src,
-                                                        SA, "", CI), "", CI);
-      SA = ConstantUInt::get(Type::UByteTy, 2);
-      Src = BinaryOperator::createOr(Src, new ShiftInst(Instruction::Shr, Src,
-                                                        SA, "", CI), "", CI);
-      SA = ConstantUInt::get(Type::UByteTy, 4);
-      Src = BinaryOperator::createOr(Src, new ShiftInst(Instruction::Shr, Src,
-                                                        SA, "", CI), "", CI);
-    };
-    Src = BinaryOperator::createNot(Src, "", CI);
-
-
-    Src = LowerCTPOP(Src, CI);
-    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);
     Value *NotSrc = BinaryOperator::createNot(Src, Src->getName()+".not", CI);
-    Src = BinaryOperator::createAnd(NotSrc,
-                                    BinaryOperator::createSub(Src, 
-                           ConstantUInt::get(CI->getOperand(0)->getType(), 1), "", CI));
-
-    Src = LowerCTPOP(Src, 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;
   }