11da4afdfSMichael Zolotukhin //===- LoopUnrollAnalyzer.cpp - Unrolling Effect Estimation -----*- C++ -*-===//
21da4afdfSMichael Zolotukhin //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61da4afdfSMichael Zolotukhin //
71da4afdfSMichael Zolotukhin //===----------------------------------------------------------------------===//
81da4afdfSMichael Zolotukhin //
91da4afdfSMichael Zolotukhin // This file implements UnrolledInstAnalyzer class. It's used for predicting
101da4afdfSMichael Zolotukhin // potential effects that loop unrolling might have, such as enabling constant
111da4afdfSMichael Zolotukhin // propagation and other optimizations.
121da4afdfSMichael Zolotukhin //
131da4afdfSMichael Zolotukhin //===----------------------------------------------------------------------===//
141da4afdfSMichael Zolotukhin
151da4afdfSMichael Zolotukhin #include "llvm/Analysis/LoopUnrollAnalyzer.h"
1671c3a551Sserge-sans-paille #include "llvm/Analysis/InstructionSimplify.h"
17a5f1f9c9SSimon Pilgrim #include "llvm/Analysis/LoopInfo.h"
1871c3a551Sserge-sans-paille #include "llvm/Analysis/ScalarEvolutionExpressions.h"
1971c3a551Sserge-sans-paille #include "llvm/IR/Operator.h"
201da4afdfSMichael Zolotukhin
211da4afdfSMichael Zolotukhin using namespace llvm;
221da4afdfSMichael Zolotukhin
235f8f34e4SAdrian Prantl /// Try to simplify instruction \param I using its SCEV expression.
241da4afdfSMichael Zolotukhin ///
251da4afdfSMichael Zolotukhin /// The idea is that some AddRec expressions become constants, which then
261da4afdfSMichael Zolotukhin /// could trigger folding of other instructions. However, that only happens
271da4afdfSMichael Zolotukhin /// for expressions whose start value is also constant, which isn't always the
281da4afdfSMichael Zolotukhin /// case. In another common and important case the start value is just some
291da4afdfSMichael Zolotukhin /// address (i.e. SCEVUnknown) - in this case we compute the offset and save
301da4afdfSMichael Zolotukhin /// it along with the base address instead.
simplifyInstWithSCEV(Instruction * I)311da4afdfSMichael Zolotukhin bool UnrolledInstAnalyzer::simplifyInstWithSCEV(Instruction *I) {
321da4afdfSMichael Zolotukhin if (!SE.isSCEVable(I->getType()))
331da4afdfSMichael Zolotukhin return false;
341da4afdfSMichael Zolotukhin
351da4afdfSMichael Zolotukhin const SCEV *S = SE.getSCEV(I);
361da4afdfSMichael Zolotukhin if (auto *SC = dyn_cast<SCEVConstant>(S)) {
371da4afdfSMichael Zolotukhin SimplifiedValues[I] = SC->getValue();
381da4afdfSMichael Zolotukhin return true;
391da4afdfSMichael Zolotukhin }
401da4afdfSMichael Zolotukhin
4123c93c25SPhilip Reames // If we have a loop invariant computation, we only need to compute it once.
4223c93c25SPhilip Reames // Given that, all but the first occurance are free.
4323c93c25SPhilip Reames if (!IterationNumber->isZero() && SE.isLoopInvariant(S, L))
4423c93c25SPhilip Reames return true;
4523c93c25SPhilip Reames
461da4afdfSMichael Zolotukhin auto *AR = dyn_cast<SCEVAddRecExpr>(S);
479f520ebcSMichael Zolotukhin if (!AR || AR->getLoop() != L)
481da4afdfSMichael Zolotukhin return false;
491da4afdfSMichael Zolotukhin
501da4afdfSMichael Zolotukhin const SCEV *ValueAtIteration = AR->evaluateAtIteration(IterationNumber, SE);
511da4afdfSMichael Zolotukhin // Check if the AddRec expression becomes a constant.
521da4afdfSMichael Zolotukhin if (auto *SC = dyn_cast<SCEVConstant>(ValueAtIteration)) {
531da4afdfSMichael Zolotukhin SimplifiedValues[I] = SC->getValue();
541da4afdfSMichael Zolotukhin return true;
551da4afdfSMichael Zolotukhin }
561da4afdfSMichael Zolotukhin
571da4afdfSMichael Zolotukhin // Check if the offset from the base address becomes a constant.
581da4afdfSMichael Zolotukhin auto *Base = dyn_cast<SCEVUnknown>(SE.getPointerBase(S));
591da4afdfSMichael Zolotukhin if (!Base)
601da4afdfSMichael Zolotukhin return false;
611da4afdfSMichael Zolotukhin auto *Offset =
621da4afdfSMichael Zolotukhin dyn_cast<SCEVConstant>(SE.getMinusSCEV(ValueAtIteration, Base));
631da4afdfSMichael Zolotukhin if (!Offset)
641da4afdfSMichael Zolotukhin return false;
651da4afdfSMichael Zolotukhin SimplifiedAddress Address;
661da4afdfSMichael Zolotukhin Address.Base = Base->getValue();
671da4afdfSMichael Zolotukhin Address.Offset = Offset->getValue();
681da4afdfSMichael Zolotukhin SimplifiedAddresses[I] = Address;
69a59a308eSMichael Zolotukhin return false;
701da4afdfSMichael Zolotukhin }
711da4afdfSMichael Zolotukhin
721da4afdfSMichael Zolotukhin /// Try to simplify binary operator I.
731da4afdfSMichael Zolotukhin ///
741da4afdfSMichael Zolotukhin /// TODO: Probably it's worth to hoist the code for estimating the
751da4afdfSMichael Zolotukhin /// simplifications effects to a separate class, since we have a very similar
761da4afdfSMichael Zolotukhin /// code in InlineCost already.
visitBinaryOperator(BinaryOperator & I)771da4afdfSMichael Zolotukhin bool UnrolledInstAnalyzer::visitBinaryOperator(BinaryOperator &I) {
781da4afdfSMichael Zolotukhin Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
791da4afdfSMichael Zolotukhin if (!isa<Constant>(LHS))
809cc2181eSPhilip Reames if (Value *SimpleLHS = SimplifiedValues.lookup(LHS))
811da4afdfSMichael Zolotukhin LHS = SimpleLHS;
821da4afdfSMichael Zolotukhin if (!isa<Constant>(RHS))
839cc2181eSPhilip Reames if (Value *SimpleRHS = SimplifiedValues.lookup(RHS))
841da4afdfSMichael Zolotukhin RHS = SimpleRHS;
851da4afdfSMichael Zolotukhin
861da4afdfSMichael Zolotukhin Value *SimpleV = nullptr;
871da4afdfSMichael Zolotukhin const DataLayout &DL = I.getModule()->getDataLayout();
881da4afdfSMichael Zolotukhin if (auto FI = dyn_cast<FPMathOperator>(&I))
891da4afdfSMichael Zolotukhin SimpleV =
90*b8c2781fSSimon Moll simplifyBinOp(I.getOpcode(), LHS, RHS, FI->getFastMathFlags(), DL);
911da4afdfSMichael Zolotukhin else
92*b8c2781fSSimon Moll SimpleV = simplifyBinOp(I.getOpcode(), LHS, RHS, DL);
931da4afdfSMichael Zolotukhin
949cc2181eSPhilip Reames if (SimpleV) {
959cc2181eSPhilip Reames SimplifiedValues[&I] = SimpleV;
961da4afdfSMichael Zolotukhin return true;
979cc2181eSPhilip Reames }
981da4afdfSMichael Zolotukhin return Base::visitBinaryOperator(I);
991da4afdfSMichael Zolotukhin }
1001da4afdfSMichael Zolotukhin
1011da4afdfSMichael Zolotukhin /// Try to fold load I.
visitLoad(LoadInst & I)1021da4afdfSMichael Zolotukhin bool UnrolledInstAnalyzer::visitLoad(LoadInst &I) {
1031da4afdfSMichael Zolotukhin Value *AddrOp = I.getPointerOperand();
1041da4afdfSMichael Zolotukhin
1051da4afdfSMichael Zolotukhin auto AddressIt = SimplifiedAddresses.find(AddrOp);
1061da4afdfSMichael Zolotukhin if (AddressIt == SimplifiedAddresses.end())
1071da4afdfSMichael Zolotukhin return false;
1081da4afdfSMichael Zolotukhin ConstantInt *SimplifiedAddrOp = AddressIt->second.Offset;
1091da4afdfSMichael Zolotukhin
1101da4afdfSMichael Zolotukhin auto *GV = dyn_cast<GlobalVariable>(AddressIt->second.Base);
1111da4afdfSMichael Zolotukhin // We're only interested in loads that can be completely folded to a
1121da4afdfSMichael Zolotukhin // constant.
1131da4afdfSMichael Zolotukhin if (!GV || !GV->hasDefinitiveInitializer() || !GV->isConstant())
1141da4afdfSMichael Zolotukhin return false;
1151da4afdfSMichael Zolotukhin
1161da4afdfSMichael Zolotukhin ConstantDataSequential *CDS =
1171da4afdfSMichael Zolotukhin dyn_cast<ConstantDataSequential>(GV->getInitializer());
1181da4afdfSMichael Zolotukhin if (!CDS)
1191da4afdfSMichael Zolotukhin return false;
1201da4afdfSMichael Zolotukhin
1211da4afdfSMichael Zolotukhin // We might have a vector load from an array. FIXME: for now we just bail
1221da4afdfSMichael Zolotukhin // out in this case, but we should be able to resolve and simplify such
1231da4afdfSMichael Zolotukhin // loads.
1242d3592d4SMichael Zolotukhin if (CDS->getElementType() != I.getType())
1251da4afdfSMichael Zolotukhin return false;
1261da4afdfSMichael Zolotukhin
127796331c0SDavid Majnemer unsigned ElemSize = CDS->getElementType()->getPrimitiveSizeInBits() / 8U;
128796331c0SDavid Majnemer if (SimplifiedAddrOp->getValue().getActiveBits() > 64)
12915e74513SMichael Zolotukhin return false;
130796331c0SDavid Majnemer int64_t SimplifiedAddrOpV = SimplifiedAddrOp->getSExtValue();
131796331c0SDavid Majnemer if (SimplifiedAddrOpV < 0) {
132796331c0SDavid Majnemer // FIXME: For now we conservatively ignore out of bound accesses, but
133796331c0SDavid Majnemer // we're allowed to perform the optimization in this case.
134796331c0SDavid Majnemer return false;
135796331c0SDavid Majnemer }
136796331c0SDavid Majnemer uint64_t Index = static_cast<uint64_t>(SimplifiedAddrOpV) / ElemSize;
1371da4afdfSMichael Zolotukhin if (Index >= CDS->getNumElements()) {
1381da4afdfSMichael Zolotukhin // FIXME: For now we conservatively ignore out of bound accesses, but
1391da4afdfSMichael Zolotukhin // we're allowed to perform the optimization in this case.
1401da4afdfSMichael Zolotukhin return false;
1411da4afdfSMichael Zolotukhin }
1421da4afdfSMichael Zolotukhin
1431da4afdfSMichael Zolotukhin Constant *CV = CDS->getElementAsConstant(Index);
1441da4afdfSMichael Zolotukhin assert(CV && "Constant expected.");
1451da4afdfSMichael Zolotukhin SimplifiedValues[&I] = CV;
1461da4afdfSMichael Zolotukhin
1471da4afdfSMichael Zolotukhin return true;
1481da4afdfSMichael Zolotukhin }
1491da4afdfSMichael Zolotukhin
1501da4afdfSMichael Zolotukhin /// Try to simplify cast instruction.
visitCastInst(CastInst & I)1511da4afdfSMichael Zolotukhin bool UnrolledInstAnalyzer::visitCastInst(CastInst &I) {
1529cc2181eSPhilip Reames Value *Op = I.getOperand(0);
1539cc2181eSPhilip Reames if (Value *Simplified = SimplifiedValues.lookup(Op))
1549cc2181eSPhilip Reames Op = Simplified;
155d69cd1e0SMichael Zolotukhin
156d69cd1e0SMichael Zolotukhin // The cast can be invalid, because SimplifiedValues contains results of SCEV
157d69cd1e0SMichael Zolotukhin // analysis, which operates on integers (and, e.g., might convert i8* null to
158d69cd1e0SMichael Zolotukhin // i32 0).
1599cc2181eSPhilip Reames if (CastInst::castIsValid(I.getOpcode(), Op, I.getType())) {
1609cc2181eSPhilip Reames const DataLayout &DL = I.getModule()->getDataLayout();
161*b8c2781fSSimon Moll if (Value *V = simplifyCastInst(I.getOpcode(), Op, I.getType(), DL)) {
1629cc2181eSPhilip Reames SimplifiedValues[&I] = V;
1631da4afdfSMichael Zolotukhin return true;
1641da4afdfSMichael Zolotukhin }
1653898b2b5SMichael Zolotukhin }
1661da4afdfSMichael Zolotukhin
1671da4afdfSMichael Zolotukhin return Base::visitCastInst(I);
1681da4afdfSMichael Zolotukhin }
1691da4afdfSMichael Zolotukhin
1701da4afdfSMichael Zolotukhin /// Try to simplify cmp instruction.
visitCmpInst(CmpInst & I)1711da4afdfSMichael Zolotukhin bool UnrolledInstAnalyzer::visitCmpInst(CmpInst &I) {
1721da4afdfSMichael Zolotukhin Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
1731da4afdfSMichael Zolotukhin
1741da4afdfSMichael Zolotukhin // First try to handle simplified comparisons.
1751da4afdfSMichael Zolotukhin if (!isa<Constant>(LHS))
1769cc2181eSPhilip Reames if (Value *SimpleLHS = SimplifiedValues.lookup(LHS))
1771da4afdfSMichael Zolotukhin LHS = SimpleLHS;
1781da4afdfSMichael Zolotukhin if (!isa<Constant>(RHS))
1799cc2181eSPhilip Reames if (Value *SimpleRHS = SimplifiedValues.lookup(RHS))
1801da4afdfSMichael Zolotukhin RHS = SimpleRHS;
1811da4afdfSMichael Zolotukhin
1821da4afdfSMichael Zolotukhin if (!isa<Constant>(LHS) && !isa<Constant>(RHS)) {
1831da4afdfSMichael Zolotukhin auto SimplifiedLHS = SimplifiedAddresses.find(LHS);
1841da4afdfSMichael Zolotukhin if (SimplifiedLHS != SimplifiedAddresses.end()) {
1851da4afdfSMichael Zolotukhin auto SimplifiedRHS = SimplifiedAddresses.find(RHS);
1861da4afdfSMichael Zolotukhin if (SimplifiedRHS != SimplifiedAddresses.end()) {
1871da4afdfSMichael Zolotukhin SimplifiedAddress &LHSAddr = SimplifiedLHS->second;
1881da4afdfSMichael Zolotukhin SimplifiedAddress &RHSAddr = SimplifiedRHS->second;
1891da4afdfSMichael Zolotukhin if (LHSAddr.Base == RHSAddr.Base) {
1901da4afdfSMichael Zolotukhin LHS = LHSAddr.Offset;
1911da4afdfSMichael Zolotukhin RHS = RHSAddr.Offset;
1921da4afdfSMichael Zolotukhin }
1931da4afdfSMichael Zolotukhin }
1941da4afdfSMichael Zolotukhin }
1951da4afdfSMichael Zolotukhin }
1961da4afdfSMichael Zolotukhin
1979cc2181eSPhilip Reames const DataLayout &DL = I.getModule()->getDataLayout();
198*b8c2781fSSimon Moll if (Value *V = simplifyCmpInst(I.getPredicate(), LHS, RHS, DL)) {
1999cc2181eSPhilip Reames SimplifiedValues[&I] = V;
2001da4afdfSMichael Zolotukhin return true;
2011da4afdfSMichael Zolotukhin }
2021da4afdfSMichael Zolotukhin
2031da4afdfSMichael Zolotukhin return Base::visitCmpInst(I);
2041da4afdfSMichael Zolotukhin }
205963a6d9cSMichael Zolotukhin
visitPHINode(PHINode & PN)206963a6d9cSMichael Zolotukhin bool UnrolledInstAnalyzer::visitPHINode(PHINode &PN) {
207963a6d9cSMichael Zolotukhin // Run base visitor first. This way we can gather some useful for later
208963a6d9cSMichael Zolotukhin // analysis information.
209963a6d9cSMichael Zolotukhin if (Base::visitPHINode(PN))
210963a6d9cSMichael Zolotukhin return true;
211963a6d9cSMichael Zolotukhin
212963a6d9cSMichael Zolotukhin // The loop induction PHI nodes are definitionally free.
213963a6d9cSMichael Zolotukhin return PN.getParent() == L->getHeader();
214963a6d9cSMichael Zolotukhin }
215cc5f6ae4SPhilip Reames
visitInstruction(Instruction & I)216cc5f6ae4SPhilip Reames bool UnrolledInstAnalyzer::visitInstruction(Instruction &I) {
217cc5f6ae4SPhilip Reames return simplifyInstWithSCEV(&I);
218cc5f6ae4SPhilip Reames }
219