//===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===////// The LLVM Compiler Infrastructure//// This file was developed by the LLVM research group and 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"#include"llvm/Type.h"#include"llvm/CodeGen/IntrinsicLowering.h"#include"llvm/Support/Streams.h"#include"llvm/Target/TargetData.h"#include"llvm/ADT/SmallVector.h"#include"llvm/ADT/STLExtras.h"usingnamespacellvm;template<classArgIt>staticvoidEnsureFunctionExists(Module&M,constchar*Name,ArgItArgBegin,ArgItArgEnd,constType*RetTy){// Insert a correctly-typed definition now.std::vector<constType*>ParamTys;for(ArgItI=ArgBegin;I!=ArgEnd;++I)ParamTys.push_back(I->getType());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<classArgIt>staticCallInst*ReplaceCallWith(constchar*NewFn,CallInst*CI,ArgItArgBegin,ArgItArgEnd,constType*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();// Get or insert the definition now.std::vector<constType*>ParamTys;for(ArgItI=ArgBegin;I!=ArgEnd;++I)ParamTys.push_back((*I)->getType());FCache=M->getOrInsertFunction(NewFn,FunctionType::get(RetTy,ParamTys,false));}SmallVector<Value*,8>Args(ArgBegin,ArgEnd);CallInst*NewCI=newCallInst(FCache,Args.begin(),Args.end(),CI->getName(),CI);if(!CI->use_empty())CI->replaceAllUsesWith(NewCI);returnNewCI;}voidIntrinsicLowering::AddPrototypes(Module&M){for(Module::iteratorI=M.begin(),E=M.end();I!=E;++I)if(I->isDeclaration()&&!I->use_empty())switch(I->getIntrinsicID()){default:break;caseIntrinsic::setjmp:EnsureFunctionExists(M,"setjmp",I->arg_begin(),I->arg_end(),Type::Int32Ty);break;caseIntrinsic::longjmp:EnsureFunctionExists(M,"longjmp",I->arg_begin(),I->arg_end(),Type::VoidTy);break;caseIntrinsic::siglongjmp:EnsureFunctionExists(M,"abort",I->arg_end(),I->arg_end(),Type::VoidTy);break;caseIntrinsic::memcpy_i32:caseIntrinsic::memcpy_i64:M.getOrInsertFunction("memcpy",PointerType::getUnqual(Type::Int8Ty),PointerType::getUnqual(Type::Int8Ty),PointerType::getUnqual(Type::Int8Ty),TD.getIntPtrType(),(Type*)0);break;caseIntrinsic::memmove_i32:caseIntrinsic::memmove_i64:M.getOrInsertFunction("memmove",PointerType::getUnqual(Type::Int8Ty),PointerType::getUnqual(Type::Int8Ty),PointerType::getUnqual(Type::Int8Ty),TD.getIntPtrType(),(Type*)0);break;caseIntrinsic::memset_i32:caseIntrinsic::memset_i64:M.getOrInsertFunction("memset",PointerType::getUnqual(Type::Int8Ty),PointerType::getUnqual(Type::Int8Ty),Type::Int32Ty,TD.getIntPtrType(),(Type*)0);break;caseIntrinsic::sqrt:switch((int)I->arg_begin()->getType()->getTypeID()){caseType::FloatTyID:EnsureFunctionExists(M,"sqrtf",I->arg_begin(),I->arg_end(),Type::FloatTy);caseType::DoubleTyID:EnsureFunctionExists(M,"sqrt",I->arg_begin(),I->arg_end(),Type::DoubleTy);caseType::X86_FP80TyID:caseType::FP128TyID:caseType::PPC_FP128TyID:EnsureFunctionExists(M,"sqrtl",I->arg_begin(),I->arg_end(),I->arg_begin()->getType());}break;caseIntrinsic::sin:switch((int)I->arg_begin()->getType()->getTypeID()){caseType::FloatTyID:EnsureFunctionExists(M,"sinf",I->arg_begin(),I->arg_end(),Type::FloatTy);caseType::DoubleTyID:EnsureFunctionExists(M,"sin",I->arg_begin(),I->arg_end(),Type::DoubleTy);caseType::X86_FP80TyID:caseType::FP128TyID:caseType::PPC_FP128TyID:EnsureFunctionExists(M,"sinl",I->arg_begin(),I->arg_end(),I->arg_begin()->getType());}break;caseIntrinsic::cos:switch((int)I->arg_begin()->getType()->getTypeID()){caseType::FloatTyID:EnsureFunctionExists(M,"cosf",I->arg_begin(),I->arg_end(),Type::FloatTy);caseType::DoubleTyID:EnsureFunctionExists(M,"cos",I->arg_begin(),I->arg_end(),Type::DoubleTy);caseType::X86_FP80TyID:caseType::FP128TyID:caseType::PPC_FP128TyID:EnsureFunctionExists(M,"cosl",I->arg_begin(),I->arg_end(),I->arg_begin()->getType());}break;caseIntrinsic::pow:switch((int)I->arg_begin()->getType()->getTypeID()){caseType::FloatTyID:EnsureFunctionExists(M,"powf",I->arg_begin(),I->arg_end(),Type::FloatTy);caseType::DoubleTyID:EnsureFunctionExists(M,"pow",I->arg_begin(),I->arg_end(),Type::DoubleTy);caseType::X86_FP80TyID:caseType::FP128TyID:caseType::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.staticValue*LowerBSWAP(Value*V,Instruction*IP){assert(V->getType()->isInteger()&&"Can't bswap a non-integer type!");unsignedBitSize=V->getType()->getPrimitiveSizeInBits();switch(BitSize){default:assert(0&&"Unhandled type size of value to byteswap!");case16:{Value*Tmp1=BinaryOperator::createShl(V,ConstantInt::get(V->getType(),8),"bswap.2",IP);Value*Tmp2=BinaryOperator::createLShr(V,ConstantInt::get(V->getType(),8),"bswap.1",IP);V=BinaryOperator::createOr(Tmp1,Tmp2,"bswap.i16",IP);break;}case32:{Value*Tmp4=BinaryOperator::createShl(V,ConstantInt::get(V->getType(),24),"bswap.4",IP);Value*Tmp3=BinaryOperator::createShl(V,ConstantInt::get(V->getType(),8),"bswap.3",IP);Value*Tmp2=BinaryOperator::createLShr(V,ConstantInt::get(V->getType(),8),"bswap.2",IP);Value*Tmp1=BinaryOperator::createLShr(V,ConstantInt::get(V->getType(),24),"bswap.1",IP);Tmp3=BinaryOperator::createAnd(Tmp3,ConstantInt::get(Type::Int32Ty,0xFF0000),"bswap.and3",IP);Tmp2=BinaryOperator::createAnd(Tmp2,ConstantInt::get(Type::Int32Ty,0xFF00),"bswap.and2",IP);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;}case64:{Value*Tmp8=BinaryOperator::createShl(V,ConstantInt::get(V->getType(),56),"bswap.8",IP);Value*Tmp7=BinaryOperator::createShl(V,ConstantInt::get(V->getType(),40),"bswap.7",IP);Value*Tmp6=BinaryOperator::createShl(V,ConstantInt::get(V->getType(),24),"bswap.6",IP);Value*Tmp5=BinaryOperator::createShl(V,ConstantInt::get(V->getType(),8),"bswap.5",IP);Value*Tmp4=BinaryOperator::createLShr(V,ConstantInt::get(V->getType(),8),"bswap.4",IP);Value*Tmp3=BinaryOperator::createLShr(V,ConstantInt::get(V->getType(),24),"bswap.3",IP);Value*Tmp2=BinaryOperator::createLShr(V,ConstantInt::get(V->getType(),40),"bswap.2",IP);Value*Tmp1=BinaryOperator::createLShr(V,ConstantInt::get(V->getType(),56),"bswap.1",IP);Tmp7=BinaryOperator::createAnd(Tmp7,ConstantInt::get(Type::Int64Ty,0xFF000000000000ULL),"bswap.and7",IP);Tmp6=BinaryOperator::createAnd(Tmp6,ConstantInt::get(Type::Int64Ty,0xFF0000000000ULL),"bswap.and6",IP);Tmp5=BinaryOperator::createAnd(Tmp5,ConstantInt::get(Type::Int64Ty,0xFF00000000ULL),"bswap.and5",IP);Tmp4=BinaryOperator::createAnd(Tmp4,ConstantInt::get(Type::Int64Ty,0xFF000000ULL),"bswap.and4",IP);Tmp3=BinaryOperator::createAnd(Tmp3,ConstantInt::get(Type::Int64Ty,0xFF0000ULL),"bswap.and3",IP);Tmp2=BinaryOperator::createAnd(Tmp2,ConstantInt::get(Type::Int64Ty,0xFF00ULL),"bswap.and2",IP);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;}}returnV;}/// LowerCTPOP - Emit the code to lower ctpop of V before the specified/// instruction IP.staticValue*LowerCTPOP(Value*V,Instruction*IP){assert(V->getType()->isInteger()&&"Can't ctpop a non-integer type!");staticconstuint64_tMaskValues[6]={0x5555555555555555ULL,0x3333333333333333ULL,0x0F0F0F0F0F0F0F0FULL,0x00FF00FF00FF00FFULL,0x0000FFFF0000FFFFULL,0x00000000FFFFFFFFULL};unsignedBitSize=V->getType()->getPrimitiveSizeInBits();unsignedWordSize=(BitSize+63)/64;Value*Count=ConstantInt::get(V->getType(),0);for(unsignedn=0;n<WordSize;++n){Value*PartValue=V;for(unsignedi=1,ct=0;i<(BitSize>64?64:BitSize);i<<=1,++ct){Value*MaskCst=ConstantInt::get(V->getType(),MaskValues[ct]);Value*LHS=BinaryOperator::createAnd(PartValue,MaskCst,"cppop.and1",IP);Value*VShift=BinaryOperator::createLShr(PartValue,ConstantInt::get(V->getType(),i),"ctpop.sh",IP);Value*RHS=BinaryOperator::createAnd(VShift,MaskCst,"cppop.and2",IP);PartValue=BinaryOperator::createAdd(LHS,RHS,"ctpop.step",IP);}Count=BinaryOperator::createAdd(PartValue,Count,"ctpop.part",IP);if(BitSize>64){V=BinaryOperator::createLShr(V,ConstantInt::get(V->getType(),64),"ctpop.part.sh",IP);BitSize-=64;}}returnCount;}/// LowerCTLZ - Emit the code to lower ctlz of V before the specified/// instruction IP.staticValue*LowerCTLZ(Value*V,Instruction*IP){unsignedBitSize=V->getType()->getPrimitiveSizeInBits();for(unsignedi=1;i<BitSize;i<<=1){Value*ShVal=ConstantInt::get(V->getType(),i);ShVal=BinaryOperator::createLShr(V,ShVal,"ctlz.sh",IP);V=BinaryOperator::createOr(V,ShVal,"ctlz.step",IP);}V=BinaryOperator::createNot(V,"",IP);returnLowerCTPOP(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.staticInstruction*LowerPartSelect(CallInst*CI){// Make sure we're dealing with a part select intrinsic hereFunction*F=CI->getCalledFunction();constFunctionType*FT=F->getFunctionType();if(!F->isDeclaration()||!FT->getReturnType()->isInteger()||FT->getNumParams()!=3||!FT->getParamType(0)->isInteger()||!FT->getParamType(1)->isInteger()||!FT->getParamType(2)->isInteger())returnCI;// Get the intrinsic implementation function by converting all the . to _// in the intrinsic's function name and then reconstructing the function// declaration.std::stringName(F->getName());for(unsignedi=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 nowif(F->isDeclaration()){// Get the arguments to the functionFunction::arg_iteratorargs=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=newBasicBlock("entry",F);BasicBlock*RevSize=newBasicBlock("revsize",CurBB->getParent());BasicBlock*FwdSize=newBasicBlock("fwdsize",CurBB->getParent());BasicBlock*Compute=newBasicBlock("compute",CurBB->getParent());BasicBlock*Reverse=newBasicBlock("reverse",CurBB->getParent());BasicBlock*RsltBlk=newBasicBlock("result",CurBB->getParent());// Cast Hi and Lo to the size of Val so the widths are all the sameif(Hi->getType()!=Val->getType())Hi=CastInst::createIntegerCast(Hi,Val->getType(),false,"tmp",CurBB);if(Lo->getType()!=Val->getType())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=newICmpInst(ICmpInst::ICMP_ULT,Hi,Lo,"less",CurBB);newBranchInst(RevSize,FwdSize,Cmp,CurBB);// First, copmute the number of bits in the forward case.Instruction*FBitSize=BinaryOperator::createSub(Hi,Lo,"fbits",FwdSize);newBranchInst(Compute,FwdSize);// Second, compute the number of bits in the reverse case.Instruction*RBitSize=BinaryOperator::createSub(Lo,Hi,"rbits",RevSize);newBranchInst(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 subtractionsPHINode*BitSize=newPHINode(Val->getType(),"bits",Compute);BitSize->reserveOperandSpace(2);BitSize->addIncoming(FBitSize,FwdSize);BitSize->addIncoming(RBitSize,RevSize);// Get the ShiftAmount as the smaller of Hi/LoPHINode*ShiftAmt=newPHINode(Val->getType(),"shiftamt",Compute);ShiftAmt->reserveOperandSpace(2);ShiftAmt->addIncoming(Lo,FwdSize);ShiftAmt->addIncoming(Hi,RevSize);// Increment the bit sizeInstruction*BitSizePlusOne=BinaryOperator::createAdd(BitSize,One,"bits",Compute);// Create a Mask to zero out the high order bits.Instruction*Mask=BinaryOperator::createShl(AllOnes,BitSizePlusOne,"mask",Compute);Mask=BinaryOperator::createNot(Mask,"mask",Compute);// Shift the bits down and apply the maskInstruction*FRes=BinaryOperator::createLShr(Val,ShiftAmt,"fres",Compute);FRes=BinaryOperator::createAnd(FRes,Mask,"fres",Compute);newBranchInst(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 countersPHINode*Count=newPHINode(Val->getType(),"count",Reverse);Count->reserveOperandSpace(2);Count->addIncoming(BitSizePlusOne,Compute);// Next, get the value that we are shifting.PHINode*BitsToShift=newPHINode(Val->getType(),"val",Reverse);BitsToShift->reserveOperandSpace(2);BitsToShift->addIncoming(FRes,Compute);// Finally, get the result of the last computationPHINode*RRes=newPHINode(Val->getType(),"rres",Reverse);RRes->reserveOperandSpace(2);RRes->addIncoming(Zero,Compute);// Decrement the counterInstruction*Decr=BinaryOperator::createSub(Count,One,"decr",Reverse);Count->addIncoming(Decr,Reverse);// Compute the Bit that we want to moveInstruction*Bit=BinaryOperator::createAnd(BitsToShift,One,"bit",Reverse);// Compute the new value for next iteration.Instruction*NewVal=BinaryOperator::createLShr(BitsToShift,One,"rshift",Reverse);BitsToShift->addIncoming(NewVal,Reverse);// Shift the bit into the low bits of the result.Instruction*NewRes=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=newICmpInst(ICmpInst::ICMP_EQ,Decr,Zero,"cond",Reverse);newBranchInst(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=newPHINode(Val->getType(),"part_select",CurBB);BitSelect->reserveOperandSpace(2);BitSelect->addIncoming(FRes,Compute);BitSelect->addIncoming(NewRes,Reverse);newReturnInst(BitSelect,CurBB);}// Return a call to the implementation functionValue*Args[]={CI->getOperand(1),CI->getOperand(2),CI->getOperand(3)};returnnewCallInst(F,Args,array_endof(Args),CI->getName(),CI);}/// 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.staticInstruction*LowerPartSet(CallInst*CI){// Make sure we're dealing with a part select intrinsic hereFunction*F=CI->getCalledFunction();constFunctionType*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())returnCI;// Get the intrinsic implementation function by converting all the . to _// in the intrinsic's function name and then reconstructing the function// declaration.std::stringName(F->getName());for(unsignedi=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 nowif(F->isDeclaration()){// Get the arguments for the function.Function::arg_iteratorargs=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 needconstIntegerType*ValTy=cast<IntegerType>(Val->getType());constIntegerType*RepTy=cast<IntegerType>(Rep->getType());uint32_tValBits=ValTy->getBitWidth();uint32_tRepBits=RepTy->getBitWidth();// Constant DefinitionsConstantInt*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=newBasicBlock("entry",F,0);BasicBlock*large=newBasicBlock("large",F,0);BasicBlock*small=newBasicBlock("small",F,0);BasicBlock*reverse=newBasicBlock("reverse",F,0);BasicBlock*result=newBasicBlock("result",F,0);// BASIC BLOCK: entry// First, get the number of bits that we're placing as an i32ICmpInst*is_forward=newICmpInst(ICmpInst::ICMP_ULT,Lo,Hi,"",entry);SelectInst*Hi_pn=newSelectInst(is_forward,Hi,Lo,"",entry);SelectInst*Lo_pn=newSelectInst(is_forward,Lo,Hi,"",entry);BinaryOperator*NumBits=BinaryOperator::createSub(Hi_pn,Lo_pn,"",entry);NumBits=BinaryOperator::createAdd(NumBits,One,"",entry);// Now, convert Lo and Hi to ValTy bit widthif(ValBits>32){Lo=newZExtInst(Lo_pn,ValTy,"",entry);}elseif(ValBits<32){Lo=newTruncInst(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=newICmpInst(ICmpInst::ICMP_ULT,NumBits,RepBitWidth,"",entry);newBranchInst(large,small,is_large,entry);// BASIC BLOCK: largeInstruction*MaskBits=BinaryOperator::createSub(RepBitWidth,NumBits,"",large);MaskBits=CastInst::createIntegerCast(MaskBits,RepMask->getType(),false,"",large);BinaryOperator*Mask1=BinaryOperator::createLShr(RepMask,MaskBits,"",large);BinaryOperator*Rep2=BinaryOperator::createAnd(Mask1,Rep,"",large);newBranchInst(small,large);// BASIC BLOCK: smallPHINode*Rep3=newPHINode(RepTy,"",small);Rep3->reserveOperandSpace(2);Rep3->addIncoming(Rep2,large);Rep3->addIncoming(Rep,entry);Value*Rep4=Rep3;if(ValBits>RepBits)Rep4=newZExtInst(Rep3,ValTy,"",small);elseif(ValBits<RepBits)Rep4=newTruncInst(Rep3,ValTy,"",small);newBranchInst(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=newPHINode(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=newPHINode(Val->getType(),"val",reverse);BitsToShift->reserveOperandSpace(2);BitsToShift->addIncoming(Rep4,small);// Get the result of the last computation or zero on first iterationPHINode*RRes=newPHINode(Val->getType(),"rres",reverse);RRes->reserveOperandSpace(2);RRes->addIncoming(ValZero,small);// Decrement the loop counter by oneInstruction*Decr=BinaryOperator::createSub(Count,One,"",reverse);Count->addIncoming(Decr,reverse);// Get the bit that we want to move into the resultValue*Bit=BinaryOperator::createAnd(BitsToShift,ValOne,"",reverse);// Compute the new value of the bits to shift for the next iteration.Value*NewVal=BinaryOperator::createLShr(BitsToShift,ValOne,"",reverse);BitsToShift->addIncoming(NewVal,reverse);// Shift the bit we extracted into the low bit of the result.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=newICmpInst(ICmpInst::ICMP_EQ,Decr,Zero,"",reverse);newBranchInst(result,reverse,Cond,reverse);// BASIC BLOCK: resultPHINode*Rplcmnt=newPHINode(Val->getType(),"",result);Rplcmnt->reserveOperandSpace(2);Rplcmnt->addIncoming(NewRes,reverse);Rplcmnt->addIncoming(Rep4,small);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);newReturnInst(Rslt,result);}// Return a call to the implementation functionValue*Args[]={CI->getOperand(1),CI->getOperand(2),CI->getOperand(3),CI->getOperand(4)};returnnewCallInst(F,Args,array_endof(Args),CI->getName(),CI);}voidIntrinsicLowering::LowerIntrinsicCall(CallInst*CI){Function*Callee=CI->getCalledFunction();assert(Callee&&"Cannot lower an indirect call!");switch(Callee->getIntrinsicID()){caseIntrinsic::not_intrinsic:cerr<<"Cannot lower a call to a non-intrinsic function '"<<Callee->getName()<<"'!\n";abort();default: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.caseIntrinsic::setjmp:{staticConstant*SetjmpFCache=0;Value*V=ReplaceCallWith("setjmp",CI,CI->op_begin()+1,CI->op_end(),Type::Int32Ty,SetjmpFCache);if(CI->getType()!=Type::VoidTy)CI->replaceAllUsesWith(V);break;}caseIntrinsic::sigsetjmp:if(CI->getType()!=Type::VoidTy)CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));break;caseIntrinsic::longjmp:{staticConstant*LongjmpFCache=0;ReplaceCallWith("longjmp",CI,CI->op_begin()+1,CI->op_end(),Type::VoidTy,LongjmpFCache);break;}caseIntrinsic::siglongjmp:{// Insert the call to abortstaticConstant*AbortFCache=0;ReplaceCallWith("abort",CI,CI->op_end(),CI->op_end(),Type::VoidTy,AbortFCache);break;}caseIntrinsic::ctpop:CI->replaceAllUsesWith(LowerCTPOP(CI->getOperand(1),CI));break;caseIntrinsic::bswap:CI->replaceAllUsesWith(LowerBSWAP(CI->getOperand(1),CI));break;caseIntrinsic::ctlz:CI->replaceAllUsesWith(LowerCTLZ(CI->getOperand(1),CI));break;caseIntrinsic::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;}caseIntrinsic::part_select:CI->replaceAllUsesWith(LowerPartSelect(CI));break;caseIntrinsic::part_set:CI->replaceAllUsesWith(LowerPartSet(CI));break;caseIntrinsic::stacksave:caseIntrinsic::stackrestore:{staticboolWarned=false;if(!Warned)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;}caseIntrinsic::returnaddress:caseIntrinsic::frameaddress: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;caseIntrinsic::prefetch:break;// Simply strip out prefetches on unsupported architecturescaseIntrinsic::pcmarker:break;// Simply strip out pcmarker on unsupported architecturescaseIntrinsic::readcyclecounter:{cerr<<"WARNING: this target does not support the llvm.readcyclecoun"<<"ter intrinsic. It is being lowered to a constant 0\n";CI->replaceAllUsesWith(ConstantInt::get(Type::Int64Ty,0));break;}caseIntrinsic::dbg_stoppoint:caseIntrinsic::dbg_region_start:caseIntrinsic::dbg_region_end:caseIntrinsic::dbg_func_start:caseIntrinsic::dbg_declare:break;// Simply strip out debugging intrinsicscaseIntrinsic::eh_exception:caseIntrinsic::eh_selector_i32:caseIntrinsic::eh_selector_i64:CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));break;caseIntrinsic::eh_typeid_for_i32:caseIntrinsic::eh_typeid_for_i64:// Return something different to eh_selector.CI->replaceAllUsesWith(ConstantInt::get(CI->getType(),1));break;caseIntrinsic::var_annotation:break;// Strip out annotate intrinsiccaseIntrinsic::memcpy_i32:caseIntrinsic::memcpy_i64:{staticConstant*MemcpyFCache=0;Value*Size=CI->getOperand(3);constType*IntPtr=TD.getIntPtrType();if(Size->getType()->getPrimitiveSizeInBits()<IntPtr->getPrimitiveSizeInBits())Size=newZExtInst(Size,IntPtr,"",CI);elseif(Size->getType()->getPrimitiveSizeInBits()>IntPtr->getPrimitiveSizeInBits())Size=newTruncInst(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;}caseIntrinsic::memmove_i32:caseIntrinsic::memmove_i64:{staticConstant*MemmoveFCache=0;Value*Size=CI->getOperand(3);constType*IntPtr=TD.getIntPtrType();if(Size->getType()->getPrimitiveSizeInBits()<IntPtr->getPrimitiveSizeInBits())Size=newZExtInst(Size,IntPtr,"",CI);elseif(Size->getType()->getPrimitiveSizeInBits()>IntPtr->getPrimitiveSizeInBits())Size=newTruncInst(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;}caseIntrinsic::memset_i32:caseIntrinsic::memset_i64:{staticConstant*MemsetFCache=0;Value*Size=CI->getOperand(3);constType*IntPtr=TD.getIntPtrType();if(Size->getType()->getPrimitiveSizeInBits()<IntPtr->getPrimitiveSizeInBits())Size=newZExtInst(Size,IntPtr,"",CI);elseif(Size->getType()->getPrimitiveSizeInBits()>IntPtr->getPrimitiveSizeInBits())Size=newTruncInst(Size,IntPtr,"",CI);Value*Ops[3];Ops[0]=CI->getOperand(1);// Extend the amount to i32.Ops[1]=newZExtInst(CI->getOperand(2),Type::Int32Ty,"",CI);Ops[2]=Size;ReplaceCallWith("memset",CI,Ops,Ops+3,CI->getOperand(1)->getType(),MemsetFCache);break;}caseIntrinsic::sqrt:{staticConstant*sqrtfFCache=0;staticConstant*sqrtFCache=0;staticConstant*sqrtLDCache=0;switch(CI->getOperand(1)->getType()->getTypeID()){default:assert(0&&"Invalid type in sqrt");abort();caseType::FloatTyID:ReplaceCallWith("sqrtf",CI,CI->op_begin()+1,CI->op_end(),Type::FloatTy,sqrtfFCache);break;caseType::DoubleTyID:ReplaceCallWith("sqrt",CI,CI->op_begin()+1,CI->op_end(),Type::DoubleTy,sqrtFCache);break;caseType::X86_FP80TyID:caseType::FP128TyID:caseType::PPC_FP128TyID:ReplaceCallWith("sqrtl",CI,CI->op_begin()+1,CI->op_end(),CI->getOperand(1)->getType(),sqrtLDCache);break;}break;}caseIntrinsic::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();}