"llvm/lib/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "3ce57c6baf0961108f76d3d377ff554b765b848e"
Newer
Older
//===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//===----------------------------------------------------------------------===//
//
// This file implements the IntrinsicLowering class.
//
//===----------------------------------------------------------------------===//
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
Andrew Lenharth
committed
#include "llvm/Type.h"
#include "llvm/CodeGen/IntrinsicLowering.h"
#include "llvm/Support/Streams.h"
#include "llvm/Target/TargetData.h"
#include "llvm/ADT/STLExtras.h"
using namespace llvm;
template <class ArgIt>
Chris Lattner
committed
static void EnsureFunctionExists(Module &M, const char *Name,
ArgIt ArgBegin, ArgIt ArgEnd,
const Type *RetTy) {
// Insert a correctly-typed definition now.
std::vector<const Type *> ParamTys;
for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
ParamTys.push_back(I->getType());
Chris Lattner
committed
M.getOrInsertFunction(Name, FunctionType::get(RetTy, ParamTys, false));
}
/// ReplaceCallWith - This function is used when we want to lower an intrinsic
/// call to a call of an external function. This handles hard cases such as
/// when there was already a prototype for the external function, and if that
/// prototype doesn't match the arguments we expect to pass in.
template <class ArgIt>
static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
Chris Lattner
committed
ArgIt ArgBegin, ArgIt ArgEnd,
const Type *RetTy, Constant *&FCache) {
if (!FCache) {
// If we haven't already looked up this function, check to see if the
// program already contains a function with this name.
Module *M = CI->getParent()->getParent()->getParent();
Chris Lattner
committed
// Get or insert the definition now.
std::vector<const Type *> ParamTys;
for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
ParamTys.push_back((*I)->getType());
FCache = M->getOrInsertFunction(NewFn,
FunctionType::get(RetTy, ParamTys, false));
}
CallInst *NewCI = CallInst::Create(FCache, Args.begin(), Args.end(),
CI->getName(), CI);
Chris Lattner
committed
if (!CI->use_empty())
CI->replaceAllUsesWith(NewCI);
return NewCI;
}
void IntrinsicLowering::AddPrototypes(Module &M) {
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
if (I->isDeclaration() && !I->use_empty())
switch (I->getIntrinsicID()) {
default: break;
case Intrinsic::setjmp:
Chris Lattner
committed
EnsureFunctionExists(M, "setjmp", I->arg_begin(), I->arg_end(),
break;
case Intrinsic::longjmp:
Chris Lattner
committed
EnsureFunctionExists(M, "longjmp", I->arg_begin(), I->arg_end(),
Type::VoidTy);
break;
case Intrinsic::siglongjmp:
Chris Lattner
committed
EnsureFunctionExists(M, "abort", I->arg_end(), I->arg_end(),
Type::VoidTy);
break;
case Intrinsic::memcpy_i32:
case Intrinsic::memcpy_i64:
Christopher Lamb
committed
M.getOrInsertFunction("memcpy", PointerType::getUnqual(Type::Int8Ty),
PointerType::getUnqual(Type::Int8Ty),
PointerType::getUnqual(Type::Int8Ty),
TD.getIntPtrType(), (Type *)0);
break;
case Intrinsic::memmove_i32:
case Intrinsic::memmove_i64:
Christopher Lamb
committed
M.getOrInsertFunction("memmove", PointerType::getUnqual(Type::Int8Ty),
PointerType::getUnqual(Type::Int8Ty),
PointerType::getUnqual(Type::Int8Ty),
TD.getIntPtrType(), (Type *)0);
break;
case Intrinsic::memset_i32:
case Intrinsic::memset_i64:
Christopher Lamb
committed
M.getOrInsertFunction("memset", PointerType::getUnqual(Type::Int8Ty),
PointerType::getUnqual(Type::Int8Ty),
Type::Int32Ty,
TD.getIntPtrType(), (Type *)0);
break;
case Intrinsic::sqrt:
switch((int)I->arg_begin()->getType()->getTypeID()) {
case Type::FloatTyID:
Chris Lattner
committed
EnsureFunctionExists(M, "sqrtf", I->arg_begin(), I->arg_end(),
Type::FloatTy);
case Type::DoubleTyID:
Chris Lattner
committed
EnsureFunctionExists(M, "sqrt", I->arg_begin(), I->arg_end(),
Type::DoubleTy);
case Type::X86_FP80TyID:
case Type::FP128TyID:
case Type::PPC_FP128TyID:
EnsureFunctionExists(M, "sqrtl", I->arg_begin(), I->arg_end(),
I->arg_begin()->getType());
}
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
case Intrinsic::sin:
switch((int)I->arg_begin()->getType()->getTypeID()) {
case Type::FloatTyID:
EnsureFunctionExists(M, "sinf", I->arg_begin(), I->arg_end(),
Type::FloatTy);
case Type::DoubleTyID:
EnsureFunctionExists(M, "sin", I->arg_begin(), I->arg_end(),
Type::DoubleTy);
case Type::X86_FP80TyID:
case Type::FP128TyID:
case Type::PPC_FP128TyID:
EnsureFunctionExists(M, "sinl", I->arg_begin(), I->arg_end(),
I->arg_begin()->getType());
}
break;
case Intrinsic::cos:
switch((int)I->arg_begin()->getType()->getTypeID()) {
case Type::FloatTyID:
EnsureFunctionExists(M, "cosf", I->arg_begin(), I->arg_end(),
Type::FloatTy);
case Type::DoubleTyID:
EnsureFunctionExists(M, "cos", I->arg_begin(), I->arg_end(),
Type::DoubleTy);
case Type::X86_FP80TyID:
case Type::FP128TyID:
case Type::PPC_FP128TyID:
EnsureFunctionExists(M, "cosl", I->arg_begin(), I->arg_end(),
I->arg_begin()->getType());
}
break;
case Intrinsic::pow:
switch((int)I->arg_begin()->getType()->getTypeID()) {
case Type::FloatTyID:
EnsureFunctionExists(M, "powf", I->arg_begin(), I->arg_end(),
Type::FloatTy);
case Type::DoubleTyID:
EnsureFunctionExists(M, "pow", I->arg_begin(), I->arg_end(),
Type::DoubleTy);
case Type::X86_FP80TyID:
case Type::FP128TyID:
case Type::PPC_FP128TyID:
EnsureFunctionExists(M, "powl", I->arg_begin(), I->arg_end(),
I->arg_begin()->getType());
}
break;
}
}
/// LowerBSWAP - Emit the code to lower bswap of V before the specified
/// instruction IP.
static Value *LowerBSWAP(Value *V, Instruction *IP) {
Chris Lattner
committed
assert(V->getType()->isInteger() && "Can't bswap a non-integer type!");
unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
switch(BitSize) {
default: assert(0 && "Unhandled type size of value to byteswap!");
case 16: {
Gabor Greif
committed
Value *Tmp1 = BinaryOperator::CreateShl(V,
ConstantInt::get(V->getType(),8),"bswap.2",IP);
Gabor Greif
committed
Value *Tmp2 = BinaryOperator::CreateLShr(V,
ConstantInt::get(V->getType(),8),"bswap.1",IP);
Gabor Greif
committed
V = BinaryOperator::CreateOr(Tmp1, Tmp2, "bswap.i16", IP);
break;
}
case 32: {
Gabor Greif
committed
Value *Tmp4 = BinaryOperator::CreateShl(V,
ConstantInt::get(V->getType(),24),"bswap.4", IP);
Gabor Greif
committed
Value *Tmp3 = BinaryOperator::CreateShl(V,
ConstantInt::get(V->getType(),8),"bswap.3",IP);
Gabor Greif
committed
Value *Tmp2 = BinaryOperator::CreateLShr(V,
ConstantInt::get(V->getType(),8),"bswap.2",IP);
Gabor Greif
committed
Value *Tmp1 = BinaryOperator::CreateLShr(V,
ConstantInt::get(V->getType(),24),"bswap.1", IP);
Gabor Greif
committed
Tmp3 = BinaryOperator::CreateAnd(Tmp3,
"bswap.and3", IP);
Gabor Greif
committed
Tmp2 = BinaryOperator::CreateAnd(Tmp2,
"bswap.and2", IP);
Gabor Greif
committed
Tmp4 = BinaryOperator::CreateOr(Tmp4, Tmp3, "bswap.or1", IP);
Tmp2 = BinaryOperator::CreateOr(Tmp2, Tmp1, "bswap.or2", IP);
V = BinaryOperator::CreateOr(Tmp4, Tmp2, "bswap.i32", IP);
break;
}
case 64: {
Gabor Greif
committed
Value *Tmp8 = BinaryOperator::CreateShl(V,
ConstantInt::get(V->getType(),56),"bswap.8", IP);
Gabor Greif
committed
Value *Tmp7 = BinaryOperator::CreateShl(V,
ConstantInt::get(V->getType(),40),"bswap.7", IP);
Gabor Greif
committed
Value *Tmp6 = BinaryOperator::CreateShl(V,
ConstantInt::get(V->getType(),24),"bswap.6", IP);
Gabor Greif
committed
Value *Tmp5 = BinaryOperator::CreateShl(V,
ConstantInt::get(V->getType(),8),"bswap.5", IP);
Gabor Greif
committed
Value* Tmp4 = BinaryOperator::CreateLShr(V,
ConstantInt::get(V->getType(),8),"bswap.4", IP);
Gabor Greif
committed
Value* Tmp3 = BinaryOperator::CreateLShr(V,
ConstantInt::get(V->getType(),24),"bswap.3", IP);
Gabor Greif
committed
Value* Tmp2 = BinaryOperator::CreateLShr(V,
ConstantInt::get(V->getType(),40),"bswap.2", IP);
Gabor Greif
committed
Value* Tmp1 = BinaryOperator::CreateLShr(V,
ConstantInt::get(V->getType(),56),"bswap.1", IP);
Gabor Greif
committed
Tmp7 = BinaryOperator::CreateAnd(Tmp7,
Gabor Greif
committed
Tmp6 = BinaryOperator::CreateAnd(Tmp6,
Gabor Greif
committed
Tmp5 = BinaryOperator::CreateAnd(Tmp5,
Gabor Greif
committed
Tmp4 = BinaryOperator::CreateAnd(Tmp4,
Gabor Greif
committed
Tmp3 = BinaryOperator::CreateAnd(Tmp3,
Gabor Greif
committed
Tmp2 = BinaryOperator::CreateAnd(Tmp2,
Gabor Greif
committed
Tmp8 = BinaryOperator::CreateOr(Tmp8, Tmp7, "bswap.or1", IP);
Tmp6 = BinaryOperator::CreateOr(Tmp6, Tmp5, "bswap.or2", IP);
Tmp4 = BinaryOperator::CreateOr(Tmp4, Tmp3, "bswap.or3", IP);
Tmp2 = BinaryOperator::CreateOr(Tmp2, Tmp1, "bswap.or4", IP);
Tmp8 = BinaryOperator::CreateOr(Tmp8, Tmp6, "bswap.or5", IP);
Tmp4 = BinaryOperator::CreateOr(Tmp4, Tmp2, "bswap.or6", IP);
V = BinaryOperator::CreateOr(Tmp8, Tmp4, "bswap.i64", IP);
break;
}
}
return V;
}
/// LowerCTPOP - Emit the code to lower ctpop of V before the specified
/// instruction IP.
static Value *LowerCTPOP(Value *V, Instruction *IP) {
Chris Lattner
committed
assert(V->getType()->isInteger() && "Can't ctpop a non-integer type!");
static const uint64_t MaskValues[6] = {
0x5555555555555555ULL, 0x3333333333333333ULL,
0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,
0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL
};
unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
unsigned WordSize = (BitSize + 63) / 64;
Value *Count = ConstantInt::get(V->getType(), 0);
for (unsigned n = 0; n < WordSize; ++n) {
Value *PartValue = V;
for (unsigned i = 1, ct = 0; i < (BitSize>64 ? 64 : BitSize);
i <<= 1, ++ct) {
Value *MaskCst = ConstantInt::get(V->getType(), MaskValues[ct]);
Gabor Greif
committed
Value *LHS = BinaryOperator::CreateAnd(
PartValue, MaskCst, "cppop.and1", IP);
Gabor Greif
committed
Value *VShift = BinaryOperator::CreateLShr(PartValue,
ConstantInt::get(V->getType(), i), "ctpop.sh", IP);
Gabor Greif
committed
Value *RHS = BinaryOperator::CreateAnd(VShift, MaskCst, "cppop.and2", IP);
PartValue = BinaryOperator::CreateAdd(LHS, RHS, "ctpop.step", IP);
Gabor Greif
committed
Count = BinaryOperator::CreateAdd(PartValue, Count, "ctpop.part", IP);
if (BitSize > 64) {
Gabor Greif
committed
V = BinaryOperator::CreateLShr(V, ConstantInt::get(V->getType(), 64),
"ctpop.part.sh", IP);
BitSize -= 64;
}
}
return Count;
}
/// LowerCTLZ - Emit the code to lower ctlz of V before the specified
/// instruction IP.
static Value *LowerCTLZ(Value *V, Instruction *IP) {
unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
for (unsigned i = 1; i < BitSize; i <<= 1) {
Value *ShVal = ConstantInt::get(V->getType(), i);
Gabor Greif
committed
ShVal = BinaryOperator::CreateLShr(V, ShVal, "ctlz.sh", IP);
V = BinaryOperator::CreateOr(V, ShVal, "ctlz.step", IP);
}
Gabor Greif
committed
V = BinaryOperator::CreateNot(V, "", IP);
return LowerCTPOP(V, IP);
}
/// Convert the llvm.part.select.iX.iY intrinsic. This intrinsic takes
/// three integer arguments. The first argument is the Value from which the
/// bits will be selected. It may be of any bit width. The second and third
/// arguments specify a range of bits to select with the second argument
/// specifying the low bit and the third argument specifying the high bit. Both
/// must be type i32. The result is the corresponding selected bits from the
/// Value in the same width as the Value (first argument). If the low bit index
/// is higher than the high bit index then the inverse selection is done and
/// the bits are returned in inverse order.
/// @brief Lowering of llvm.part.select intrinsic.
static Instruction *LowerPartSelect(CallInst *CI) {
// Make sure we're dealing with a part select intrinsic here
Function *F = CI->getCalledFunction();
const FunctionType *FT = F->getFunctionType();
if (!F->isDeclaration() || !FT->getReturnType()->isInteger() ||
FT->getNumParams() != 3 || !FT->getParamType(0)->isInteger() ||
!FT->getParamType(1)->isInteger() || !FT->getParamType(2)->isInteger())
return CI;
// Get the intrinsic implementation function by converting all the . to _
// in the intrinsic's function name and then reconstructing the function
// declaration.
std::string Name(F->getName());
for (unsigned i = 4; i < Name.length(); ++i)
if (Name[i] == '.')
Name[i] = '_';
Module* M = F->getParent();
F = cast<Function>(M->getOrInsertFunction(Name, FT));
F->setLinkage(GlobalValue::WeakLinkage);
// If we haven't defined the impl function yet, do so now
if (F->isDeclaration()) {
// Get the arguments to the function
Function::arg_iterator args = F->arg_begin();
Value* Val = args++; Val->setName("Val");
Value* Lo = args++; Lo->setName("Lo");
Value* Hi = args++; Hi->setName("High");
// We want to select a range of bits here such that [Hi, Lo] is shifted
// down to the low bits. However, it is quite possible that Hi is smaller
// than Lo in which case the bits have to be reversed.
// Create the blocks we will need for the two cases (forward, reverse)
BasicBlock* CurBB = BasicBlock::Create("entry", F);
BasicBlock *RevSize = BasicBlock::Create("revsize", CurBB->getParent());
BasicBlock *FwdSize = BasicBlock::Create("fwdsize", CurBB->getParent());
BasicBlock *Compute = BasicBlock::Create("compute", CurBB->getParent());
BasicBlock *Reverse = BasicBlock::Create("reverse", CurBB->getParent());
BasicBlock *RsltBlk = BasicBlock::Create("result", CurBB->getParent());
// Cast Hi and Lo to the size of Val so the widths are all the same
if (Hi->getType() != Val->getType())
Gabor Greif
committed
Hi = CastInst::CreateIntegerCast(Hi, Val->getType(), false,
"tmp", CurBB);
if (Lo->getType() != Val->getType())
Gabor Greif
committed
Lo = CastInst::CreateIntegerCast(Lo, Val->getType(), false,
"tmp", CurBB);
// Compute a few things that both cases will need, up front.
Constant* Zero = ConstantInt::get(Val->getType(), 0);
Constant* One = ConstantInt::get(Val->getType(), 1);
Constant* AllOnes = ConstantInt::getAllOnesValue(Val->getType());
// Compare the Hi and Lo bit positions. This is used to determine
// which case we have (forward or reverse)
ICmpInst *Cmp = new ICmpInst(ICmpInst::ICMP_ULT, Hi, Lo, "less",CurBB);
BranchInst::Create(RevSize, FwdSize, Cmp, CurBB);
// First, copmute the number of bits in the forward case.
Instruction* FBitSize =
Gabor Greif
committed
BinaryOperator::CreateSub(Hi, Lo,"fbits", FwdSize);
BranchInst::Create(Compute, FwdSize);
// Second, compute the number of bits in the reverse case.
Instruction* RBitSize =
Gabor Greif
committed
BinaryOperator::CreateSub(Lo, Hi, "rbits", RevSize);
BranchInst::Create(Compute, RevSize);
// Now, compute the bit range. Start by getting the bitsize and the shift
// amount (either Hi or Lo) from PHI nodes. Then we compute a mask for
// the number of bits we want in the range. We shift the bits down to the
// least significant bits, apply the mask to zero out unwanted high bits,
// and we have computed the "forward" result. It may still need to be
// reversed.
// Get the BitSize from one of the two subtractions
PHINode *BitSize = PHINode::Create(Val->getType(), "bits", Compute);
BitSize->reserveOperandSpace(2);
BitSize->addIncoming(FBitSize, FwdSize);
BitSize->addIncoming(RBitSize, RevSize);
// Get the ShiftAmount as the smaller of Hi/Lo
PHINode *ShiftAmt = PHINode::Create(Val->getType(), "shiftamt", Compute);
ShiftAmt->reserveOperandSpace(2);
ShiftAmt->addIncoming(Lo, FwdSize);
ShiftAmt->addIncoming(Hi, RevSize);
// Increment the bit size
Instruction *BitSizePlusOne =
Gabor Greif
committed
BinaryOperator::CreateAdd(BitSize, One, "bits", Compute);
// Create a Mask to zero out the high order bits.
Instruction* Mask =
Gabor Greif
committed
BinaryOperator::CreateShl(AllOnes, BitSizePlusOne, "mask", Compute);
Mask = BinaryOperator::CreateNot(Mask, "mask", Compute);
// Shift the bits down and apply the mask
Instruction* FRes =
Gabor Greif
committed
BinaryOperator::CreateLShr(Val, ShiftAmt, "fres", Compute);
FRes = BinaryOperator::CreateAnd(FRes, Mask, "fres", Compute);
BranchInst::Create(Reverse, RsltBlk, Cmp, Compute);
// In the Reverse block we have the mask already in FRes but we must reverse
// it by shifting FRes bits right and putting them in RRes by shifting them
// in from left.
// First set up our loop counters
PHINode *Count = PHINode::Create(Val->getType(), "count", Reverse);
Count->reserveOperandSpace(2);
Count->addIncoming(BitSizePlusOne, Compute);
// Next, get the value that we are shifting.
PHINode *BitsToShift = PHINode::Create(Val->getType(), "val", Reverse);
BitsToShift->reserveOperandSpace(2);
BitsToShift->addIncoming(FRes, Compute);
// Finally, get the result of the last computation
PHINode *RRes = PHINode::Create(Val->getType(), "rres", Reverse);
RRes->reserveOperandSpace(2);
RRes->addIncoming(Zero, Compute);
// Decrement the counter
Gabor Greif
committed
Instruction *Decr = BinaryOperator::CreateSub(Count, One, "decr", Reverse);
Count->addIncoming(Decr, Reverse);
// Compute the Bit that we want to move
Instruction *Bit =
Gabor Greif
committed
BinaryOperator::CreateAnd(BitsToShift, One, "bit", Reverse);
// Compute the new value for next iteration.
Instruction *NewVal =
Gabor Greif
committed
BinaryOperator::CreateLShr(BitsToShift, One, "rshift", Reverse);
BitsToShift->addIncoming(NewVal, Reverse);
// Shift the bit into the low bits of the result.
Instruction *NewRes =
Gabor Greif
committed
BinaryOperator::CreateShl(RRes, One, "lshift", Reverse);
NewRes = BinaryOperator::CreateOr(NewRes, Bit, "addbit", Reverse);
RRes->addIncoming(NewRes, Reverse);
// Terminate loop if we've moved all the bits.
ICmpInst *Cond =
new ICmpInst(ICmpInst::ICMP_EQ, Decr, Zero, "cond", Reverse);
BranchInst::Create(RsltBlk, Reverse, Cond, Reverse);
// Finally, in the result block, select one of the two results with a PHI
// node and return the result;
CurBB = RsltBlk;
PHINode *BitSelect = PHINode::Create(Val->getType(), "part_select", CurBB);
BitSelect->reserveOperandSpace(2);
BitSelect->addIncoming(FRes, Compute);
BitSelect->addIncoming(NewRes, Reverse);
ReturnInst::Create(BitSelect, CurBB);
}
// Return a call to the implementation function
Value *Args[] = {
CI->getOperand(1),
CI->getOperand(2),
CI->getOperand(3)
};
return CallInst::Create(F, Args, array_endof(Args), CI->getName(), CI);
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
/// Convert the llvm.part.set.iX.iY.iZ intrinsic. This intrinsic takes
/// four integer arguments (iAny %Value, iAny %Replacement, i32 %Low, i32 %High)
/// The first two arguments can be any bit width. The result is the same width
/// as %Value. The operation replaces bits between %Low and %High with the value
/// in %Replacement. If %Replacement is not the same width, it is truncated or
/// zero extended as appropriate to fit the bits being replaced. If %Low is
/// greater than %High then the inverse set of bits are replaced.
/// @brief Lowering of llvm.bit.part.set intrinsic.
static Instruction *LowerPartSet(CallInst *CI) {
// Make sure we're dealing with a part select intrinsic here
Function *F = CI->getCalledFunction();
const FunctionType *FT = F->getFunctionType();
if (!F->isDeclaration() || !FT->getReturnType()->isInteger() ||
FT->getNumParams() != 4 || !FT->getParamType(0)->isInteger() ||
!FT->getParamType(1)->isInteger() || !FT->getParamType(2)->isInteger() ||
!FT->getParamType(3)->isInteger())
return CI;
// Get the intrinsic implementation function by converting all the . to _
// in the intrinsic's function name and then reconstructing the function
// declaration.
std::string Name(F->getName());
for (unsigned i = 4; i < Name.length(); ++i)
if (Name[i] == '.')
Name[i] = '_';
Module* M = F->getParent();
F = cast<Function>(M->getOrInsertFunction(Name, FT));
F->setLinkage(GlobalValue::WeakLinkage);
// If we haven't defined the impl function yet, do so now
if (F->isDeclaration()) {
// Get the arguments for the function.
Function::arg_iterator args = F->arg_begin();
Value* Val = args++; Val->setName("Val");
Value* Rep = args++; Rep->setName("Rep");
Value* Lo = args++; Lo->setName("Lo");
Value* Hi = args++; Hi->setName("Hi");
// Get some types we need
const IntegerType* ValTy = cast<IntegerType>(Val->getType());
const IntegerType* RepTy = cast<IntegerType>(Rep->getType());
uint32_t ValBits = ValTy->getBitWidth();
uint32_t RepBits = RepTy->getBitWidth();
// Constant Definitions
ConstantInt* RepBitWidth = ConstantInt::get(Type::Int32Ty, RepBits);
ConstantInt* RepMask = ConstantInt::getAllOnesValue(RepTy);
ConstantInt* ValMask = ConstantInt::getAllOnesValue(ValTy);
ConstantInt* One = ConstantInt::get(Type::Int32Ty, 1);
ConstantInt* ValOne = ConstantInt::get(ValTy, 1);
ConstantInt* Zero = ConstantInt::get(Type::Int32Ty, 0);
ConstantInt* ValZero = ConstantInt::get(ValTy, 0);
// Basic blocks we fill in below.
BasicBlock* entry = BasicBlock::Create("entry", F, 0);
BasicBlock* large = BasicBlock::Create("large", F, 0);
BasicBlock* small = BasicBlock::Create("small", F, 0);
BasicBlock* reverse = BasicBlock::Create("reverse", F, 0);
BasicBlock* result = BasicBlock::Create("result", F, 0);
// BASIC BLOCK: entry
// First, get the number of bits that we're placing as an i32
ICmpInst* is_forward =
new ICmpInst(ICmpInst::ICMP_ULT, Lo, Hi, "", entry);
SelectInst* Hi_pn = SelectInst::Create(is_forward, Hi, Lo, "", entry);
SelectInst* Lo_pn = SelectInst::Create(is_forward, Lo, Hi, "", entry);
Gabor Greif
committed
BinaryOperator* NumBits = BinaryOperator::CreateSub(Hi_pn, Lo_pn, "",entry);
NumBits = BinaryOperator::CreateAdd(NumBits, One, "", entry);
// Now, convert Lo and Hi to ValTy bit width
Lo = new ZExtInst(Lo_pn, ValTy, "", entry);
Lo = new TruncInst(Lo_pn, ValTy, "", entry);
// Determine if the replacement bits are larger than the number of bits we
// are replacing and deal with it.
ICmpInst* is_large =
new ICmpInst(ICmpInst::ICMP_ULT, NumBits, RepBitWidth, "", entry);
BranchInst::Create(large, small, is_large, entry);
// BASIC BLOCK: large
Instruction* MaskBits =
Gabor Greif
committed
BinaryOperator::CreateSub(RepBitWidth, NumBits, "", large);
MaskBits = CastInst::CreateIntegerCast(MaskBits, RepMask->getType(),
false, "", large);
Gabor Greif
committed
BinaryOperator::CreateLShr(RepMask, MaskBits, "", large);
BinaryOperator* Rep2 = BinaryOperator::CreateAnd(Mask1, Rep, "", large);
BranchInst::Create(small, large);
// BASIC BLOCK: small
PHINode* Rep3 = PHINode::Create(RepTy, "", small);
Rep3->addIncoming(Rep2, large);
Value* Rep4 = Rep3;
if (ValBits > RepBits)
Rep4 = new ZExtInst(Rep3, ValTy, "", small);
else if (ValBits < RepBits)
Rep4 = new TruncInst(Rep3, ValTy, "", small);
BranchInst::Create(result, reverse, is_forward, small);
// BASIC BLOCK: reverse (reverses the bits of the replacement)
// Set up our loop counter as a PHI so we can decrement on each iteration.
// We will loop for the number of bits in the replacement value.
PHINode *Count = PHINode::Create(Type::Int32Ty, "count", reverse);
Count->reserveOperandSpace(2);
Count->addIncoming(NumBits, small);
// Get the value that we are shifting bits out of as a PHI because
// we'll change this with each iteration.
PHINode *BitsToShift = PHINode::Create(Val->getType(), "val", reverse);
BitsToShift->reserveOperandSpace(2);
BitsToShift->addIncoming(Rep4, small);
// Get the result of the last computation or zero on first iteration
PHINode *RRes = PHINode::Create(Val->getType(), "rres", reverse);
RRes->reserveOperandSpace(2);
RRes->addIncoming(ValZero, small);
// Decrement the loop counter by one
Gabor Greif
committed
Instruction *Decr = BinaryOperator::CreateSub(Count, One, "", reverse);
Count->addIncoming(Decr, reverse);
// Get the bit that we want to move into the result
Gabor Greif
committed
Value *Bit = BinaryOperator::CreateAnd(BitsToShift, ValOne, "", reverse);
// Compute the new value of the bits to shift for the next iteration.
Gabor Greif
committed
Value *NewVal = BinaryOperator::CreateLShr(BitsToShift, ValOne,"", reverse);
BitsToShift->addIncoming(NewVal, reverse);
// Shift the bit we extracted into the low bit of the result.
Gabor Greif
committed
Instruction *NewRes = BinaryOperator::CreateShl(RRes, ValOne, "", reverse);
NewRes = BinaryOperator::CreateOr(NewRes, Bit, "", reverse);
RRes->addIncoming(NewRes, reverse);
// Terminate loop if we've moved all the bits.
ICmpInst *Cond = new ICmpInst(ICmpInst::ICMP_EQ, Decr, Zero, "", reverse);
BranchInst::Create(result, reverse, Cond, reverse);
// BASIC BLOCK: result
PHINode *Rplcmnt = PHINode::Create(Val->getType(), "", result);
Rplcmnt->reserveOperandSpace(2);
Rplcmnt->addIncoming(NewRes, reverse);
Rplcmnt->addIncoming(Rep4, small);
Gabor Greif
committed
Value* t0 = CastInst::CreateIntegerCast(NumBits,ValTy,false,"",result);
Value* t1 = BinaryOperator::CreateShl(ValMask, Lo, "", result);
Value* t2 = BinaryOperator::CreateNot(t1, "", result);
Value* t3 = BinaryOperator::CreateShl(t1, t0, "", result);
Value* t4 = BinaryOperator::CreateOr(t2, t3, "", result);
Value* t5 = BinaryOperator::CreateAnd(t4, Val, "", result);
Value* t6 = BinaryOperator::CreateShl(Rplcmnt, Lo, "", result);
Value* Rslt = BinaryOperator::CreateOr(t5, t6, "part_set", result);
ReturnInst::Create(Rslt, result);
Value *Args[] = {
CI->getOperand(1),
CI->getOperand(2),
CI->getOperand(3),
CI->getOperand(4)
};
return CallInst::Create(F, Args, array_endof(Args), CI->getName(), CI);
void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
Function *Callee = CI->getCalledFunction();
assert(Callee && "Cannot lower an indirect call!");
switch (Callee->getIntrinsicID()) {
case Intrinsic::not_intrinsic:
Bill Wendling
committed
cerr << "Cannot lower a call to a non-intrinsic function '"
<< Callee->getName() << "'!\n";
abort();
default:
Bill Wendling
committed
cerr << "Error: Code generator does not support intrinsic function '"
<< Callee->getName() << "'!\n";
abort();
// The setjmp/longjmp intrinsics should only exist in the code if it was
// never optimized (ie, right out of the CFE), or if it has been hacked on
// by the lowerinvoke pass. In both cases, the right thing to do is to
// convert the call to an explicit setjmp or longjmp call.
case Intrinsic::setjmp: {
Chris Lattner
committed
static Constant *SetjmpFCache = 0;
Value *V = ReplaceCallWith("setjmp", CI, CI->op_begin()+1, CI->op_end(),
Chris Lattner
committed
Type::Int32Ty, SetjmpFCache);
if (CI->getType() != Type::VoidTy)
CI->replaceAllUsesWith(V);
break;
}
if (CI->getType() != Type::VoidTy)
CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
break;
case Intrinsic::longjmp: {
Chris Lattner
committed
static Constant *LongjmpFCache = 0;
ReplaceCallWith("longjmp", CI, CI->op_begin()+1, CI->op_end(),
Chris Lattner
committed
Type::VoidTy, LongjmpFCache);
break;
}
case Intrinsic::siglongjmp: {
// Insert the call to abort
Chris Lattner
committed
static Constant *AbortFCache = 0;
Chris Lattner
committed
Type::VoidTy, AbortFCache);
break;
}
CI->replaceAllUsesWith(LowerCTPOP(CI->getOperand(1), CI));
break;
CI->replaceAllUsesWith(LowerBSWAP(CI->getOperand(1), CI));
break;
CI->replaceAllUsesWith(LowerCTLZ(CI->getOperand(1), CI));
Andrew Lenharth
committed
break;
// cttz(x) -> ctpop(~X & (X-1))
Andrew Lenharth
committed
Value *Src = CI->getOperand(1);
Gabor Greif
committed
Value *NotSrc = BinaryOperator::CreateNot(Src, Src->getName()+".not", CI);
Value *SrcM1 = ConstantInt::get(Src->getType(), 1);
Gabor Greif
committed
SrcM1 = BinaryOperator::CreateSub(Src, SrcM1, "", CI);
Src = LowerCTPOP(BinaryOperator::CreateAnd(NotSrc, SrcM1, "", CI), CI);
Andrew Lenharth
committed
CI->replaceAllUsesWith(Src);
break;
}
case Intrinsic::part_select:
CI->replaceAllUsesWith(LowerPartSelect(CI));
break;
case Intrinsic::part_set:
CI->replaceAllUsesWith(LowerPartSet(CI));
break;
case Intrinsic::stacksave:
case Intrinsic::stackrestore: {
static bool Warned = false;
if (!Warned)
Bill Wendling
committed
cerr << "WARNING: this target does not support the llvm.stack"
<< (Callee->getIntrinsicID() == Intrinsic::stacksave ?
"save" : "restore") << " intrinsic.\n";
Warned = true;
if (Callee->getIntrinsicID() == Intrinsic::stacksave)
CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
break;
}
case Intrinsic::returnaddress:
case Intrinsic::frameaddress:
Bill Wendling
committed
cerr << "WARNING: this target does not support the llvm."
<< (Callee->getIntrinsicID() == Intrinsic::returnaddress ?
"return" : "frame") << "address intrinsic.\n";
CI->replaceAllUsesWith(ConstantPointerNull::get(
cast<PointerType>(CI->getType())));
break;
case Intrinsic::prefetch:
break; // Simply strip out prefetches on unsupported architectures
Andrew Lenharth
committed
case Intrinsic::pcmarker:
break; // Simply strip out pcmarker on unsupported architectures
case Intrinsic::readcyclecounter: {
Bill Wendling
committed
cerr << "WARNING: this target does not support the llvm.readcyclecoun"
<< "ter intrinsic. It is being lowered to a constant 0\n";
Andrew Lenharth
committed
case Intrinsic::dbg_stoppoint:
case Intrinsic::dbg_region_start:
case Intrinsic::dbg_region_end:
case Intrinsic::dbg_func_start:
break; // Simply strip out debugging intrinsics
case Intrinsic::eh_exception:
Anton Korobeynikov
committed
case Intrinsic::eh_selector_i32:
case Intrinsic::eh_selector_i64:
CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
break;
Anton Korobeynikov
committed
case Intrinsic::eh_typeid_for_i32:
case Intrinsic::eh_typeid_for_i64:
// Return something different to eh_selector.
CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1));
break;
case Intrinsic::var_annotation:
break; // Strip out annotate intrinsic
Chris Lattner
committed
static Constant *MemcpyFCache = 0;
Value *Size = CI->getOperand(3);
const Type *IntPtr = TD.getIntPtrType();
if (Size->getType()->getPrimitiveSizeInBits() <
IntPtr->getPrimitiveSizeInBits())
Size = new ZExtInst(Size, IntPtr, "", CI);
else if (Size->getType()->getPrimitiveSizeInBits() >
IntPtr->getPrimitiveSizeInBits())
Size = new TruncInst(Size, IntPtr, "", CI);
Value *Ops[3];
Ops[0] = CI->getOperand(1);
Ops[1] = CI->getOperand(2);
Ops[2] = Size;
ReplaceCallWith("memcpy", CI, Ops, Ops+3, CI->getOperand(1)->getType(),
MemcpyFCache);
break;
}
case Intrinsic::memmove_i64: {
Chris Lattner
committed
static Constant *MemmoveFCache = 0;
const Type *IntPtr = TD.getIntPtrType();
if (Size->getType()->getPrimitiveSizeInBits() <
IntPtr->getPrimitiveSizeInBits())
Size = new ZExtInst(Size, IntPtr, "", CI);
else if (Size->getType()->getPrimitiveSizeInBits() >
IntPtr->getPrimitiveSizeInBits())
Size = new TruncInst(Size, IntPtr, "", CI);
Value *Ops[3];
Ops[0] = CI->getOperand(1);
Ops[1] = CI->getOperand(2);
Ops[2] = Size;
ReplaceCallWith("memmove", CI, Ops, Ops+3, CI->getOperand(1)->getType(),
MemmoveFCache);
break;
case Intrinsic::memset_i64: {
Chris Lattner
committed
static Constant *MemsetFCache = 0;
const Type *IntPtr = TD.getIntPtrType();
if (Size->getType()->getPrimitiveSizeInBits() <
IntPtr->getPrimitiveSizeInBits())
Size = new ZExtInst(Size, IntPtr, "", CI);
else if (Size->getType()->getPrimitiveSizeInBits() >
IntPtr->getPrimitiveSizeInBits())
Size = new TruncInst(Size, IntPtr, "", CI);
Value *Ops[3];
Ops[0] = CI->getOperand(1);
// Extend the amount to i32.
Ops[1] = new ZExtInst(CI->getOperand(2), Type::Int32Ty, "", CI);
Ops[2] = Size;
ReplaceCallWith("memset", CI, Ops, Ops+3, CI->getOperand(1)->getType(),
MemsetFCache);
break;
}
case Intrinsic::sqrt: {
Chris Lattner
committed
static Constant *sqrtfFCache = 0;
static Constant *sqrtFCache = 0;
static Constant *sqrtLDCache = 0;
switch (CI->getOperand(1)->getType()->getTypeID()) {
default: assert(0 && "Invalid type in sqrt"); abort();
case Type::FloatTyID:
ReplaceCallWith("sqrtf", CI, CI->op_begin()+1, CI->op_end(),
Type::FloatTy, sqrtfFCache);
break;
case Type::DoubleTyID:
ReplaceCallWith("sqrt", CI, CI->op_begin()+1, CI->op_end(),
Chris Lattner
committed
Type::DoubleTy, sqrtFCache);
break;
case Type::X86_FP80TyID:
case Type::FP128TyID:
case Type::PPC_FP128TyID:
ReplaceCallWith("sqrtl", CI, CI->op_begin()+1, CI->op_end(),
CI->getOperand(1)->getType(), sqrtLDCache);
break;
}
case Intrinsic::flt_rounds:
// Lower to "round to the nearest"
if (CI->getType() != Type::VoidTy)
CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1));
break;
}
assert(CI->use_empty() &&
"Lowering should have eliminated any uses of the intrinsic call!");
CI->eraseFromParent();