46 #define DEBUG_TYPE "libcalls-shrinkwrap"
48 STATISTIC(NumWrappedOneCond,
"Number of One-Condition Wrappers Inserted");
49 STATISTIC(NumWrappedTwoCond,
"Number of Two-Condition Wrappers Inserted");
53 cl::desc(
"Perform shrink-wrap on lib calls with domain errors"));
56 cl::desc(
"Perform shrink-wrap on lib calls with range errors"));
59 cl::desc(
"Perform shrink-wrap on lib calls with pole errors"));
62 class LibCallsShrinkWrapLegacyPass :
public FunctionPass {
76 "Conditionally eliminate dead library calls",
false,
80 "Conditionally eliminate dead library
calls",
false, false)
89 for (
auto &CI : WorkList) {
90 DEBUG(
dbgs() <<
"CDCE calls: " << CI->getCalledFunction()->getName()
115 auto Cond2 = createCond(BBBuilder, Arg, Cmp2, Val2);
116 auto Cond1 = createCond(BBBuilder, Arg, Cmp, Val);
117 return BBBuilder.CreateOr(Cond1, Cond2);
133 return createCond(BBBuilder, Arg, Cmp, Val);
143 bool LibCallsShrinkWrap::performCallDomainErrorOnly(
CallInst *CI,
145 Value *Cond =
nullptr;
172 case LibFunc::acoshf:
173 case LibFunc::acoshl:
190 shrinkWrapCI(CI, Cond);
195 bool LibCallsShrinkWrap::performCallRangeErrorOnly(
CallInst *CI,
197 Value *Cond =
nullptr;
207 case LibFunc::exp10f:
208 case LibFunc::exp10l:
214 case LibFunc::sinhl: {
215 Cond = generateTwoRangeCond(CI, Func);
219 case LibFunc::expm1f:
220 case LibFunc::expm1l:
222 Cond = generateOneRangeCond(CI, Func);
228 shrinkWrapCI(CI, Cond);
233 bool LibCallsShrinkWrap::performCallErrors(
CallInst *CI,
235 Value *Cond =
nullptr;
241 case LibFunc::atanhf:
242 case LibFunc::atanhl:
256 case LibFunc::log10f:
257 case LibFunc::log10l:
274 case LibFunc::log1pf:
275 case LibFunc::log1pl:
287 case LibFunc::powl: {
291 Cond = generateCondForPow(CI, Func);
299 assert(Cond &&
"performCallErrors should not see an empty condition");
300 shrinkWrapCI(CI, Cond);
306 void LibCallsShrinkWrap::checkCandidate(
CallInst &CI) {
320 if (!TLI.getLibFunc(*Callee, Func) || !TLI.has(Func))
331 WorkList.push_back(&CI);
335 Value *LibCallsShrinkWrap::generateOneRangeCond(
CallInst *CI,
342 case LibFunc::expm1f:
345 case LibFunc::expm1l:
346 UpperBound = 11356.0f;
357 Value *LibCallsShrinkWrap::generateTwoRangeCond(
CallInst *CI,
359 float UpperBound, LowerBound;
363 LowerBound = -710.0f;
373 LowerBound = -11357.0f;
374 UpperBound = 11357.0f;
377 LowerBound = -745.0f;
381 LowerBound = -103.0f;
385 LowerBound = -11399.0f;
386 UpperBound = 11356.0f;
389 LowerBound = -323.0f;
392 case LibFunc::exp10f:
396 case LibFunc::exp10l:
397 LowerBound = -4950.0f;
398 UpperBound = 4932.0f;
401 LowerBound = -1074.0f;
402 UpperBound = 1023.0f;
405 LowerBound = -149.0f;
409 LowerBound = -16445.0f;
410 UpperBound = 11383.0f;
439 if (Func != LibFunc::pow) {
440 DEBUG(
dbgs() <<
"Not handled powf() and powl()\n");
449 if (
ConstantFP *CF = dyn_cast<ConstantFP>(Base)) {
450 double D = CF->getValueAPF().convertToDouble();
452 DEBUG(
dbgs() <<
"Not handled pow(): constant base out of range\n");
466 DEBUG(
dbgs() <<
"Not handled pow(): FP type base\n");
470 if (Opcode == Instruction::UIToFP || Opcode == Instruction::SIToFP) {
480 DEBUG(
dbgs() <<
"Not handled pow(): type too wide\n");
494 return BBBuilder.
CreateOr(Cond0, Cond);
496 DEBUG(
dbgs() <<
"Not handled pow(): base not from integer convert\n");
501 void LibCallsShrinkWrap::shrinkWrapCI(
CallInst *CI,
Value *Cond) {
502 assert(Cond !=
nullptr &&
"hrinkWrapCI is not expecting an empty call inst");
512 DEBUG(
dbgs() <<
"== Basic Block After ==");
518 bool LibCallsShrinkWrap::perform(
CallInst *CI) {
521 assert(Callee &&
"perform() should apply to a non-empty callee");
522 TLI.getLibFunc(*Callee, Func);
523 assert(Func &&
"perform() is not expecting an empty function");
531 return performCallErrors(CI, Func);
534 void LibCallsShrinkWrapLegacyPass::getAnalysisUsage(
AnalysisUsage &AU)
const {
542 LibCallsShrinkWrap CCDCE(TLI);
545 return CCDCE.isChanged();
548 bool LibCallsShrinkWrapLegacyPass::runOnFunction(
Function &
F) {
549 auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
558 return new LibCallsShrinkWrapLegacyPass();
564 bool Changed =
runImpl(F, TLI);
Legacy wrapper pass to provide the GlobalsAAResult object.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Base class for instruction visitors.
STATISTIC(NumFunctions,"Total number of functions")
This is the interface for a simple mod/ref and alias analysis over globals.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
This class represents a function call, abstracting a target machine's calling convention.
char & LibCallsShrinkWrapPassID
libcalls Conditionally eliminate dead library calls
0 1 0 0 True if ordered and less than
static cl::opt< bool > LibCallsShrinkWrapDoPoleError("libcalls-shrinkwrap-pole-error", cl::init(true), cl::Hidden, cl::desc("Perform shrink-wrap on lib calls with pole errors"))
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
bool isNoBuiltin() const
Return true if the call should not be treated as a call to a builtin.
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
static GCRegistry::Add< StatepointGC > D("statepoint-example","an example strategy for statepoint")
unsigned getNumArgOperands() const
Return the number of call arguments.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
0 1 0 1 True if ordered and less than or equal
void setName(const Twine &Name)
Change the name of the value.
void initializeLibCallsShrinkWrapLegacyPassPass(PassRegistry &)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
void visitCallInst(CallInst &CI)
Value * CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
INITIALIZE_PASS_BEGIN(LibCallsShrinkWrapLegacyPass,"libcalls-shrinkwrap","Conditionally eliminate dead library calls", false, false) INITIALIZE_PASS_END(LibCallsShrinkWrapLegacyPass
initializer< Ty > init(const Ty &Val)
Subclasses of this class are all able to terminate a basic block.
A set of analyses that are preserved following a run of a transformation pass.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs...ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
LibCallsShrinkWrap(const TargetLibraryInfo &TLI)
This is an important base class in LLVM.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
ConstantFP - Floating Point Values [float, double].
static bool runImpl(Function &F, const TargetLibraryInfo &TLI)
Represent the analysis usage information of a pass.
const InstListType & getInstList() const
Return the underlying instruction list container.
Analysis pass providing a never-invalidated alias analysis result.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
FunctionPass class - This class is used to implement most global optimizations.
Value * getOperand(unsigned i) const
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
LLVMContext & getContext() const
LLVMContext & getContext() const
All values hold a context through their type.
static cl::opt< bool > LibCallsShrinkWrapDoDomainError("libcalls-shrinkwrap-domain-error", cl::init(true), cl::Hidden, cl::desc("Perform shrink-wrap on lib calls with domain errors"))
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
0 0 1 0 True if ordered and greater than
Type * getType() const
All values are typed, get the type of this value.
Provides information about what library functions are available for the current target.
TerminatorInst * SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
Function * getCalledFunction() const
Return the function called, or null if this is an indirect function invocation.
static Constant * get(Type *Ty, double V)
This returns a ConstantFP, or a vector containing a splat of a ConstantFP, for the specified value in...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Value * getArgOperand(unsigned i) const
getArgOperand/setArgOperand - Return/set the i-th call argument.
FunctionPass * createLibCallsShrinkWrapPass()
BasicBlock * getSingleSuccessor()
Return the successor of this block if it has a single successor.
BasicBlock * getSinglePredecessor()
Return the predecessor of this block if it has a single predecessor block.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
iterator insert(iterator where, pointer New)
bool isX86_FP80Ty() const
Return true if this is x86 long double.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
libcalls Conditionally eliminate dead library false
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Analysis pass providing the TargetLibraryInfo.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
partially inline libcalls
unsigned getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
0 0 0 1 True if ordered and equal
LLVM Value Representation.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
A container for analyses that lazily runs them and caches their results.
iterator getFirstInsertionPt()
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
0 0 1 1 True if ordered and greater than or equal
static Constant * getFPExtend(Constant *C, Type *Ty, bool OnlyIfReduced=false)
const BasicBlock * getParent() const
static cl::opt< bool > LibCallsShrinkWrapDoRangeError("libcalls-shrinkwrap-range-error", cl::init(true), cl::Hidden, cl::desc("Perform shrink-wrap on lib calls with range errors"))