Enzyme main
Loading...
Searching...
No Matches
CacheUtility.h
Go to the documentation of this file.
1//===- CacheUtility.h - Caching values in the forward pass for later use
2//---===//
3//
4// Enzyme Project
5//
6// Part of the Enzyme Project, under the Apache License v2.0 with LLVM
7// Exceptions. See https://llvm.org/LICENSE.txt for license information.
8// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
9//
10// If using this code in an academic setting, please cite the following:
11// @incollection{enzymeNeurips,
12// title = {Instead of Rewriting Foreign Code for Machine Learning,
13// Automatically Synthesize Fast Gradients},
14// author = {Moses, William S. and Churavy, Valentin},
15// booktitle = {Advances in Neural Information Processing Systems 33},
16// year = {2020},
17// note = {To appear in},
18// }
19//
20//===----------------------------------------------------------------------===//
21//
22// This file declares a base helper class CacheUtility that manages the cache
23// of values from the forward pass for later use.
24//
25//===----------------------------------------------------------------------===//
26
27#ifndef ENZYME_CACHE_UTILITY_H
28#define ENZYME_CACHE_UTILITY_H
29
30#include <llvm/Config/llvm-config.h>
31#if LLVM_VERSION_MAJOR >= 16
32#define private public
33#include "llvm/Analysis/ScalarEvolution.h"
34#include "llvm/Transforms/Utils/ScalarEvolutionExpander.h"
35#undef private
36#else
37#include "SCEV/ScalarEvolution.h"
38#include "SCEV/ScalarEvolutionExpander.h"
39#endif
40
41#include "llvm/ADT/STLExtras.h"
42#include "llvm/ADT/SmallPtrSet.h"
43#include "llvm/Analysis/LoopInfo.h"
44#include "llvm/IR/Instructions.h"
45
46#include "llvm/Analysis/AssumptionCache.h"
47#include "llvm/Analysis/TargetLibraryInfo.h"
48#include "llvm/IR/Dominators.h"
49#include "llvm/Support/CommandLine.h"
50#include "llvm/Transforms/Utils/ValueMapper.h"
51
52#include "FunctionUtils.h"
54
55extern "C" {
56/// Pack 8 bools together in a single byte
57extern llvm::cl::opt<bool> EfficientBoolCache;
58
59extern llvm::cl::opt<bool> EnzymeZeroCache;
60}
61
62/// Container for all loop information to synthesize gradients
64 /// Canonical induction variable of the loop
65 llvm::AssertingVH<llvm::PHINode> var;
66
67 /// Increment of the induction
68 llvm::AssertingVH<llvm::Instruction> incvar;
69
70 /// Allocation of induction variable of reverse pass
71 llvm::AssertingVH<llvm::AllocaInst> antivaralloc;
72
73 /// Header of this loop
74 llvm::BasicBlock *header;
75
76 /// Preheader of this loop
77 llvm::BasicBlock *preheader;
78
79 /// Whether this loop has a statically analyzable number of iterations
80 bool dynamic;
81
82 /// limit is last value of a canonical induction variable
83 /// iters is number of times loop is run (thus iters = limit + 1)
85
87
88 /// An offset to add to the index when getting the cache pointer.
90
91 /// An overriding allocation limit size.
93
94 /// All blocks this loop exits too
95 llvm::SmallPtrSet<llvm::BasicBlock *, 8> exitBlocks;
96
97 /// Parent loop of this loop
98 llvm::Loop *parent;
99};
100static inline bool operator==(const LoopContext &lhs, const LoopContext &rhs) {
101 return lhs.parent == rhs.parent;
102}
103
104/// Modes of potential unwraps
105enum class UnwrapMode {
106 // It is already known that it is legal to fully unwrap
107 // this instruction. This means unwrap this instruction,
108 // its operands, etc. However, this will stop at known
109 // cached available from a tape.
111 // Unlike LegalFullUnwrap, this will unwrap through a tape
113 // Attempt to fully unwrap this, looking up whenever it
114 // is not legal to unwrap
116 // Attempt to fully unwrap this
118 // Unwrap the current instruction but not its operand
120};
121
122static inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
123 UnwrapMode mode) {
124 switch (mode) {
126 os << "LegalFullUnwrap";
127 break;
129 os << "LegalFullUnwrapNoTapeReplace";
130 break;
132 os << "AttemptFullUnwrapWithLookup";
133 break;
135 os << "AttemptFullUnwrap";
136 break;
138 os << "AttemptSingleUnwrap";
139 break;
140 }
141 return os;
142}
143
145public:
146 /// The function whose instructions we are caching
147 llvm::Function *const newFunc;
148
149 /// Various analysis results of newFunc
150 llvm::TargetLibraryInfo &TLI;
151 llvm::DominatorTree DT;
152
153protected:
154 llvm::LoopInfo LI;
155 llvm::AssumptionCache AC;
157
158public:
159 // Helper basicblock where all new allocations will be added to
160 // This includes allocations for cache variables
161 llvm::BasicBlock *inversionAllocs;
162
163protected:
164 CacheUtility(llvm::TargetLibraryInfo &TLI, llvm::Function *newFunc)
165 : newFunc(newFunc), TLI(TLI), DT(*newFunc), LI(DT), AC(*newFunc),
166 SE(*newFunc, TLI, AC, DT, LI) {
167 inversionAllocs = llvm::BasicBlock::Create(newFunc->getContext(),
168 "allocsForInversion", newFunc);
169 }
170
171public:
172 virtual ~CacheUtility();
173
174protected:
175 /// Map of Loop to requisite loop information needed for AD (forward/reverse
176 /// induction/etc)
177 std::map<llvm::Loop *, LoopContext> loopContexts;
178
179public:
180 /// Given a BasicBlock BB in newFunc, set loopContext to the relevant
181 /// contained loop and return true. If BB is not in a loop, return false
182 bool getContext(llvm::BasicBlock *BB, LoopContext &loopContext,
183 bool ReverseLimit);
184 /// Compute the exact backedge-taken count of L (CouldNotCompute if it is
185 /// not statically known) and the maximum number of iterations.
186 std::pair<const llvm::SCEV *, const llvm::SCEV *>
187 computeLoopLimit(llvm::Loop *L);
188
189 /// Return whether the given instruction is used as necessary as part of a
190 /// loop context This includes as the canonical induction variable or
191 /// increment
192 bool isInstructionUsedInLoopInduction(llvm::Instruction &I) {
193 for (auto &context : loopContexts) {
194 if (context.second.var == &I || context.second.incvar == &I ||
195 context.second.maxLimit == &I || context.second.trueLimit == &I) {
196 return true;
197 }
198 }
199 return false;
200 }
201
202 llvm::AllocaInst *getDynamicLoopLimit(llvm::Loop *L,
203 bool ReverseLimit = true);
204
205 /// Print out all currently cached values
206 void dumpScope() {
207 llvm::errs() << "scope:\n";
208 for (auto a : scopeMap) {
209 llvm::errs() << " scopeMap[" << *a.first << "] = " << *a.second.first
210 << " ctx:" << a.second.second.Block->getName() << "\n";
211 }
212 llvm::errs() << "end scope\n";
213 }
214
215 unsigned getCacheAlignment(unsigned bsize) const {
216 if ((bsize & (bsize - 1)) == 0) {
217 if (bsize > 8)
218 return 8;
219 else
220 return bsize;
221 } else if (bsize > 0 && bsize % 8 == 0) {
222 return 8;
223 } else if (bsize > 0 && bsize % 4 == 0) {
224 return 4;
225 } else if (bsize > 0 && bsize % 2 == 0) {
226 return 2;
227 } else
228 return 1;
229 }
230
231 /// Erase this instruction both from LLVM modules and any local
232 /// data-structures
233 virtual void erase(llvm::Instruction *I);
234 /// Replace this instruction both in LLVM modules and any local
235 /// data-structures
236 virtual void replaceAWithB(llvm::Value *A, llvm::Value *B,
237 bool storeInCache = false);
238
239 // Context information to request calculation of loop limit information
241 // Whether the limit needs to be accessible for a reverse pass
243
244 // A block inside of the loop, defining the location
245 llvm::BasicBlock *Block;
246 // Instead of getting the actual limits, return a limit of one
248
253 };
254
255 /// Given a LimitContext ctx, representing a location inside a loop nest,
256 /// break each of the loops up into chunks of loops where each chunk's number
257 /// of iterations can be computed at the chunk preheader. Every dynamic loop
258 /// defines the start of a chunk. SubLimitType is a vector of chunk objects.
259 /// More specifically it is a vector of { # iters in a Chunk (sublimit), Chunk
260 /// } Each chunk object is a vector of loops contained within the chunk. For
261 /// every loop, this returns pair of the LoopContext and the limit of that
262 /// loop Both the vector of Chunks and vector of Loops within a Chunk go from
263 /// innermost loop to outermost loop.
264 typedef llvm::SmallVector<std::pair<
265 /*sublimit*/ llvm::Value *,
266 /*loop limits*/ llvm::SmallVector<
267 std::pair<LoopContext, llvm::Value *>, 4>>,
268 0>
270 SubLimitType getSubLimits(bool inForwardPass, llvm::IRBuilder<> *RB,
271 LimitContext ctx, llvm::Value *extraSize = nullptr);
272
273private:
274 /// Internal data structure used by getSubLimit to avoid computing the same
275 /// loop limit multiple times if possible. Map's a desired limitMinus1 (see
276 /// getSubLimits) and the block the true limit requested to the value of the
277 /// limit accessible at that block
278 llvm::ValueMap<llvm::Value *,
279 std::map<llvm::BasicBlock *, llvm::WeakTrackingVH>>
280 LimitCache;
281 /// Internal data structure used by getSubLimit to avoid computing the
282 /// cumulative loop limit multiple times if possible. Map's a desired pair of
283 /// operands to be multiplied (see getSubLimits) and the block the cumulative
284 /// limit requested to the value of the limit accessible at that block This
285 /// cache is also shared with computeIndexOfChunk
286 std::map<std::tuple<llvm::Value *, llvm::Value *, llvm::BasicBlock *>,
287 llvm::Value *>
288 SizeCache;
289
290 /// Given a loop context, compute the corresponding index into said loop at
291 /// the IRBuilder<>
292 llvm::Value *computeIndexOfChunk(
293 bool inForwardPass, llvm::IRBuilder<> &v,
294 llvm::ArrayRef<std::pair<LoopContext, llvm::Value *>> containedloops,
295 const llvm::ValueToValueMapTy &available);
296
297private:
298 /// Given a cache allocation and an index denoting how many Chunks deep the
299 /// allocation is being indexed into, return the invariant metadata describing
300 /// used to describe loads/stores to the indexed pointer
301 /// Note that the cache allocation should either be an allocainst (if in
302 /// fwd/both) or an extraction from the tape
303 std::map<std::pair<llvm::Value *, int>, llvm::MDNode *>
304 CachePointerInvariantGroups;
305 /// Given a value being cached, return the invariant metadata of any
306 /// loads/stores to memory storing that value
307 std::map<llvm::Value *, llvm::MDNode *> ValueInvariantGroups;
308
309protected:
310 /// A map of values being cached to their underlying allocation/limit context
311 std::map<llvm::Value *,
312 std::pair<llvm::AssertingVH<llvm::AllocaInst>, LimitContext>>
314
315 /// A map of allocations to a vector of instruction used to create by the
316 /// allocation Keeping track of these values is useful for deallocation. This
317 /// is stored as a vector explicitly to order theses instructions in such a
318 /// way that they can be erased by iterating in reverse order.
319 std::map<llvm::AllocaInst *,
320 llvm::SmallVector<llvm::AssertingVH<llvm::Instruction>, 4>>
322
323 /// A map of allocations to a set of instructions which free memory as part of
324 /// the cache.
325 std::map<llvm::AllocaInst *, std::set<llvm::AssertingVH<llvm::CallInst>>>
327
328 /// A map of allocations to a set of instructions which allocate memory as
329 /// part of the cache
330 std::map<llvm::AllocaInst *,
331 llvm::SmallVector<llvm::AssertingVH<llvm::CallInst>, 4>>
333
334 /// Perform the final load from the cache, applying requisite invariant
335 /// group and alignment
336 llvm::Value *loadFromCachePointer(llvm::Type *T, llvm::IRBuilder<> &BuilderM,
337 llvm::Value *cptr, llvm::Value *cache);
338
339public:
340 /// Create a cache of Type T at the given LimitContext. If allocateInternal is
341 /// set this will allocate the requesite memory. If extraSize is set,
342 /// allocations will be a factor of extraSize larger
343 llvm::AllocaInst *createCacheForScope(LimitContext ctx, llvm::Type *T,
344 llvm::StringRef name, bool shouldFree,
345 bool allocateInternal = true,
346 llvm::Value *extraSize = nullptr);
347
348 /// High-level utility to "unwrap" an instruction at a new location specified
349 /// by BuilderM. Depending on the mode, it will either just unwrap this
350 /// instruction, all of its instructions operands, and optionally lookup
351 /// values when it is not legal to unwrap. If a value cannot be unwrap'd at a
352 /// given location, this will null. This high-level utility should be
353 /// implemented based off the low-level caching infrastructure provided in
354 /// this class.
355 virtual llvm::Value *
356 unwrapM(llvm::Value *const val, llvm::IRBuilder<> &BuilderM,
357 const llvm::ValueToValueMapTy &available, UnwrapMode mode,
358 llvm::BasicBlock *scope = nullptr, bool permitCache = true) = 0;
359
360 /// High-level utility to get the value an instruction at a new location
361 /// specified by BuilderM. Unlike unwrap, this function can never fail --
362 /// falling back to creating a cache if necessary. This function is
363 /// prepopulated with a set of values that are already known to be available
364 /// and may contain optimizations for getting the value in more efficient ways
365 /// (e.g. unwrap'ing when legal, looking up equivalent values, etc). This
366 /// high-level utility should be implemented based off the low-level caching
367 /// infrastructure provided in this class.
368 virtual llvm::Value *
369 lookupM(llvm::Value *val, llvm::IRBuilder<> &BuilderM,
370 const llvm::ValueToValueMapTy &incoming_availalble =
371 llvm::ValueToValueMapTy(),
372 bool tryLegalityCheck = true, llvm::BasicBlock *scope = nullptr) = 0;
373
374 virtual bool assumeDynamicLoopOfSizeOne(llvm::Loop *L) const = 0;
375
376 /// If an allocation is requested to be freed, this subclass will be called to
377 /// chose how and where to free it. It is by default not implemented, falling
378 /// back to an error. Subclasses who want to free memory should implement this
379 /// function.
380 virtual llvm::CallInst *freeCache(llvm::BasicBlock *forwardPreheader,
381 const SubLimitType &antimap, int i,
382 llvm::AllocaInst *alloc, llvm::Type *myType,
383 llvm::ConstantInt *byteSizeOfType,
384 llvm::Value *storeInto,
385 llvm::MDNode *InvariantMD) {
386 assert(0 && "freeing cache not handled in this scenario");
387 llvm_unreachable("freeing cache not handled in this scenario");
388 }
389
390 /// Given an allocation defined at a particular ctx, store the value val
391 /// in the cache at the location defined in the given builder
392 void storeInstructionInCache(LimitContext ctx, llvm::IRBuilder<> &BuilderM,
393 llvm::Value *val, llvm::AllocaInst *cache,
394 llvm::MDNode *TBAA = nullptr);
395
396 /// Given an allocation defined at a particular ctx, store the instruction
397 /// in the cache right after the instruction is executed
398 void storeInstructionInCache(LimitContext ctx, llvm::Instruction *inst,
399 llvm::AllocaInst *cache,
400 llvm::MDNode *TBAA = nullptr);
401
402 /// Given an allocation specified by the LimitContext ctx and cache, compute a
403 /// pointer that can hold the underlying type being cached. This value should
404 /// be computed at BuilderM. Optionally, instructions needed to generate this
405 /// pointer can be stored in scopeInstructions
406 llvm::Value *getCachePointer(llvm::Type *T, bool inForwardPass,
407 llvm::IRBuilder<> &BuilderM, LimitContext ctx,
408 llvm::Value *cache, bool storeInInstructionsMap,
409 const llvm::ValueToValueMapTy &available,
410 llvm::Value *extraSize);
411
412 /// Given an allocation specified by the LimitContext ctx and cache, lookup
413 /// the underlying cached value.
414 llvm::Value *lookupValueFromCache(llvm::Type *T, bool inForwardPass,
415 llvm::IRBuilder<> &BuilderM,
416 LimitContext ctx, llvm::Value *cache,
417 bool isi1,
418 const llvm::ValueToValueMapTy &available,
419 llvm::Value *extraSize = nullptr,
420 llvm::Value *extraOffset = nullptr);
421
422protected:
423 // List of values loaded from the cache
424 llvm::SmallPtrSet<llvm::LoadInst *, 10> CacheLookups;
425};
426
427// Create a new canonical induction variable of Type Ty for Loop L
428// Return the variable and the increment instruction
429std::pair<llvm::PHINode *, llvm::Instruction *>
430InsertNewCanonicalIV(llvm::Loop *L, llvm::Type *Ty,
431 const llvm::Twine &Name = "iv");
432
433// Attempt to rewrite all phinode's in the loop in terms of the
434// induction variable
436 llvm::Loop *L, llvm::PHINode *CanonicalIV, llvm::Instruction *Increment,
438 llvm::function_ref<void(llvm::Instruction *, llvm::Value *)> replacer,
439 llvm::function_ref<void(llvm::Instruction *)> eraser);
440#endif
void RemoveRedundantIVs(llvm::Loop *L, llvm::PHINode *CanonicalIV, llvm::Instruction *Increment, MustExitScalarEvolution &SE, llvm::function_ref< void(llvm::Instruction *, llvm::Value *)> replacer, llvm::function_ref< void(llvm::Instruction *)> eraser)
std::pair< llvm::PHINode *, llvm::Instruction * > InsertNewCanonicalIV(llvm::Loop *L, llvm::Type *Ty, const llvm::Twine &Name="iv")
llvm::cl::opt< bool > EnzymeZeroCache
llvm::cl::opt< bool > EfficientBoolCache
Pack 8 bools together in a single byte.
UnwrapMode
Modes of potential unwraps.
@ AttemptSingleUnwrap
@ LegalFullUnwrapNoTapeReplace
@ AttemptFullUnwrapWithLookup
static llvm::raw_ostream & operator<<(llvm::raw_ostream &os, UnwrapMode mode)
static bool operator==(const LoopContext &lhs, const LoopContext &rhs)
llvm::Function *const newFunc
The function whose instructions we are caching.
MustExitScalarEvolution SE
virtual llvm::Value * unwrapM(llvm::Value *const val, llvm::IRBuilder<> &BuilderM, const llvm::ValueToValueMapTy &available, UnwrapMode mode, llvm::BasicBlock *scope=nullptr, bool permitCache=true)=0
High-level utility to "unwrap" an instruction at a new location specified by BuilderM.
virtual llvm::CallInst * freeCache(llvm::BasicBlock *forwardPreheader, const SubLimitType &antimap, int i, llvm::AllocaInst *alloc, llvm::Type *myType, llvm::ConstantInt *byteSizeOfType, llvm::Value *storeInto, llvm::MDNode *InvariantMD)
If an allocation is requested to be freed, this subclass will be called to chose how and where to fre...
std::map< llvm::AllocaInst *, llvm::SmallVector< llvm::AssertingVH< llvm::CallInst >, 4 > > scopeAllocs
A map of allocations to a set of instructions which allocate memory as part of the cache.
std::pair< const llvm::SCEV *, const llvm::SCEV * > computeLoopLimit(llvm::Loop *L)
Compute the exact backedge-taken count of L (CouldNotCompute if it is not statically known) and the m...
llvm::AllocaInst * createCacheForScope(LimitContext ctx, llvm::Type *T, llvm::StringRef name, bool shouldFree, bool allocateInternal=true, llvm::Value *extraSize=nullptr)
Create a cache of Type T at the given LimitContext.
virtual void erase(llvm::Instruction *I)
Erase this instruction both from LLVM modules and any local data-structures.
CacheUtility(llvm::TargetLibraryInfo &TLI, llvm::Function *newFunc)
llvm::Value * getCachePointer(llvm::Type *T, bool inForwardPass, llvm::IRBuilder<> &BuilderM, LimitContext ctx, llvm::Value *cache, bool storeInInstructionsMap, const llvm::ValueToValueMapTy &available, llvm::Value *extraSize)
Given an allocation specified by the LimitContext ctx and cache, compute a pointer that can hold the ...
llvm::Value * lookupValueFromCache(llvm::Type *T, bool inForwardPass, llvm::IRBuilder<> &BuilderM, LimitContext ctx, llvm::Value *cache, bool isi1, const llvm::ValueToValueMapTy &available, llvm::Value *extraSize=nullptr, llvm::Value *extraOffset=nullptr)
Given an allocation specified by the LimitContext ctx and cache, lookup the underlying cached value.
bool getContext(llvm::BasicBlock *BB, LoopContext &loopContext, bool ReverseLimit)
Given a BasicBlock BB in newFunc, set loopContext to the relevant contained loop and return true.
llvm::Value * loadFromCachePointer(llvm::Type *T, llvm::IRBuilder<> &BuilderM, llvm::Value *cptr, llvm::Value *cache)
Perform the final load from the cache, applying requisite invariant group and alignment.
std::map< llvm::AllocaInst *, std::set< llvm::AssertingVH< llvm::CallInst > > > scopeFrees
A map of allocations to a set of instructions which free memory as part of the cache.
virtual ~CacheUtility()
void dumpScope()
Print out all currently cached values.
llvm::DominatorTree DT
llvm::TargetLibraryInfo & TLI
Various analysis results of newFunc.
llvm::LoopInfo LI
std::map< llvm::Loop *, LoopContext > loopContexts
Map of Loop to requisite loop information needed for AD (forward/reverse induction/etc)
std::map< llvm::AllocaInst *, llvm::SmallVector< llvm::AssertingVH< llvm::Instruction >, 4 > > scopeInstructions
A map of allocations to a vector of instruction used to create by the allocation Keeping track of the...
llvm::BasicBlock * inversionAllocs
std::map< llvm::Value *, std::pair< llvm::AssertingVH< llvm::AllocaInst >, LimitContext > > scopeMap
A map of values being cached to their underlying allocation/limit context.
llvm::SmallVector< std::pair< llvm::Value *, llvm::SmallVector< std::pair< LoopContext, llvm::Value * >, 4 > >, 0 > SubLimitType
Given a LimitContext ctx, representing a location inside a loop nest, break each of the loops up into...
virtual void replaceAWithB(llvm::Value *A, llvm::Value *B, bool storeInCache=false)
Replace this instruction both in LLVM modules and any local data-structures.
unsigned getCacheAlignment(unsigned bsize) const
llvm::AllocaInst * getDynamicLoopLimit(llvm::Loop *L, bool ReverseLimit=true)
llvm::SmallPtrSet< llvm::LoadInst *, 10 > CacheLookups
SubLimitType getSubLimits(bool inForwardPass, llvm::IRBuilder<> *RB, LimitContext ctx, llvm::Value *extraSize=nullptr)
Given a LimitContext ctx, representing a location inside a loop nest, break each of the loops up into...
void storeInstructionInCache(LimitContext ctx, llvm::IRBuilder<> &BuilderM, llvm::Value *val, llvm::AllocaInst *cache, llvm::MDNode *TBAA=nullptr)
Given an allocation defined at a particular ctx, store the value val in the cache at the location def...
bool isInstructionUsedInLoopInduction(llvm::Instruction &I)
Return whether the given instruction is used as necessary as part of a loop context This includes as ...
llvm::AssumptionCache AC
virtual llvm::Value * lookupM(llvm::Value *val, llvm::IRBuilder<> &BuilderM, const llvm::ValueToValueMapTy &incoming_availalble=llvm::ValueToValueMapTy(), bool tryLegalityCheck=true, llvm::BasicBlock *scope=nullptr)=0
High-level utility to get the value an instruction at a new location specified by BuilderM.
virtual bool assumeDynamicLoopOfSizeOne(llvm::Loop *L) const =0
LimitContext(bool ReverseLimit, llvm::BasicBlock *Block, bool ForceSingleIteration=false)
llvm::BasicBlock * Block
Container for all loop information to synthesize gradients.
llvm::Loop * parent
Parent loop of this loop.
llvm::BasicBlock * header
Header of this loop.
llvm::AssertingVH< llvm::Instruction > incvar
Increment of the induction.
bool dynamic
Whether this loop has a statically analyzable number of iterations.
llvm::SmallPtrSet< llvm::BasicBlock *, 8 > exitBlocks
All blocks this loop exits too.
llvm::AssertingVH< llvm::AllocaInst > antivaralloc
Allocation of induction variable of reverse pass.
llvm::AssertingVH< llvm::PHINode > var
Canonical induction variable of the loop.
AssertingReplacingVH offset
An offset to add to the index when getting the cache pointer.
llvm::BasicBlock * preheader
Preheader of this loop.
AssertingReplacingVH maxLimit
limit is last value of a canonical induction variable iters is number of times loop is run (thus iter...
AssertingReplacingVH allocLimit
An overriding allocation limit size.
AssertingReplacingVH trueLimit