36 using namespace llvm::PatternMatch;
38 #define DEBUG_TYPE "early-cse"
40 STATISTIC(NumSimplify,
"Number of instructions simplified or DCE'd");
41 STATISTIC(NumCSE,
"Number of instructions CSE'd");
42 STATISTIC(NumCSELoad,
"Number of load instructions CSE'd");
43 STATISTIC(NumCSECall,
"Number of call instructions CSE'd");
44 STATISTIC(NumDSE,
"Number of trivial dead stores removed");
56 assert((isSentinel() || canHandle(I)) &&
"Inst can't be handled!");
59 bool isSentinel()
const {
66 if (
CallInst *CI = dyn_cast<CallInst>(Inst))
67 return CI->doesNotAccessMemory() && !CI->getType()->isVoidTy();
68 return isa<CastInst>(Inst) || isa<BinaryOperator>(Inst) ||
69 isa<GetElementPtrInst>(Inst) || isa<CmpInst>(Inst) ||
70 isa<SelectInst>(Inst) || isa<ExtractElementInst>(Inst) ||
71 isa<InsertElementInst>(Inst) || isa<ShuffleVectorInst>(Inst) ||
72 isa<ExtractValueInst>(Inst) || isa<InsertValueInst>(Inst);
85 static unsigned getHashValue(SimpleValue Val);
86 static bool isEqual(SimpleValue LHS, SimpleValue RHS);
94 Value *LHS = BinOp->getOperand(0);
95 Value *RHS = BinOp->getOperand(1);
96 if (BinOp->isCommutative() && BinOp->getOperand(0) > BinOp->getOperand(1))
99 if (isa<OverflowingBinaryOperator>(BinOp)) {
103 BinOp->hasNoUnsignedWrap() *
105 return hash_combine(BinOp->getOpcode(), Overflow, LHS, RHS);
111 if (
CmpInst *CI = dyn_cast<CmpInst>(Inst)) {
112 Value *LHS = CI->getOperand(0);
113 Value *RHS = CI->getOperand(1);
117 Pred = CI->getSwappedPredicate();
122 if (
CastInst *CI = dyn_cast<CastInst>(Inst))
123 return hash_combine(CI->getOpcode(), CI->getType(), CI->getOperand(0));
126 return hash_combine(EVI->getOpcode(), EVI->getOperand(0),
130 return hash_combine(IVI->getOpcode(), IVI->getOperand(0),
134 assert((isa<CallInst>(Inst) || isa<BinaryOperator>(Inst) ||
135 isa<GetElementPtrInst>(Inst) || isa<SelectInst>(Inst) ||
136 isa<ExtractElementInst>(Inst) || isa<InsertElementInst>(Inst) ||
137 isa<ShuffleVectorInst>(Inst)) &&
138 "Invalid/unknown instruction");
149 if (LHS.isSentinel() || RHS.isSentinel())
152 if (LHSI->
getOpcode() != RHSI->getOpcode())
159 if (!LHSBinOp->isCommutative())
162 assert(isa<BinaryOperator>(RHSI) &&
163 "same opcode, but different instruction type?");
167 if (isa<OverflowingBinaryOperator>(LHSBinOp)) {
168 assert(isa<OverflowingBinaryOperator>(RHSBinOp) &&
169 "same opcode, but different operator type?");
176 return LHSBinOp->getOperand(0) == RHSBinOp->
getOperand(1) &&
177 LHSBinOp->getOperand(1) == RHSBinOp->
getOperand(0);
179 if (
CmpInst *LHSCmp = dyn_cast<CmpInst>(LHSI)) {
180 assert(isa<CmpInst>(RHSI) &&
181 "same opcode, but different instruction type?");
182 CmpInst *RHSCmp = cast<CmpInst>(RHSI);
185 LHSCmp->getOperand(1) == RHSCmp->
getOperand(0) &&
186 LHSCmp->getSwappedPredicate() == RHSCmp->
getPredicate();
203 assert((isSentinel() || canHandle(I)) &&
"Inst can't be handled!");
206 bool isSentinel()
const {
232 static unsigned getHashValue(CallValue Val);
233 static bool isEqual(CallValue LHS, CallValue RHS);
247 if (LHS.isSentinel() || RHS.isSentinel())
274 AllocatorTy> ScopedHTType;
282 ScopedHTType AvailableValues;
298 LoadHTType AvailableLoads;
305 CallHTType AvailableCalls;
308 unsigned CurrentGeneration;
314 : F(F), TLI(TLI), TTI(TTI), DT(DT), AC(AC), CurrentGeneration(0) {}
324 NodeScope(ScopedHTType &AvailableValues, LoadHTType &AvailableLoads,
325 CallHTType &AvailableCalls)
326 : Scope(AvailableValues), LoadScope(AvailableLoads),
327 CallScope(AvailableCalls) {}
330 NodeScope(
const NodeScope &) =
delete;
331 void operator=(
const NodeScope &) =
delete;
333 ScopedHTType::ScopeTy Scope;
334 LoadHTType::ScopeTy LoadScope;
335 CallHTType::ScopeTy CallScope;
344 StackNode(ScopedHTType &AvailableValues, LoadHTType &AvailableLoads,
345 CallHTType &AvailableCalls,
unsigned cg,
DomTreeNode *n,
347 : CurrentGeneration(cg), ChildGeneration(cg), Node(n), ChildIter(child),
348 EndIter(end), Scopes(AvailableValues, AvailableLoads, AvailableCalls),
352 unsigned currentGeneration() {
return CurrentGeneration; }
353 unsigned childGeneration() {
return ChildGeneration; }
354 void childGeneration(
unsigned generation) { ChildGeneration = generation; }
363 bool isProcessed() {
return Processed; }
364 void process() { Processed =
true; }
367 StackNode(
const StackNode &) =
delete;
368 void operator=(
const StackNode &) =
delete;
371 unsigned CurrentGeneration;
372 unsigned ChildGeneration;
382 class ParseMemoryInst {
386 MayWriteToMemory(
false), MatchingId(-1), Ptr(nullptr) {
397 MayReadFromMemory = Info.
ReadMem;
402 }
else if (
LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
404 Vol = !LI->isSimple();
405 Ptr = LI->getPointerOperand();
406 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
408 Vol = !
SI->isSimple();
409 Ptr =
SI->getPointerOperand();
412 bool isLoad() {
return Load; }
413 bool isStore() {
return Store; }
415 bool isMatchingMemLoc(
const ParseMemoryInst &Inst) {
416 return Ptr == Inst.Ptr && MatchingId == Inst.MatchingId;
418 bool isValid() {
return Ptr !=
nullptr; }
419 int getMatchingId() {
return MatchingId; }
421 bool mayReadFromMemory() {
return MayReadFromMemory; }
422 bool mayWriteToMemory() {
return MayWriteToMemory; }
428 bool MayReadFromMemory;
429 bool MayWriteToMemory;
441 if (
LoadInst *LI = dyn_cast<LoadInst>(Inst))
443 else if (
StoreInst *SI = dyn_cast<StoreInst>(Inst))
444 return SI->getValueOperand();
445 assert(isa<IntrinsicInst>(Inst) &&
"Instruction not supported");
471 if (
auto *BI = dyn_cast<BranchInst>(Pred->getTerminator()))
472 if (BI->isConditional())
473 if (
auto *CondInst = dyn_cast<Instruction>(BI->getCondition()))
474 if (SimpleValue::canHandle(CondInst)) {
475 assert(BI->getSuccessor(0) == BB || BI->getSuccessor(1) == BB);
476 auto *ConditionalConstant = (BI->getSuccessor(0) == BB) ?
479 AvailableValues.insert(CondInst, ConditionalConstant);
480 DEBUG(
dbgs() <<
"EarlyCSE CVP: Add conditional value for '"
481 << CondInst->getName() <<
"' as " << *ConditionalConstant
482 <<
" in " << BB->
getName() <<
"\n");
494 bool Changed =
false;
504 DEBUG(
dbgs() <<
"EarlyCSE DCE: " << *Inst <<
'\n');
515 if (
match(Inst, m_Intrinsic<Intrinsic::assume>())) {
516 DEBUG(
dbgs() <<
"EarlyCSE skipping assumption: " << *Inst <<
'\n');
523 DEBUG(
dbgs() <<
"EarlyCSE Simplify: " << *Inst <<
" to: " << *V <<
'\n');
532 if (SimpleValue::canHandle(Inst)) {
534 if (
Value *V = AvailableValues.lookup(Inst)) {
535 DEBUG(
dbgs() <<
"EarlyCSE CSE: " << *Inst <<
" to: " << *V <<
'\n');
544 AvailableValues.insert(Inst, Inst);
548 ParseMemoryInst MemInst(Inst, TTI);
550 if (MemInst.isValid() && MemInst.isLoad()) {
552 if (MemInst.isVolatile()) {
562 std::pair<Value *, unsigned> InVal =
563 AvailableLoads.lookup(MemInst.getPtr());
564 if (InVal.first !=
nullptr && InVal.second == CurrentGeneration) {
565 Value *Op = getOrCreateResult(InVal.first, Inst->
getType());
567 DEBUG(
dbgs() <<
"EarlyCSE CSE LOAD: " << *Inst
568 <<
" to: " << *InVal.first <<
'\n');
579 AvailableLoads.insert(MemInst.getPtr(), std::pair<Value *, unsigned>(
580 Inst, CurrentGeneration));
591 !(MemInst.isValid() && !MemInst.mayReadFromMemory()))
595 if (CallValue::canHandle(Inst)) {
598 std::pair<Value *, unsigned> InVal = AvailableCalls.lookup(Inst);
599 if (InVal.first !=
nullptr && InVal.second == CurrentGeneration) {
600 DEBUG(
dbgs() <<
"EarlyCSE CSE CALL: " << *Inst
601 <<
" to: " << *InVal.first <<
'\n');
611 AvailableCalls.insert(
612 Inst, std::pair<Value *, unsigned>(Inst, CurrentGeneration));
622 if (MemInst.isValid() && MemInst.isStore()) {
626 ParseMemoryInst LastStoreMemInst(LastStore, TTI);
627 if (LastStoreMemInst.isMatchingMemLoc(MemInst)) {
628 DEBUG(
dbgs() <<
"EarlyCSE DEAD STORE: " << *LastStore
629 <<
" due to: " << *Inst <<
'\n');
643 AvailableLoads.insert(MemInst.getPtr(), std::pair<Value *, unsigned>(
644 Inst, CurrentGeneration));
647 if (!MemInst.isVolatile())
656 bool EarlyCSE::run() {
662 std::deque<StackNode *> nodesToProcess;
664 bool Changed =
false;
667 nodesToProcess.push_back(
new StackNode(
668 AvailableValues, AvailableLoads, AvailableCalls, CurrentGeneration,
669 DT.getRootNode(), DT.getRootNode()->begin(), DT.getRootNode()->end()));
672 unsigned LiveOutGeneration = CurrentGeneration;
675 while (!nodesToProcess.empty()) {
678 StackNode *NodeToProcess = nodesToProcess.back();
681 CurrentGeneration = NodeToProcess->currentGeneration();
684 if (!NodeToProcess->isProcessed()) {
686 Changed |= processNode(NodeToProcess->node());
687 NodeToProcess->childGeneration(CurrentGeneration);
688 NodeToProcess->process();
689 }
else if (NodeToProcess->childIter() != NodeToProcess->end()) {
692 nodesToProcess.push_back(
693 new StackNode(AvailableValues, AvailableLoads, AvailableCalls,
694 NodeToProcess->childGeneration(), child, child->
begin(),
699 delete NodeToProcess;
700 nodesToProcess.pop_back();
705 CurrentGeneration = LiveOutGeneration;
717 EarlyCSE
CSE(F, TLI, TTI, DT, AC);
745 bool runOnFunction(
Function &
F)
override {
746 if (skipOptnoneFunction(F))
749 auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
750 auto &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
751 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
752 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
754 EarlyCSE
CSE(F, TLI, TTI, DT, AC);
void initializeEarlyCSELegacyPassPass(PassRegistry &)
iplist< Instruction >::iterator eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing basic block and deletes it...
A parsed version of the target data layout string in and methods for querying it. ...
const_iterator end(StringRef path)
Get end iterator over path.
static ConstantInt * getFalse(LLVMContext &Context)
static SimpleValue getTombstoneKey()
This class is the base class for the comparison instructions.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
STATISTIC(NumFunctions,"Total number of functions")
value_op_iterator value_op_begin()
CallInst - This class represents a function call, abstracting a target machine's calling convention...
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of .assume calls within a function.
Analysis pass providing the TargetTransformInfo.
static CallValue getTombstoneKey()
value_op_iterator value_op_end()
Analysis pass which computes a DominatorTree.
LoadInst - an instruction for reading from memory.
unsigned replaceDominatedUsesWith(Value *From, Value *To, DominatorTree &DT, const BasicBlockEdge &Edge)
Replace each use of 'From' with 'To' if that use is dominated by the given edge.
StringRef getName() const
Return a constant reference to the value's name.
iterator begin()
Instruction iterator methods.
bool onlyReadsMemory() const
Determine if the call does not access or only reads memory.
bool match(Val *V, const Pattern &P)
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
unsigned short MatchingId
bool isIdenticalTo(const Instruction *I) const
isIdenticalTo - Return true if the specified instruction is exactly identical to the current one...
std::vector< DomTreeNodeBase< NodeT > * >::iterator iterator
This is the base class for all instructions that perform data casts.
const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr it the function does no...
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
separate const offset from Split GEPs to a variadic base and a constant offset for better CSE
static CallValue getEmptyKey()
RecyclingAllocator - This class wraps an Allocator, adding the functionality of recycling deleted obj...
bool mayReadFromMemory() const
mayReadFromMemory - Return true if this instruction may read memory.
This file provides the interface for a simple, fast CSE pass.
Base class for the actual dominator tree node.
StoreInst - an instruction for storing to memory.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
BumpPtrAllocatorImpl BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template paramaters.
An abstract set of preserved analyses following a transformation pass run.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
static SimpleValue getEmptyKey()
Represent the analysis usage information of a pass.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
FunctionPass class - This class is used to implement most global optimizations.
Value * getOperand(unsigned i) const
FunctionPass * createEarlyCSEPass()
Predicate getPredicate() const
Return the predicate for this instruction.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses run(Function &F, AnalysisManager< Function > *AM)
Run the pass over the function.
bool hasNoSignedWrap() const
Determine whether the no signed wrap flag is set.
bool mayWriteToMemory() const
mayWriteToMemory - Return true if this instruction may modify memory.
A function analysis which provides an AssumptionCache.
static const char * getPtr(const MachOObjectFile *O, size_t Offset)
Type * getType() const
All values are typed, get the type of this value.
Provides information about what library functions are available for the current target.
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
PassT::Result & getResult(IRUnitT &IR)
Get the result of an analysis pass for this module.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
static ConstantInt * getTrue(LLVMContext &Context)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
BasicBlock * getSinglePredecessor()
Return the predecessor of this block if it has a single predecessor block.
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
void preserve()
Mark a particular pass as preserved, adding it to the set.
Analysis pass providing the TargetLibraryInfo.
LLVMContext & getContext() const
Get the context in which this basic block lives.
bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
isInstructionTriviallyDead - Return true if the result produced by the instruction is not used...
LLVM Value Representation.
bool hasNoUnsignedWrap() const
Determine whether the no unsigned wrap flag is set.
unsigned getOpcode() const
getOpcode() returns a member of one of the enums like Instruction::Add.
A generic analysis pass manager with lazy running and caching of results.
Value * SimplifyInstruction(Instruction *I, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr, const DominatorTree *DT=nullptr, AssumptionCache *AC=nullptr)
SimplifyInstruction - See if we can compute a simplified version of this instruction.
Legacy analysis pass which computes a DominatorTree.
static bool isVolatile(Instruction *Inst)
Information about a load/store intrinsic defined by the target.
IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic functions.
bool isVoidTy() const
isVoidTy - Return true if this is 'void'.
InsertValueInst - This instruction inserts a struct field of array element value into an aggregate va...