xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/Analysis/LoopUnrollAnalyzer.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 //===- LoopUnrollAnalyzer.cpp - Unrolling Effect Estimation -----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements UnrolledInstAnalyzer class. It's used for predicting
10 // potential effects that loop unrolling might have, such as enabling constant
11 // propagation and other optimizations.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/Analysis/LoopUnrollAnalyzer.h"
16 #include "llvm/Analysis/LoopInfo.h"
17 
18 using namespace llvm;
19 
20 /// Try to simplify instruction \param I using its SCEV expression.
21 ///
22 /// The idea is that some AddRec expressions become constants, which then
23 /// could trigger folding of other instructions. However, that only happens
24 /// for expressions whose start value is also constant, which isn't always the
25 /// case. In another common and important case the start value is just some
26 /// address (i.e. SCEVUnknown) - in this case we compute the offset and save
27 /// it along with the base address instead.
simplifyInstWithSCEV(Instruction * I)28 bool UnrolledInstAnalyzer::simplifyInstWithSCEV(Instruction *I) {
29   if (!SE.isSCEVable(I->getType()))
30     return false;
31 
32   const SCEV *S = SE.getSCEV(I);
33   if (auto *SC = dyn_cast<SCEVConstant>(S)) {
34     SimplifiedValues[I] = SC->getValue();
35     return true;
36   }
37 
38   // If we have a loop invariant computation, we only need to compute it once.
39   // Given that, all but the first occurance are free.
40   if (!IterationNumber->isZero() && SE.isLoopInvariant(S, L))
41     return true;
42 
43   auto *AR = dyn_cast<SCEVAddRecExpr>(S);
44   if (!AR || AR->getLoop() != L)
45     return false;
46 
47   const SCEV *ValueAtIteration = AR->evaluateAtIteration(IterationNumber, SE);
48   // Check if the AddRec expression becomes a constant.
49   if (auto *SC = dyn_cast<SCEVConstant>(ValueAtIteration)) {
50     SimplifiedValues[I] = SC->getValue();
51     return true;
52   }
53 
54   // Check if the offset from the base address becomes a constant.
55   auto *Base = dyn_cast<SCEVUnknown>(SE.getPointerBase(S));
56   if (!Base)
57     return false;
58   auto *Offset =
59       dyn_cast<SCEVConstant>(SE.getMinusSCEV(ValueAtIteration, Base));
60   if (!Offset)
61     return false;
62   SimplifiedAddress Address;
63   Address.Base = Base->getValue();
64   Address.Offset = Offset->getValue();
65   SimplifiedAddresses[I] = Address;
66   return false;
67 }
68 
69 /// Try to simplify binary operator I.
70 ///
71 /// TODO: Probably it's worth to hoist the code for estimating the
72 /// simplifications effects to a separate class, since we have a very similar
73 /// code in InlineCost already.
visitBinaryOperator(BinaryOperator & I)74 bool UnrolledInstAnalyzer::visitBinaryOperator(BinaryOperator &I) {
75   Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
76   if (!isa<Constant>(LHS))
77     if (Constant *SimpleLHS = SimplifiedValues.lookup(LHS))
78       LHS = SimpleLHS;
79   if (!isa<Constant>(RHS))
80     if (Constant *SimpleRHS = SimplifiedValues.lookup(RHS))
81       RHS = SimpleRHS;
82 
83   Value *SimpleV = nullptr;
84   const DataLayout &DL = I.getModule()->getDataLayout();
85   if (auto FI = dyn_cast<FPMathOperator>(&I))
86     SimpleV =
87         SimplifyBinOp(I.getOpcode(), LHS, RHS, FI->getFastMathFlags(), DL);
88   else
89     SimpleV = SimplifyBinOp(I.getOpcode(), LHS, RHS, DL);
90 
91   if (Constant *C = dyn_cast_or_null<Constant>(SimpleV))
92     SimplifiedValues[&I] = C;
93 
94   if (SimpleV)
95     return true;
96   return Base::visitBinaryOperator(I);
97 }
98 
99 /// Try to fold load I.
visitLoad(LoadInst & I)100 bool UnrolledInstAnalyzer::visitLoad(LoadInst &I) {
101   Value *AddrOp = I.getPointerOperand();
102 
103   auto AddressIt = SimplifiedAddresses.find(AddrOp);
104   if (AddressIt == SimplifiedAddresses.end())
105     return false;
106   ConstantInt *SimplifiedAddrOp = AddressIt->second.Offset;
107 
108   auto *GV = dyn_cast<GlobalVariable>(AddressIt->second.Base);
109   // We're only interested in loads that can be completely folded to a
110   // constant.
111   if (!GV || !GV->hasDefinitiveInitializer() || !GV->isConstant())
112     return false;
113 
114   ConstantDataSequential *CDS =
115       dyn_cast<ConstantDataSequential>(GV->getInitializer());
116   if (!CDS)
117     return false;
118 
119   // We might have a vector load from an array. FIXME: for now we just bail
120   // out in this case, but we should be able to resolve and simplify such
121   // loads.
122   if (CDS->getElementType() != I.getType())
123     return false;
124 
125   unsigned ElemSize = CDS->getElementType()->getPrimitiveSizeInBits() / 8U;
126   if (SimplifiedAddrOp->getValue().getActiveBits() > 64)
127     return false;
128   int64_t SimplifiedAddrOpV = SimplifiedAddrOp->getSExtValue();
129   if (SimplifiedAddrOpV < 0) {
130     // FIXME: For now we conservatively ignore out of bound accesses, but
131     // we're allowed to perform the optimization in this case.
132     return false;
133   }
134   uint64_t Index = static_cast<uint64_t>(SimplifiedAddrOpV) / ElemSize;
135   if (Index >= CDS->getNumElements()) {
136     // FIXME: For now we conservatively ignore out of bound accesses, but
137     // we're allowed to perform the optimization in this case.
138     return false;
139   }
140 
141   Constant *CV = CDS->getElementAsConstant(Index);
142   assert(CV && "Constant expected.");
143   SimplifiedValues[&I] = CV;
144 
145   return true;
146 }
147 
148 /// Try to simplify cast instruction.
visitCastInst(CastInst & I)149 bool UnrolledInstAnalyzer::visitCastInst(CastInst &I) {
150   // Propagate constants through casts.
151   Constant *COp = dyn_cast<Constant>(I.getOperand(0));
152   if (!COp)
153     COp = SimplifiedValues.lookup(I.getOperand(0));
154 
155   // If we know a simplified value for this operand and cast is valid, save the
156   // result to SimplifiedValues.
157   // The cast can be invalid, because SimplifiedValues contains results of SCEV
158   // analysis, which operates on integers (and, e.g., might convert i8* null to
159   // i32 0).
160   if (COp && CastInst::castIsValid(I.getOpcode(), COp, I.getType())) {
161     if (Constant *C =
162             ConstantExpr::getCast(I.getOpcode(), COp, I.getType())) {
163       SimplifiedValues[&I] = C;
164       return true;
165     }
166   }
167 
168   return Base::visitCastInst(I);
169 }
170 
171 /// Try to simplify cmp instruction.
visitCmpInst(CmpInst & I)172 bool UnrolledInstAnalyzer::visitCmpInst(CmpInst &I) {
173   Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
174 
175   // First try to handle simplified comparisons.
176   if (!isa<Constant>(LHS))
177     if (Constant *SimpleLHS = SimplifiedValues.lookup(LHS))
178       LHS = SimpleLHS;
179   if (!isa<Constant>(RHS))
180     if (Constant *SimpleRHS = SimplifiedValues.lookup(RHS))
181       RHS = SimpleRHS;
182 
183   if (!isa<Constant>(LHS) && !isa<Constant>(RHS)) {
184     auto SimplifiedLHS = SimplifiedAddresses.find(LHS);
185     if (SimplifiedLHS != SimplifiedAddresses.end()) {
186       auto SimplifiedRHS = SimplifiedAddresses.find(RHS);
187       if (SimplifiedRHS != SimplifiedAddresses.end()) {
188         SimplifiedAddress &LHSAddr = SimplifiedLHS->second;
189         SimplifiedAddress &RHSAddr = SimplifiedRHS->second;
190         if (LHSAddr.Base == RHSAddr.Base) {
191           LHS = LHSAddr.Offset;
192           RHS = RHSAddr.Offset;
193         }
194       }
195     }
196   }
197 
198   if (Constant *CLHS = dyn_cast<Constant>(LHS)) {
199     if (Constant *CRHS = dyn_cast<Constant>(RHS)) {
200       if (CLHS->getType() == CRHS->getType()) {
201         if (Constant *C = ConstantExpr::getCompare(I.getPredicate(), CLHS, CRHS)) {
202           SimplifiedValues[&I] = C;
203           return true;
204         }
205       }
206     }
207   }
208 
209   return Base::visitCmpInst(I);
210 }
211 
visitPHINode(PHINode & PN)212 bool UnrolledInstAnalyzer::visitPHINode(PHINode &PN) {
213   // Run base visitor first. This way we can gather some useful for later
214   // analysis information.
215   if (Base::visitPHINode(PN))
216     return true;
217 
218   // The loop induction PHI nodes are definitionally free.
219   return PN.getParent() == L->getHeader();
220 }
221 
visitInstruction(Instruction & I)222 bool UnrolledInstAnalyzer::visitInstruction(Instruction &I) {
223   return simplifyInstWithSCEV(&I);
224 }
225