#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
+#include "llvm/Type.h"
#include <iostream>
using namespace llvm;
switch (I->getIntrinsicID()) {
default: break;
case Intrinsic::setjmp:
- EnsureFunctionExists(M, "setjmp", I->arg_begin(), I->arg_end(), Type::IntTy);
+ EnsureFunctionExists(M, "setjmp", I->arg_begin(), I->arg_end(),
+ Type::IntTy);
break;
case Intrinsic::longjmp:
- EnsureFunctionExists(M, "longjmp", I->arg_begin(), I->arg_end(),Type::VoidTy);
+ EnsureFunctionExists(M, "longjmp", I->arg_begin(), I->arg_end(),
+ Type::VoidTy);
break;
case Intrinsic::siglongjmp:
- EnsureFunctionExists(M, "abort", I->arg_end(), I->arg_end(), Type::VoidTy);
+ EnsureFunctionExists(M, "abort", I->arg_end(), I->arg_end(),
+ Type::VoidTy);
break;
case Intrinsic::memcpy:
EnsureFunctionExists(M, "memcpy", I->arg_begin(), --I->arg_end(),
I->arg_begin()->getType());
break;
case Intrinsic::memset:
- EnsureFunctionExists(M, "memset", I->arg_begin(), --I->arg_end(),
- I->arg_begin()->getType());
+ M.getOrInsertFunction("memset", PointerType::get(Type::SByteTy),
+ PointerType::get(Type::SByteTy),
+ Type::IntTy, (--(--I->arg_end()))->getType(),
+ (Type *)0);
break;
case Intrinsic::isunordered:
- EnsureFunctionExists(M, "isunordered", I->arg_begin(), I->arg_end(), Type::BoolTy);
+ EnsureFunctionExists(M, "isunordered", I->arg_begin(), I->arg_end(),
+ Type::BoolTy);
break;
case Intrinsic::sqrt:
- if(I->abegin()->getType() == Type::FloatTy)
- EnsureFunctionExists(M, "sqrtf", I->arg_begin(), I->arg_end(), Type::FloatTy);
+ if(I->arg_begin()->getType() == Type::FloatTy)
+ EnsureFunctionExists(M, "sqrtf", I->arg_begin(), I->arg_end(),
+ Type::FloatTy);
else
- EnsureFunctionExists(M, "sqrt", I->arg_begin(), I->arg_end(), Type::DoubleTy);
+ EnsureFunctionExists(M, "sqrt", I->arg_begin(), I->arg_end(),
+ Type::DoubleTy);
break;
}
}
+/// 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!");
AbortFCache);
break;
}
+ case Intrinsic::ctpop:
+ CI->replaceAllUsesWith(LowerCTPOP(CI->getOperand(1), CI));
+ break;
+
+ 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);
+ 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;
+ }
case Intrinsic::returnaddress:
case Intrinsic::frameaddress:
assert(CI->use_empty() &&
"Lowering should have eliminated any uses of the intrinsic call!");
- CI->getParent()->getInstList().erase(CI);
+ CI->eraseFromParent();
}