117#define DEBUG_TYPE "nary-reassociate"
129 bool doInitialization(
Module &M)
override {
153char NaryReassociateLegacyPass::ID = 0;
156 "Nary reassociation",
false,
false)
166 return new NaryReassociateLegacyPass();
169bool NaryReassociateLegacyPass::runOnFunction(
Function &
F) {
173 auto *AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
174 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
175 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
176 auto *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
177 auto *
TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
179 return Impl.runImpl(
F, AC, DT, SE, TLI,
TTI);
190 if (!
runImpl(
F, AC, DT, SE, TLI, TTI))
208 DL = &
F.getDataLayout();
210 bool Changed =
false, ChangedInThisIteration;
212 ChangedInThisIteration = doOneIteration(
F);
213 Changed |= ChangedInThisIteration;
214 }
while (ChangedInThisIteration);
218bool NaryReassociatePass::doOneIteration(
Function &
F) {
229 if (
Instruction *NewI = tryReassociate(&OrigI, OrigSCEV)) {
231 OrigI.replaceAllUsesWith(NewI);
237 SCEVUse NewSCEV = SE->getSCEV(NewI);
259 if (NewSCEV != OrigSCEV)
268 DeadInsts, TLI,
nullptr, [
this](
Value *V) { SE->forgetValue(V); });
273Instruction *NaryReassociatePass::tryReassociate(Instruction *
I,
276 if (!SE->isSCEVable(
I->getType()))
279 switch (
I->getOpcode()) {
280 case Instruction::Add:
281 case Instruction::Mul:
282 OrigSCEV = SE->getSCEV(
I);
284 case Instruction::GetElementPtr:
285 OrigSCEV = SE->getSCEV(
I);
293 OrigSCEV = SE->getSCEV(
I);
304 return TTI->getGEPCost(
GEP->getSourceElementType(),
GEP->getPointerOperand(),
308Instruction *NaryReassociatePass::tryReassociateGEP(GetElementPtrInst *
GEP) {
314 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
316 if (
auto *NewGEP = tryReassociateGEPAtIndex(
GEP,
I - 1,
325bool NaryReassociatePass::requiresSignExtension(
Value *Index,
326 GetElementPtrInst *
GEP) {
327 unsigned IndexSizeInBits =
328 DL->getIndexSizeInBits(
GEP->getType()->getPointerAddressSpace());
333NaryReassociatePass::tryReassociateGEPAtIndex(GetElementPtrInst *
GEP,
334 unsigned I,
Type *IndexedType) {
335 SimplifyQuery SQ(*
DL, DT, AC,
GEP);
336 Value *IndexToSplit =
GEP->getOperand(
I + 1);
338 IndexToSplit = SExt->getOperand(0);
342 IndexToSplit = ZExt->getOperand(0);
349 if (requiresSignExtension(IndexToSplit,
GEP) &&
353 Value *
LHS = AO->getOperand(0), *
RHS = AO->getOperand(1);
355 if (
auto *NewGEP = tryReassociateGEPAtIndex(
GEP,
I,
LHS,
RHS, IndexedType))
360 tryReassociateGEPAtIndex(
GEP,
I,
RHS,
LHS, IndexedType))
368NaryReassociatePass::tryReassociateGEPAtIndex(GetElementPtrInst *
GEP,
374 for (Use &Index :
GEP->indices())
375 IndexExprs.
push_back(SE->getSCEV(Index));
377 IndexExprs[
I] = SE->getSCEV(
LHS);
378 Type *GEPArgType = SE->getEffectiveSCEVType(
GEP->getOperand(
I)->getType());
380 size_t LHSSize =
DL->getTypeSizeInBits(LHSType).getFixedValue();
381 size_t GEPArgSize =
DL->getTypeSizeInBits(GEPArgType).getFixedValue();
383 LHSSize < GEPArgSize) {
388 IndexExprs[
I] = SE->getZeroExtendExpr(IndexExprs[
I], GEPArgType);
392 Value *Candidate = findClosestMatchingDominator(CandidateExpr,
GEP);
393 if (Candidate ==
nullptr)
401 uint64_t IndexedSize =
DL->getTypeAllocSize(IndexedType);
403 uint64_t ElementSize =
DL->getTypeAllocSize(ElementType);
418 if (ElementSize == 0 || IndexedSize % ElementSize != 0)
422 Type *PtrIdxTy =
DL->getIndexType(
GEP->getType());
424 RHS = Builder.CreateSExtOrTrunc(
RHS, PtrIdxTy);
425 if (IndexedSize != ElementSize) {
426 RHS = Builder.CreateMul(
427 RHS, ConstantInt::get(PtrIdxTy, IndexedSize / ElementSize));
430 Builder.CreateGEP(
GEP->getResultElementType(), Candidate,
RHS));
436Instruction *NaryReassociatePass::tryReassociateBinaryOp(BinaryOperator *
I) {
439 if (SE->getSCEV(
I)->isZero())
441 if (
auto *NewI = tryReassociateBinaryOp(
LHS,
RHS,
I))
443 if (
auto *NewI = tryReassociateBinaryOp(
RHS,
LHS,
I))
450 Value *
A =
nullptr, *
B =
nullptr;
456 SCEVUse AExpr = SE->getSCEV(
A), BExpr = SE->getSCEV(
B);
458 if (BExpr != RHSExpr) {
460 tryReassociatedBinaryOp(getBinarySCEV(
I, AExpr, RHSExpr),
B,
I))
463 if (AExpr != RHSExpr) {
465 tryReassociatedBinaryOp(getBinarySCEV(
I, BExpr, RHSExpr),
A,
I))
477 auto *
LHS = findClosestMatchingDominator(LHSExpr,
I);
482 switch (
I->getOpcode()) {
483 case Instruction::Add:
484 NewI = BinaryOperator::CreateAdd(
LHS,
RHS,
"",
I->getIterator());
486 case Instruction::Mul:
487 NewI = BinaryOperator::CreateMul(
LHS,
RHS,
"",
I->getIterator());
497bool NaryReassociatePass::matchTernaryOp(BinaryOperator *
I,
Value *V,
499 switch (
I->getOpcode()) {
500 case Instruction::Add:
502 case Instruction::Mul:
512 switch (
I->getOpcode()) {
513 case Instruction::Add:
514 return SE->getAddExpr(
LHS,
RHS);
515 case Instruction::Mul:
516 return SE->getMulExpr(
LHS,
RHS);
524NaryReassociatePass::findClosestMatchingDominator(
SCEVUse CandidateExpr,
525 Instruction *Dominatee) {
526 auto Pos = SeenExprs.find(CandidateExpr);
527 if (Pos == SeenExprs.end())
530 auto &Candidates = Pos->second;
535 while (!Candidates.empty()) {
538 if (
Value *Candidate = Candidates.pop_back_val()) {
540 if (!DT->dominates(CandidateInstruction, Dominatee))
546 if (!SE->canReuseInstruction(CandidateExpr, CandidateInstruction,
547 DropPoisonGeneratingInsts))
550 for (Instruction *
I : DropPoisonGeneratingInsts)
551 I->dropPoisonGeneratingAnnotations();
553 return CandidateInstruction;
561 case Intrinsic::smax:
563 case Intrinsic::umax:
565 case Intrinsic::smin:
567 case Intrinsic::umin:
575Value *NaryReassociatePass::tryReassociateMinOrMax(IntrinsicInst *
I) {
579 RHSI && RHSI->getIntrinsicID() ==
I->getIntrinsicID())
582 if (!LHSI || LHSI->getIntrinsicID() !=
I->getIntrinsicID())
585 Value *
A = LHSI->getArgOperand(0), *
B = LHSI->getArgOperand(1);
591 return U != I && !(U->hasOneUser() && *U->users().begin() == I);
599 SCEVUse R1Expr = SE->getMinMaxExpr(SCEVType, Ops1);
601 Instruction *R1MinMax = findClosestMatchingDominator(R1Expr,
I);
606 LLVM_DEBUG(
dbgs() <<
"NARY: Found common sub-expr: " << *R1MinMax <<
"\n");
609 SCEVUse R2Expr = SE->getMinMaxExpr(SCEVType, Ops2);
611 SCEVExpander Expander(*SE,
"nary-reassociate");
612 Value *NewMinMax = Expander.expandCodeFor(R2Expr,
I->getType(),
I);
613 NewMinMax->
setName(Twine(
I->getName()).concat(
".nary"));
616 <<
"NARY: Inserting: " << *NewMinMax <<
"\n");
624 if (BExpr != RHSExpr) {
626 if (
auto *NewMinMax = tryCombination(
A, AExpr,
RHS, RHSExpr,
B, BExpr))
630 if (AExpr != RHSExpr) {
632 if (
auto *NewMinMax = tryCombination(
RHS, RHSExpr,
B, BExpr,
A, AExpr))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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")
static bool runImpl(MachineFunction &MF)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
static bool isGEPFoldable(GetElementPtrInst *GEP, const TargetTransformInfo *TTI)
static SCEVTypes convertToSCEVType(Intrinsic::ID IntrinID)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the SmallVector class.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
Represents analyses that only rely on functions' control flow.
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
FunctionPass class - This class is used to implement most global optimizations.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
LLVM_ABI void setIsInBounds(bool b=true)
Set or clear the inbounds flag on this GEP instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
A Module instance is used to store all the information related to an LLVM module.
LLVM_ABI bool runImpl(Function &F, AssumptionCache *AC_, DominatorTree *DT_, ScalarEvolution *SE_, TargetLibraryInfo *TLI_, TargetTransformInfo *TTI_)
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
iterator_range< user_iterator > users()
LLVM_ABI bool hasNUsesOrMore(unsigned N) const
Return true if this value has N uses or more.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Value handle that is nullable, but tries to track the Value.
bool isSequential() const
Type * getIndexedType() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
auto m_MaxOrMin(const Opnd0 &Op0, const Opnd1 &Op1)
ElementType
The element type of an SRV or UAV resource.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI FunctionPass * createNaryReassociatePass()
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
generic_gep_type_iterator<> gep_type_iterator
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI OverflowResult computeOverflowForSignedAdd(const WithCache< const Value * > &LHS, const WithCache< const Value * > &RHS, const SimplifyQuery &SQ)
LLVM_ABI void initializeNaryReassociateLegacyPassPass(PassRegistry &)
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructionsPermissive(SmallVectorImpl< WeakTrackingVH > &DeadInsts, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
Same functionality as RecursivelyDeleteTriviallyDeadInstructions, but allow instructions that are not...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
gep_type_iterator gep_type_begin(const User *GEP)
iterator_range< df_iterator< T > > depth_first(const T &G)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI bool isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the give value is known to be non-negative.
SCEVUseT< const SCEV * > SCEVUse
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.