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); });
273template <
typename PredT>
275NaryReassociatePass::matchAndReassociateMinOrMax(Instruction *
I,
281 MaxMin_match<ICmpInst, bind_ty<Value>, bind_ty<Value>, PredT>(
283 if (
match(
I, MinMaxMatcher)) {
284 OrigSCEV = SE->getSCEV(
I);
286 tryReassociateMinOrMax(
I, MinMaxMatcher,
LHS,
RHS)))
289 tryReassociateMinOrMax(
I, MinMaxMatcher,
RHS,
LHS)))
295Instruction *NaryReassociatePass::tryReassociate(Instruction *
I,
298 if (!SE->isSCEVable(
I->getType()))
301 switch (
I->getOpcode()) {
302 case Instruction::Add:
303 case Instruction::Mul:
304 OrigSCEV = SE->getSCEV(
I);
306 case Instruction::GetElementPtr:
307 OrigSCEV = SE->getSCEV(
I);
318 if (
I->getType()->isIntegerTy())
319 if ((ResI = matchAndReassociateMinOrMax<umin_pred_ty>(
I, OrigSCEV)) ||
320 (ResI = matchAndReassociateMinOrMax<smin_pred_ty>(
I, OrigSCEV)) ||
321 (ResI = matchAndReassociateMinOrMax<umax_pred_ty>(
I, OrigSCEV)) ||
322 (ResI = matchAndReassociateMinOrMax<smax_pred_ty>(
I, OrigSCEV)))
331 return TTI->getGEPCost(
GEP->getSourceElementType(),
GEP->getPointerOperand(),
335Instruction *NaryReassociatePass::tryReassociateGEP(GetElementPtrInst *
GEP) {
341 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
343 if (
auto *NewGEP = tryReassociateGEPAtIndex(
GEP,
I - 1,
352bool NaryReassociatePass::requiresSignExtension(
Value *Index,
353 GetElementPtrInst *
GEP) {
354 unsigned IndexSizeInBits =
355 DL->getIndexSizeInBits(
GEP->getType()->getPointerAddressSpace());
360NaryReassociatePass::tryReassociateGEPAtIndex(GetElementPtrInst *
GEP,
361 unsigned I,
Type *IndexedType) {
362 SimplifyQuery SQ(*
DL, DT, AC,
GEP);
363 Value *IndexToSplit =
GEP->getOperand(
I + 1);
365 IndexToSplit = SExt->getOperand(0);
369 IndexToSplit = ZExt->getOperand(0);
376 if (requiresSignExtension(IndexToSplit,
GEP) &&
380 Value *
LHS = AO->getOperand(0), *
RHS = AO->getOperand(1);
382 if (
auto *NewGEP = tryReassociateGEPAtIndex(
GEP,
I,
LHS,
RHS, IndexedType))
387 tryReassociateGEPAtIndex(
GEP,
I,
RHS,
LHS, IndexedType))
395NaryReassociatePass::tryReassociateGEPAtIndex(GetElementPtrInst *
GEP,
401 for (Use &Index :
GEP->indices())
402 IndexExprs.
push_back(SE->getSCEV(Index));
404 IndexExprs[
I] = SE->getSCEV(
LHS);
405 Type *GEPArgType = SE->getEffectiveSCEVType(
GEP->getOperand(
I)->getType());
407 size_t LHSSize =
DL->getTypeSizeInBits(LHSType).getFixedValue();
408 size_t GEPArgSize =
DL->getTypeSizeInBits(GEPArgType).getFixedValue();
410 LHSSize < GEPArgSize) {
415 IndexExprs[
I] = SE->getZeroExtendExpr(IndexExprs[
I], GEPArgType);
419 Value *Candidate = findClosestMatchingDominator(CandidateExpr,
GEP);
420 if (Candidate ==
nullptr)
428 uint64_t IndexedSize =
DL->getTypeAllocSize(IndexedType);
430 uint64_t ElementSize =
DL->getTypeAllocSize(ElementType);
445 if (IndexedSize % ElementSize != 0)
449 Type *PtrIdxTy =
DL->getIndexType(
GEP->getType());
451 RHS = Builder.CreateSExtOrTrunc(
RHS, PtrIdxTy);
452 if (IndexedSize != ElementSize) {
453 RHS = Builder.CreateMul(
454 RHS, ConstantInt::get(PtrIdxTy, IndexedSize / ElementSize));
457 Builder.CreateGEP(
GEP->getResultElementType(), Candidate,
RHS));
463Instruction *NaryReassociatePass::tryReassociateBinaryOp(BinaryOperator *
I) {
466 if (SE->getSCEV(
I)->isZero())
468 if (
auto *NewI = tryReassociateBinaryOp(
LHS,
RHS,
I))
470 if (
auto *NewI = tryReassociateBinaryOp(
RHS,
LHS,
I))
477 Value *
A =
nullptr, *
B =
nullptr;
483 SCEVUse AExpr = SE->getSCEV(
A), BExpr = SE->getSCEV(
B);
484 SCEVUse RHSExpr = SE->getSCEV(
RHS);
485 if (BExpr != RHSExpr) {
487 tryReassociatedBinaryOp(getBinarySCEV(
I, AExpr, RHSExpr),
B,
I))
490 if (AExpr != RHSExpr) {
492 tryReassociatedBinaryOp(getBinarySCEV(
I, BExpr, RHSExpr),
A,
I))
499Instruction *NaryReassociatePass::tryReassociatedBinaryOp(SCEVUse LHSExpr,
504 auto *
LHS = findClosestMatchingDominator(LHSExpr,
I);
509 switch (
I->getOpcode()) {
510 case Instruction::Add:
511 NewI = BinaryOperator::CreateAdd(
LHS,
RHS,
"",
I->getIterator());
513 case Instruction::Mul:
514 NewI = BinaryOperator::CreateMul(
LHS,
RHS,
"",
I->getIterator());
524bool NaryReassociatePass::matchTernaryOp(BinaryOperator *
I,
Value *V,
526 switch (
I->getOpcode()) {
527 case Instruction::Add:
529 case Instruction::Mul:
537SCEVUse NaryReassociatePass::getBinarySCEV(BinaryOperator *
I, SCEVUse
LHS,
539 switch (
I->getOpcode()) {
540 case Instruction::Add:
541 return SE->getAddExpr(
LHS,
RHS);
542 case Instruction::Mul:
543 return SE->getMulExpr(
LHS,
RHS);
551NaryReassociatePass::findClosestMatchingDominator(SCEVUse CandidateExpr,
552 Instruction *Dominatee) {
553 auto Pos = SeenExprs.find(CandidateExpr);
554 if (Pos == SeenExprs.end())
557 auto &Candidates = Pos->second;
562 while (!Candidates.empty()) {
565 if (
Value *Candidate = Candidates.pop_back_val()) {
567 if (!DT->dominates(CandidateInstruction, Dominatee))
573 if (!SE->canReuseInstruction(CandidateExpr, CandidateInstruction,
574 DropPoisonGeneratingInsts))
577 for (Instruction *
I : DropPoisonGeneratingInsts)
578 I->dropPoisonGeneratingAnnotations();
580 return CandidateInstruction;
587 if (std::is_same_v<smax_pred_ty, typename MaxMinT::PredType>)
589 else if (std::is_same_v<umax_pred_ty, typename MaxMinT::PredType>)
591 else if (std::is_same_v<smin_pred_ty, typename MaxMinT::PredType>)
593 else if (std::is_same_v<umin_pred_ty, typename MaxMinT::PredType>)
605template <
typename MaxMinT>
606Value *NaryReassociatePass::tryReassociateMinOrMax(Instruction *
I,
609 Value *
A =
nullptr, *
B =
nullptr;
619 return U != I && !(U->hasOneUser() && *U->users().begin() == I);
623 auto tryCombination = [&](
Value *
A, SCEVUse AExpr,
Value *
B, SCEVUse BExpr,
627 SCEVUse R1Expr = SE->getMinMaxExpr(SCEVType, Ops1);
629 Instruction *R1MinMax = findClosestMatchingDominator(R1Expr,
I);
634 LLVM_DEBUG(
dbgs() <<
"NARY: Found common sub-expr: " << *R1MinMax <<
"\n");
637 SCEVUse R2Expr = SE->getMinMaxExpr(SCEVType, Ops2);
639 SCEVExpander Expander(*SE,
"nary-reassociate");
640 Value *NewMinMax = Expander.expandCodeFor(R2Expr,
I->getType(),
I);
641 NewMinMax->
setName(Twine(
I->getName()).concat(
".nary"));
644 <<
"NARY: Inserting: " << *NewMinMax <<
"\n");
648 SCEVUse AExpr = SE->getSCEV(
A);
649 SCEVUse BExpr = SE->getSCEV(
B);
650 SCEVUse RHSExpr = SE->getSCEV(
RHS);
652 if (BExpr != RHSExpr) {
654 if (
auto *NewMinMax = tryCombination(
A, AExpr,
RHS, RHSExpr,
B, BExpr))
658 if (AExpr != RHSExpr) {
660 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")
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)
static bool runImpl(Function &F, const TargetLowering &TLI, const LibcallLoweringInfo &Libcalls, AssumptionCache *AC)
Module.h This file contains the declarations for the Module class.
static SCEVTypes convertToSCEVype(MaxMinT &MM)
static bool isGEPFoldable(GetElementPtrInst *GEP, const TargetTransformInfo *TTI)
#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.
bool runImpl(Function &F, AssumptionCache *AC_, DominatorTree *DT_, ScalarEvolution *SE_, TargetLibraryInfo *TLI_, TargetTransformInfo *TTI_)
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)
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
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.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI FunctionPass * createNaryReassociatePass()
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.