10b57cec5SDimitry Andric //===- LoopUnrollAnalyzer.cpp - Unrolling Effect Estimation -----*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements UnrolledInstAnalyzer class. It's used for predicting 100b57cec5SDimitry Andric // potential effects that loop unrolling might have, such as enabling constant 110b57cec5SDimitry Andric // propagation and other optimizations. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "llvm/Analysis/LoopUnrollAnalyzer.h" 1681ad6265SDimitry Andric #include "llvm/Analysis/InstructionSimplify.h" 175ffd83dbSDimitry Andric #include "llvm/Analysis/LoopInfo.h" 1881ad6265SDimitry Andric #include "llvm/Analysis/ScalarEvolutionExpressions.h" 1981ad6265SDimitry Andric #include "llvm/IR/Operator.h" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric using namespace llvm; 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric /// Try to simplify instruction \param I using its SCEV expression. 240b57cec5SDimitry Andric /// 250b57cec5SDimitry Andric /// The idea is that some AddRec expressions become constants, which then 260b57cec5SDimitry Andric /// could trigger folding of other instructions. However, that only happens 270b57cec5SDimitry Andric /// for expressions whose start value is also constant, which isn't always the 280b57cec5SDimitry Andric /// case. In another common and important case the start value is just some 290b57cec5SDimitry Andric /// address (i.e. SCEVUnknown) - in this case we compute the offset and save 300b57cec5SDimitry Andric /// it along with the base address instead. 310b57cec5SDimitry Andric bool UnrolledInstAnalyzer::simplifyInstWithSCEV(Instruction *I) { 320b57cec5SDimitry Andric if (!SE.isSCEVable(I->getType())) 330b57cec5SDimitry Andric return false; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric const SCEV *S = SE.getSCEV(I); 360b57cec5SDimitry Andric if (auto *SC = dyn_cast<SCEVConstant>(S)) { 370b57cec5SDimitry Andric SimplifiedValues[I] = SC->getValue(); 380b57cec5SDimitry Andric return true; 390b57cec5SDimitry Andric } 400b57cec5SDimitry Andric 41fe6060f1SDimitry Andric // If we have a loop invariant computation, we only need to compute it once. 42fe6060f1SDimitry Andric // Given that, all but the first occurance are free. 43fe6060f1SDimitry Andric if (!IterationNumber->isZero() && SE.isLoopInvariant(S, L)) 44fe6060f1SDimitry Andric return true; 45fe6060f1SDimitry Andric 460b57cec5SDimitry Andric auto *AR = dyn_cast<SCEVAddRecExpr>(S); 470b57cec5SDimitry Andric if (!AR || AR->getLoop() != L) 480b57cec5SDimitry Andric return false; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric const SCEV *ValueAtIteration = AR->evaluateAtIteration(IterationNumber, SE); 510b57cec5SDimitry Andric // Check if the AddRec expression becomes a constant. 520b57cec5SDimitry Andric if (auto *SC = dyn_cast<SCEVConstant>(ValueAtIteration)) { 530b57cec5SDimitry Andric SimplifiedValues[I] = SC->getValue(); 540b57cec5SDimitry Andric return true; 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric // Check if the offset from the base address becomes a constant. 580b57cec5SDimitry Andric auto *Base = dyn_cast<SCEVUnknown>(SE.getPointerBase(S)); 590b57cec5SDimitry Andric if (!Base) 600b57cec5SDimitry Andric return false; 610b57cec5SDimitry Andric auto *Offset = 620b57cec5SDimitry Andric dyn_cast<SCEVConstant>(SE.getMinusSCEV(ValueAtIteration, Base)); 630b57cec5SDimitry Andric if (!Offset) 640b57cec5SDimitry Andric return false; 650b57cec5SDimitry Andric SimplifiedAddress Address; 660b57cec5SDimitry Andric Address.Base = Base->getValue(); 670b57cec5SDimitry Andric Address.Offset = Offset->getValue(); 680b57cec5SDimitry Andric SimplifiedAddresses[I] = Address; 690b57cec5SDimitry Andric return false; 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric /// Try to simplify binary operator I. 730b57cec5SDimitry Andric /// 740b57cec5SDimitry Andric /// TODO: Probably it's worth to hoist the code for estimating the 750b57cec5SDimitry Andric /// simplifications effects to a separate class, since we have a very similar 760b57cec5SDimitry Andric /// code in InlineCost already. 770b57cec5SDimitry Andric bool UnrolledInstAnalyzer::visitBinaryOperator(BinaryOperator &I) { 780b57cec5SDimitry Andric Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); 790b57cec5SDimitry Andric if (!isa<Constant>(LHS)) 80fe6060f1SDimitry Andric if (Value *SimpleLHS = SimplifiedValues.lookup(LHS)) 810b57cec5SDimitry Andric LHS = SimpleLHS; 820b57cec5SDimitry Andric if (!isa<Constant>(RHS)) 83fe6060f1SDimitry Andric if (Value *SimpleRHS = SimplifiedValues.lookup(RHS)) 840b57cec5SDimitry Andric RHS = SimpleRHS; 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric Value *SimpleV = nullptr; 87*0fca6ea1SDimitry Andric const DataLayout &DL = I.getDataLayout(); 880b57cec5SDimitry Andric if (auto FI = dyn_cast<FPMathOperator>(&I)) 890b57cec5SDimitry Andric SimpleV = 9081ad6265SDimitry Andric simplifyBinOp(I.getOpcode(), LHS, RHS, FI->getFastMathFlags(), DL); 910b57cec5SDimitry Andric else 9281ad6265SDimitry Andric SimpleV = simplifyBinOp(I.getOpcode(), LHS, RHS, DL); 930b57cec5SDimitry Andric 94fe6060f1SDimitry Andric if (SimpleV) { 95fe6060f1SDimitry Andric SimplifiedValues[&I] = SimpleV; 960b57cec5SDimitry Andric return true; 97fe6060f1SDimitry Andric } 980b57cec5SDimitry Andric return Base::visitBinaryOperator(I); 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric /// Try to fold load I. 1020b57cec5SDimitry Andric bool UnrolledInstAnalyzer::visitLoad(LoadInst &I) { 1030b57cec5SDimitry Andric Value *AddrOp = I.getPointerOperand(); 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric auto AddressIt = SimplifiedAddresses.find(AddrOp); 1060b57cec5SDimitry Andric if (AddressIt == SimplifiedAddresses.end()) 1070b57cec5SDimitry Andric return false; 1080b57cec5SDimitry Andric ConstantInt *SimplifiedAddrOp = AddressIt->second.Offset; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric auto *GV = dyn_cast<GlobalVariable>(AddressIt->second.Base); 1110b57cec5SDimitry Andric // We're only interested in loads that can be completely folded to a 1120b57cec5SDimitry Andric // constant. 1130b57cec5SDimitry Andric if (!GV || !GV->hasDefinitiveInitializer() || !GV->isConstant()) 1140b57cec5SDimitry Andric return false; 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric ConstantDataSequential *CDS = 1170b57cec5SDimitry Andric dyn_cast<ConstantDataSequential>(GV->getInitializer()); 1180b57cec5SDimitry Andric if (!CDS) 1190b57cec5SDimitry Andric return false; 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric // We might have a vector load from an array. FIXME: for now we just bail 1220b57cec5SDimitry Andric // out in this case, but we should be able to resolve and simplify such 1230b57cec5SDimitry Andric // loads. 1240b57cec5SDimitry Andric if (CDS->getElementType() != I.getType()) 1250b57cec5SDimitry Andric return false; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric unsigned ElemSize = CDS->getElementType()->getPrimitiveSizeInBits() / 8U; 1280b57cec5SDimitry Andric if (SimplifiedAddrOp->getValue().getActiveBits() > 64) 1290b57cec5SDimitry Andric return false; 1300b57cec5SDimitry Andric int64_t SimplifiedAddrOpV = SimplifiedAddrOp->getSExtValue(); 1310b57cec5SDimitry Andric if (SimplifiedAddrOpV < 0) { 1320b57cec5SDimitry Andric // FIXME: For now we conservatively ignore out of bound accesses, but 1330b57cec5SDimitry Andric // we're allowed to perform the optimization in this case. 1340b57cec5SDimitry Andric return false; 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric uint64_t Index = static_cast<uint64_t>(SimplifiedAddrOpV) / ElemSize; 1370b57cec5SDimitry Andric if (Index >= CDS->getNumElements()) { 1380b57cec5SDimitry Andric // FIXME: For now we conservatively ignore out of bound accesses, but 1390b57cec5SDimitry Andric // we're allowed to perform the optimization in this case. 1400b57cec5SDimitry Andric return false; 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric Constant *CV = CDS->getElementAsConstant(Index); 1440b57cec5SDimitry Andric assert(CV && "Constant expected."); 1450b57cec5SDimitry Andric SimplifiedValues[&I] = CV; 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric return true; 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric /// Try to simplify cast instruction. 1510b57cec5SDimitry Andric bool UnrolledInstAnalyzer::visitCastInst(CastInst &I) { 152fe6060f1SDimitry Andric Value *Op = I.getOperand(0); 153fe6060f1SDimitry Andric if (Value *Simplified = SimplifiedValues.lookup(Op)) 154fe6060f1SDimitry Andric Op = Simplified; 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric // The cast can be invalid, because SimplifiedValues contains results of SCEV 1570b57cec5SDimitry Andric // analysis, which operates on integers (and, e.g., might convert i8* null to 1580b57cec5SDimitry Andric // i32 0). 159fe6060f1SDimitry Andric if (CastInst::castIsValid(I.getOpcode(), Op, I.getType())) { 160*0fca6ea1SDimitry Andric const DataLayout &DL = I.getDataLayout(); 16181ad6265SDimitry Andric if (Value *V = simplifyCastInst(I.getOpcode(), Op, I.getType(), DL)) { 162fe6060f1SDimitry Andric SimplifiedValues[&I] = V; 1630b57cec5SDimitry Andric return true; 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric return Base::visitCastInst(I); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric /// Try to simplify cmp instruction. 1710b57cec5SDimitry Andric bool UnrolledInstAnalyzer::visitCmpInst(CmpInst &I) { 1720b57cec5SDimitry Andric Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric // First try to handle simplified comparisons. 1750b57cec5SDimitry Andric if (!isa<Constant>(LHS)) 176fe6060f1SDimitry Andric if (Value *SimpleLHS = SimplifiedValues.lookup(LHS)) 1770b57cec5SDimitry Andric LHS = SimpleLHS; 1780b57cec5SDimitry Andric if (!isa<Constant>(RHS)) 179fe6060f1SDimitry Andric if (Value *SimpleRHS = SimplifiedValues.lookup(RHS)) 1800b57cec5SDimitry Andric RHS = SimpleRHS; 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric if (!isa<Constant>(LHS) && !isa<Constant>(RHS)) { 1830b57cec5SDimitry Andric auto SimplifiedLHS = SimplifiedAddresses.find(LHS); 1840b57cec5SDimitry Andric if (SimplifiedLHS != SimplifiedAddresses.end()) { 1850b57cec5SDimitry Andric auto SimplifiedRHS = SimplifiedAddresses.find(RHS); 1860b57cec5SDimitry Andric if (SimplifiedRHS != SimplifiedAddresses.end()) { 1870b57cec5SDimitry Andric SimplifiedAddress &LHSAddr = SimplifiedLHS->second; 1880b57cec5SDimitry Andric SimplifiedAddress &RHSAddr = SimplifiedRHS->second; 1890b57cec5SDimitry Andric if (LHSAddr.Base == RHSAddr.Base) { 1900b57cec5SDimitry Andric LHS = LHSAddr.Offset; 1910b57cec5SDimitry Andric RHS = RHSAddr.Offset; 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 197*0fca6ea1SDimitry Andric const DataLayout &DL = I.getDataLayout(); 19881ad6265SDimitry Andric if (Value *V = simplifyCmpInst(I.getPredicate(), LHS, RHS, DL)) { 199fe6060f1SDimitry Andric SimplifiedValues[&I] = V; 2000b57cec5SDimitry Andric return true; 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric return Base::visitCmpInst(I); 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric bool UnrolledInstAnalyzer::visitPHINode(PHINode &PN) { 2070b57cec5SDimitry Andric // Run base visitor first. This way we can gather some useful for later 2080b57cec5SDimitry Andric // analysis information. 2090b57cec5SDimitry Andric if (Base::visitPHINode(PN)) 2100b57cec5SDimitry Andric return true; 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric // The loop induction PHI nodes are definitionally free. 2130b57cec5SDimitry Andric return PN.getParent() == L->getHeader(); 2140b57cec5SDimitry Andric } 215fe6060f1SDimitry Andric 216fe6060f1SDimitry Andric bool UnrolledInstAnalyzer::visitInstruction(Instruction &I) { 217fe6060f1SDimitry Andric return simplifyInstWithSCEV(&I); 218fe6060f1SDimitry Andric } 219