1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125 |
- #include "llvm/Transforms/Scalar/IndVarSimplify.h"
- #include "llvm/ADT/APFloat.h"
- #include "llvm/ADT/APInt.h"
- #include "llvm/ADT/ArrayRef.h"
- #include "llvm/ADT/DenseMap.h"
- #include "llvm/ADT/None.h"
- #include "llvm/ADT/Optional.h"
- #include "llvm/ADT/STLExtras.h"
- #include "llvm/ADT/SmallPtrSet.h"
- #include "llvm/ADT/SmallSet.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/Statistic.h"
- #include "llvm/ADT/iterator_range.h"
- #include "llvm/Analysis/LoopInfo.h"
- #include "llvm/Analysis/LoopPass.h"
- #include "llvm/Analysis/MemorySSA.h"
- #include "llvm/Analysis/MemorySSAUpdater.h"
- #include "llvm/Analysis/ScalarEvolution.h"
- #include "llvm/Analysis/ScalarEvolutionExpressions.h"
- #include "llvm/Analysis/TargetLibraryInfo.h"
- #include "llvm/Analysis/TargetTransformInfo.h"
- #include "llvm/Analysis/ValueTracking.h"
- #include "llvm/IR/BasicBlock.h"
- #include "llvm/IR/Constant.h"
- #include "llvm/IR/ConstantRange.h"
- #include "llvm/IR/Constants.h"
- #include "llvm/IR/DataLayout.h"
- #include "llvm/IR/DerivedTypes.h"
- #include "llvm/IR/Dominators.h"
- #include "llvm/IR/Function.h"
- #include "llvm/IR/IRBuilder.h"
- #include "llvm/IR/InstrTypes.h"
- #include "llvm/IR/Instruction.h"
- #include "llvm/IR/Instructions.h"
- #include "llvm/IR/IntrinsicInst.h"
- #include "llvm/IR/Intrinsics.h"
- #include "llvm/IR/Module.h"
- #include "llvm/IR/Operator.h"
- #include "llvm/IR/PassManager.h"
- #include "llvm/IR/PatternMatch.h"
- #include "llvm/IR/Type.h"
- #include "llvm/IR/Use.h"
- #include "llvm/IR/User.h"
- #include "llvm/IR/Value.h"
- #include "llvm/IR/ValueHandle.h"
- #include "llvm/InitializePasses.h"
- #include "llvm/Pass.h"
- #include "llvm/Support/Casting.h"
- #include "llvm/Support/CommandLine.h"
- #include "llvm/Support/Compiler.h"
- #include "llvm/Support/Debug.h"
- #include "llvm/Support/ErrorHandling.h"
- #include "llvm/Support/MathExtras.h"
- #include "llvm/Support/raw_ostream.h"
- #include "llvm/Transforms/Scalar.h"
- #include "llvm/Transforms/Scalar/LoopPassManager.h"
- #include "llvm/Transforms/Utils/BasicBlockUtils.h"
- #include "llvm/Transforms/Utils/Local.h"
- #include "llvm/Transforms/Utils/LoopUtils.h"
- #include "llvm/Transforms/Utils/ScalarEvolutionExpander.h"
- #include "llvm/Transforms/Utils/SimplifyIndVar.h"
- #include <cassert>
- #include <cstdint>
- #include <utility>
- using namespace llvm;
- using namespace PatternMatch;
- #define DEBUG_TYPE "indvars"
- STATISTIC(NumWidened , "Number of indvars widened");
- STATISTIC(NumReplaced , "Number of exit values replaced");
- STATISTIC(NumLFTR , "Number of loop exit tests replaced");
- STATISTIC(NumElimExt , "Number of IV sign/zero extends eliminated");
- STATISTIC(NumElimIV , "Number of congruent IVs eliminated");
- static cl::opt<bool> VerifyIndvars(
- "verify-indvars", cl::Hidden,
- cl::desc("Verify the ScalarEvolution result after running indvars. Has no "
- "effect in release builds. (Note: this adds additional SCEV "
- "queries potentially changing the analysis result)"));
- static cl::opt<ReplaceExitVal> ReplaceExitValue(
- "replexitval", cl::Hidden, cl::init(OnlyCheapRepl),
- cl::desc("Choose the strategy to replace exit value in IndVarSimplify"),
- cl::values(clEnumValN(NeverRepl, "never", "never replace exit value"),
- clEnumValN(OnlyCheapRepl, "cheap",
- "only replace exit value when the cost is cheap"),
- clEnumValN(NoHardUse, "noharduse",
- "only replace exit values when loop def likely dead"),
- clEnumValN(AlwaysRepl, "always",
- "always replace exit value whenever possible")));
- static cl::opt<bool> UsePostIncrementRanges(
- "indvars-post-increment-ranges", cl::Hidden,
- cl::desc("Use post increment control-dependent ranges in IndVarSimplify"),
- cl::init(true));
- static cl::opt<bool>
- DisableLFTR("disable-lftr", cl::Hidden, cl::init(false),
- cl::desc("Disable Linear Function Test Replace optimization"));
- static cl::opt<bool>
- LoopPredication("indvars-predicate-loops", cl::Hidden, cl::init(true),
- cl::desc("Predicate conditions in read only loops"));
- static cl::opt<bool>
- AllowIVWidening("indvars-widen-indvars", cl::Hidden, cl::init(true),
- cl::desc("Allow widening of indvars to eliminate s/zext"));
- namespace {
- class IndVarSimplify {
- LoopInfo *LI;
- ScalarEvolution *SE;
- DominatorTree *DT;
- const DataLayout &DL;
- TargetLibraryInfo *TLI;
- const TargetTransformInfo *TTI;
- std::unique_ptr<MemorySSAUpdater> MSSAU;
- SmallVector<WeakTrackingVH, 16> DeadInsts;
- bool WidenIndVars;
- bool handleFloatingPointIV(Loop *L, PHINode *PH);
- bool rewriteNonIntegerIVs(Loop *L);
- bool simplifyAndExtend(Loop *L, SCEVExpander &Rewriter, LoopInfo *LI);
-
-
-
- bool canonicalizeExitCondition(Loop *L);
-
- bool optimizeLoopExits(Loop *L, SCEVExpander &Rewriter);
-
-
- bool predicateLoopExits(Loop *L, SCEVExpander &Rewriter);
- bool rewriteFirstIterationLoopExitValues(Loop *L);
- bool linearFunctionTestReplace(Loop *L, BasicBlock *ExitingBB,
- const SCEV *ExitCount,
- PHINode *IndVar, SCEVExpander &Rewriter);
- bool sinkUnusedInvariants(Loop *L);
- public:
- IndVarSimplify(LoopInfo *LI, ScalarEvolution *SE, DominatorTree *DT,
- const DataLayout &DL, TargetLibraryInfo *TLI,
- TargetTransformInfo *TTI, MemorySSA *MSSA, bool WidenIndVars)
- : LI(LI), SE(SE), DT(DT), DL(DL), TLI(TLI), TTI(TTI),
- WidenIndVars(WidenIndVars) {
- if (MSSA)
- MSSAU = std::make_unique<MemorySSAUpdater>(MSSA);
- }
- bool run(Loop *L);
- };
- }
- static bool ConvertToSInt(const APFloat &APF, int64_t &IntVal) {
- bool isExact = false;
-
- uint64_t UIntVal;
- if (APF.convertToInteger(makeMutableArrayRef(UIntVal), 64, true,
- APFloat::rmTowardZero, &isExact) != APFloat::opOK ||
- !isExact)
- return false;
- IntVal = UIntVal;
- return true;
- }
- bool IndVarSimplify::handleFloatingPointIV(Loop *L, PHINode *PN) {
- unsigned IncomingEdge = L->contains(PN->getIncomingBlock(0));
- unsigned BackEdge = IncomingEdge^1;
-
- auto *InitValueVal = dyn_cast<ConstantFP>(PN->getIncomingValue(IncomingEdge));
- int64_t InitValue;
- if (!InitValueVal || !ConvertToSInt(InitValueVal->getValueAPF(), InitValue))
- return false;
-
-
- auto *Incr = dyn_cast<BinaryOperator>(PN->getIncomingValue(BackEdge));
- if (Incr == nullptr || Incr->getOpcode() != Instruction::FAdd) return false;
-
-
- ConstantFP *IncValueVal = dyn_cast<ConstantFP>(Incr->getOperand(1));
- int64_t IncValue;
- if (IncValueVal == nullptr || Incr->getOperand(0) != PN ||
- !ConvertToSInt(IncValueVal->getValueAPF(), IncValue))
- return false;
-
-
- Value::user_iterator IncrUse = Incr->user_begin();
- Instruction *U1 = cast<Instruction>(*IncrUse++);
- if (IncrUse == Incr->user_end()) return false;
- Instruction *U2 = cast<Instruction>(*IncrUse++);
- if (IncrUse != Incr->user_end()) return false;
-
-
- FCmpInst *Compare = dyn_cast<FCmpInst>(U1);
- if (!Compare)
- Compare = dyn_cast<FCmpInst>(U2);
- if (!Compare || !Compare->hasOneUse() ||
- !isa<BranchInst>(Compare->user_back()))
- return false;
- BranchInst *TheBr = cast<BranchInst>(Compare->user_back());
-
-
-
-
- assert(TheBr->isConditional() && "Can't use fcmp if not conditional");
- if (!L->contains(TheBr->getParent()) ||
- (L->contains(TheBr->getSuccessor(0)) &&
- L->contains(TheBr->getSuccessor(1))))
- return false;
-
-
- ConstantFP *ExitValueVal = dyn_cast<ConstantFP>(Compare->getOperand(1));
- int64_t ExitValue;
- if (ExitValueVal == nullptr ||
- !ConvertToSInt(ExitValueVal->getValueAPF(), ExitValue))
- return false;
-
- CmpInst::Predicate NewPred = CmpInst::BAD_ICMP_PREDICATE;
- switch (Compare->getPredicate()) {
- default: return false;
- case CmpInst::FCMP_OEQ:
- case CmpInst::FCMP_UEQ: NewPred = CmpInst::ICMP_EQ; break;
- case CmpInst::FCMP_ONE:
- case CmpInst::FCMP_UNE: NewPred = CmpInst::ICMP_NE; break;
- case CmpInst::FCMP_OGT:
- case CmpInst::FCMP_UGT: NewPred = CmpInst::ICMP_SGT; break;
- case CmpInst::FCMP_OGE:
- case CmpInst::FCMP_UGE: NewPred = CmpInst::ICMP_SGE; break;
- case CmpInst::FCMP_OLT:
- case CmpInst::FCMP_ULT: NewPred = CmpInst::ICMP_SLT; break;
- case CmpInst::FCMP_OLE:
- case CmpInst::FCMP_ULE: NewPred = CmpInst::ICMP_SLE; break;
- }
-
-
-
-
-
-
- if (!isInt<32>(InitValue) || !isInt<32>(IncValue) || !isInt<32>(ExitValue))
- return false;
-
- if (IncValue == 0)
- return false;
-
- if (IncValue > 0) {
-
-
- if (InitValue >= ExitValue)
- return false;
- uint32_t Range = uint32_t(ExitValue-InitValue);
-
-
- if (NewPred == CmpInst::ICMP_SLE || NewPred == CmpInst::ICMP_SGT) {
- if (++Range == 0) return false;
- }
- unsigned Leftover = Range % uint32_t(IncValue);
-
-
-
- if ((NewPred == CmpInst::ICMP_EQ || NewPred == CmpInst::ICMP_NE) &&
- Leftover != 0)
- return false;
-
-
- if (Leftover != 0 && int32_t(ExitValue+IncValue) < ExitValue)
- return false;
- } else {
-
-
- if (InitValue <= ExitValue)
- return false;
- uint32_t Range = uint32_t(InitValue-ExitValue);
-
-
- if (NewPred == CmpInst::ICMP_SGE || NewPred == CmpInst::ICMP_SLT) {
- if (++Range == 0) return false;
- }
- unsigned Leftover = Range % uint32_t(-IncValue);
-
-
-
- if ((NewPred == CmpInst::ICMP_EQ || NewPred == CmpInst::ICMP_NE) &&
- Leftover != 0)
- return false;
-
-
- if (Leftover != 0 && int32_t(ExitValue+IncValue) > ExitValue)
- return false;
- }
- IntegerType *Int32Ty = Type::getInt32Ty(PN->getContext());
-
- PHINode *NewPHI = PHINode::Create(Int32Ty, 2, PN->getName()+".int", PN);
- NewPHI->addIncoming(ConstantInt::get(Int32Ty, InitValue),
- PN->getIncomingBlock(IncomingEdge));
- Value *NewAdd =
- BinaryOperator::CreateAdd(NewPHI, ConstantInt::get(Int32Ty, IncValue),
- Incr->getName()+".int", Incr);
- NewPHI->addIncoming(NewAdd, PN->getIncomingBlock(BackEdge));
- ICmpInst *NewCompare = new ICmpInst(TheBr, NewPred, NewAdd,
- ConstantInt::get(Int32Ty, ExitValue),
- Compare->getName());
-
-
- WeakTrackingVH WeakPH = PN;
-
-
- NewCompare->takeName(Compare);
- Compare->replaceAllUsesWith(NewCompare);
- RecursivelyDeleteTriviallyDeadInstructions(Compare, TLI, MSSAU.get());
-
- Incr->replaceAllUsesWith(UndefValue::get(Incr->getType()));
- RecursivelyDeleteTriviallyDeadInstructions(Incr, TLI, MSSAU.get());
-
-
-
-
-
-
-
- if (WeakPH) {
- Value *Conv = new SIToFPInst(NewPHI, PN->getType(), "indvar.conv",
- &*PN->getParent()->getFirstInsertionPt());
- PN->replaceAllUsesWith(Conv);
- RecursivelyDeleteTriviallyDeadInstructions(PN, TLI, MSSAU.get());
- }
- return true;
- }
- bool IndVarSimplify::rewriteNonIntegerIVs(Loop *L) {
-
-
-
- BasicBlock *Header = L->getHeader();
- SmallVector<WeakTrackingVH, 8> PHIs;
- for (PHINode &PN : Header->phis())
- PHIs.push_back(&PN);
- bool Changed = false;
- for (unsigned i = 0, e = PHIs.size(); i != e; ++i)
- if (PHINode *PN = dyn_cast_or_null<PHINode>(&*PHIs[i]))
- Changed |= handleFloatingPointIV(L, PN);
-
-
-
- if (Changed)
- SE->forgetLoop(L);
- return Changed;
- }
- bool IndVarSimplify::rewriteFirstIterationLoopExitValues(Loop *L) {
-
- assert(L->isLCSSAForm(*DT));
- SmallVector<BasicBlock *, 8> ExitBlocks;
- L->getUniqueExitBlocks(ExitBlocks);
- bool MadeAnyChanges = false;
- for (auto *ExitBB : ExitBlocks) {
-
-
- for (PHINode &PN : ExitBB->phis()) {
- for (unsigned IncomingValIdx = 0, E = PN.getNumIncomingValues();
- IncomingValIdx != E; ++IncomingValIdx) {
- auto *IncomingBB = PN.getIncomingBlock(IncomingValIdx);
-
-
-
-
-
- if (!L->getLoopLatch() ||
- !DT->dominates(IncomingBB, L->getLoopLatch()))
- continue;
-
- auto *TermInst = IncomingBB->getTerminator();
- Value *Cond = nullptr;
- if (auto *BI = dyn_cast<BranchInst>(TermInst)) {
-
-
- Cond = BI->getCondition();
- } else if (auto *SI = dyn_cast<SwitchInst>(TermInst))
- Cond = SI->getCondition();
- else
- continue;
- if (!L->isLoopInvariant(Cond))
- continue;
- auto *ExitVal = dyn_cast<PHINode>(PN.getIncomingValue(IncomingValIdx));
-
- if (!ExitVal || ExitVal->getParent() != L->getHeader())
- continue;
-
-
-
- auto *LoopPreheader = L->getLoopPreheader();
- assert(LoopPreheader && "Invalid loop");
- int PreheaderIdx = ExitVal->getBasicBlockIndex(LoopPreheader);
- if (PreheaderIdx != -1) {
- assert(ExitVal->getParent() == L->getHeader() &&
- "ExitVal must be in loop header");
- MadeAnyChanges = true;
- PN.setIncomingValue(IncomingValIdx,
- ExitVal->getIncomingValue(PreheaderIdx));
- SE->forgetValue(&PN);
- }
- }
- }
- }
- return MadeAnyChanges;
- }
- static void visitIVCast(CastInst *Cast, WideIVInfo &WI,
- ScalarEvolution *SE,
- const TargetTransformInfo *TTI) {
- bool IsSigned = Cast->getOpcode() == Instruction::SExt;
- if (!IsSigned && Cast->getOpcode() != Instruction::ZExt)
- return;
- Type *Ty = Cast->getType();
- uint64_t Width = SE->getTypeSizeInBits(Ty);
- if (!Cast->getModule()->getDataLayout().isLegalInteger(Width))
- return;
-
-
-
-
- uint64_t NarrowIVWidth = SE->getTypeSizeInBits(WI.NarrowIV->getType());
- if (NarrowIVWidth >= Width)
- return;
-
-
-
-
-
-
- if (TTI &&
- TTI->getArithmeticInstrCost(Instruction::Add, Ty) >
- TTI->getArithmeticInstrCost(Instruction::Add,
- Cast->getOperand(0)->getType())) {
- return;
- }
- if (!WI.WidestNativeType ||
- Width > SE->getTypeSizeInBits(WI.WidestNativeType)) {
- WI.WidestNativeType = SE->getEffectiveSCEVType(Ty);
- WI.IsSigned = IsSigned;
- return;
- }
-
-
-
-
- WI.IsSigned |= IsSigned;
- }
- namespace {
- class IndVarSimplifyVisitor : public IVVisitor {
- ScalarEvolution *SE;
- const TargetTransformInfo *TTI;
- PHINode *IVPhi;
- public:
- WideIVInfo WI;
- IndVarSimplifyVisitor(PHINode *IV, ScalarEvolution *SCEV,
- const TargetTransformInfo *TTI,
- const DominatorTree *DTree)
- : SE(SCEV), TTI(TTI), IVPhi(IV) {
- DT = DTree;
- WI.NarrowIV = IVPhi;
- }
-
- void visitCast(CastInst *Cast) override { visitIVCast(Cast, WI, SE, TTI); }
- };
- }
- bool IndVarSimplify::simplifyAndExtend(Loop *L,
- SCEVExpander &Rewriter,
- LoopInfo *LI) {
- SmallVector<WideIVInfo, 8> WideIVs;
- auto *GuardDecl = L->getBlocks()[0]->getModule()->getFunction(
- Intrinsic::getName(Intrinsic::experimental_guard));
- bool HasGuards = GuardDecl && !GuardDecl->use_empty();
- SmallVector<PHINode*, 8> LoopPhis;
- for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I) {
- LoopPhis.push_back(cast<PHINode>(I));
- }
-
-
-
-
- bool Changed = false;
- while (!LoopPhis.empty()) {
-
-
-
-
-
-
- do {
- PHINode *CurrIV = LoopPhis.pop_back_val();
-
- IndVarSimplifyVisitor Visitor(CurrIV, SE, TTI, DT);
- Changed |= simplifyUsersOfIV(CurrIV, SE, DT, LI, TTI, DeadInsts, Rewriter,
- &Visitor);
- if (Visitor.WI.WidestNativeType) {
- WideIVs.push_back(Visitor.WI);
- }
- } while(!LoopPhis.empty());
-
- if (!WidenIndVars)
- continue;
- for (; !WideIVs.empty(); WideIVs.pop_back()) {
- unsigned ElimExt;
- unsigned Widened;
- if (PHINode *WidePhi = createWideIV(WideIVs.back(), LI, SE, Rewriter,
- DT, DeadInsts, ElimExt, Widened,
- HasGuards, UsePostIncrementRanges)) {
- NumElimExt += ElimExt;
- NumWidened += Widened;
- Changed = true;
- LoopPhis.push_back(WidePhi);
- }
- }
- }
- return Changed;
- }
- static PHINode *getLoopPhiForCounter(Value *IncV, Loop *L) {
- Instruction *IncI = dyn_cast<Instruction>(IncV);
- if (!IncI)
- return nullptr;
- switch (IncI->getOpcode()) {
- case Instruction::Add:
- case Instruction::Sub:
- break;
- case Instruction::GetElementPtr:
-
- if (IncI->getNumOperands() == 2)
- break;
- LLVM_FALLTHROUGH;
- default:
- return nullptr;
- }
- PHINode *Phi = dyn_cast<PHINode>(IncI->getOperand(0));
- if (Phi && Phi->getParent() == L->getHeader()) {
- if (L->isLoopInvariant(IncI->getOperand(1)))
- return Phi;
- return nullptr;
- }
- if (IncI->getOpcode() == Instruction::GetElementPtr)
- return nullptr;
-
- Phi = dyn_cast<PHINode>(IncI->getOperand(1));
- if (Phi && Phi->getParent() == L->getHeader()) {
- if (L->isLoopInvariant(IncI->getOperand(0)))
- return Phi;
- }
- return nullptr;
- }
- static bool isLoopExitTestBasedOn(Value *V, BasicBlock *ExitingBB) {
- BranchInst *BI = cast<BranchInst>(ExitingBB->getTerminator());
- ICmpInst *ICmp = dyn_cast<ICmpInst>(BI->getCondition());
-
- if (!ICmp)
- return false;
-
- return ICmp->getOperand(0) == V || ICmp->getOperand(1) == V;
- }
- static bool needsLFTR(Loop *L, BasicBlock *ExitingBB) {
- assert(L->getLoopLatch() && "Must be in simplified form");
-
-
-
-
- BranchInst *BI = cast<BranchInst>(ExitingBB->getTerminator());
- if (L->isLoopInvariant(BI->getCondition()))
- return false;
-
- ICmpInst *Cond = dyn_cast<ICmpInst>(BI->getCondition());
- if (!Cond)
- return true;
-
- ICmpInst::Predicate Pred = Cond->getPredicate();
- if (Pred != ICmpInst::ICMP_NE && Pred != ICmpInst::ICMP_EQ)
- return true;
-
- Value *LHS = Cond->getOperand(0);
- Value *RHS = Cond->getOperand(1);
- if (!L->isLoopInvariant(RHS)) {
- if (!L->isLoopInvariant(LHS))
- return true;
- std::swap(LHS, RHS);
- }
-
- PHINode *Phi = dyn_cast<PHINode>(LHS);
- if (!Phi)
- Phi = getLoopPhiForCounter(LHS, L);
- if (!Phi)
- return true;
-
- int Idx = Phi->getBasicBlockIndex(L->getLoopLatch());
- if (Idx < 0)
- return true;
-
- Value *IncV = Phi->getIncomingValue(Idx);
- return Phi != getLoopPhiForCounter(IncV, L);
- }
- static bool mustExecuteUBIfPoisonOnPathTo(Instruction *Root,
- Instruction *OnPathTo,
- DominatorTree *DT) {
-
-
-
-
-
-
- SmallSet<const Value *, 16> KnownPoison;
- SmallVector<const Instruction*, 16> Worklist;
- Worklist.push_back(Root);
- while (!Worklist.empty()) {
- const Instruction *I = Worklist.pop_back_val();
-
- if (mustTriggerUB(I, KnownPoison) && DT->dominates(I, OnPathTo))
- return true;
-
-
- if (!propagatesPoison(cast<Operator>(I)) && I != Root)
- continue;
- if (KnownPoison.insert(I).second)
- for (const User *User : I->users())
- Worklist.push_back(cast<Instruction>(User));
- }
-
-
- return false;
- }
- static bool hasConcreteDefImpl(Value *V, SmallPtrSetImpl<Value*> &Visited,
- unsigned Depth) {
- if (isa<Constant>(V))
- return !isa<UndefValue>(V);
- if (Depth >= 6)
- return false;
-
-
- Instruction *I = dyn_cast<Instruction>(V);
- if (!I)
- return false;
-
- if(I->mayReadFromMemory() || isa<CallInst>(I) || isa<InvokeInst>(I))
- return false;
-
- for (Value *Op : I->operands()) {
- if (!Visited.insert(Op).second)
- continue;
- if (!hasConcreteDefImpl(Op, Visited, Depth+1))
- return false;
- }
- return true;
- }
- static bool hasConcreteDef(Value *V) {
- SmallPtrSet<Value*, 8> Visited;
- Visited.insert(V);
- return hasConcreteDefImpl(V, Visited, 0);
- }
- static bool AlmostDeadIV(PHINode *Phi, BasicBlock *LatchBlock, Value *Cond) {
- int LatchIdx = Phi->getBasicBlockIndex(LatchBlock);
- Value *IncV = Phi->getIncomingValue(LatchIdx);
- for (User *U : Phi->users())
- if (U != Cond && U != IncV) return false;
- for (User *U : IncV->users())
- if (U != Cond && U != Phi) return false;
- return true;
- }
- static bool isLoopCounter(PHINode* Phi, Loop *L,
- ScalarEvolution *SE) {
- assert(Phi->getParent() == L->getHeader());
- assert(L->getLoopLatch());
- if (!SE->isSCEVable(Phi->getType()))
- return false;
- const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(SE->getSCEV(Phi));
- if (!AR || AR->getLoop() != L || !AR->isAffine())
- return false;
- const SCEV *Step = dyn_cast<SCEVConstant>(AR->getStepRecurrence(*SE));
- if (!Step || !Step->isOne())
- return false;
- int LatchIdx = Phi->getBasicBlockIndex(L->getLoopLatch());
- Value *IncV = Phi->getIncomingValue(LatchIdx);
- return (getLoopPhiForCounter(IncV, L) == Phi &&
- isa<SCEVAddRecExpr>(SE->getSCEV(IncV)));
- }
- static PHINode *FindLoopCounter(Loop *L, BasicBlock *ExitingBB,
- const SCEV *BECount,
- ScalarEvolution *SE, DominatorTree *DT) {
- uint64_t BCWidth = SE->getTypeSizeInBits(BECount->getType());
- Value *Cond = cast<BranchInst>(ExitingBB->getTerminator())->getCondition();
-
- PHINode *BestPhi = nullptr;
- const SCEV *BestInit = nullptr;
- BasicBlock *LatchBlock = L->getLoopLatch();
- assert(LatchBlock && "Must be in simplified form");
- const DataLayout &DL = L->getHeader()->getModule()->getDataLayout();
- for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I) {
- PHINode *Phi = cast<PHINode>(I);
- if (!isLoopCounter(Phi, L, SE))
- continue;
-
- if (BECount->getType()->isPointerTy() && !Phi->getType()->isPointerTy())
- continue;
- const auto *AR = cast<SCEVAddRecExpr>(SE->getSCEV(Phi));
-
-
-
- uint64_t PhiWidth = SE->getTypeSizeInBits(AR->getType());
- if (PhiWidth < BCWidth || !DL.isLegalInteger(PhiWidth))
- continue;
-
-
- if (!hasConcreteDef(Phi)) {
-
-
-
- Value *IncPhi = Phi->getIncomingValueForBlock(LatchBlock);
- if (!isLoopExitTestBasedOn(Phi, ExitingBB) &&
- !isLoopExitTestBasedOn(IncPhi, ExitingBB))
- continue;
- }
-
-
-
-
-
-
-
-
- if (!Phi->getType()->isIntegerTy() &&
- !mustExecuteUBIfPoisonOnPathTo(Phi, ExitingBB->getTerminator(), DT))
- continue;
- const SCEV *Init = AR->getStart();
- if (BestPhi && !AlmostDeadIV(BestPhi, LatchBlock, Cond)) {
-
- if (AlmostDeadIV(Phi, LatchBlock, Cond))
- continue;
-
-
- if (BestInit->isZero() != Init->isZero()) {
- if (BestInit->isZero())
- continue;
- }
-
-
-
- else if (PhiWidth <= SE->getTypeSizeInBits(BestPhi->getType()))
- continue;
- }
- BestPhi = Phi;
- BestInit = Init;
- }
- return BestPhi;
- }
- static Value *genLoopLimit(PHINode *IndVar, BasicBlock *ExitingBB,
- const SCEV *ExitCount, bool UsePostInc, Loop *L,
- SCEVExpander &Rewriter, ScalarEvolution *SE) {
- assert(isLoopCounter(IndVar, L, SE));
- const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(SE->getSCEV(IndVar));
- const SCEV *IVInit = AR->getStart();
- assert(AR->getStepRecurrence(*SE)->isOne() && "only handles unit stride");
-
-
-
-
- if (IndVar->getType()->isPointerTy() &&
- !ExitCount->getType()->isPointerTy()) {
-
-
-
-
-
-
- Type *OfsTy = SE->getEffectiveSCEVType(IVInit->getType());
- const SCEV *IVOffset = SE->getTruncateOrZeroExtend(ExitCount, OfsTy);
- if (UsePostInc)
- IVOffset = SE->getAddExpr(IVOffset, SE->getOne(OfsTy));
-
- assert(SE->isLoopInvariant(IVOffset, L) &&
- "Computed iteration count is not loop invariant!");
- const SCEV *IVLimit = SE->getAddExpr(IVInit, IVOffset);
- BranchInst *BI = cast<BranchInst>(ExitingBB->getTerminator());
- return Rewriter.expandCodeFor(IVLimit, IndVar->getType(), BI);
- } else {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- if (SE->getTypeSizeInBits(IVInit->getType())
- > SE->getTypeSizeInBits(ExitCount->getType())) {
- if (isa<SCEVConstant>(IVInit) && isa<SCEVConstant>(ExitCount))
- ExitCount = SE->getZeroExtendExpr(ExitCount, IVInit->getType());
- else
- IVInit = SE->getTruncateExpr(IVInit, ExitCount->getType());
- }
- const SCEV *IVLimit = SE->getAddExpr(IVInit, ExitCount);
- if (UsePostInc)
- IVLimit = SE->getAddExpr(IVLimit, SE->getOne(IVLimit->getType()));
-
- assert(SE->isLoopInvariant(IVLimit, L) &&
- "Computed iteration count is not loop invariant!");
-
-
-
- Type *LimitTy = ExitCount->getType()->isPointerTy() ?
- IndVar->getType() : ExitCount->getType();
- BranchInst *BI = cast<BranchInst>(ExitingBB->getTerminator());
- return Rewriter.expandCodeFor(IVLimit, LimitTy, BI);
- }
- }
- bool IndVarSimplify::
- linearFunctionTestReplace(Loop *L, BasicBlock *ExitingBB,
- const SCEV *ExitCount,
- PHINode *IndVar, SCEVExpander &Rewriter) {
- assert(L->getLoopLatch() && "Loop no longer in simplified form?");
- assert(isLoopCounter(IndVar, L, SE));
- Instruction * const IncVar =
- cast<Instruction>(IndVar->getIncomingValueForBlock(L->getLoopLatch()));
-
- Value *CmpIndVar = IndVar;
- bool UsePostInc = false;
-
-
-
- if (ExitingBB == L->getLoopLatch()) {
-
-
-
-
- bool SafeToPostInc =
- IndVar->getType()->isIntegerTy() ||
- isLoopExitTestBasedOn(IncVar, ExitingBB) ||
- mustExecuteUBIfPoisonOnPathTo(IncVar, ExitingBB->getTerminator(), DT);
- if (SafeToPostInc) {
- UsePostInc = true;
- CmpIndVar = IncVar;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
- if (auto *BO = dyn_cast<BinaryOperator>(IncVar)) {
- const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(SE->getSCEV(IncVar));
- if (BO->hasNoUnsignedWrap())
- BO->setHasNoUnsignedWrap(AR->hasNoUnsignedWrap());
- if (BO->hasNoSignedWrap())
- BO->setHasNoSignedWrap(AR->hasNoSignedWrap());
- }
- Value *ExitCnt = genLoopLimit(
- IndVar, ExitingBB, ExitCount, UsePostInc, L, Rewriter, SE);
- assert(ExitCnt->getType()->isPointerTy() ==
- IndVar->getType()->isPointerTy() &&
- "genLoopLimit missed a cast");
-
- BranchInst *BI = cast<BranchInst>(ExitingBB->getTerminator());
- ICmpInst::Predicate P;
- if (L->contains(BI->getSuccessor(0)))
- P = ICmpInst::ICMP_NE;
- else
- P = ICmpInst::ICMP_EQ;
- IRBuilder<> Builder(BI);
-
-
- if (auto *Cond = dyn_cast<Instruction>(BI->getCondition()))
- Builder.SetCurrentDebugLocation(Cond->getDebugLoc());
-
-
-
-
-
- unsigned CmpIndVarSize = SE->getTypeSizeInBits(CmpIndVar->getType());
- unsigned ExitCntSize = SE->getTypeSizeInBits(ExitCnt->getType());
- if (CmpIndVarSize > ExitCntSize) {
- assert(!CmpIndVar->getType()->isPointerTy() &&
- !ExitCnt->getType()->isPointerTy());
-
-
-
-
-
- bool Extended = false;
- const SCEV *IV = SE->getSCEV(CmpIndVar);
- const SCEV *TruncatedIV = SE->getTruncateExpr(SE->getSCEV(CmpIndVar),
- ExitCnt->getType());
- const SCEV *ZExtTrunc =
- SE->getZeroExtendExpr(TruncatedIV, CmpIndVar->getType());
- if (ZExtTrunc == IV) {
- Extended = true;
- ExitCnt = Builder.CreateZExt(ExitCnt, IndVar->getType(),
- "wide.trip.count");
- } else {
- const SCEV *SExtTrunc =
- SE->getSignExtendExpr(TruncatedIV, CmpIndVar->getType());
- if (SExtTrunc == IV) {
- Extended = true;
- ExitCnt = Builder.CreateSExt(ExitCnt, IndVar->getType(),
- "wide.trip.count");
- }
- }
- if (Extended) {
- bool Discard;
- L->makeLoopInvariant(ExitCnt, Discard);
- } else
- CmpIndVar = Builder.CreateTrunc(CmpIndVar, ExitCnt->getType(),
- "lftr.wideiv");
- }
- LLVM_DEBUG(dbgs() << "INDVARS: Rewriting loop exit condition to:\n"
- << " LHS:" << *CmpIndVar << '\n'
- << " op:\t" << (P == ICmpInst::ICMP_NE ? "!=" : "==")
- << "\n"
- << " RHS:\t" << *ExitCnt << "\n"
- << "ExitCount:\t" << *ExitCount << "\n"
- << " was: " << *BI->getCondition() << "\n");
- Value *Cond = Builder.CreateICmp(P, CmpIndVar, ExitCnt, "exitcond");
- Value *OrigCond = BI->getCondition();
-
-
-
-
-
- BI->setCondition(Cond);
- DeadInsts.emplace_back(OrigCond);
- ++NumLFTR;
- return true;
- }
- bool IndVarSimplify::sinkUnusedInvariants(Loop *L) {
- BasicBlock *ExitBlock = L->getExitBlock();
- if (!ExitBlock) return false;
- BasicBlock *Preheader = L->getLoopPreheader();
- if (!Preheader) return false;
- bool MadeAnyChanges = false;
- BasicBlock::iterator InsertPt = ExitBlock->getFirstInsertionPt();
- BasicBlock::iterator I(Preheader->getTerminator());
- while (I != Preheader->begin()) {
- --I;
-
- if (isa<PHINode>(I))
- break;
-
-
-
-
-
-
- if (I->mayHaveSideEffects() || I->mayReadFromMemory())
- continue;
-
- if (isa<DbgInfoIntrinsic>(I))
- continue;
-
- if (I->isEHPad())
- continue;
-
-
-
-
- if (isa<AllocaInst>(I))
- continue;
-
-
- bool UsedInLoop = false;
- for (Use &U : I->uses()) {
- Instruction *User = cast<Instruction>(U.getUser());
- BasicBlock *UseBB = User->getParent();
- if (PHINode *P = dyn_cast<PHINode>(User)) {
- unsigned i =
- PHINode::getIncomingValueNumForOperand(U.getOperandNo());
- UseBB = P->getIncomingBlock(i);
- }
- if (UseBB == Preheader || L->contains(UseBB)) {
- UsedInLoop = true;
- break;
- }
- }
-
- if (UsedInLoop)
- continue;
-
- Instruction *ToMove = &*I;
- bool Done = false;
- if (I != Preheader->begin()) {
-
- do {
- --I;
- } while (I->isDebugOrPseudoInst() && I != Preheader->begin());
- if (I->isDebugOrPseudoInst() && I == Preheader->begin())
- Done = true;
- } else {
- Done = true;
- }
- MadeAnyChanges = true;
- ToMove->moveBefore(*ExitBlock, InsertPt);
- if (Done) break;
- InsertPt = ToMove->getIterator();
- }
- return MadeAnyChanges;
- }
- static void replaceExitCond(BranchInst *BI, Value *NewCond,
- SmallVectorImpl<WeakTrackingVH> &DeadInsts) {
- auto *OldCond = BI->getCondition();
- BI->setCondition(NewCond);
- if (OldCond->use_empty())
- DeadInsts.emplace_back(OldCond);
- }
- static void foldExit(const Loop *L, BasicBlock *ExitingBB, bool IsTaken,
- SmallVectorImpl<WeakTrackingVH> &DeadInsts) {
- BranchInst *BI = cast<BranchInst>(ExitingBB->getTerminator());
- bool ExitIfTrue = !L->contains(*succ_begin(ExitingBB));
- auto *OldCond = BI->getCondition();
- auto *NewCond =
- ConstantInt::get(OldCond->getType(), IsTaken ? ExitIfTrue : !ExitIfTrue);
- replaceExitCond(BI, NewCond, DeadInsts);
- }
- static void replaceLoopPHINodesWithPreheaderValues(
- Loop *L, SmallVectorImpl<WeakTrackingVH> &DeadInsts) {
- assert(L->isLoopSimplifyForm() && "Should only do it in simplify form!");
- auto *LoopPreheader = L->getLoopPreheader();
- auto *LoopHeader = L->getHeader();
- for (auto &PN : LoopHeader->phis()) {
- auto *PreheaderIncoming = PN.getIncomingValueForBlock(LoopPreheader);
- PN.replaceAllUsesWith(PreheaderIncoming);
- DeadInsts.emplace_back(&PN);
- }
- }
- static void replaceWithInvariantCond(
- const Loop *L, BasicBlock *ExitingBB, ICmpInst::Predicate InvariantPred,
- const SCEV *InvariantLHS, const SCEV *InvariantRHS, SCEVExpander &Rewriter,
- SmallVectorImpl<WeakTrackingVH> &DeadInsts) {
- BranchInst *BI = cast<BranchInst>(ExitingBB->getTerminator());
- Rewriter.setInsertPoint(BI);
- auto *LHSV = Rewriter.expandCodeFor(InvariantLHS);
- auto *RHSV = Rewriter.expandCodeFor(InvariantRHS);
- bool ExitIfTrue = !L->contains(*succ_begin(ExitingBB));
- if (ExitIfTrue)
- InvariantPred = ICmpInst::getInversePredicate(InvariantPred);
- IRBuilder<> Builder(BI);
- auto *NewCond = Builder.CreateICmp(InvariantPred, LHSV, RHSV,
- BI->getCondition()->getName());
- replaceExitCond(BI, NewCond, DeadInsts);
- }
- static bool optimizeLoopExitWithUnknownExitCount(
- const Loop *L, BranchInst *BI, BasicBlock *ExitingBB,
- const SCEV *MaxIter, bool Inverted, bool SkipLastIter,
- ScalarEvolution *SE, SCEVExpander &Rewriter,
- SmallVectorImpl<WeakTrackingVH> &DeadInsts) {
- ICmpInst::Predicate Pred;
- Value *LHS, *RHS;
- BasicBlock *TrueSucc, *FalseSucc;
- if (!match(BI, m_Br(m_ICmp(Pred, m_Value(LHS), m_Value(RHS)),
- m_BasicBlock(TrueSucc), m_BasicBlock(FalseSucc))))
- return false;
- assert((L->contains(TrueSucc) != L->contains(FalseSucc)) &&
- "Not a loop exit!");
-
- if (L->contains(FalseSucc))
- Pred = CmpInst::getInversePredicate(Pred);
-
- if (Inverted)
- Pred = CmpInst::getInversePredicate(Pred);
- const SCEV *LHSS = SE->getSCEVAtScope(LHS, L);
- const SCEV *RHSS = SE->getSCEVAtScope(RHS, L);
-
- if (SE->isKnownPredicateAt(Pred, LHSS, RHSS, BI)) {
- foldExit(L, ExitingBB, Inverted, DeadInsts);
- return true;
- }
-
- if (Inverted)
- return false;
- auto *ARTy = LHSS->getType();
- auto *MaxIterTy = MaxIter->getType();
-
- if (SE->getTypeSizeInBits(ARTy) > SE->getTypeSizeInBits(MaxIterTy))
- MaxIter = SE->getZeroExtendExpr(MaxIter, ARTy);
- else if (SE->getTypeSizeInBits(ARTy) < SE->getTypeSizeInBits(MaxIterTy)) {
- const SCEV *MinusOne = SE->getMinusOne(ARTy);
- auto *MaxAllowedIter = SE->getZeroExtendExpr(MinusOne, MaxIterTy);
- if (SE->isKnownPredicateAt(ICmpInst::ICMP_ULE, MaxIter, MaxAllowedIter, BI))
- MaxIter = SE->getTruncateExpr(MaxIter, ARTy);
- }
- if (SkipLastIter) {
- const SCEV *One = SE->getOne(MaxIter->getType());
- MaxIter = SE->getMinusSCEV(MaxIter, One);
- }
-
- auto LIP = SE->getLoopInvariantExitCondDuringFirstIterations(Pred, LHSS, RHSS,
- L, BI, MaxIter);
- if (!LIP)
- return false;
-
- if (SE->isKnownPredicateAt(LIP->Pred, LIP->LHS, LIP->RHS, BI))
- foldExit(L, ExitingBB, Inverted, DeadInsts);
- else
- replaceWithInvariantCond(L, ExitingBB, LIP->Pred, LIP->LHS, LIP->RHS,
- Rewriter, DeadInsts);
- return true;
- }
- bool IndVarSimplify::canonicalizeExitCondition(Loop *L) {
-
-
-
-
-
-
-
-
-
- SmallVector<BasicBlock*, 16> ExitingBlocks;
- L->getExitingBlocks(ExitingBlocks);
- bool Changed = false;
- for (auto *ExitingBB : ExitingBlocks) {
- auto *BI = dyn_cast<BranchInst>(ExitingBB->getTerminator());
- if (!BI)
- continue;
- assert(BI->isConditional() && "exit branch must be conditional");
- auto *ICmp = dyn_cast<ICmpInst>(BI->getCondition());
- if (!ICmp || !ICmp->hasOneUse())
- continue;
- auto *LHS = ICmp->getOperand(0);
- auto *RHS = ICmp->getOperand(1);
-
-
-
- if (!L->isLoopInvariant(RHS)) {
- if (!L->isLoopInvariant(LHS))
- continue;
-
- std::swap(LHS, RHS);
- }
-
- Value *LHSOp = nullptr;
- if (!match(LHS, m_ZExt(m_Value(LHSOp))) || !ICmp->isSigned())
- continue;
- const DataLayout &DL = ExitingBB->getModule()->getDataLayout();
- const unsigned InnerBitWidth = DL.getTypeSizeInBits(LHSOp->getType());
- const unsigned OuterBitWidth = DL.getTypeSizeInBits(RHS->getType());
- auto FullCR = ConstantRange::getFull(InnerBitWidth);
- FullCR = FullCR.zeroExtend(OuterBitWidth);
- auto RHSCR = SE->getUnsignedRange(SE->applyLoopGuards(SE->getSCEV(RHS), L));
- if (FullCR.contains(RHSCR)) {
-
-
- ICmp->setPredicate(ICmp->getUnsignedPredicate());
- Changed = true;
-
-
- continue;
- }
- }
-
-
- for (auto *ExitingBB : ExitingBlocks) {
- auto *BI = dyn_cast<BranchInst>(ExitingBB->getTerminator());
- if (!BI)
- continue;
- assert(BI->isConditional() && "exit branch must be conditional");
- auto *ICmp = dyn_cast<ICmpInst>(BI->getCondition());
- if (!ICmp || !ICmp->hasOneUse() || !ICmp->isUnsigned())
- continue;
- bool Swapped = false;
- auto *LHS = ICmp->getOperand(0);
- auto *RHS = ICmp->getOperand(1);
- if (L->isLoopInvariant(LHS) == L->isLoopInvariant(RHS))
-
- continue;
- if (L->isLoopInvariant(LHS)) {
-
-
- Swapped = true;
- std::swap(LHS, RHS);
- }
- assert(!L->isLoopInvariant(LHS) && L->isLoopInvariant(RHS));
-
-
-
- Value *LHSOp = nullptr;
- if (!match(LHS, m_ZExt(m_Value(LHSOp))))
- continue;
-
-
-
-
-
-
- if (!LHS->hasOneUse() && !isa<SCEVAddRecExpr>(SE->getSCEV(LHSOp)))
- continue;
-
-
-
-
- auto doRotateTransform = [&]() {
- assert(ICmp->isUnsigned() && "must have proven unsigned already");
- auto *NewRHS =
- CastInst::Create(Instruction::Trunc, RHS, LHSOp->getType(), "",
- L->getLoopPreheader()->getTerminator());
- ICmp->setOperand(Swapped ? 1 : 0, LHSOp);
- ICmp->setOperand(Swapped ? 0 : 1, NewRHS);
- if (LHS->use_empty())
- DeadInsts.push_back(LHS);
- };
- const DataLayout &DL = ExitingBB->getModule()->getDataLayout();
- const unsigned InnerBitWidth = DL.getTypeSizeInBits(LHSOp->getType());
- const unsigned OuterBitWidth = DL.getTypeSizeInBits(RHS->getType());
- auto FullCR = ConstantRange::getFull(InnerBitWidth);
- FullCR = FullCR.zeroExtend(OuterBitWidth);
- auto RHSCR = SE->getUnsignedRange(SE->applyLoopGuards(SE->getSCEV(RHS), L));
- if (FullCR.contains(RHSCR)) {
- doRotateTransform();
- Changed = true;
-
-
-
- continue;
- }
- }
- return Changed;
- }
- bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
- SmallVector<BasicBlock*, 16> ExitingBlocks;
- L->getExitingBlocks(ExitingBlocks);
-
-
- llvm::erase_if(ExitingBlocks, [&](BasicBlock *ExitingBB) {
-
-
-
- if (LI->getLoopFor(ExitingBB) != L)
- return true;
-
- BranchInst *BI = dyn_cast<BranchInst>(ExitingBB->getTerminator());
- if (!BI)
- return true;
-
- if (isa<Constant>(BI->getCondition()))
- return true;
-
- if (!DT->dominates(ExitingBB, L->getLoopLatch()))
- return true;
- return false;
- });
- if (ExitingBlocks.empty())
- return false;
-
- const SCEV *MaxExitCount = SE->getSymbolicMaxBackedgeTakenCount(L);
- if (isa<SCEVCouldNotCompute>(MaxExitCount))
- return false;
-
-
-
- llvm::sort(ExitingBlocks, [&](BasicBlock *A, BasicBlock *B) {
-
-
- if (A == B) return false;
- if (DT->properlyDominates(A, B))
- return true;
- else {
- assert(DT->properlyDominates(B, A) &&
- "expected total dominance order!");
- return false;
- }
- });
- #ifdef ASSERT
- for (unsigned i = 1; i < ExitingBlocks.size(); i++) {
- assert(DT->dominates(ExitingBlocks[i-1], ExitingBlocks[i]));
- }
- #endif
- bool Changed = false;
- bool SkipLastIter = false;
- SmallSet<const SCEV*, 8> DominatingExitCounts;
- for (BasicBlock *ExitingBB : ExitingBlocks) {
- const SCEV *ExitCount = SE->getExitCount(L, ExitingBB);
- if (isa<SCEVCouldNotCompute>(ExitCount)) {
-
-
- auto *BI = cast<BranchInst>(ExitingBB->getTerminator());
- auto OptimizeCond = [&](bool Inverted, bool SkipLastIter) {
- return optimizeLoopExitWithUnknownExitCount(
- L, BI, ExitingBB, MaxExitCount, Inverted, SkipLastIter, SE,
- Rewriter, DeadInsts);
- };
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- if (OptimizeCond(false, false) || OptimizeCond(true, false))
- Changed = true;
- else if (SkipLastIter)
- if (OptimizeCond(false, true) || OptimizeCond(true, true))
- Changed = true;
- continue;
- }
- if (MaxExitCount == ExitCount)
-
-
- SkipLastIter = true;
-
-
-
-
-
- if (ExitCount->isZero()) {
- foldExit(L, ExitingBB, true, DeadInsts);
- replaceLoopPHINodesWithPreheaderValues(L, DeadInsts);
- Changed = true;
- continue;
- }
- assert(ExitCount->getType()->isIntegerTy() &&
- MaxExitCount->getType()->isIntegerTy() &&
- "Exit counts must be integers");
- Type *WiderType =
- SE->getWiderType(MaxExitCount->getType(), ExitCount->getType());
- ExitCount = SE->getNoopOrZeroExtend(ExitCount, WiderType);
- MaxExitCount = SE->getNoopOrZeroExtend(MaxExitCount, WiderType);
- assert(MaxExitCount->getType() == ExitCount->getType());
-
-
- if (SE->isLoopEntryGuardedByCond(L, CmpInst::ICMP_ULT,
- MaxExitCount, ExitCount)) {
- foldExit(L, ExitingBB, false, DeadInsts);
- Changed = true;
- continue;
- }
-
-
-
-
- if (!DominatingExitCounts.insert(ExitCount).second) {
- foldExit(L, ExitingBB, false, DeadInsts);
- Changed = true;
- continue;
- }
-
-
-
-
-
-
- }
- return Changed;
- }
- bool IndVarSimplify::predicateLoopExits(Loop *L, SCEVExpander &Rewriter) {
- SmallVector<BasicBlock*, 16> ExitingBlocks;
- L->getExitingBlocks(ExitingBlocks);
-
-
-
-
-
-
-
-
-
- if (!LoopPredication)
- return false;
-
-
-
- const SCEV *ExactBTC = SE->getBackedgeTakenCount(L);
- if (isa<SCEVCouldNotCompute>(ExactBTC) || !isSafeToExpand(ExactBTC, *SE))
- return false;
- assert(SE->isLoopInvariant(ExactBTC, L) && "BTC must be loop invariant");
- assert(ExactBTC->getType()->isIntegerTy() && "BTC must be integer");
- auto BadExit = [&](BasicBlock *ExitingBB) {
-
-
-
- if (LI->getLoopFor(ExitingBB) != L)
- return true;
-
- BranchInst *BI = dyn_cast<BranchInst>(ExitingBB->getTerminator());
- if (!BI)
- return true;
-
- if (isa<Constant>(BI->getCondition()))
- return true;
-
-
-
- BasicBlock *ExitBlock =
- BI->getSuccessor(L->contains(BI->getSuccessor(0)) ? 1 : 0);
- if (!ExitBlock->phis().empty())
- return true;
- const SCEV *ExitCount = SE->getExitCount(L, ExitingBB);
- if (isa<SCEVCouldNotCompute>(ExitCount) || !isSafeToExpand(ExitCount, *SE))
- return true;
- assert(SE->isLoopInvariant(ExitCount, L) &&
- "Exit count must be loop invariant");
- assert(ExitCount->getType()->isIntegerTy() && "Exit count must be integer");
- return false;
- };
-
-
-
-
-
-
-
- llvm::sort(ExitingBlocks,
- [&](BasicBlock *A, BasicBlock *B) {
-
-
-
- if (DT->properlyDominates(A, B)) return true;
- if (DT->properlyDominates(B, A)) return false;
- return A->getName() < B->getName();
- });
-
-
-
- for (unsigned i = 1; i < ExitingBlocks.size(); i++)
- if (!DT->dominates(ExitingBlocks[i-1], ExitingBlocks[i]))
- return false;
-
-
- for (unsigned i = 0, e = ExitingBlocks.size(); i < e; i++)
- if (BadExit(ExitingBlocks[i])) {
- ExitingBlocks.resize(i);
- break;
- }
- if (ExitingBlocks.empty())
- return false;
-
-
-
-
- assert(llvm::all_of(ExitingBlocks, [&](BasicBlock *ExitingBB) {
- return DT->dominates(ExitingBB, L->getLoopLatch());
- }));
-
-
-
-
-
-
-
-
- for (BasicBlock *BB : L->blocks())
- for (auto &I : *BB)
-
- if (I.mayHaveSideEffects())
- return false;
- bool Changed = false;
-
-
-
-
-
-
-
-
-
-
- Rewriter.setInsertPoint(L->getLoopPreheader()->getTerminator());
- IRBuilder<> B(L->getLoopPreheader()->getTerminator());
- Value *ExactBTCV = nullptr;
- for (BasicBlock *ExitingBB : ExitingBlocks) {
- const SCEV *ExitCount = SE->getExitCount(L, ExitingBB);
- auto *BI = cast<BranchInst>(ExitingBB->getTerminator());
- Value *NewCond;
- if (ExitCount == ExactBTC) {
- NewCond = L->contains(BI->getSuccessor(0)) ?
- B.getFalse() : B.getTrue();
- } else {
- Value *ECV = Rewriter.expandCodeFor(ExitCount);
- if (!ExactBTCV)
- ExactBTCV = Rewriter.expandCodeFor(ExactBTC);
- Value *RHS = ExactBTCV;
- if (ECV->getType() != RHS->getType()) {
- Type *WiderTy = SE->getWiderType(ECV->getType(), RHS->getType());
- ECV = B.CreateZExt(ECV, WiderTy);
- RHS = B.CreateZExt(RHS, WiderTy);
- }
- auto Pred = L->contains(BI->getSuccessor(0)) ?
- ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ;
- NewCond = B.CreateICmp(Pred, ECV, RHS);
- }
- Value *OldCond = BI->getCondition();
- BI->setCondition(NewCond);
- if (OldCond->use_empty())
- DeadInsts.emplace_back(OldCond);
- Changed = true;
- }
- return Changed;
- }
- bool IndVarSimplify::run(Loop *L) {
-
- assert(L->isRecursivelyLCSSAForm(*DT, *LI) &&
- "LCSSA required to run indvars!");
-
-
-
-
-
-
-
-
-
- if (!L->isLoopSimplifyForm())
- return false;
- #ifndef NDEBUG
-
-
-
-
- const SCEV *BackedgeTakenCount;
- if (VerifyIndvars)
- BackedgeTakenCount = SE->getBackedgeTakenCount(L);
- #endif
- bool Changed = false;
-
-
- Changed |= rewriteNonIntegerIVs(L);
-
- SCEVExpander Rewriter(*SE, DL, "indvars");
- #ifndef NDEBUG
- Rewriter.setDebugType(DEBUG_TYPE);
- #endif
-
-
-
-
-
-
- Rewriter.disableCanonicalMode();
- Changed |= simplifyAndExtend(L, Rewriter, LI);
-
-
-
-
- if (ReplaceExitValue != NeverRepl) {
- if (int Rewrites = rewriteLoopExitValues(L, LI, TLI, SE, TTI, Rewriter, DT,
- ReplaceExitValue, DeadInsts)) {
- NumReplaced += Rewrites;
- Changed = true;
- }
- }
-
- NumElimIV += Rewriter.replaceCongruentIVs(L, DT, DeadInsts, TTI);
-
-
- Changed |= canonicalizeExitCondition(L);
-
- if (optimizeLoopExits(L, Rewriter)) {
- Changed = true;
-
-
-
- SE->forgetTopmostLoop(L);
- }
-
-
- if (predicateLoopExits(L, Rewriter)) {
- Changed = true;
-
- SE->forgetLoop(L);
- }
-
-
- if (!DisableLFTR) {
- BasicBlock *PreHeader = L->getLoopPreheader();
- SmallVector<BasicBlock*, 16> ExitingBlocks;
- L->getExitingBlocks(ExitingBlocks);
- for (BasicBlock *ExitingBB : ExitingBlocks) {
-
- if (!isa<BranchInst>(ExitingBB->getTerminator()))
- continue;
-
-
-
- if (LI->getLoopFor(ExitingBB) != L)
- continue;
- if (!needsLFTR(L, ExitingBB))
- continue;
- const SCEV *ExitCount = SE->getExitCount(L, ExitingBB);
- if (isa<SCEVCouldNotCompute>(ExitCount))
- continue;
-
-
-
-
- if (ExitCount->isZero())
- continue;
- PHINode *IndVar = FindLoopCounter(L, ExitingBB, ExitCount, SE, DT);
- if (!IndVar)
- continue;
-
-
- if (Rewriter.isHighCostExpansion(ExitCount, L, SCEVCheapExpansionBudget,
- TTI, PreHeader->getTerminator()))
- continue;
-
-
-
-
-
-
-
-
-
- const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(ExitCount);
- if (!AR || AR->getLoop()->getLoopPreheader())
- Changed |= linearFunctionTestReplace(L, ExitingBB,
- ExitCount, IndVar,
- Rewriter);
- }
- }
-
-
-
- Rewriter.clear();
-
-
- while (!DeadInsts.empty()) {
- Value *V = DeadInsts.pop_back_val();
- if (PHINode *PHI = dyn_cast_or_null<PHINode>(V))
- Changed |= RecursivelyDeleteDeadPHINode(PHI, TLI, MSSAU.get());
- else if (Instruction *Inst = dyn_cast_or_null<Instruction>(V))
- Changed |=
- RecursivelyDeleteTriviallyDeadInstructions(Inst, TLI, MSSAU.get());
- }
-
-
-
- Changed |= sinkUnusedInvariants(L);
-
-
-
- Changed |= rewriteFirstIterationLoopExitValues(L);
-
- Changed |= DeleteDeadPHIs(L->getHeader(), TLI, MSSAU.get());
-
- assert(L->isRecursivelyLCSSAForm(*DT, *LI) &&
- "Indvars did not preserve LCSSA!");
-
-
-
- #ifndef NDEBUG
- if (VerifyIndvars && !isa<SCEVCouldNotCompute>(BackedgeTakenCount)) {
- SE->forgetLoop(L);
- const SCEV *NewBECount = SE->getBackedgeTakenCount(L);
- if (SE->getTypeSizeInBits(BackedgeTakenCount->getType()) <
- SE->getTypeSizeInBits(NewBECount->getType()))
- NewBECount = SE->getTruncateOrNoop(NewBECount,
- BackedgeTakenCount->getType());
- else
- BackedgeTakenCount = SE->getTruncateOrNoop(BackedgeTakenCount,
- NewBECount->getType());
- assert(!SE->isKnownPredicate(ICmpInst::ICMP_ULT, BackedgeTakenCount,
- NewBECount) && "indvars must preserve SCEV");
- }
- if (VerifyMemorySSA && MSSAU)
- MSSAU->getMemorySSA()->verifyMemorySSA();
- #endif
- return Changed;
- }
- PreservedAnalyses IndVarSimplifyPass::run(Loop &L, LoopAnalysisManager &AM,
- LoopStandardAnalysisResults &AR,
- LPMUpdater &) {
- Function *F = L.getHeader()->getParent();
- const DataLayout &DL = F->getParent()->getDataLayout();
- IndVarSimplify IVS(&AR.LI, &AR.SE, &AR.DT, DL, &AR.TLI, &AR.TTI, AR.MSSA,
- WidenIndVars && AllowIVWidening);
- if (!IVS.run(&L))
- return PreservedAnalyses::all();
- auto PA = getLoopPassPreservedAnalyses();
- PA.preserveSet<CFGAnalyses>();
- if (AR.MSSA)
- PA.preserve<MemorySSAAnalysis>();
- return PA;
- }
- namespace {
- struct IndVarSimplifyLegacyPass : public LoopPass {
- static char ID;
- IndVarSimplifyLegacyPass() : LoopPass(ID) {
- initializeIndVarSimplifyLegacyPassPass(*PassRegistry::getPassRegistry());
- }
- bool runOnLoop(Loop *L, LPPassManager &LPM) override {
- if (skipLoop(L))
- return false;
- auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
- auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
- auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
- auto *TLIP = getAnalysisIfAvailable<TargetLibraryInfoWrapperPass>();
- auto *TLI = TLIP ? &TLIP->getTLI(*L->getHeader()->getParent()) : nullptr;
- auto *TTIP = getAnalysisIfAvailable<TargetTransformInfoWrapperPass>();
- auto *TTI = TTIP ? &TTIP->getTTI(*L->getHeader()->getParent()) : nullptr;
- const DataLayout &DL = L->getHeader()->getModule()->getDataLayout();
- auto *MSSAAnalysis = getAnalysisIfAvailable<MemorySSAWrapperPass>();
- MemorySSA *MSSA = nullptr;
- if (MSSAAnalysis)
- MSSA = &MSSAAnalysis->getMSSA();
- IndVarSimplify IVS(LI, SE, DT, DL, TLI, TTI, MSSA, AllowIVWidening);
- return IVS.run(L);
- }
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesCFG();
- AU.addPreserved<MemorySSAWrapperPass>();
- getLoopAnalysisUsage(AU);
- }
- };
- }
- char IndVarSimplifyLegacyPass::ID = 0;
- INITIALIZE_PASS_BEGIN(IndVarSimplifyLegacyPass, "indvars",
- "Induction Variable Simplification", false, false)
- INITIALIZE_PASS_DEPENDENCY(LoopPass)
- INITIALIZE_PASS_END(IndVarSimplifyLegacyPass, "indvars",
- "Induction Variable Simplification", false, false)
- Pass *llvm::createIndVarSimplifyPass() {
- return new IndVarSimplifyLegacyPass();
- }
|