51 #define DEBUG_TYPE "consthoist"
53 STATISTIC(NumConstantsHoisted,
"Number of constants hoisted");
54 STATISTIC(NumConstantsRebased,
"Number of constants rebased");
65 bool runOnFunction(
Function &Fn)
override;
67 StringRef getPassName()
const override {
return "Constant Hoisting"; }
84 "Constant Hoisting",
false,
false)
91 return new ConstantHoistingLegacyPass();
95 bool ConstantHoistingLegacyPass::runOnFunction(
Function &Fn) {
99 DEBUG(
dbgs() <<
"********** Begin Constant Hoisting **********\n");
102 bool MadeChange = Impl.runImpl(
103 Fn, getAnalysis<TargetTransformInfoWrapperPass>().getTTI(Fn),
104 getAnalysis<DominatorTreeWrapperPass>().getDomTree(), Fn.
getEntryBlock());
107 DEBUG(
dbgs() <<
"********** Function after Constant Hoisting: "
111 DEBUG(
dbgs() <<
"********** End Constant Hoisting **********\n");
119 unsigned Idx)
const {
124 if (
auto CastInst = dyn_cast<Instruction>(Opnd))
130 if (!isa<PHINode>(Inst) && !Inst->
isEHPad())
135 assert(Entry != Inst->
getParent() &&
"PHI or landing pad in entry block!");
136 if (Idx != ~0U && isa<PHINode>(Inst))
137 return cast<PHINode>(Inst)->getIncomingBlock(Idx)->getTerminator();
144 Instruction *ConstantHoistingPass::findConstantInsertionPoint(
150 for (
auto const &U : RCI.Uses)
151 BBs.
insert(findMatInsertPt(U.Inst, U.OpndIdx)->getParent());
153 if (BBs.count(Entry))
154 return &Entry->front();
156 while (BBs.size() >= 2) {
159 BB2 = *std::next(BBs.begin());
160 BB = DT->findNearestCommonDominator(BB1, BB2);
162 return &Entry->
front();
167 assert((BBs.size() == 1) &&
"Expected only one element.");
169 return findMatInsertPt(&FirstInst);
179 void ConstantHoistingPass::collectConstantCandidates(
180 ConstCandMapType &ConstCandMap,
Instruction *Inst,
unsigned Idx,
185 if (
auto IntrInst = dyn_cast<IntrinsicInst>(Inst))
186 Cost = TTI->getIntImmCost(IntrInst->getIntrinsicID(), Idx,
194 ConstCandMapType::iterator Itr;
196 std::tie(Itr, Inserted) = ConstCandMap.insert(std::make_pair(ConstInt, 0));
199 Itr->second = ConstCandVec.size() - 1;
201 ConstCandVec[Itr->second].addUser(Inst, Idx, Cost);
203 dbgs() << "Collect constant " << *ConstInt << " from " << *Inst
204 << " with cost " << Cost << '\n';
206 dbgs() << "Collect constant " << *ConstInt << " indirectly from "
207 << *Inst << " via " << *Inst->getOperand(Idx) << " with cost "
216 ConstCandMapType &ConstCandMap,
Instruction *Inst) {
222 if (
auto Call = dyn_cast<CallInst>(Inst))
223 if (isa<InlineAsm>(
Call->getCalledValue()))
228 if (isa<SwitchInst>(Inst))
235 if (AI && AI->isStaticAlloca())
239 for (
unsigned Idx = 0,
E = Inst->getNumOperands(); Idx !=
E; ++Idx) {
240 Value *Opnd = Inst->getOperand(Idx);
243 if (
auto ConstInt = dyn_cast<ConstantInt>(Opnd)) {
244 collectConstantCandidates(ConstCandMap, Inst, Idx, ConstInt);
249 if (
auto CastInst = dyn_cast<Instruction>(Opnd)) {
258 collectConstantCandidates(ConstCandMap, Inst, Idx, ConstInt);
264 if (
auto ConstExpr = dyn_cast<ConstantExpr>(Opnd)) {
266 if (!ConstExpr->isCast())
269 if (
auto ConstInt = dyn_cast<ConstantInt>(ConstExpr->getOperand(0))) {
272 collectConstantCandidates(ConstCandMap, Inst, Idx, ConstInt);
281 void ConstantHoistingPass::collectConstantCandidates(
Function &Fn) {
282 ConstCandMapType ConstCandMap;
285 collectConstantCandidates(ConstCandMap, &Inst);
300 if (LimVal1 == ~0ULL || LimVal2 == ~0ULL)
303 uint64_t Diff = LimVal1 - LimVal2;
304 return APInt(BW, Diff,
true);
331 ConstantHoistingPass::maximizeConstantsInRange(ConstCandVecType::iterator S,
332 ConstCandVecType::iterator
E,
333 ConstCandVecType::iterator &MaxCostItr) {
334 unsigned NumUses = 0;
336 if(!Entry->getParent()->optForSize() || std::distance(S,E) > 100) {
337 for (
auto ConstCand = S; ConstCand !=
E; ++ConstCand) {
338 NumUses += ConstCand->Uses.size();
339 if (ConstCand->CumulativeCost > MaxCostItr->CumulativeCost)
340 MaxCostItr = ConstCand;
345 DEBUG(
dbgs() <<
"== Maximize constants in range ==\n");
347 for (
auto ConstCand = S; ConstCand !=
E; ++ConstCand) {
348 auto Value = ConstCand->ConstInt->getValue();
349 Type *Ty = ConstCand->ConstInt->getType();
351 NumUses += ConstCand->Uses.size();
352 DEBUG(
dbgs() <<
"= Constant: " << ConstCand->ConstInt->getValue() <<
"\n");
354 for (
auto User : ConstCand->Uses) {
355 unsigned Opcode =
User.Inst->getOpcode();
356 unsigned OpndIdx =
User.OpndIdx;
357 Cost += TTI->getIntImmCost(Opcode, OpndIdx,
Value, Ty);
358 DEBUG(
dbgs() <<
"Cost: " << Cost <<
"\n");
360 for (
auto C2 = S; C2 !=
E; ++C2) {
362 C2->ConstInt->getValue(),
363 ConstCand->ConstInt->getValue());
366 TTI->getIntImmCodeSizeCost(Opcode, OpndIdx, Diff.
getValue(), Ty);
369 <<
"has penalty: " << ImmCosts <<
"\n"
370 <<
"Adjusted cost: " << Cost <<
"\n");
374 DEBUG(
dbgs() <<
"Cumulative cost: " << Cost <<
"\n");
375 if (Cost > MaxCost) {
377 MaxCostItr = ConstCand;
378 DEBUG(
dbgs() <<
"New candidate: " << MaxCostItr->ConstInt->getValue()
387 void ConstantHoistingPass::findAndMakeBaseConstant(
388 ConstCandVecType::iterator S, ConstCandVecType::iterator E) {
390 unsigned NumUses = maximizeConstantsInRange(S, E, MaxCostItr);
401 for (
auto ConstCand = S; ConstCand !=
E; ++ConstCand) {
402 APInt Diff = ConstCand->ConstInt->getValue() -
408 ConstantVec.push_back(std::move(ConstInfo));
413 void ConstantHoistingPass::findBaseConstants() {
415 std::sort(ConstCandVec.begin(), ConstCandVec.end(),
419 RHS.ConstInt->getType()->getBitWidth();
425 auto MinValItr = ConstCandVec.begin();
426 for (
auto CC = std::next(ConstCandVec.begin()), E = ConstCandVec.end();
428 if (MinValItr->ConstInt->getType() == CC->ConstInt->getType()) {
430 APInt Diff = CC->ConstInt->getValue() - MinValItr->ConstInt->getValue();
437 findAndMakeBaseConstant(MinValItr, CC);
442 findAndMakeBaseConstant(MinValItr, ConstCandVec.end());
452 if (
auto PHI = dyn_cast<PHINode>(Inst)) {
459 BasicBlock *IncomingBB = PHI->getIncomingBlock(Idx);
460 for (
unsigned i = 0;
i < Idx; ++
i) {
461 if (PHI->getIncomingBlock(
i) == IncomingBB) {
462 Value *IncomingVal = PHI->getIncomingValue(
i);
475 void ConstantHoistingPass::emitBaseConstants(
Instruction *Base,
483 "const_mat", InsertionPt);
486 <<
" + " << *Offset <<
") in BB "
493 if (isa<ConstantInt>(Opnd)) {
502 if (
auto CastInst = dyn_cast<Instruction>(Opnd)) {
507 if (!ClonedCastInst) {
510 ClonedCastInst->insertAfter(
CastInst);
514 <<
"To : " << *ClonedCastInst <<
'\n');
524 if (
auto ConstExpr = dyn_cast<ConstantExpr>(Opnd)) {
525 Instruction *ConstExprInst = ConstExpr->getAsInstruction();
533 DEBUG(
dbgs() <<
"Create instruction: " << *ConstExprInst <<
'\n'
534 <<
"From : " << *ConstExpr <<
'\n');
548 bool ConstantHoistingPass::emitBaseConstants() {
549 bool MadeChange =
false;
550 for (
auto const &ConstInfo : ConstantVec) {
558 NumConstantsHoisted++;
562 NumConstantsRebased++;
563 for (
auto const &U : RCI.Uses)
564 emitBaseConstants(Base, RCI.Offset, U);
570 "All uses should be instructions.");
574 NumConstantsRebased--;
582 void ConstantHoistingPass::deleteDeadCastInst()
const {
583 for (
auto const &
I : ClonedCastMap)
584 if (
I.first->use_empty())
585 I.first->eraseFromParent();
593 this->Entry = &Entry;
595 collectConstantCandidates(Fn);
598 if (ConstCandVec.empty())
606 if (ConstantVec.empty())
611 bool MadeChange = emitBaseConstants();
614 deleteDeadCastInst();
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void push_back(const T &Elt)
IntegerType * getType() const
getType - Specialize the getType() method to always return an IntegerType, which reduces the amount o...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A base constant and all its rebased constants.
STATISTIC(NumFunctions,"Total number of functions")
void initializeConstantHoistingLegacyPassPass(PassRegistry &)
virtual void releaseMemory()
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
Keeps track of a constant candidate and its uses.
Analysis pass providing the TargetTransformInfo.
static bool updateOperand(Instruction *Inst, unsigned Idx, Instruction *Mat)
Updates the operand at Idx in instruction Inst with the result of instruction Mat.
uint64_t getLimitedValue(uint64_t Limit=~0ULL) const
If this value is smaller than the specified limit, return it, otherwise return the limit value...
const Instruction & front() const
Analysis pass which computes a DominatorTree.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
This represents a constant that has been rebased with respect to a base constant. ...
StringRef getName() const
Return a constant reference to the value's name.
iterator begin()
Instruction iterator methods.
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
This is the base class for all instructions that perform data casts.
const APInt & getValue() const
Return the constant as an APInt value reference.
bool runImpl(Function &F, TargetTransformInfo &TTI, DominatorTree &DT, BasicBlock &Entry)
Optimize expensive integer constants in the given function.
Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following: ...
LLVM_NODISCARD bool empty() const
const T & getValue() const LLVM_LVALUE_FUNCTION
This class represents a no-op cast from one type to another.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
bool ult(const APInt &RHS) const
Unsigned less than comparison.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
ConstantInt * BaseConstant
A set of analyses that are preserved following a run of a transformation pass.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs...ExtraArgs)
Get the result of an analysis pass for a given IR unit.
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction...
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important base class in LLVM.
int64_t getSExtValue() const
Get sign extended value.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
Represent the analysis usage information of a pass.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
unsigned getBitWidth() const
Return the number of bits in the APInt.
FunctionPass class - This class is used to implement most global optimizations.
Value * getOperand(unsigned i) const
Class to represent integer types.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
static llvm::Optional< APInt > calculateOffsetDiff(APInt V1, APInt V2)
Keeps track of the user of a constant and the operand index where the constant is used...
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
This is the shared class of boolean and integer constants.
Instruction * user_back()
Specialize the methods defined in Value, as we know that an instruction can only be used by other ins...
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
const BasicBlock & getEntryBlock() const
void setOperand(unsigned i, Value *Val)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Class for arbitrary precision integers.
static BinaryOperator * Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name=Twine(), Instruction *InsertBefore=nullptr)
Construct a binary instruction, given the opcode and the two operands.
INITIALIZE_PASS_BEGIN(ConstantHoistingLegacyPass,"consthoist","Constant Hoisting", false, false) INITIALIZE_PASS_END(ConstantHoistingLegacyPass
bool isEHPad() const
Return true if the instruction is a variety of EH-block.
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
StringRef - Represent a constant reference to a string, i.e.
A container for analyses that lazily runs them and caches their results.
RebasedConstantListType RebasedConstants
Legacy analysis pass which computes a DominatorTree.
const BasicBlock * getParent() const
FunctionPass * createConstantHoistingPass()
an instruction to allocate memory on the stack