84 #define DEBUG_TYPE "gvn-sink" 86 STATISTIC(NumRemoved,
"Number of instructions removed");
89 namespace GVNExpression {
102 return isa<LoadInst>(
I) || isa<StoreInst>(I) ||
103 (isa<InvokeInst>(
I) && !cast<InvokeInst>(I)->doesNotAccessMemory()) ||
104 (isa<CallInst>(I) && !cast<CallInst>(
I)->doesNotAccessMemory());
119 class LockstepReverseIterator {
132 ActiveBlocks.
clear();
137 if (BB->size() <= 1) {
142 Insts.
push_back(BB->getTerminator()->getPrevNode());
148 bool isValid()
const {
return !
Fail; }
160 for (
auto II = Insts.
begin(); II != Insts.
end();) {
163 ActiveBlocks.
remove((*II)->getParent());
164 II = Insts.
erase(II);
175 for (
auto *Inst : Insts) {
176 if (Inst == &Inst->getParent()->front())
177 ActiveBlocks.
remove(Inst->getParent());
181 if (NewInsts.
empty()) {
195 struct SinkingInstructionCandidate {
197 unsigned NumInstructions;
199 unsigned NumMemoryInsts;
203 void calculateCost(
unsigned NumOrigPHIs,
unsigned NumOrigBlocks) {
204 unsigned NumExtraPHIs = NumPHIs - NumOrigPHIs;
205 unsigned SplitEdgeCost = (NumOrigBlocks > NumBlocks) ? 2 : 0;
206 Cost = (NumInstructions * (NumBlocks - 1)) -
213 return Cost > Other.Cost;
219 OS <<
"<Candidate Cost=" << C.Cost <<
" #Blocks=" << C.NumBlocks
220 <<
" #Insts=" << C.NumInstructions <<
" #PHIs=" << C.NumPHIs <<
">";
235 ModelledPHI() =
default;
237 ModelledPHI(
const PHINode *PN) {
241 Ops.
push_back({PN->getIncomingBlock(I), PN->getIncomingValue(I)});
243 for (
auto &
P : Ops) {
252 static ModelledPHI createDummy(
size_t ID) {
254 M.Values.push_back(reinterpret_cast<Value*>(ID));
259 template <
typename VArray,
typename BArray>
260 ModelledPHI(
const VArray &V,
const BArray &
B) {
266 template <
typename BArray>
269 for (
auto *I : Insts)
276 auto BI = Blocks.
begin();
278 while (BI != Blocks.
end()) {
282 BI = Blocks.
erase(BI);
294 bool areAllIncomingValuesSame()
const {
298 bool areAllIncomingValuesSameType()
const {
300 Values, [&](
Value *V) {
return V->
getType() == Values[0]->getType(); });
303 bool areAnyIncomingValuesConstant()
const {
308 unsigned hash()
const {
313 return Values == Other.Values && Blocks == Other.Blocks;
319 static ModelledPHI
Dummy = ModelledPHI::createDummy(0);
324 static ModelledPHI
Dummy = ModelledPHI::createDummy(1);
328 static unsigned getHashValue(
const ModelledPHI &V) {
return V.hash(); }
330 static bool isEqual(
const ModelledPHI &LHS,
const ModelledPHI &RHS) {
351 unsigned MemoryUseOrder = -1;
352 bool Volatile =
false;
358 allocateOperands(R, A);
362 for (
auto &U : I->
uses())
363 op_push_back(U.getUser());
367 void setMemoryUseOrder(
unsigned MUO) { MemoryUseOrder = MUO; }
368 void setVolatile(
bool V) { Volatile = V; }
372 MemoryUseOrder, Volatile);
378 for (
auto *V : operands())
396 InstructionUseExpr *
E =
397 new (
Allocator) InstructionUseExpr(I, Recycler, Allocator);
399 E->setMemoryUseOrder(getMemoryUseOrder(I));
401 if (
CmpInst *C = dyn_cast<CmpInst>(I)) {
403 E->setOpcode((C->getOpcode() << 8) | Predicate);
411 template <
class Inst> InstructionUseExpr *createMemoryExpr(Inst *I) {
414 InstructionUseExpr *
E = createExpr(I);
415 E->setVolatile(I->isVolatile());
420 ValueTable() =
default;
425 auto VI = ValueNumbering.
find(V);
426 if (
VI != ValueNumbering.
end())
429 if (!isa<Instruction>(V)) {
430 ValueNumbering[V] = nextValueNumber;
431 return nextValueNumber++;
435 InstructionUseExpr *
exp =
nullptr;
438 exp = createMemoryExpr(cast<LoadInst>(I));
441 exp = createMemoryExpr(cast<StoreInst>(I));
444 case Instruction::Invoke:
446 case Instruction::FAdd:
447 case Instruction::Sub:
448 case Instruction::FSub:
449 case Instruction::Mul:
450 case Instruction::FMul:
451 case Instruction::UDiv:
452 case Instruction::SDiv:
453 case Instruction::FDiv:
454 case Instruction::URem:
455 case Instruction::SRem:
456 case Instruction::FRem:
457 case Instruction::Shl:
458 case Instruction::LShr:
459 case Instruction::AShr:
460 case Instruction::And:
461 case Instruction::Or:
462 case Instruction::Xor:
463 case Instruction::ICmp:
464 case Instruction::FCmp:
465 case Instruction::Trunc:
466 case Instruction::ZExt:
467 case Instruction::SExt:
468 case Instruction::FPToUI:
469 case Instruction::FPToSI:
470 case Instruction::UIToFP:
471 case Instruction::SIToFP:
472 case Instruction::FPTrunc:
473 case Instruction::FPExt:
474 case Instruction::PtrToInt:
475 case Instruction::IntToPtr:
476 case Instruction::BitCast:
478 case Instruction::ExtractElement:
479 case Instruction::InsertElement:
480 case Instruction::ShuffleVector:
481 case Instruction::InsertValue:
482 case Instruction::GetElementPtr:
490 ValueNumbering[V] = nextValueNumber;
491 return nextValueNumber++;
496 hash_code H = exp->getHashValue([=](
Value *V) {
return lookupOrAdd(V); });
497 auto I = HashNumbering.
find(H);
498 if (I != HashNumbering.
end()) {
501 e = nextValueNumber++;
502 HashNumbering[
H] = e;
503 ExpressionNumbering[
exp] = e;
506 ValueNumbering[V] = e;
513 auto VI = ValueNumbering.
find(V);
514 assert(
VI != ValueNumbering.
end() &&
"Value not numbered?");
520 ValueNumbering.
clear();
521 ExpressionNumbering.
clear();
522 HashNumbering.
clear();
523 Recycler.
clear(Allocator);
539 for (
auto I = std::next(Inst->
getIterator()),
E = BB->end();
540 I !=
E && !I->isTerminator(); ++
I) {
541 if (!isMemoryInst(&*I))
543 if (isa<LoadInst>(&*I))
551 return lookupOrAdd(&*I);
567 unsigned NumSunk = 0;
570 NumSunk += sinkBB(
N);
580 if (isa<PHINode>(I) || I->
isEHPad() || isa<AllocaInst>(
I) ||
590 LockstepReverseIterator &LRI,
unsigned &InstNum,
unsigned &MemoryInstNum,
594 void analyzeInitialPHIs(
BasicBlock *BB, ModelledPHISet &PHIs,
597 auto MPHI = ModelledPHI(&PN);
599 for (
auto *V : MPHI.getValues())
614 auto I = BB->
begin();
615 while (
PHINode *PN = dyn_cast<PHINode>(I++)) {
617 return V == PN->getIncomingValue(0);
620 if (PN->getIncomingValue(0) != PN)
621 PN->replaceAllUsesWith(PN->getIncomingValue(0));
624 PN->eraseFromParent();
630 LockstepReverseIterator &LRI,
unsigned &InstNum,
unsigned &MemoryInstNum,
633 LLVM_DEBUG(
dbgs() <<
" -- Analyzing instruction set: [\n";
for (
auto *I
636 }
dbgs() <<
" ]\n";);
639 for (
auto *I : Insts) {
646 unsigned VNumToSink =
647 std::max_element(VNums.begin(), VNums.end(),
648 [](
const std::pair<uint32_t, unsigned> &
I,
649 const std::pair<uint32_t, unsigned> &J) {
650 return I.second < J.second;
654 if (VNums[VNumToSink] == 1)
660 auto &ActivePreds = LRI.getActiveBlocks();
661 unsigned InitialActivePredSize = ActivePreds.size();
663 for (
auto *I : Insts) {
664 if (VN.lookup(I) != VNumToSink)
665 ActivePreds.remove(I->getParent());
669 for (
auto *I : NewInsts)
670 if (isInstructionBlacklisted(I))
675 bool RecomputePHIContents =
false;
676 if (ActivePreds.size() != InitialActivePredSize) {
677 ModelledPHISet NewNeededPHIs;
678 for (
auto P : NeededPHIs) {
679 P.restrictToBlocks(ActivePreds);
680 NewNeededPHIs.insert(
P);
682 NeededPHIs = NewNeededPHIs;
683 LRI.restrictToBlocks(ActivePreds);
684 RecomputePHIContents =
true;
688 ModelledPHI NewPHI(NewInsts, ActivePreds);
691 if (NeededPHIs.find(NewPHI) != NeededPHIs.end()) {
692 NeededPHIs.erase(NewPHI);
693 RecomputePHIContents =
true;
696 if (RecomputePHIContents) {
700 for (
auto &PHI : NeededPHIs)
701 PHIContents.
insert(PHI.getValues().begin(), PHI.getValues().end());
706 for (
auto *V : NewPHI.getValues())
707 if (PHIContents.
count(V))
718 ModelledPHI PHI(NewInsts, OpNum, ActivePreds);
719 if (PHI.areAllIncomingValuesSame())
724 if (NeededPHIs.count(PHI))
726 if (!PHI.areAllIncomingValuesSameType())
729 if ((isa<CallInst>(I0) || isa<InvokeInst>(I0)) && OpNum ==
E - 1 &&
730 PHI.areAnyIncomingValuesConstant())
733 NeededPHIs.reserve(NeededPHIs.size());
734 NeededPHIs.insert(PHI);
735 PHIContents.
insert(PHI.getValues().begin(), PHI.getValues().end());
738 if (isMemoryInst(NewInsts[0]))
741 SinkingInstructionCandidate Cand;
742 Cand.NumInstructions = ++InstNum;
743 Cand.NumMemoryInsts = MemoryInstNum;
744 Cand.NumBlocks = ActivePreds.size();
745 Cand.NumPHIs = NeededPHIs.size();
746 for (
auto *C : ActivePreds)
747 Cand.Blocks.push_back(C);
757 auto *
T =
B->getTerminator();
758 if (isa<BranchInst>(
T) || isa<SwitchInst>(
T))
763 if (Preds.size() < 2)
767 unsigned NumOrigPreds = Preds.size();
769 for (
auto I = Preds.begin(); I != Preds.end();) {
770 if ((*I)->getTerminator()->getNumSuccessors() != 1)
776 LockstepReverseIterator LRI(Preds);
778 unsigned InstNum = 0, MemoryInstNum = 0;
779 ModelledPHISet NeededPHIs;
781 analyzeInitialPHIs(BBEnd, NeededPHIs, PHIContents);
782 unsigned NumOrigPHIs = NeededPHIs.size();
784 while (LRI.isValid()) {
785 auto Cand = analyzeInstructionForSinking(LRI, InstNum, MemoryInstNum,
786 NeededPHIs, PHIContents);
789 Cand->calculateCost(NumOrigPHIs, Preds.size());
795 Candidates.
begin(), Candidates.
end(),
796 [](
const SinkingInstructionCandidate &A,
797 const SinkingInstructionCandidate &
B) {
return A >
B; });
800 <<
" " << C <<
"\n";);
803 if (Candidates.empty() || Candidates.front().Cost <= 0)
805 auto C = Candidates.front();
809 if (C.Blocks.size() < NumOrigPreds) {
820 for (
unsigned I = 0; I < C.NumInstructions; ++
I)
823 return C.NumInstructions;
830 Insts.
push_back(BB->getTerminator()->getPrevNode());
845 assert(!
Op->getType()->isTokenTy() &&
"Can't PHI tokens!");
847 Op->getName() +
".sink", &BBEnd->
front());
848 for (
auto *I : Insts)
860 for (
auto *I : Insts)
866 for (
auto *I : Insts)
869 foldPointlessPHINodes(BBEnd);
872 for (
auto *I : Insts)
876 NumRemoved += Insts.size() - 1;
917 "Early GVN sinking of Expressions",
false,
false)
Legacy wrapper pass to provide the GlobalsAAResult object.
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
This class is the base class for the comparison instructions.
iterator_range< use_iterator > uses()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
bool isStrongerThanUnordered(AtomicOrdering ao)
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
gvn sink
When an instruction is found to only be used outside of the loop, this function moves it to the exit ...
Atomic ordering constants.
This class represents lattice values for constants.
size_type size() const
Determine the number of elements in the SetVector.
This is the interface for a simple mod/ref and alias analysis over globals.
Implements a dense probed hash-table based set.
void push_back(const T &Elt)
bool operator>(int64_t V1, const APSInt &V2)
This class represents a function call, abstracting a target machine's calling convention.
Recycle small arrays allocated from a BumpPtrAllocator.
const Use & getOperandUse(unsigned i) const
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly...
STATISTIC(NumFunctions, "Total number of functions")
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
bool operator==(const Expression &Other) const
This defines the Use class.
iterator end()
Get an iterator to the end of the SetVector.
This file defines the MallocAllocator and BumpPtrAllocator interfaces.
iterator begin()
Instruction iterator methods.
void dump() const
Support for debugging, callable in GDB: V->dump()
#define INITIALIZE_PASS_DEPENDENCY(depName)
raw_ostream & operator<<(raw_ostream &OS, const Expression &E)
INITIALIZE_PASS_BEGIN(GVNSinkLegacyPass, "gvn-sink", "Early GVN sinking of Expressions", false, false) INITIALIZE_PASS_END(GVNSinkLegacyPass
static const uint16_t * lookup(unsigned opcode, unsigned domain, ArrayRef< uint16_t[3]> Table)
bool remove(const value_type &X)
Remove an item from the set vector.
APInt operator*(APInt a, uint64_t RHS)
Type * getType() const
All values are typed, get the type of this value.
static unsigned getEmptyKey()
bool insert(const value_type &X)
Insert a new element into the SetVector.
static bool isEqual(const Function &Caller, const Function &Callee)
The core GVN pass object.
void andIRFlags(const Value *V)
Logical 'and' of any supported wrapping, exact, and fast-math flags of V and this instruction...
iterator begin()
Get an iterator to the beginning of the SetVector.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM_DUMP_METHOD void dump() const
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
virtual hash_code getHashValue() const
Value * getOperand(unsigned i) const
iterator find(const_arg_type_t< KeyT > Val)
static bool runOnFunction(Function &F, bool PostInlining)
BasicBlock * SplitBlockPredecessors(BasicBlock *BB, ArrayRef< BasicBlock *> Preds, const char *Suffix, DominatorTree *DT=nullptr, 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...
void print(raw_ostream &OS) const
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
A set of analyses that are preserved following a run of a transformation pass.
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
static bool sinkLastInstruction(ArrayRef< BasicBlock *> Blocks)
LLVM Basic Block Representation.
Allocate memory in an ever growing pool, as if by bump-pointer.
This file provides the interface for LLVM's Global Value Numbering pass which eliminates fully redund...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
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...
const Instruction & front() const
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.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly...
Analysis pass providing a never-invalidated alias analysis result.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
FunctionPass class - This class is used to implement most global optimizations.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
self_iterator getIterator()
static unsigned getTombstoneKey()
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
iterator erase(const_iterator CI)
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
static wasm::ValType getType(const TargetRegisterClass *RC)
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
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.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
void sort(IteratorTy Start, IteratorTy End)
hash_code getHashValue() const override
A SetVector that performs no allocations if smaller than a certain size.
unsigned getNumOperands() const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
void setOpcode(unsigned opcode)
Recycler - This class manages a linked-list of deallocated nodes and facilitates reusing deallocated ...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
gvn Early GVN sinking of Expressions
static Twine utohexstr(const uint64_t &Val)
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
pred_range predecessors(BasicBlock *BB)
void clear(AllocatorType &Allocator)
Release all the tracked allocations to the allocator.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void clear()
Completely clear the SetVector.
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 opaque object representing a hash code.
static void clear(coro::Shape &Shape)
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
unsigned getNumUses() const
This method computes the number of uses of this Value.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
void emplace_back(ArgTypes &&... Args)
LLVM_NODISCARD bool empty() const
FunctionPass * createGVNSinkPass()
bool isTokenTy() const
Return true if this is 'token'.
StringRef getName() const
Return a constant reference to the value's name.
void initializeGVNSinkLegacyPassPass(PassRegistry &)
bool onlyReadsMemory(unsigned OpNo) const
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
void preserve()
Mark an analysis as preserved.
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
The header file for the GVN pass that contains expression handling classes.
void moveBefore(Instruction *MovePos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
This class implements an extremely fast bulk output stream that can only output to a stream...
void combineMetadataForCSE(Instruction *K, const Instruction *J, bool DoesKMove)
Combine the metadata of two instructions so that K can replace J.
bool isEHPad() const
Return true if the instruction is a variety of EH-block.
A container for analyses that lazily runs them and caches their results.
Legacy analysis pass which computes a DominatorTree.
unsigned getOpcode() const
This header defines various interfaces for pass management in LLVM.
OutputIt copy(R &&Range, OutputIt Out)
const BasicBlock * getParent() const