112 using namespace llvm;
115 #define DEBUG_TYPE "nary-reassociate" 127 bool doInitialization(
Module &M)
override {
154 "Nary reassociation",
false,
false)
164 return new NaryReassociateLegacyPass();
171 auto *AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
172 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
173 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
174 auto *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
175 auto *TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
177 return Impl.runImpl(F, AC, DT, SE, TLI, TTI);
188 if (!
runImpl(F, AC, DT, SE, TLI, TTI))
208 bool Changed =
false, ChangedInThisIteration;
210 ChangedInThisIteration = doOneIteration(F);
211 Changed |= ChangedInThisIteration;
212 }
while (ChangedInThisIteration);
220 case Instruction::GetElementPtr:
221 case Instruction::Mul:
228 bool NaryReassociatePass::doOneIteration(
Function &F) {
229 bool Changed =
false;
238 const SCEV *OldSCEV = SE->getSCEV(&*
I);
241 SE->forgetValue(&*
I);
242 I->replaceAllUsesWith(NewI);
254 I = NewI->getIterator();
258 const SCEV *NewSCEV = SE->getSCEV(&*
I);
278 if (NewSCEV != OldSCEV)
289 case Instruction::Mul:
290 return tryReassociateBinaryOp(cast<BinaryOperator>(I));
291 case Instruction::GetElementPtr:
292 return tryReassociateGEP(cast<GetElementPtrInst>(I));
294 llvm_unreachable(
"should be filtered out by isPotentiallyNaryReassociable");
315 if (
auto *NewGEP = tryReassociateGEPAtIndex(GEP, I - 1,
324 bool NaryReassociatePass::requiresSignExtension(
Value *
Index,
326 unsigned PointerSizeInBits =
333 unsigned I,
Type *IndexedType) {
335 if (
SExtInst *SExt = dyn_cast<SExtInst>(IndexToSplit)) {
336 IndexToSplit = SExt->getOperand(0);
337 }
else if (
ZExtInst *ZExt = dyn_cast<ZExtInst>(IndexToSplit)) {
340 IndexToSplit = ZExt->getOperand(0);
343 if (
AddOperator *AO = dyn_cast<AddOperator>(IndexToSplit)) {
347 if (requiresSignExtension(IndexToSplit, GEP) &&
352 Value *LHS = AO->getOperand(0), *RHS = AO->getOperand(1);
354 if (
auto *NewGEP = tryReassociateGEPAtIndex(GEP, I, LHS, RHS, IndexedType))
359 tryReassociateGEPAtIndex(GEP, I, RHS, LHS, IndexedType))
368 unsigned I,
Value *LHS,
374 IndexExprs.
push_back(SE->getSCEV(*Index));
376 IndexExprs[
I] = SE->getSCEV(LHS);
378 DL->getTypeSizeInBits(LHS->
getType()) <
387 const SCEV *CandidateExpr = SE->getGEPExpr(cast<GEPOperator>(GEP),
390 Value *Candidate = findClosestMatchingDominator(CandidateExpr, GEP);
391 if (Candidate ==
nullptr)
402 uint64_t IndexedSize = DL->getTypeAllocSize(IndexedType);
404 uint64_t ElementSize = DL->getTypeAllocSize(ElementType);
419 if (IndexedSize % ElementSize != 0)
423 Type *IntPtrTy = DL->getIntPtrType(GEP->
getType());
424 if (RHS->
getType() != IntPtrTy)
426 if (IndexedSize != ElementSize) {
431 cast<GetElementPtrInst>(Builder.
CreateGEP(Candidate, RHS));
440 if (SE->getSCEV(I)->isZero())
442 if (
auto *NewI = tryReassociateBinaryOp(LHS, RHS, I))
444 if (
auto *NewI = tryReassociateBinaryOp(RHS, LHS, I))
451 Value *A =
nullptr, *
B =
nullptr;
454 if (LHS->
hasOneUse() && matchTernaryOp(I, LHS, A,
B)) {
457 const SCEV *AExpr = SE->getSCEV(A), *BExpr = SE->getSCEV(
B);
458 const SCEV *RHSExpr = SE->getSCEV(RHS);
459 if (BExpr != RHSExpr) {
461 tryReassociatedBinaryOp(getBinarySCEV(I, AExpr, RHSExpr),
B, I))
464 if (AExpr != RHSExpr) {
466 tryReassociatedBinaryOp(getBinarySCEV(I, BExpr, RHSExpr), A, I))
473 Instruction *NaryReassociatePass::tryReassociatedBinaryOp(
const SCEV *LHSExpr,
478 auto *LHS = findClosestMatchingDominator(LHSExpr, I);
487 case Instruction::Mul:
502 case Instruction::Mul:
515 return SE->getAddExpr(LHS, RHS);
516 case Instruction::Mul:
517 return SE->getMulExpr(LHS, RHS);
525 NaryReassociatePass::findClosestMatchingDominator(
const SCEV *CandidateExpr,
527 auto Pos = SeenExprs.find(CandidateExpr);
528 if (Pos == SeenExprs.end())
531 auto &Candidates = Pos->second;
536 while (!Candidates.empty()) {
540 if (
Value *Candidate = Candidates.back()) {
541 Instruction *CandidateInstruction = cast<Instruction>(Candidate);
542 if (DT->dominates(CandidateInstruction, Dominatee))
543 return CandidateInstruction;
545 Candidates.pop_back();
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
Value * getPointerOperand()
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
static bool runImpl(Function &F, TargetLibraryInfo &TLI, DominatorTree &DT)
This is the entry point for all transforms.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
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.
BinaryOps getOpcode() const
A Module instance is used to store all the information related to an LLVM module. ...
This class represents zero extension of integer types.
void push_back(const T &Elt)
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
The main scalar evolution driver.
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of @llvm.assume calls within a function.
Analysis pass providing the TargetTransformInfo.
Analysis pass which computes a DominatorTree.
This class represents a sign extension of integer types.
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
iterator begin()
Instruction iterator methods.
bool match(Val *V, const Pattern &P)
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
void setIsInBounds(bool b=true)
Set or clear the inbounds flag on this GEP instruction.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Type * getSourceElementType() const
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
Type * getType() const
All values are typed, get the type of this value.
Value handle that is nullable, but tries to track the Value.
Value * CreateSExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a SExt or Trunc from the integer value V to DestTy.
bool isInBounds() const
Determine whether the GEP has the inbounds flag.
A nullable Value handle that is nullable.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
bool isKnownNonNegative(const Value *V, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true)
Returns true if the give value is known to be non-negative.
void takeName(Value *V)
Transfer the name from V to this value.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
static BinaryOperator * CreateAdd(Value *S1, Value *S2, const Twine &Name, Instruction *InsertBefore, Value *FlagsOp)
Value * getOperand(unsigned i) const
INITIALIZE_PASS_BEGIN(NaryReassociateLegacyPass, "nary-reassociate", "Nary reassociation", false, false) INITIALIZE_PASS_END(NaryReassociateLegacyPass
an instruction for type-safe pointer arithmetic to access elements of arrays and structs ...
static bool runOnFunction(Function &F, bool PostInlining)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
OverflowResult computeOverflowForSignedAdd(const Value *LHS, const Value *RHS, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr)
A set of analyses that are preserved following a run of a transformation pass.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr)
If the specified value is a trivially dead instruction, delete it.
Type * getIndexedType() const
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateGEP(Value *Ptr, ArrayRef< Value *> IdxList, const Twine &Name="")
A function analysis which provides an AssumptionCache.
unsigned getNumOperands() const
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Provides information about what library functions are available for the current target.
bool runImpl(Function &F, AssumptionCache *AC_, DominatorTree *DT_, ScalarEvolution *SE_, TargetLibraryInfo *TLI_, TargetTransformInfo *TTI_)
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:
Represents analyses that only rely on functions' control flow.
bool isSequential() const
Analysis pass that exposes the ScalarEvolution for a function.
Value * CreateBitOrPointerCast(Value *V, Type *DestTy, const Twine &Name="")
This class represents an analyzed expression in the program.
void preserveSet()
Mark an analysis set as preserved.
Type * getResultElementType() const
void initializeNaryReassociateLegacyPassPass(PassRegistry &)
void preserve()
Mark an analysis as preserved.
Analysis pass providing the TargetLibraryInfo.
iterator_range< df_iterator< T > > depth_first(const T &G)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
static bool isPotentiallyNaryReassociable(Instruction *I)
static bool isGEPFoldable(GetElementPtrInst *GEP, const TargetTransformInfo *TTI)
bool hasOneUse() const
Return true if there is exactly one user of this value.
A container for analyses that lazily runs them and caches their results.
Legacy analysis pass which computes a DominatorTree.
static BinaryOperator * CreateMul(Value *S1, Value *S2, const Twine &Name, Instruction *InsertBefore, Value *FlagsOp)
FunctionPass * createNaryReassociatePass()
gep_type_iterator gep_type_begin(const User *GEP)