77#define DEBUG_TYPE "gvn-sink"
79STATISTIC(NumRemoved,
"Number of instructions removed");
82namespace GVNExpression {
95 return isa<LoadInst>(
I) || isa<StoreInst>(
I) ||
96 (isa<InvokeInst>(
I) && !cast<InvokeInst>(
I)->doesNotAccessMemory()) ||
97 (isa<CallInst>(
I) && !cast<CallInst>(
I)->doesNotAccessMemory());
106struct SinkingInstructionCandidate {
108 unsigned NumInstructions;
110 unsigned NumMemoryInsts;
114 void calculateCost(
unsigned NumOrigPHIs,
unsigned NumOrigBlocks) {
115 unsigned NumExtraPHIs = NumPHIs - NumOrigPHIs;
116 unsigned SplitEdgeCost = (NumOrigBlocks > NumBlocks) ? 2 : 0;
117 Cost = (NumInstructions * (NumBlocks - 1)) -
130 OS <<
"<Candidate Cost=" <<
C.Cost <<
" #Blocks=" <<
C.NumBlocks
131 <<
" #Insts=" <<
C.NumInstructions <<
" #PHIs=" <<
C.NumPHIs <<
">";
146 ModelledPHI() =
default;
153 using OpsType = std::pair<BasicBlock *, Value *>;
158 auto ComesBefore = [BlockOrder](OpsType O1, OpsType O2) {
159 return BlockOrder.
lookup(O1.first) < BlockOrder.
lookup(O2.first);
164 for (
auto &
P : Ops) {
173 static ModelledPHI createDummy(
size_t ID) {
175 M.Values.push_back(
reinterpret_cast<Value*
>(
ID));
182 "Modelling PHI with less than 2 values");
183 auto ComesBefore = [BlockOrder](
const BasicBlock *BB1,
189 for (
const Value *V : Values) {
190 if (!isa<UndefValue>(V)) {
204 verifyModelledPHI(BlockOrder);
212 for (
auto *
I : Insts)
213 Values.push_back(
I->getOperand(OpNum));
220 auto VI = Values.begin();
221 while (BI !=
Blocks.end()) {
222 assert(VI != Values.end());
225 VI = Values.erase(VI);
236 bool areAllIncomingValuesSame()
const {
240 bool areAllIncomingValuesSameType()
const {
242 Values, [&](
Value *V) {
return V->getType() == Values[0]->
getType(); });
245 bool areAnyIncomingValuesConstant()
const {
250 unsigned hash()
const {
261 static inline ModelledPHI &getEmptyKey() {
262 static ModelledPHI Dummy = ModelledPHI::createDummy(0);
266 static inline ModelledPHI &getTombstoneKey() {
267 static ModelledPHI Dummy = ModelledPHI::createDummy(1);
271 static unsigned getHashValue(
const ModelledPHI &V) {
return V.hash(); }
273 static bool isEqual(
const ModelledPHI &LHS,
const ModelledPHI &RHS) {
294 unsigned MemoryUseOrder = -1;
301 : GVNExpression::BasicExpression(
I->getNumUses()) {
307 ShuffleMask = SVI->getShuffleMask().
copy(
A);
309 for (
auto &U :
I->uses())
314 void setMemoryUseOrder(
unsigned MUO) { MemoryUseOrder = MUO; }
315 void setVolatile(
bool V) {
Volatile =
V; }
319 MemoryUseOrder, Volatile, ShuffleMask);
340 BasicBlocksSet ReachableBBs;
346 InstructionUseExpr *E =
349 E->setMemoryUseOrder(getMemoryUseOrder(
I));
353 E->setOpcode((
C->getOpcode() << 8) |
Predicate);
361 template <
class Inst> InstructionUseExpr *createMemoryExpr(Inst *
I) {
364 InstructionUseExpr *E = createExpr(
I);
365 E->setVolatile(
I->isVolatile());
373 void setReachableBBs(
const BasicBlocksSet &ReachableBBs) {
374 this->ReachableBBs = ReachableBBs;
380 auto VI = ValueNumbering.
find(V);
381 if (VI != ValueNumbering.
end())
384 if (!isa<Instruction>(V)) {
385 ValueNumbering[
V] = nextValueNumber;
386 return nextValueNumber++;
390 if (!ReachableBBs.contains(
I->getParent()))
393 InstructionUseExpr *exp =
nullptr;
394 switch (
I->getOpcode()) {
395 case Instruction::Load:
396 exp = createMemoryExpr(cast<LoadInst>(
I));
398 case Instruction::Store:
399 exp = createMemoryExpr(cast<StoreInst>(
I));
401 case Instruction::Call:
402 case Instruction::Invoke:
403 case Instruction::FNeg:
404 case Instruction::Add:
405 case Instruction::FAdd:
406 case Instruction::Sub:
407 case Instruction::FSub:
408 case Instruction::Mul:
409 case Instruction::FMul:
410 case Instruction::UDiv:
411 case Instruction::SDiv:
412 case Instruction::FDiv:
413 case Instruction::URem:
414 case Instruction::SRem:
415 case Instruction::FRem:
416 case Instruction::Shl:
417 case Instruction::LShr:
418 case Instruction::AShr:
419 case Instruction::And:
420 case Instruction::Or:
421 case Instruction::Xor:
422 case Instruction::ICmp:
423 case Instruction::FCmp:
424 case Instruction::Trunc:
425 case Instruction::ZExt:
426 case Instruction::SExt:
427 case Instruction::FPToUI:
428 case Instruction::FPToSI:
429 case Instruction::UIToFP:
430 case Instruction::SIToFP:
431 case Instruction::FPTrunc:
432 case Instruction::FPExt:
433 case Instruction::PtrToInt:
434 case Instruction::IntToPtr:
435 case Instruction::BitCast:
436 case Instruction::AddrSpaceCast:
437 case Instruction::Select:
438 case Instruction::ExtractElement:
439 case Instruction::InsertElement:
440 case Instruction::ShuffleVector:
441 case Instruction::InsertValue:
442 case Instruction::GetElementPtr:
450 ValueNumbering[
V] = nextValueNumber;
451 return nextValueNumber++;
456 hash_code H = exp->getHashValue([=](
Value *V) {
return lookupOrAdd(V); });
460 ExpressionNumbering[exp] = nextValueNumber++;
462 ValueNumbering[
V] =
e;
469 auto VI = ValueNumbering.
find(V);
470 assert(VI != ValueNumbering.
end() &&
"Value not numbered?");
476 ValueNumbering.
clear();
477 ExpressionNumbering.
clear();
478 HashNumbering.
clear();
495 for (
auto I = std::next(Inst->
getIterator()), E = BB->end();
496 I != E && !
I->isTerminator(); ++
I) {
497 if (!isMemoryInst(&*
I))
499 if (isa<LoadInst>(&*
I))
505 if (
II &&
II->onlyReadsMemory())
507 return lookupOrAdd(&*
I);
523 unsigned NumSunk = 0;
531 unsigned NodeOrdering = 0;
532 RPOTOrder[*RPOT.begin()] = ++NodeOrdering;
533 for (
auto *BB : RPOT)
535 RPOTOrder[BB] = ++NodeOrdering;
537 NumSunk += sinkBB(
N);
548 if (isa<PHINode>(
I) ||
I->isEHPad() || isa<AllocaInst>(
I) ||
549 I->getType()->isTokenTy())
557 std::optional<SinkingInstructionCandidate>
559 unsigned &InstNum,
unsigned &MemoryInstNum,
560 ModelledPHISet &NeededPHIs,
564 void analyzeInitialPHIs(
BasicBlock *BB, ModelledPHISet &PHIs,
567 auto MPHI = ModelledPHI(&PN, RPOTOrder);
584 while (
PHINode *PN = dyn_cast<PHINode>(
I++)) {
586 return V == PN->getIncomingValue(0);
598std::optional<SinkingInstructionCandidate>
601 unsigned &MemoryInstNum,
602 ModelledPHISet &NeededPHIs,
605 LLVM_DEBUG(
dbgs() <<
" -- Analyzing instruction set: [\n";
for (
auto *
I
608 }
dbgs() <<
" ]\n";);
611 for (
auto *
I : Insts) {
620 if (VNums[VNumToSink] == 1)
627 unsigned InitialActivePredSize = ActivePreds.size();
629 for (
auto *
I : Insts) {
630 if (VN.lookup(
I) != VNumToSink)
631 ActivePreds.remove(
I->getParent());
635 for (
auto *
I : NewInsts)
636 if (shouldAvoidSinkingInstruction(
I))
641 bool RecomputePHIContents =
false;
642 if (ActivePreds.size() != InitialActivePredSize) {
643 ModelledPHISet NewNeededPHIs;
644 for (
auto P : NeededPHIs) {
645 P.restrictToBlocks(ActivePreds);
646 NewNeededPHIs.insert(
P);
648 NeededPHIs = NewNeededPHIs;
650 RecomputePHIContents =
true;
654 ModelledPHI NewPHI(NewInsts, ActivePreds, RPOTOrder);
657 if (NeededPHIs.erase(NewPHI))
658 RecomputePHIContents =
true;
660 if (RecomputePHIContents) {
664 for (
auto &
PHI : NeededPHIs)
670 for (
auto *V : NewPHI.getValues())
671 if (PHIContents.
count(V))
686 if (
any_of(NewInsts, isNotSameOperation))
689 for (
unsigned OpNum = 0, E = I0->
getNumOperands(); OpNum != E; ++OpNum) {
690 ModelledPHI
PHI(NewInsts, OpNum, ActivePreds);
691 if (
PHI.areAllIncomingValuesSame())
696 if (NeededPHIs.count(
PHI))
698 if (!
PHI.areAllIncomingValuesSameType())
701 if ((isa<CallInst>(I0) || isa<InvokeInst>(I0)) && OpNum == E - 1 &&
702 PHI.areAnyIncomingValuesConstant())
705 NeededPHIs.reserve(NeededPHIs.size());
706 NeededPHIs.insert(
PHI);
710 if (isMemoryInst(NewInsts[0]))
713 SinkingInstructionCandidate Cand;
714 Cand.NumInstructions = ++InstNum;
715 Cand.NumMemoryInsts = MemoryInstNum;
716 Cand.NumBlocks = ActivePreds.size();
717 Cand.NumPHIs = NeededPHIs.size();
731 auto *
T =
B->getTerminator();
732 if (isa<BranchInst>(
T) || isa<SwitchInst>(
T))
737 if (Preds.size() < 2)
745 unsigned NumOrigPreds = Preds.size();
753 unsigned InstNum = 0, MemoryInstNum = 0;
754 ModelledPHISet NeededPHIs;
756 analyzeInitialPHIs(BBEnd, NeededPHIs, PHIContents);
757 unsigned NumOrigPHIs = NeededPHIs.size();
760 auto Cand = analyzeInstructionForSinking(LRI, InstNum, MemoryInstNum,
761 NeededPHIs, PHIContents);
764 Cand->calculateCost(NumOrigPHIs, Preds.size());
772 <<
" " <<
C <<
"\n";);
775 if (Candidates.empty() || Candidates.front().Cost <= 0)
777 auto C = Candidates.front();
781 if (
C.Blocks.size() < NumOrigPreds) {
792 for (
unsigned I = 0;
I <
C.NumInstructions; ++
I)
795 return C.NumInstructions;
817 assert(!
Op->getType()->isTokenTy() &&
"Can't PHI tokens!");
821 for (
auto *
I : Insts)
833 for (
auto *
I : Insts)
839 for (
auto *
I : Insts)
841 I->replaceAllUsesWith(I0);
844 foldPointlessPHINodes(BBEnd);
847 for (
auto *
I : Insts)
849 I->eraseFromParent();
851 NumRemoved += Insts.size() - 1;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the BumpPtrAllocator interface.
Atomic ordering constants.
static const Function * getParent(const Value *V)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
std::optional< std::vector< StOtherPiece > > Other
DenseMap< Block *, BlockRelaxAux > Blocks
The header file for the GVN pass that contains expression handling classes.
This file provides the interface for LLVM's Global Value Numbering pass which eliminates fully redund...
This is the interface for a simple mod/ref and alias analysis over globals.
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
static bool lookup(const GsymReader &GR, DataExtractor &Data, uint64_t &Offset, uint64_t BaseAddr, uint64_t Addr, SourceLocations &SrcLocs, llvm::Error &Err)
A Lookup helper functions.
uint64_t IntrinsicInst * II
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
static void sinkLastInstruction(ArrayRef< BasicBlock * > Blocks)
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
A container for analyses that lazily runs them and caches their results.
Recycle small arrays allocated from a BumpPtrAllocator.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
MutableArrayRef< T > copy(Allocator &A)
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Allocate memory in an ever growing pool, as if by bump-pointer.
bool onlyReadsMemory(unsigned OpNo) const
This class represents a function call, abstracting a target machine's calling convention.
This class is the base class for the comparison instructions.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
This class represents an Operation in the Expression.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Implements a dense probed hash-table based set.
void allocateOperands(RecyclerType &Recycler, BumpPtrAllocator &Allocator)
void op_push_back(Value *Arg)
hash_code getHashValue() const override
iterator_range< op_iterator > operands()
unsigned getOpcode() const
LLVM_DUMP_METHOD void dump() const
void setOpcode(unsigned opcode)
void print(raw_ostream &OS) const
LLVM_ABI bool isSameOperationAs(const Instruction *I, unsigned flags=0) const LLVM_READONLY
This function determines if the specified instruction executes the same operation as the current one.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI void andIRFlags(const Value *V)
Logical 'and' of any supported wrapping, exact, and fast-math flags of V and this instruction.
LLVM_ABI void moveBefore(InstListType::iterator InsertPos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI void applyMergedLocation(DebugLoc LocA, DebugLoc LocB)
Merge 2 debug locations and apply it to the Instruction.
Iterates through instructions in a set of blocks in reverse order from the first non-terminator.
void restrictToBlocks(SmallSetVector< BasicBlock *, 4 > &Blocks)
SmallSetVector< BasicBlock *, 4 > & getActiveBlocks()
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
op_range incoming_values()
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Recycler - This class manages a linked-list of deallocated nodes and facilitates reusing deallocated ...
void clear(AllocatorType &Allocator)
clear - Release all the tracked allocations to the allocator.
size_type size() const
Determine the number of elements in the SetVector.
bool contains(const key_type &key) const
Check if the SetVector contains the given key.
This instruction constructs a fixed permutation of two input vectors.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void insert_range(Range &&R)
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static Twine utohexstr(const uint64_t &Val)
LLVM_ABI void set(Value *Val)
const Use & getOperandUse(unsigned i) const
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
An opaque object representing a hash code.
const ParentTy * getParent() const
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
@ C
The default llvm calling convention, compatible with C.
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool isEqual(const GCNRPTracker::LiveRegSet &S1, const GCNRPTracker::LiveRegSet &S2)
constexpr from_range_t from_range
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
bool isStrongerThanUnordered(AtomicOrdering AO)
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool operator>(int64_t V1, const APSInt &V2)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
LLVM_ABI void combineMetadataForCSE(Instruction *K, const Instruction *J, bool DoesKMove)
Combine the metadata of two instructions so that K can replace J.
LLVM_ABI BasicBlock * SplitBlockPredecessors(BasicBlock *BB, ArrayRef< BasicBlock * > Preds, const char *Suffix, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool PreserveLCSSA=false)
This method introduces at least one new basic block into the function and moves some of the predecess...
LLVM_ABI bool canReplaceOperandWithVariable(const Instruction *I, unsigned OpIdx)
Given an instruction, is it legal to set operand OpIdx to a non-constant value?
auto max_element(R &&Range)
Provide wrappers to std::max_element which take ranges instead of having to pass begin/end explicitly...
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
auto predecessors(const MachineBasicBlock *BB)
bool pred_empty(const BasicBlock *BB)
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
An information struct used to provide DenseMap with the various necessary components for a given valu...
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
Function object to check whether the second component of a container supported by std::get (like std:...