117#define DEBUG_TYPE "nary-reassociate"
129 bool doInitialization(
Module &M)
override {
152char NaryReassociateLegacyPass::ID = 0;
155 "Nary reassociation",
false,
false)
165 return new NaryReassociateLegacyPass();
168bool NaryReassociateLegacyPass::runOnFunction(
Function &
F) {
172 auto *AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
173 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
174 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
175 auto *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
176 auto *
TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
178 return Impl.runImpl(
F, AC, DT, SE, TLI,
TTI);
189 if (!
runImpl(
F, AC, DT, SE, TLI, TTI))
207 DL = &
F.getDataLayout();
209 bool Changed =
false, ChangedInThisIteration;
211 ChangedInThisIteration = doOneIteration(
F);
212 Changed |= ChangedInThisIteration;
213 }
while (ChangedInThisIteration);
217bool NaryReassociatePass::doOneIteration(
Function &
F) {
228 if (
Instruction *NewI = tryReassociate(&OrigI, OrigSCEV)) {
230 OrigI.replaceAllUsesWith(NewI);
236 SCEVUse NewSCEV = SE->getSCEV(NewI);
258 if (NewSCEV != OrigSCEV)
267 DeadInsts, TLI,
nullptr, [
this](
Value *V) { SE->forgetValue(V); });
272Instruction *NaryReassociatePass::tryReassociate(Instruction *
I,
275 if (!SE->isSCEVable(
I->getType()))
278 switch (
I->getOpcode()) {
279 case Instruction::Add:
280 case Instruction::Mul:
281 OrigSCEV = SE->getSCEV(
I);
283 case Instruction::GetElementPtr:
284 OrigSCEV = SE->getSCEV(
I);
292 OrigSCEV = SE->getSCEV(
I);
303 return TTI->getGEPCost(
304 GEP->getSourceElementType(),
GEP->getPointerOperand(), Indices,
309Instruction *NaryReassociatePass::tryReassociateGEP(GetElementPtrInst *
GEP) {
315 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
317 if (
auto *NewGEP = tryReassociateGEPAtIndex(
GEP,
I - 1,
326bool NaryReassociatePass::requiresSignExtension(
Value *Index,
327 GetElementPtrInst *
GEP) {
328 unsigned IndexSizeInBits =
329 DL->getIndexSizeInBits(
GEP->getType()->getPointerAddressSpace());
334NaryReassociatePass::tryReassociateGEPAtIndex(GetElementPtrInst *
GEP,
335 unsigned I,
Type *IndexedType) {
336 SimplifyQuery SQ(*
DL, DT, AC,
GEP);
337 Value *IndexToSplit =
GEP->getOperand(
I + 1);
339 IndexToSplit = SExt->getOperand(0);
343 IndexToSplit = ZExt->getOperand(0);
350 if (requiresSignExtension(IndexToSplit,
GEP) &&
354 Value *
LHS = AO->getOperand(0), *
RHS = AO->getOperand(1);
356 if (
auto *NewGEP = tryReassociateGEPAtIndex(
GEP,
I,
LHS,
RHS, IndexedType))
361 tryReassociateGEPAtIndex(
GEP,
I,
RHS,
LHS, IndexedType))
369NaryReassociatePass::tryReassociateGEPAtIndex(GetElementPtrInst *
GEP,
375 for (Use &Index :
GEP->indices())
376 IndexExprs.
push_back(SE->getSCEV(Index));
378 IndexExprs[
I] = SE->getSCEV(
LHS);
379 Type *GEPArgType = SE->getEffectiveSCEVType(
GEP->getOperand(
I)->getType());
381 size_t LHSSize =
DL->getTypeSizeInBits(LHSType).getFixedValue();
382 size_t GEPArgSize =
DL->getTypeSizeInBits(GEPArgType).getFixedValue();
384 LHSSize < GEPArgSize) {
389 IndexExprs[
I] = SE->getZeroExtendExpr(IndexExprs[
I], GEPArgType);
393 Value *Candidate = findClosestMatchingDominator(CandidateExpr,
GEP);
394 if (Candidate ==
nullptr)
402 uint64_t IndexedSize =
DL->getTypeAllocSize(IndexedType);
404 uint64_t ElementSize =
DL->getTypeAllocSize(ElementType);
419 if (ElementSize == 0 || IndexedSize % ElementSize != 0)
423 Type *PtrIdxTy =
DL->getIndexType(
GEP->getType());
425 RHS = Builder.CreateSExtOrTrunc(
RHS, PtrIdxTy);
426 if (IndexedSize != ElementSize) {
427 RHS = Builder.CreateMul(
428 RHS, ConstantInt::get(PtrIdxTy, IndexedSize / ElementSize));
431 Builder.CreateGEP(
GEP->getResultElementType(), Candidate,
RHS));
437Instruction *NaryReassociatePass::tryReassociateBinaryOp(BinaryOperator *
I) {
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;
457 SCEVUse AExpr = SE->getSCEV(
A), BExpr = SE->getSCEV(
B);
459 if (BExpr != RHSExpr) {
461 tryReassociatedBinaryOp(getBinarySCEV(
I, AExpr, RHSExpr),
B,
I))
464 if (AExpr != RHSExpr) {
466 tryReassociatedBinaryOp(getBinarySCEV(
I, BExpr, RHSExpr),
A,
I))
478 auto *
LHS = findClosestMatchingDominator(LHSExpr,
I);
483 switch (
I->getOpcode()) {
484 case Instruction::Add:
485 NewI = BinaryOperator::CreateAdd(
LHS,
RHS,
"",
I->getIterator());
487 case Instruction::Mul:
488 NewI = BinaryOperator::CreateMul(
LHS,
RHS,
"",
I->getIterator());
498bool NaryReassociatePass::matchTernaryOp(BinaryOperator *
I,
Value *V,
500 switch (
I->getOpcode()) {
501 case Instruction::Add:
503 case Instruction::Mul:
513 switch (
I->getOpcode()) {
514 case Instruction::Add:
515 return SE->getAddExpr(
LHS,
RHS);
516 case Instruction::Mul:
517 return SE->getMulExpr(
LHS,
RHS);
525NaryReassociatePass::findClosestMatchingDominator(
SCEVUse CandidateExpr,
526 Instruction *Dominatee) {
527 auto Pos = SeenExprs.find(CandidateExpr);
528 if (Pos == SeenExprs.end())
531 auto &Candidates = Pos->second;
536 while (!Candidates.empty()) {
539 if (
Value *Candidate = Candidates.pop_back_val()) {
541 if (!DT->dominates(CandidateInstruction, Dominatee))
546 SmallVector<Instruction *> DropPoisonGeneratingInsts;
547 if (!SE->canReuseInstruction(CandidateExpr, CandidateInstruction,
548 DropPoisonGeneratingInsts))
551 for (Instruction *
I : DropPoisonGeneratingInsts)
552 I->dropPoisonGeneratingAnnotations();
554 return CandidateInstruction;
562 case Intrinsic::smax:
564 case Intrinsic::umax:
566 case Intrinsic::smin:
568 case Intrinsic::umin:
576Value *NaryReassociatePass::tryReassociateMinOrMax(IntrinsicInst *
I) {
580 RHSI && RHSI->getIntrinsicID() ==
I->getIntrinsicID())
583 if (!LHSI || LHSI->getIntrinsicID() !=
I->getIntrinsicID())
586 Value *
A = LHSI->getArgOperand(0), *
B = LHSI->getArgOperand(1);
592 return U != I && !(U->hasOneUser() && *U->users().begin() == I);
600 SCEVUse R1Expr = SE->getMinMaxExpr(SCEVType, Ops1);
602 Instruction *R1MinMax = findClosestMatchingDominator(R1Expr,
I);
607 LLVM_DEBUG(
dbgs() <<
"NARY: Found common sub-expr: " << *R1MinMax <<
"\n");
610 SCEVUse R2Expr = SE->getMinMaxExpr(SCEVType, Ops2);
612 SCEVExpander Expander(*SE,
"nary-reassociate");
613 Value *NewMinMax = Expander.expandCodeFor(R2Expr,
I->getType(),
I);
614 NewMinMax->
setName(Twine(
I->getName()).concat(
".nary"));
617 <<
"NARY: Inserting: " << *NewMinMax <<
"\n");
625 if (BExpr != RHSExpr) {
627 if (
auto *NewMinMax = tryCombination(
A, AExpr,
RHS, RHSExpr,
B, BExpr))
631 if (AExpr != RHSExpr) {
633 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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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.
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.