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