78#define DEBUG_TYPE "gvn-sink"
80STATISTIC(NumRemoved,
"Number of instructions removed");
101struct SinkingInstructionCandidate {
103 unsigned NumInstructions;
105 unsigned NumMemoryInsts;
109 void calculateCost(
unsigned NumOrigPHIs,
unsigned NumOrigBlocks) {
110 unsigned NumExtraPHIs = NumPHIs - NumOrigPHIs;
111 unsigned SplitEdgeCost = (NumOrigBlocks > NumBlocks) ? 2 : 0;
112 Cost = (NumInstructions * (NumBlocks - 1)) -
129 SmallVector<Value *, 4> Values;
133 ModelledPHI() =
default;
135 ModelledPHI(
const PHINode *PN,
136 const DenseMap<const BasicBlock *, unsigned> &BlockOrder) {
140 using OpsType = std::pair<BasicBlock *, Value *>;
145 auto ComesBefore = [&](OpsType O1, OpsType O2) {
146 return BlockOrder.
lookup(O1.first) < BlockOrder.
lookup(O2.first);
151 for (
auto &
P :
Ops) {
160 static ModelledPHI createDummy(
size_t ID) {
162 M.Values.push_back(
reinterpret_cast<Value*
>(
ID));
167 verifyModelledPHI(
const DenseMap<const BasicBlock *, unsigned> &BlockOrder) {
169 "Modelling PHI with less than 2 values");
170 [[maybe_unused]]
auto ComesBefore = [&](
const BasicBlock *BB1,
176 for (
const Value *V : Values) {
185 ModelledPHI(SmallVectorImpl<Instruction *> &V,
186 SmallSetVector<BasicBlock *, 4> &
B,
187 const DenseMap<const BasicBlock *, unsigned> &BlockOrder) {
191 verifyModelledPHI(BlockOrder);
197 SmallSetVector<BasicBlock *, 4> &
B) {
199 for (
auto *
I : Insts)
200 Values.push_back(
I->getOperand(OpNum));
205 void restrictToBlocks(
const SmallSetVector<BasicBlock *, 4> &NewBlocks) {
206 auto BI = Blocks.
begin();
207 auto VI = Values.begin();
208 while (BI != Blocks.
end()) {
209 assert(VI != Values.end());
211 BI = Blocks.
erase(BI);
212 VI = Values.erase(VI);
223 bool areAllIncomingValuesSame()
const {
227 bool areAllIncomingValuesSameType()
const {
229 Values, [&](
Value *V) {
return V->getType() == Values[0]->getType(); });
232 bool areAnyIncomingValuesConstant()
const {
237 unsigned hash()
const {
243 return Values ==
Other.Values && Blocks ==
Other.Blocks;
250 const SinkingInstructionCandidate &
C) {
251 OS <<
"<Candidate Cost=" <<
C.Cost <<
" #Blocks=" <<
C.NumBlocks
252 <<
" #Insts=" <<
C.NumInstructions <<
" #PHIs=" <<
C.NumPHIs <<
">";
259 static ModelledPHI Dummy = ModelledPHI::createDummy(0);
263 static unsigned getHashValue(
const ModelledPHI &V) {
return V.hash(); }
265 static bool isEqual(
const ModelledPHI &LHS,
const ModelledPHI &RHS) {
288 unsigned MemoryUseOrder = -1;
289 bool Volatile =
false;
296 allocateOperands(R,
A);
297 setOpcode(
I->getOpcode());
298 setType(
I->getType());
301 ShuffleMask = SVI->getShuffleMask().copy(
A);
303 for (
auto &U :
I->uses())
304 op_push_back(U.getUser());
308 void setMemoryUseOrder(
unsigned MUO) { MemoryUseOrder = MUO; }
309 void setVolatile(
bool V) { Volatile = V; }
311 hash_code getHashValue()
const override {
313 Volatile, ShuffleMask);
319 for (
auto *V : operands())
334 BasicBlocksSet ReachableBBs;
340 InstructionUseExpr *
E =
343 E->setMemoryUseOrder(getMemoryUseOrder(
I));
355 template <
class Inst> InstructionUseExpr *createMemoryExpr(Inst *
I) {
358 InstructionUseExpr *
E = createExpr(
I);
359 E->setVolatile(
I->isVolatile());
367 void setReachableBBs(
const BasicBlocksSet &ReachableBBs) {
368 this->ReachableBBs = ReachableBBs;
374 auto VI = ValueNumbering.
find(V);
375 if (VI != ValueNumbering.
end())
379 ValueNumbering[V] = nextValueNumber;
380 return nextValueNumber++;
384 if (!ReachableBBs.contains(
I->getParent()))
387 InstructionUseExpr *
exp =
nullptr;
388 switch (
I->getOpcode()) {
389 case Instruction::Load:
392 case Instruction::Store:
395 case Instruction::Call:
396 case Instruction::Invoke:
397 case Instruction::FNeg:
398 case Instruction::Add:
399 case Instruction::FAdd:
400 case Instruction::Sub:
401 case Instruction::FSub:
402 case Instruction::Mul:
403 case Instruction::FMul:
404 case Instruction::UDiv:
405 case Instruction::SDiv:
406 case Instruction::FDiv:
407 case Instruction::URem:
408 case Instruction::SRem:
409 case Instruction::FRem:
410 case Instruction::Shl:
411 case Instruction::LShr:
412 case Instruction::AShr:
413 case Instruction::And:
414 case Instruction::Or:
415 case Instruction::Xor:
416 case Instruction::ICmp:
417 case Instruction::FCmp:
418 case Instruction::Trunc:
419 case Instruction::ZExt:
420 case Instruction::SExt:
421 case Instruction::FPToUI:
422 case Instruction::FPToSI:
423 case Instruction::UIToFP:
424 case Instruction::SIToFP:
425 case Instruction::FPTrunc:
426 case Instruction::FPExt:
427 case Instruction::PtrToInt:
428 case Instruction::PtrToAddr:
429 case Instruction::IntToPtr:
430 case Instruction::BitCast:
431 case Instruction::AddrSpaceCast:
432 case Instruction::Select:
433 case Instruction::ExtractElement:
434 case Instruction::InsertElement:
435 case Instruction::ShuffleVector:
436 case Instruction::InsertValue:
437 case Instruction::GetElementPtr:
445 ValueNumbering[V] = nextValueNumber;
446 return nextValueNumber++;
452 auto [
I, Inserted] = HashNumbering.
try_emplace(
H, nextValueNumber);
455 ExpressionNumbering[
exp] = nextValueNumber++;
457 ValueNumbering[V] = e;
464 auto VI = ValueNumbering.
find(V);
465 assert(VI != ValueNumbering.
end() &&
"Value not numbered?");
471 ValueNumbering.
clear();
472 ExpressionNumbering.
clear();
473 HashNumbering.
clear();
491 I !=
E && !
I->isTerminator(); ++
I) {
500 if (
II &&
II->onlyReadsMemory())
502 return lookupOrAdd(&*
I);
518 unsigned NumSunk = 0;
526 unsigned NodeOrdering = 0;
527 RPOTOrder[*RPOT.
begin()] = ++NodeOrdering;
528 for (
auto *BB : RPOT)
530 RPOTOrder[BB] = ++NodeOrdering;
532 NumSunk += sinkBB(
N);
544 I->getType()->isTokenTy())
552 std::optional<SinkingInstructionCandidate>
554 unsigned &InstNum,
unsigned &MemoryInstNum,
562 auto MPHI = ModelledPHI(&PN, RPOTOrder);
581 return V == PN->getIncomingValue(0);
594std::optional<SinkingInstructionCandidate>
595GVNSink::analyzeInstructionForSinking(LockstepReverseIterator<false> &LRI,
597 unsigned &MemoryInstNum,
599 SmallPtrSetImpl<Value *> &PHIContents) {
601 LLVM_DEBUG(
dbgs() <<
" -- Analyzing instruction set: [\n";
for (
auto *
I
604 }
dbgs() <<
" ]\n";);
606 DenseMap<uint32_t, unsigned> VNums;
607 for (
auto *
I : Insts) {
608 uint32_t
N = VN.lookupOrAdd(
I);
616 if (VNums[VNumToSink] == 1)
623 unsigned InitialActivePredSize = ActivePreds.size();
624 SmallVector<Instruction *, 4> NewInsts;
625 for (
auto *
I : Insts) {
626 if (VN.lookup(
I) != VNumToSink)
627 ActivePreds.remove(
I->getParent());
631 for (
auto *
I : NewInsts)
632 if (shouldAvoidSinkingInstruction(
I))
637 bool RecomputePHIContents =
false;
638 if (ActivePreds.size() != InitialActivePredSize) {
640 for (
auto P : NeededPHIs) {
641 P.restrictToBlocks(ActivePreds);
644 NeededPHIs = NewNeededPHIs;
646 RecomputePHIContents =
true;
650 ModelledPHI NewPHI(NewInsts, ActivePreds, RPOTOrder);
653 if (NeededPHIs.erase(NewPHI))
654 RecomputePHIContents =
true;
656 if (RecomputePHIContents) {
660 for (
auto &
PHI : NeededPHIs)
666 for (
auto *V : NewPHI.getValues())
667 if (PHIContents.
count(V))
682 if (
any_of(NewInsts, isNotSameOperation))
686 ModelledPHI
PHI(NewInsts, OpNum, ActivePreds);
687 if (
PHI.areAllIncomingValuesSame())
692 if (NeededPHIs.count(
PHI))
694 if (!
PHI.areAllIncomingValuesSameType())
698 PHI.areAnyIncomingValuesConstant())
701 NeededPHIs.reserve(NeededPHIs.size());
702 NeededPHIs.insert(
PHI);
709 SinkingInstructionCandidate Cand;
710 Cand.NumInstructions = ++InstNum;
711 Cand.NumMemoryInsts = MemoryInstNum;
712 Cand.NumBlocks = ActivePreds.size();
713 Cand.NumPHIs = NeededPHIs.size();
719unsigned GVNSink::sinkBB(BasicBlock *BBEnd) {
725 if (!RPOTOrder.count(
B))
727 auto *
T =
B->getTerminator();
733 if (Preds.size() < 2)
736 return RPOTOrder.lookup(BB1) < RPOTOrder.lookup(BB2);
741 unsigned NumOrigPreds = Preds.size();
747 LockstepReverseIterator<false> LRI(Preds);
749 unsigned InstNum = 0, MemoryInstNum = 0;
751 SmallPtrSet<Value *, 4> PHIContents;
752 analyzeInitialPHIs(BBEnd, NeededPHIs, PHIContents);
753 unsigned NumOrigPHIs = NeededPHIs.
size();
756 auto Cand = analyzeInstructionForSinking(LRI, InstNum, MemoryInstNum,
757 NeededPHIs, PHIContents);
760 Cand->calculateCost(NumOrigPHIs, Preds.size());
768 <<
" " <<
C <<
"\n";);
771 if (Candidates.empty() || Candidates.front().Cost <= 0)
773 auto C = Candidates.front();
777 if (
C.Blocks.size() < NumOrigPreds) {
788 for (
unsigned I = 0;
I <
C.NumInstructions; ++
I)
791 return C.NumInstructions;
796 SmallVector<Instruction *, 4> Insts;
797 for (BasicBlock *BB : Blocks)
801 SmallVector<Value *, 4> NewOperands;
803 bool NeedPHI =
llvm::any_of(Insts, [&I0, O](
const Instruction *
I) {
813 assert(!
Op->getType()->isTokenTy() &&
"Can't PHI tokens!");
817 for (
auto *
I : Insts)
829 for (
auto *
I : Insts)
835 for (
auto *
I : Insts)
837 I->replaceAllUsesWith(I0);
840 foldPointlessPHINodes(BBEnd);
843 for (
auto *
I : Insts)
845 I->eraseFromParent();
847 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< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#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.
The header file for the GVN pass that contains expression handling classes.
static bool isMemoryInst(const Instruction *I)
DenseSet< ModelledPHI > ModelledPHISet
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, GsymDataExtractor &Data, uint64_t &Offset, uint64_t BaseAddr, uint64_t Addr, SourceLocations &SrcLocs, llvm::Error &Err)
A Lookup helper functions.
static Value * getOpcode(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
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)
Recycle small arrays allocated from a BumpPtrAllocator.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
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; assumes that the block is well-formed.
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.
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Implements a dense probed hash-table based set.
hash_code getHashValue() const override
LLVM_DUMP_METHOD void dump() const
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.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
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_arg_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.
reference emplace_back(ArgTypes &&... Args)
iterator erase(const_iterator CI)
void push_back(const T &Elt)
static Twine utohexstr(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.
std::pair< iterator, bool > insert(const ValueT &V)
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.
SmallVector< ValueIDNum, 0 > ValueTable
Type for a table of values in a block.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
raw_ostream & operator<<(raw_ostream &OS, const Expression &E)
@ BasicBlock
Various leaf nodes.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
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.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
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_READONLY APFloat exp(const APFloat &X, RoundingMode RM=APFloat::rmNearestTiesToEven)
Implement IEEE 754-2019 exp functions.
LLVM_ABI bool canReplaceOperandWithVariable(const Instruction *I, unsigned OpIdx)
Given an instruction, is it legal to set operand OpIdx to a non-constant value?
DWARFExpression::Operation Op
auto max_element(R &&Range)
Provide wrappers to std::max_element which take ranges instead of having to pass begin/end explicitly...
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
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.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
static ModelledPHI & getEmptyKey()
static bool isEqual(const ModelledPHI &LHS, const ModelledPHI &RHS)
static unsigned getHashValue(const ModelledPHI &V)
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.