74 #define DEBUG_TYPE "consthoist" 76 STATISTIC(NumConstantsHoisted,
"Number of constants hoisted");
77 STATISTIC(NumConstantsRebased,
"Number of constants rebased");
81 cl::desc(
"Enable the use of the block frequency analysis to reduce the " 82 "chance to execute const materialization more frequently than " 83 "without hoisting."));
87 cl::desc(
"Try hoisting constant gep expressions"));
91 cl::desc(
"Do not rebase if number of dependent constants of a Base is less " 108 StringRef getPassName()
const override {
return "Constant Hoisting"; }
129 "Constant Hoisting",
false,
false)
137 return new ConstantHoistingLegacyPass();
142 if (skipFunction(Fn))
145 LLVM_DEBUG(
dbgs() <<
"********** Begin Constant Hoisting **********\n");
149 Impl.runImpl(Fn, getAnalysis<TargetTransformInfoWrapperPass>().getTTI(Fn),
150 getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
152 ? &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI()
157 LLVM_DEBUG(
dbgs() <<
"********** Function after Constant Hoisting: " 161 LLVM_DEBUG(
dbgs() <<
"********** End Constant Hoisting **********\n");
168 unsigned Idx)
const {
173 if (
auto CastInst = dyn_cast<Instruction>(Opnd))
179 if (!isa<PHINode>(Inst) && !Inst->
isEHPad())
184 assert(Entry != Inst->
getParent() &&
"PHI or landing pad in entry block!");
185 if (Idx != ~0U && isa<PHINode>(Inst))
186 return cast<PHINode>(Inst)->getIncomingBlock(Idx)->getTerminator();
191 auto IDom = DT->getNode(Inst->
getParent())->getIDom();
192 while (IDom->getBlock()->isEHPad()) {
193 assert(Entry != IDom->getBlock() &&
"eh pad in entry block");
194 IDom = IDom->getIDom();
197 return IDom->getBlock()->getTerminator();
206 assert(!BBs.
count(Entry) &&
"Assume Entry is not in BBs");
213 for (
auto BB : BBs) {
219 bool isCandidate =
false;
222 if (Node == Entry || Candidates.
count(Node)) {
227 "Entry doens't dominate current Node");
229 }
while (!BBs.count(Node));
237 Candidates.
insert(Path.begin(), Path.end());
245 while (Idx != Orders.
size()) {
248 if (Candidates.
count(ChildDomNode->getBlock()))
249 Orders.
push_back(ChildDomNode->getBlock());
254 using InsertPtsCostPair =
261 for (
auto RIt = Orders.
rbegin(); RIt != Orders.
rend(); RIt++) {
263 bool NodeInBBs = BBs.count(Node);
265 BlockFrequency &InsertPtsFreq = InsertPtsMap[Node].second;
274 BBs.insert(InsertPts.
begin(), InsertPts.
end());
282 BlockFrequency &ParentPtsFreq = InsertPtsMap[Parent].second;
293 ParentInsertPts.
insert(Node);
297 ParentPtsFreq += InsertPtsFreq;
310 for (
auto const &U : RCI.Uses)
311 BBs.
insert(findMatInsertPt(U.Inst, U.OpndIdx)->getParent());
313 if (BBs.count(Entry)) {
314 InsertPts.
insert(&Entry->front());
320 for (
auto BB : BBs) {
322 for (; isa<PHINode>(InsertPt) || InsertPt->isEHPad(); ++InsertPt)
324 InsertPts.
insert(&*InsertPt);
329 while (BBs.size() >= 2) {
332 BB2 = *std::next(BBs.begin());
333 BB = DT->findNearestCommonDominator(BB1, BB2);
335 InsertPts.
insert(&Entry->front());
342 assert((BBs.size() == 1) &&
"Expected only one element.");
344 InsertPts.
insert(findMatInsertPt(&FirstInst));
354 void ConstantHoistingPass::collectConstantCandidates(
355 ConstCandMapType &ConstCandMap,
Instruction *Inst,
unsigned Idx,
360 if (
auto IntrInst = dyn_cast<IntrinsicInst>(Inst))
361 Cost = TTI->getIntImmCost(IntrInst->getIntrinsicID(), Idx,
369 ConstCandMapType::iterator Itr;
371 ConstPtrUnionType Cand = ConstInt;
372 std::tie(Itr, Inserted) = ConstCandMap.insert(std::make_pair(Cand, 0));
375 Itr->second = ConstIntCandVec.size() - 1;
377 ConstIntCandVec[Itr->second].addUser(Inst, Idx, Cost);
379 <<
"Collect constant " << *ConstInt <<
" from " << *Inst
380 <<
" with cost " << Cost <<
'\n';
381 else dbgs() <<
"Collect constant " << *ConstInt
382 <<
" indirectly from " << *Inst <<
" via " 383 << *Inst->
getOperand(Idx) <<
" with cost " << Cost
389 void ConstantHoistingPass::collectConstantCandidates(
390 ConstCandMapType &ConstCandMap,
Instruction *Inst,
unsigned Idx,
403 APInt Offset(DL->getTypeSizeInBits(PtrIntTy), 0,
true);
404 auto *GEPO = cast<GEPOperator>(ConstExpr);
405 if (!GEPO->accumulateConstantOffset(*DL,
Offset))
416 ConstCandVecType &ExprCandVec = ConstGEPCandMap[BaseGV];
417 ConstCandMapType::iterator Itr;
419 ConstPtrUnionType Cand = ConstExpr;
420 std::tie(Itr, Inserted) = ConstCandMap.insert(std::make_pair(Cand, 0));
425 Itr->second = ExprCandVec.size() - 1;
427 ExprCandVec[Itr->second].addUser(Inst, Idx, Cost);
431 void ConstantHoistingPass::collectConstantCandidates(
432 ConstCandMapType &ConstCandMap,
Instruction *Inst,
unsigned Idx) {
436 if (
auto ConstInt = dyn_cast<ConstantInt>(Opnd)) {
437 collectConstantCandidates(ConstCandMap, Inst, Idx, ConstInt);
442 if (
auto CastInst = dyn_cast<Instruction>(Opnd)) {
451 collectConstantCandidates(ConstCandMap, Inst, Idx, ConstInt);
457 if (
auto ConstExpr = dyn_cast<ConstantExpr>(Opnd)) {
460 collectConstantCandidates(ConstCandMap, Inst, Idx, ConstExpr);
466 if (
auto ConstInt = dyn_cast<ConstantInt>(ConstExpr->
getOperand(0))) {
469 collectConstantCandidates(ConstCandMap, Inst, Idx, ConstInt);
477 void ConstantHoistingPass::collectConstantCandidates(
478 ConstCandMapType &ConstCandMap,
Instruction *Inst) {
490 collectConstantCandidates(ConstCandMap, Inst, Idx);
497 void ConstantHoistingPass::collectConstantCandidates(
Function &Fn) {
498 ConstCandMapType ConstCandMap;
501 collectConstantCandidates(ConstCandMap, &Inst);
515 if (LimVal1 == ~0ULL || LimVal2 == ~0ULL)
518 uint64_t Diff = LimVal1 - LimVal2;
519 return APInt(BW, Diff,
true);
546 ConstantHoistingPass::maximizeConstantsInRange(ConstCandVecType::iterator S,
547 ConstCandVecType::iterator
E,
548 ConstCandVecType::iterator &MaxCostItr) {
549 unsigned NumUses = 0;
551 if(!Entry->getParent()->optForSize() || std::distance(S,E) > 100) {
552 for (
auto ConstCand = S; ConstCand !=
E; ++ConstCand) {
553 NumUses += ConstCand->Uses.size();
554 if (ConstCand->CumulativeCost > MaxCostItr->CumulativeCost)
555 MaxCostItr = ConstCand;
562 for (
auto ConstCand = S; ConstCand !=
E; ++ConstCand) {
563 auto Value = ConstCand->ConstInt->getValue();
564 Type *Ty = ConstCand->ConstInt->getType();
566 NumUses += ConstCand->Uses.size();
567 LLVM_DEBUG(
dbgs() <<
"= Constant: " << ConstCand->ConstInt->getValue()
570 for (
auto User : ConstCand->Uses) {
571 unsigned Opcode =
User.Inst->getOpcode();
572 unsigned OpndIdx =
User.OpndIdx;
573 Cost += TTI->getIntImmCost(Opcode, OpndIdx,
Value, Ty);
576 for (
auto C2 = S; C2 !=
E; ++C2) {
578 C2->ConstInt->getValue(),
579 ConstCand->ConstInt->getValue());
582 TTI->getIntImmCodeSizeCost(Opcode, OpndIdx, Diff.
getValue(), Ty);
585 <<
"has penalty: " << ImmCosts <<
"\n" 586 <<
"Adjusted cost: " << Cost <<
"\n");
591 if (Cost > MaxCost) {
593 MaxCostItr = ConstCand;
594 LLVM_DEBUG(
dbgs() <<
"New candidate: " << MaxCostItr->ConstInt->getValue()
603 void ConstantHoistingPass::findAndMakeBaseConstant(
604 ConstCandVecType::iterator S, ConstCandVecType::iterator E,
607 unsigned NumUses = maximizeConstantsInRange(S, E, MaxCostItr);
621 for (
auto ConstCand = S; ConstCand !=
E; ++ConstCand) {
622 APInt Diff = ConstCand->ConstInt->getValue() - ConstInt->
getValue();
625 ConstCand->ConstExpr ? ConstCand->ConstExpr->getType() :
nullptr;
629 ConstInfoVec.
push_back(std::move(ConstInfo));
634 void ConstantHoistingPass::findBaseConstants(
GlobalVariable *BaseGV) {
637 ConstCandVecType &ConstCandVec = BaseGV ?
638 ConstGEPCandMap[BaseGV] : ConstIntCandVec;
639 ConstInfoVecType &ConstInfoVec = BaseGV ?
640 ConstGEPInfoMap[BaseGV] : ConstIntInfoVec;
643 std::stable_sort(ConstCandVec.begin(), ConstCandVec.end(),
647 RHS.ConstInt->getType()->getBitWidth();
653 auto MinValItr = ConstCandVec.begin();
654 for (
auto CC = std::next(ConstCandVec.begin()), E = ConstCandVec.end();
656 if (MinValItr->ConstInt->getType() == CC->ConstInt->getType()) {
657 Type *MemUseValTy =
nullptr;
658 for (
auto &U : CC->Uses) {
660 if (
LoadInst *LI = dyn_cast<LoadInst>(UI)) {
661 MemUseValTy = LI->getType();
663 }
else if (
StoreInst *
SI = dyn_cast<StoreInst>(UI)) {
665 if (
SI->getPointerOperand() ==
SI->getOperand(U.OpndIdx)) {
666 MemUseValTy =
SI->getValueOperand()->getType();
673 APInt Diff = CC->ConstInt->getValue() - MinValItr->ConstInt->getValue();
678 (!MemUseValTy || TTI->isLegalAddressingMode(MemUseValTy,
685 findAndMakeBaseConstant(MinValItr, CC, ConstInfoVec);
690 findAndMakeBaseConstant(MinValItr, ConstCandVec.end(), ConstInfoVec);
700 if (
auto PHI = dyn_cast<PHINode>(Inst)) {
707 BasicBlock *IncomingBB = PHI->getIncomingBlock(Idx);
708 for (
unsigned i = 0; i < Idx; ++i) {
709 if (PHI->getIncomingBlock(i) == IncomingBB) {
710 Value *IncomingVal = PHI->getIncomingValue(i);
730 if (!Offset && Ty && Ty != Base->
getType())
739 cast<PointerType>(Ty)->getAddressSpace());
740 Base =
new BitCastInst(Base, Int8PtrTy,
"base_bitcast", InsertionPt);
742 Offset,
"mat_gep", InsertionPt);
743 Mat =
new BitCastInst(Mat, Ty,
"mat_bitcast", InsertionPt);
747 "const_mat", InsertionPt);
750 <<
" + " << *Offset <<
") in BB " 758 if (isa<ConstantInt>(Opnd)) {
767 if (
auto CastInst = dyn_cast<Instruction>(Opnd)) {
772 if (!ClonedCastInst) {
775 ClonedCastInst->insertAfter(
CastInst);
779 <<
"To : " << *ClonedCastInst <<
'\n');
789 if (
auto ConstExpr = dyn_cast<ConstantExpr>(Opnd)) {
797 assert(ConstExpr->
isCast() &&
"ConstExpr should be a cast");
800 ConstExprInst->insertBefore(findMatInsertPt(ConstUser.
Inst,
806 LLVM_DEBUG(
dbgs() <<
"Create instruction: " << *ConstExprInst <<
'\n' 807 <<
"From : " << *ConstExpr <<
'\n');
810 ConstExprInst->eraseFromParent();
821 bool ConstantHoistingPass::emitBaseConstants(
GlobalVariable *BaseGV) {
822 bool MadeChange =
false;
824 BaseGV ? ConstGEPInfoMap[BaseGV] : ConstIntInfoVec;
825 for (
auto const &ConstInfo : ConstInfoVec) {
829 unsigned UsesNum = 0;
830 unsigned ReBasesNum = 0;
831 unsigned NotRebasedNum = 0;
835 using RebasedUse = std::tuple<Constant *, Type *, ConstantUser>;
838 for (
auto const &U : RCI.Uses) {
841 findMatInsertPt(U.Inst, U.OpndIdx)->
getParent();
844 if (IPSet.size() == 1 ||
845 DT->dominates(IP->getParent(), OrigMatInsertBB))
846 ToBeRebased.
push_back(RebasedUse(RCI.Offset, RCI.Ty, U));
854 NotRebasedNum += ToBeRebased.
size();
862 assert(BaseGV &&
"A base constant expression must have an base GV");
873 <<
") to BB " << IP->getParent()->
getName() <<
'\n' 877 for (
auto const &R : ToBeRebased) {
879 Type *Ty = std::get<1>(R);
881 emitBaseConstants(Base, Off, Ty, U);
889 "All uses should be instructions.");
895 assert(UsesNum == (ReBasesNum + NotRebasedNum) &&
896 "Not all uses are rebased");
898 NumConstantsHoisted++;
911 void ConstantHoistingPass::deleteDeadCastInst()
const {
912 for (
auto const &
I : ClonedCastMap)
913 if (
I.first->use_empty())
914 I.first->eraseFromParent();
926 this->Entry = &Entry;
928 collectConstantCandidates(Fn);
932 if (!ConstIntCandVec.empty())
933 findBaseConstants(
nullptr);
934 for (
auto &MapEntry : ConstGEPCandMap)
935 if (!MapEntry.second.empty())
936 findBaseConstants(MapEntry.first);
940 bool MadeChange =
false;
941 if (!ConstIntInfoVec.empty())
942 MadeChange = emitBaseConstants(
nullptr);
943 for (
auto MapEntry : ConstGEPInfoMap)
944 if (!MapEntry.second.empty())
945 MadeChange |= emitBaseConstants(MapEntry.first);
949 deleteDeadCastInst();
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
IntegerType * getType() const
getType - Specialize the getType() method to always return an IntegerType, which reduces the amount o...
static bool runImpl(Function &F, TargetLibraryInfo &TLI, DominatorTree &DT)
This is the entry point for all transforms.
INITIALIZE_PASS_BEGIN(ConstantHoistingLegacyPass, "consthoist", "Constant Hoisting", false, false) INITIALIZE_PASS_END(ConstantHoistingLegacyPass
static void findBestInsertionSet(DominatorTree &DT, BlockFrequencyInfo &BFI, BasicBlock *Entry, SmallPtrSet< BasicBlock *, 8 > &BBs)
Given BBs as input, find another set of BBs which collectively dominates BBs and have the minimal sum...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A base constant and all its rebased constants.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents lattice values for constants.
void initializeConstantHoistingLegacyPassPass(PassRegistry &)
static const DILocation * getMergedLocation(const DILocation *LocA, const DILocation *LocB)
When two instructions are combined into a single instruction we also need to combine the original loc...
virtual void releaseMemory()
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
void push_back(const T &Elt)
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value *> IdxList, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
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.
static cl::opt< unsigned > MinNumOfDependentToRebase("consthoist-min-num-to-rebase", cl::desc("Do not rebase if number of dependent constants of a Base is less " "than this number."), cl::init(0), cl::Hidden)
STATISTIC(NumFunctions, "Total number of functions")
Analysis pass which computes a DominatorTree.
An instruction for reading from memory.
bool isVectorTy() const
True if this is an instance of VectorType.
This represents a constant that has been rebased with respect to a base constant. ...
unsigned getBitWidth() const
Return the number of bits in the APInt.
iterator begin()
Instruction iterator methods.
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
This is the base class for all instructions that perform data casts.
static cl::opt< bool > ConstHoistGEP("consthoist-gep", cl::init(false), cl::Hidden, cl::desc("Try hoisting constant gep expressions"))
Legacy analysis pass which computes BlockFrequencyInfo.
Instruction * getAsInstruction()
Returns an Instruction which implements the same operation as this ConstantExpr.
This file implements a class to represent arbitrary precision integral constant values and operations...
Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following: ...
A constant value that is initialized with an expression using other constant values.
int64_t getSExtValue() const
Get sign extended value.
Type * getType() const
All values are typed, get the type of this value.
const T & getValue() const LLVM_LVALUE_FUNCTION
This class represents a no-op cast from one type to another.
const std::vector< DomTreeNodeBase * > & getChildren() const
const APInt & getValue() const
Return the constant as an APInt value reference.
bool isGEPWithNoNotionalOverIndexing() const
Return true if this is a getelementptr expression and all the index operands are compile-time known i...
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
An instruction for storing to memory.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Value * getOperand(unsigned i) const
Class to represent pointers.
const BasicBlock & getEntryBlock() const
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
static bool runOnFunction(Function &F, bool PostInlining)
initializer< Ty > init(const Ty &Val)
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.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
bool ult(const APInt &RHS) const
Unsigned less than comparison.
DomTreeNodeBase * getIDom() const
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
LLVM_NODISCARD bool empty() const
bool canReplaceOperandWithVariable(const Instruction *I, unsigned OpIdx)
Given an instruction, is it legal to set operand OpIdx to a non-constant 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.
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
Class to represent integer types.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
static cl::opt< bool > ConstHoistWithBlockFrequency("consthoist-with-block-frequency", cl::init(true), cl::Hidden, cl::desc("Enable the use of the block frequency analysis to reduce the " "chance to execute const materialization more frequently than " "without hoisting."))
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
Keeps track of the user of a constant and the operand index where the constant is used...
Analysis pass which computes BlockFrequencyInfo.
Iterator for intrusive lists based on ilist_node.
unsigned getNumOperands() const
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.
bool erase(PtrType Ptr)
erase - If the set contains the specified pointer, remove it and return true, otherwise return false...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
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:
static Optional< APInt > calculateOffsetDiff(const APInt &V1, const APInt &V2)
BlockFrequency getBlockFreq(const BasicBlock *BB) const
getblockFreq - Return block frequency.
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.
Represents analyses that only rely on functions' control flow.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
static IntegerType * getInt32Ty(LLVMContext &C)
LLVM_NODISCARD bool empty() const
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value...
void preserveSet()
Mark an analysis set as preserved.
StringRef getName() const
Return a constant reference to the value's name.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
bool runImpl(Function &F, TargetTransformInfo &TTI, DominatorTree &DT, BlockFrequencyInfo *BFI, BasicBlock &Entry)
Optimize expensive integer constants in the given function.
reverse_iterator rbegin()
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isEHPad() const
Return true if this basic block is an exception handling block.
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
bool isCast() const
Return true if this is a convert constant expression.
bool isEHPad() const
Return true if the instruction is a variety of EH-block.
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.
Type * getElementType() const
PointerType * getType() const
Global values are always pointers.
const BasicBlock * getParent() const
FunctionPass * createConstantHoistingPass()