Enzyme main
Loading...
Searching...
No Matches
CacheUtility.cpp
Go to the documentation of this file.
1//===- CacheUtility.cpp - 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 defines a base helper class CacheUtility that manages the cache
23// of values from the forward pass for later use.
24//
25//===----------------------------------------------------------------------===//
26
27#include "CacheUtility.h"
28
29#include "llvm/IR/PatternMatch.h"
30
31#include "FunctionUtils.h"
32#include "llvm/Analysis/ScalarEvolutionExpressions.h"
33#include <utility>
34
35using namespace llvm;
36
37/// Pack 8 bools together in a single byte
38extern "C" {
39llvm::cl::opt<bool>
40 EfficientBoolCache("enzyme-smallbool", cl::init(false), cl::Hidden,
41 cl::desc("Place 8 bools together in a single byte"));
42
43llvm::cl::opt<bool> EnzymeZeroCache("enzyme-zero-cache", cl::init(false),
44 cl::Hidden,
45 cl::desc("Zero initialize the cache"));
46
47llvm::cl::opt<bool>
48 EnzymePrintPerf("enzyme-print-perf", cl::init(false), cl::Hidden,
49 cl::desc("Enable Enzyme to print performance info"));
50
51llvm::cl::opt<bool> EfficientMaxCache(
52 "enzyme-max-cache", cl::init(false), cl::Hidden,
53 cl::desc(
54 "Avoid reallocs when possible by potentially overallocating cache"));
55
56llvm::cl::opt<bool> EnzymeRewriteAccumulators(
57 "enzyme-rewrite-accumulators", cl::init(true), cl::Hidden,
58 cl::desc("Rewrite a loop-carried counter whose step is an inner loop's "
59 "trip count into a closed form of the induction variable"));
60}
61
63
64/// Erase this instruction both from LLVM modules and any local data-structures
65void CacheUtility::erase(Instruction *I) {
66 assert(I);
67
68 if (auto found = findInMap(scopeMap, (Value *)I)) {
69 scopeFrees.erase(found->first);
70 scopeAllocs.erase(found->first);
71 scopeInstructions.erase(found->first);
72 }
73 if (auto AI = dyn_cast<AllocaInst>(I)) {
74 scopeFrees.erase(AI);
75 scopeAllocs.erase(AI);
76 scopeInstructions.erase(AI);
77 }
78 scopeMap.erase(I);
79 SE.eraseValueFromMap(I);
80
81 if (!I->use_empty()) {
82 std::string str;
83 raw_string_ostream ss(str);
84 ss << "Erased value with a use:\n";
85 ss << *newFunc->getParent() << "\n";
86 ss << *newFunc << "\n";
87 ss << *I << "\n";
90 nullptr, nullptr, nullptr);
91 } else {
92 EmitFailure("GetIndexError", I->getDebugLoc(), I, ss.str());
93 }
94 I->replaceAllUsesWith(UndefValue::get(I->getType()));
95 }
96 assert(I->use_empty());
97 I->eraseFromParent();
98}
99
100/// Replace this instruction both in LLVM modules and any local data-structures
101void CacheUtility::replaceAWithB(Value *A, Value *B, bool storeInCache) {
102 auto found = scopeMap.find(A);
103 if (found != scopeMap.end()) {
104 insert_or_assign2(scopeMap, B, found->second);
105
106 llvm::AllocaInst *cache = found->second.first;
107 if (storeInCache) {
108 assert(isa<Instruction>(B));
109 auto stfound = scopeInstructions.find(cache);
110 if (stfound != scopeInstructions.end()) {
111 SmallVector<Instruction *, 3> tmpInstructions(stfound->second.begin(),
112 stfound->second.end());
113 scopeInstructions.erase(stfound);
114 for (auto st : tmpInstructions)
115 cast<StoreInst>(&*st)->eraseFromParent();
116 MDNode *TBAA = nullptr;
117 if (auto I = dyn_cast<Instruction>(A))
118 TBAA = I->getMetadata(LLVMContext::MD_tbaa);
119 storeInstructionInCache(found->second.second, cast<Instruction>(B),
120 cache, TBAA);
121 }
122 }
123
124 scopeMap.erase(A);
125 }
126 A->replaceAllUsesWith(B);
127}
128
129// Create a new canonical induction variable of Type Ty for Loop L
130// Return the variable and the increment instruction
131std::pair<PHINode *, Instruction *>
132InsertNewCanonicalIV(Loop *L, Type *Ty, const llvm::Twine &Name) {
133 assert(L);
134 assert(Ty);
135
136 BasicBlock *Header = L->getHeader();
137 assert(Header);
138 IRBuilder<> B(Header, Header->begin());
139 PHINode *CanonicalIV = B.CreatePHI(Ty, 1, Name);
140
141 B.SetInsertPoint(getFirstNonPHIOrDbg(Header));
142 Instruction *Inc = cast<Instruction>(
143 B.CreateAdd(CanonicalIV, ConstantInt::get(Ty, 1), Name + ".next",
144 /*NUW*/ true, /*NSW*/ true));
145
146 for (BasicBlock *Pred : predecessors(Header)) {
147 assert(Pred);
148 if (L->contains(Pred)) {
149 CanonicalIV->addIncoming(Inc, Pred);
150 } else {
151 CanonicalIV->addIncoming(ConstantInt::get(Ty, 0), Pred);
152 }
153 }
154 assert(L->getCanonicalInductionVariable() == CanonicalIV);
155 return std::pair<PHINode *, Instruction *>(CanonicalIV, Inc);
156}
157
158// Create a new canonical induction variable of Type Ty for Loop L
159// Return the variable and the increment instruction
160std::pair<PHINode *, Instruction *> FindCanonicalIV(Loop *L, Type *Ty) {
161 assert(L);
162 assert(Ty);
163
164 BasicBlock *Header = L->getHeader();
165 assert(Header);
166 for (BasicBlock::iterator II = Header->begin(); isa<PHINode>(II); ++II) {
167 PHINode *PN = cast<PHINode>(II);
168 if (PN->getType() != Ty)
169 continue;
170
171 Instruction *Inc = nullptr;
172 bool legal = true;
173 for (BasicBlock *Pred : predecessors(Header)) {
174 assert(Pred);
175 if (L->contains(Pred)) {
176 auto Inc2 =
177 dyn_cast<BinaryOperator>(PN->getIncomingValueForBlock(Pred));
178 if (!Inc2 || Inc2->getOpcode() != Instruction::Add ||
179 Inc2->getOperand(0) != PN) {
180 legal = false;
181 break;
182 }
183 auto CI = dyn_cast<ConstantInt>(Inc2->getOperand(1));
184 if (!CI || !CI->isOne()) {
185 legal = false;
186 break;
187 }
188 if (Inc) {
189 if (Inc2 != Inc) {
190 legal = false;
191 break;
192 }
193 } else
194 Inc = Inc2;
195 } else {
196 auto CI = dyn_cast<ConstantInt>(PN->getIncomingValueForBlock(Pred));
197 if (!CI || !CI->isZero()) {
198 legal = false;
199 break;
200 }
201 }
202 }
203 if (!legal)
204 continue;
205 if (!Inc)
206 continue;
207 if (Inc != getFirstNonPHIOrDbg(Header))
209 return std::make_pair(PN, Inc);
210 }
211 llvm::errs() << *Header << "\n";
212 assert(0 && "Could not find canonical IV");
213 return std::pair<PHINode *, Instruction *>(nullptr, nullptr);
214}
215
216/// Replace every non-affine recurrence (of degree at most three) inside an
217/// expression by its closed form in the canonical induction variable of its
218/// loop, treated as an opaque value.
219///
220/// SCEVExpander expands a recurrence with more than two operands literally,
221/// as nested loop-carried phis (it would otherwise need a canonical IV one bit
222/// wider than the value). Such a phi is as impossible to recompute in the
223/// reverse pass as the accumulator it came from, so e.g. the start value
224/// i*(2*d-i-1)/2 of an inner index, expanded while rewriting the inner phi,
225/// would leave `acc += 2*d-1-2*i` in the outer loop and get cached once per
226/// iteration. evaluateAtIterationWithoutExt needs no wider type, so it can
227/// take the case the expander declines.
229 : public SCEVRewriteVisitor<NonAffineClosedFormRewriter> {
231
232 const SCEV *visitAddRecExpr(const SCEVAddRecExpr *AR) {
233 // Let the base visitor rewrite the operands (it also copes with the
234 // operand representation of the LLVM version at hand).
235 const SCEV *R =
237 auto AR2 = dyn_cast<SCEVAddRecExpr>(R);
238 // Beyond degree three the closed form would widen again.
239 if (!AR2 || AR2->isAffine() || AR2->getNumOperands() > 4)
240 return R;
241 if (!AR2->getType()->isIntegerTy())
242 return R;
243 PHINode *IV = AR2->getLoop()->getCanonicalInductionVariable();
244 if (!IV)
245 return R;
246 return evaluateAtIterationWithoutExt(AR2, SE.getUnknown(IV), SE);
247 }
248};
249
250// The no-wrap flag type of an add recurrence, named without reference to any
251// enumerator (FlagAnyWrap became FlagNone in LLVM 24); its zero value means
252// "no flags" in every version.
254 decltype(std::declval<const SCEVAddRecExpr &>().getNoWrapFlags());
255
256/// PN is a header phi of L that is negated on every iteration, x_{i+1} = -x_i,
257/// such as the alternating sign of a cofactor expansion. Scalar evolution
258/// cannot express this recurrence, so without a closed form the reverse pass
259/// caches its value once per iteration. At iteration I it is x_0 when I is
260/// even and -x_0 when I is odd, i.e. x_0 * (1 - 2 * (I mod 2)), with the
261/// parity formed as I - 2 * (I / 2) (truncating I keeps its parity).
262static const SCEV *closedFormOfNegatingRecurrence(PHINode *PN, Loop *L,
263 const SCEV *IterationNumber,
264 ScalarEvolution &SE) {
265 using namespace llvm::PatternMatch;
267 return nullptr;
268 auto Ty = dyn_cast<IntegerType>(PN->getType());
269 if (!Ty || Ty->getBitWidth() < 2 || PN->getNumIncomingValues() != 2)
270 return nullptr;
271 BasicBlock *Preheader = L->getLoopPreheader();
272 BasicBlock *Latch = L->getLoopLatch();
273 if (!Preheader || !Latch)
274 return nullptr;
275 Value *Next = PN->getIncomingValueForBlock(Latch);
276 if (!match(Next, m_Neg(m_Specific(PN))) &&
277 !match(Next, m_Mul(m_Specific(PN), m_AllOnes())))
278 return nullptr;
279 const SCEV *Init = SE.getSCEV(PN->getIncomingValueForBlock(Preheader));
280 if (!SE.isAvailableAtLoopEntry(Init, L))
281 return nullptr;
282 const SCEV *I = SE.getTruncateOrZeroExtend(IterationNumber, Ty);
283 const SCEV *Two = SE.getConstant(Ty, 2);
284 const SCEV *Parity =
285 SE.getMinusSCEV(I, SE.getMulExpr(Two, SE.getUDivExpr(I, Two)));
286 const SCEV *Factor =
287 SE.getMinusSCEV(SE.getOne(Ty), SE.getMulExpr(Two, Parity));
288 return SE.getMulExpr(Init, Factor);
289}
290
291/// PN is a header phi of L that scalar evolution could not classify. Recognize
292/// an accumulator whose per-iteration step is the trip count of an inner loop,
293/// as in
294///
295/// int idx = 0;
296/// for (i = 0; i < d; i++)
297/// for (j = i + 1; j < d; j++)
298/// ... l[idx++] ...
299///
300/// After loop rotation the latch value of idx reaches PN through a phi that
301/// merges "inner loop skipped" with the inner loop's exit value, which SCEV
302/// does not see through, so PN stays an unknown and would be cached once per
303/// iteration in the reverse pass. Derive the step from that exit value, check
304/// that a skipped inner loop contributes exactly zero, and return PN as a
305/// closed form in the iteration number (a polynomial, quadratic here), or
306/// nullptr when the shape does not match or the proofs fail.
307static const SCEV *closedFormOfCountedAccumulator(PHINode *PN, Loop *L,
308 const SCEV *IterationNumber,
309 ScalarEvolution &SE) {
311 return nullptr;
312 // Integer counters only: a pointer recurrence has no closed form to expand.
313 if (!PN->getType()->isIntegerTy() || PN->getNumIncomingValues() != 2)
314 return nullptr;
315 BasicBlock *Preheader = L->getLoopPreheader();
316 BasicBlock *Latch = L->getLoopLatch();
317 if (!Preheader || !Latch)
318 return nullptr;
319 Value *Init = PN->getIncomingValueForBlock(Preheader);
320 Value *Next = PN->getIncomingValueForBlock(Latch);
321 const SCEV *InitS = SE.getSCEV(Init);
322 if (!SE.isAvailableAtLoopEntry(InitS, L))
323 return nullptr;
324 const SCEV *PNS = SE.getSCEV(PN);
325
326 // The arms the latch value can take, each with the block it comes from.
327 SmallVector<std::pair<Value *, BasicBlock *>, 2> Arms;
328 // The block that merges the arms, i.e. where each arm's edge leads.
329 BasicBlock *Merge = Latch;
330 if (auto NP = dyn_cast<PHINode>(Next); NP && NP != PN &&
331 NP->getParent() != L->getHeader() &&
332 L->contains(NP->getParent())) {
333 Merge = NP->getParent();
334 for (unsigned i = 0; i < NP->getNumIncomingValues(); i++)
335 Arms.emplace_back(NP->getIncomingValue(i), NP->getIncomingBlock(i));
336 } else {
337 Arms.emplace_back(Next, Latch);
338 }
339
340 // The recurrence may be carried in a wider type than PN (e.g. an i32 index
341 // sign-extended to i64 for addressing, then truncated back). Work in that
342 // type, where trunc(ext(PN) + step) - PN cancels exactly.
343 Type *WideTy = PN->getType();
344 bool Signed = true;
345 const SCEV *Step = nullptr;
346 SmallVector<BasicBlock *, 2> ZeroArms;
347 for (auto &Arm : Arms) {
348 Value *V = Arm.first;
349 if (V == PN) {
350 ZeroArms.push_back(Arm.second);
351 continue;
352 }
353 Value *Wide = V;
354 if (auto TI = dyn_cast<TruncInst>(V))
355 Wide = TI->getOperand(0);
356 Type *Ty = Wide->getType();
357 if (!Ty->isIntegerTy())
358 return nullptr;
359 // At the scope of L, a value from an inner loop is its exit value.
360 const SCEV *WS = SE.getSCEVAtScope(Wide, L);
361 if (WS == SE.getCouldNotCompute())
362 return nullptr;
363 const SCEV *D = nullptr;
364 bool Sgn = true;
365 for (bool S : {true, false}) {
366 const SCEV *Ext =
367 S ? SE.getNoopOrSignExtend(PNS, Ty) : SE.getNoopOrZeroExtend(PNS, Ty);
368 const SCEV *Cand = SE.getMinusSCEV(WS, Ext);
369 if (isa<SCEVCouldNotCompute>(Cand))
370 continue;
371 if (!SCEVExprContains(Cand, [&](const SCEV *X) { return X == PNS; })) {
372 D = Cand;
373 Sgn = S;
374 break;
375 }
376 }
377 if (!D)
378 return nullptr;
379 if (Step) {
380 if (D != Step || Ty != WideTy || Sgn != Signed)
381 return nullptr;
382 } else {
383 Step = D;
384 WideTy = Ty;
385 Signed = Sgn;
386 }
387 }
388 if (!Step)
389 return nullptr;
390
391 // The step must be invariant or affine in L's own counter, with nothing
392 // from an inner loop left over.
393 if (SCEVExprContains(Step, [&](const SCEV *X) {
394 auto AR = dyn_cast<SCEVAddRecExpr>(X);
395 return AR && AR->getLoop() != L && !AR->getLoop()->contains(L);
396 }))
397 return nullptr;
398 auto Disp = SE.getLoopDisposition(Step, L);
399 if (Disp == ScalarEvolution::LoopVariant)
400 return nullptr;
401 if (auto AR = dyn_cast<SCEVAddRecExpr>(Step)) {
402 if (AR->getLoop() != L || !AR->isAffine())
403 return nullptr;
404 } else if (Disp != ScalarEvolution::LoopInvariant) {
405 return nullptr;
406 }
407
408 // The closed form adds Step on every iteration, including those where the
409 // inner loop was skipped and PN was carried unchanged, so on those the step
410 // must be exactly zero. Show that in two halves: Step is never negative on
411 // any iteration, and Step is non-positive wherever a skipping edge is taken.
412 if (!ZeroArms.empty()) {
413 auto AR = dyn_cast<SCEVAddRecExpr>(Step);
414 if (!AR)
415 return nullptr;
416 const SCEV *Zero = SE.getZero(WideTy);
417
418 // Step >= 0 everywhere. Ask SCEV first; failing that, an affine step with
419 // a constant increment is monotone, so it suffices to check it at the
420 // first or the last iteration.
421 bool NonNegative = SE.isKnownOnEveryIteration(ICmpInst::ICMP_SGE, AR, Zero);
422 if (!NonNegative) {
423 auto C = dyn_cast<SCEVConstant>(AR->getStepRecurrence(SE));
424 if (!C)
425 return nullptr;
426 if (C->getAPInt().isNonNegative()) {
427 NonNegative = SE.isKnownNonNegative(AR->getStart()) ||
428 SE.isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SGE,
429 AR->getStart(), Zero);
430 } else {
431 const SCEV *BTC = SE.getBackedgeTakenCount(L);
432 if (BTC == SE.getCouldNotCompute())
433 return nullptr;
434 NonNegative = SE.isKnownNonNegative(AR->evaluateAtIteration(BTC, SE));
435 }
436 }
437 if (!NonNegative)
438 return nullptr;
439
440 // Step <= 0 on each skipping edge. The edge B -> Merge is taken on one
441 // outcome of a branch on `icmp P A, B`: the conditional branch that ends
442 // B, or, when B is a block that exists only to carry the edge, the one
443 // that ends B's single predecessor. Orient the predicate that holds on
444 // the edge as X >= Y, X > Y or X == Y and require Step == (Y - X) + k for
445 // a constant k that then makes Step non-positive. Both X and Y must be
446 // known non-negative so that Y - X cannot wrap.
447 for (auto B : ZeroArms) {
448 BasicBlock *Dest = Merge;
449 Instruction *TI = B->getTerminator();
450 if (!isConditionalBranch(TI)) {
451 if (TI->getNumSuccessors() != 1)
452 return nullptr;
453 BasicBlock *Pred = B->getSinglePredecessor();
454 if (!Pred)
455 return nullptr;
456 Dest = B;
457 TI = Pred->getTerminator();
458 if (!isConditionalBranch(TI))
459 return nullptr;
460 }
461 if (TI->getSuccessor(0) == TI->getSuccessor(1) ||
462 (TI->getSuccessor(0) != Dest && TI->getSuccessor(1) != Dest))
463 return nullptr;
464 auto Cmp = dyn_cast<ICmpInst>(getBranchCondition(TI));
465 if (!Cmp)
466 return nullptr;
467 ICmpInst::Predicate Q = Cmp->getPredicate();
468 if (TI->getSuccessor(1) == Dest)
469 Q = ICmpInst::getInversePredicate(Q);
470 Value *X = Cmp->getOperand(0), *Y = Cmp->getOperand(1);
471 bool Strict = false, Equal = false;
472 switch (Q) {
473 case ICmpInst::ICMP_UGE:
474 case ICmpInst::ICMP_SGE:
475 break;
476 case ICmpInst::ICMP_ULE:
477 case ICmpInst::ICMP_SLE:
478 std::swap(X, Y);
479 break;
480 case ICmpInst::ICMP_UGT:
481 case ICmpInst::ICMP_SGT:
482 Strict = true;
483 break;
484 case ICmpInst::ICMP_ULT:
485 case ICmpInst::ICMP_SLT:
486 std::swap(X, Y);
487 Strict = true;
488 break;
489 case ICmpInst::ICMP_EQ:
490 Equal = true;
491 break;
492 default:
493 return nullptr;
494 }
495 if (!SE.isSCEVable(X->getType()) || X->getType() != WideTy)
496 return nullptr;
497 const SCEV *XS = SE.getSCEV(X), *YS = SE.getSCEV(Y);
498 auto NonNeg = [&](const SCEV *V) {
499 return SE.isKnownNonNegative(V) ||
500 SE.isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SGE, V, Zero);
501 };
502 if (!Equal && !(NonNeg(XS) && NonNeg(YS)))
503 return nullptr;
504 auto K = dyn_cast<SCEVConstant>(
505 SE.getMinusSCEV(Step, SE.getMinusSCEV(YS, XS)));
506 if (!K)
507 return nullptr;
508 // On the edge, Y - X is 0 (Equal), <= 0 (non-strict) or <= -1 (Strict).
509 if (Equal ? !K->getAPInt().isZero() : K->getAPInt().sgt(Strict ? 1 : 0))
510 return nullptr;
511 }
512 }
513
514 const SCEV *WideInit = Signed ? SE.getNoopOrSignExtend(InitS, WideTy)
515 : SE.getNoopOrZeroExtend(InitS, WideTy);
516 auto AR = dyn_cast<SCEVAddRecExpr>(
517 SE.getAddRecExpr(WideInit, Step, L, NoWrapFlagsTy(0)));
518 if (!AR)
519 return nullptr;
520 return SE.getTruncateOrNoop(
521 evaluateAtIterationWithoutExt(AR, IterationNumber, SE), PN->getType());
522}
523
524// Attempt to rewrite all phinode's in the loop in terms of the
525// induction variable
527 Loop *L, PHINode *CanonicalIV, Instruction *Increment,
529 llvm::function_ref<void(Instruction *, Value *)> replacer,
530 llvm::function_ref<void(Instruction *)> eraser) {
531 BasicBlock *Header = L->getHeader();
532 assert(Header);
533 assert(CanonicalIV);
534 SmallVector<Instruction *, 8> IVsToRemove;
535
536 auto CanonicalSCEV = SE.getSCEV(CanonicalIV);
537
538 for (BasicBlock::iterator II = Header->begin(); isa<PHINode>(II);) {
539 PHINode *PN = cast<PHINode>(II);
540 ++II;
541 if (PN == CanonicalIV)
542 continue;
543 if (!SE.isSCEVable(PN->getType()))
544 continue;
545 const SCEV *S = SE.getSCEV(PN);
546 if (SE.getCouldNotCompute() == S || isa<SCEVUnknown>(S)) {
547 // Evaluate at the canonical IV as an opaque value rather than as its
548 // add-recurrence: otherwise SCEV folds the polynomial back into a
549 // higher-degree recurrence, which the expander would materialize as a
550 // fresh loop-carried phi, defeating the purpose.
551 const SCEV *IterationNumber = SE.getUnknown(CanonicalIV);
552 S = closedFormOfNegatingRecurrence(PN, L, IterationNumber, SE);
553 if (!S)
554 S = closedFormOfCountedAccumulator(PN, L, IterationNumber, SE);
555 if (!S)
556 continue;
557 } else if (EnzymeRewriteAccumulators) {
558 S = NonAffineClosedFormRewriter(SE).visit(S);
559 }
560 // we may expand code for phi where not legal (computing with
561 // subloop expressions). Check that this isn't the case
562 if (!SE.dominates(S, Header))
563 continue;
564
565 if (S == CanonicalSCEV) {
566 replacer(PN, CanonicalIV);
567 eraser(PN);
568 continue;
569 }
570
571 IRBuilder<> B(PN);
572 auto Tmp = B.CreatePHI(PN->getType(), 0);
573 for (auto Pred : predecessors(Header))
574 Tmp->addIncoming(UndefValue::get(Tmp->getType()), Pred);
575 replacer(PN, Tmp);
576 eraser(PN);
577
578 // This scope is necessary to ensure scevexpander cleans up before we erase
579 // things
580#if LLVM_VERSION_MAJOR >= 22
581 SCEVExpander Exp(SE, "enzyme");
582#else
583 SCEVExpander Exp(SE, Header->getParent()->getParent()->getDataLayout(),
584 "enzyme");
585#endif
586
587 // We place that at first non phi as it may produce a non-phi instruction
588 // and must thus be expanded after all phi's
589 Value *NewIV = Exp.expandCodeFor(S, Tmp->getType(), getFirstNonPHI(Header));
590
591 // Explicity preserve wrap behavior from original iv. This is necessary
592 // until this PR in llvm is merged:
593 // https://github.com/llvm/llvm-project/pull/78199
594 if (auto addrec = dyn_cast<SCEVAddRecExpr>(S)) {
595 if (addrec->getLoop()->getHeader() == Header) {
596 if (auto add_or_mul = dyn_cast<BinaryOperator>(NewIV)) {
597#if LLVM_VERSION_MAJOR >= 23
598 if (any(addrec->getNoWrapFlags(llvm::SCEV::FlagNUW)))
599 add_or_mul->setHasNoUnsignedWrap(true);
600 if (any(addrec->getNoWrapFlags(llvm::SCEV::FlagNSW)))
601 add_or_mul->setHasNoSignedWrap(true);
602#else
603 if (addrec->getNoWrapFlags(llvm::SCEV::FlagNUW))
604 add_or_mul->setHasNoUnsignedWrap(true);
605 if (addrec->getNoWrapFlags(llvm::SCEV::FlagNSW))
606 add_or_mul->setHasNoSignedWrap(true);
607#endif
608 }
609 }
610 }
611 replacer(Tmp, NewIV);
612 eraser(Tmp);
613 }
614
615 // Replace existing increments with canonical Increment
616 Increment->moveAfter(getFirstNonPHI(CanonicalIV->getParent()));
617 SmallVector<Instruction *, 1> toErase;
618 for (auto use : CanonicalIV->users()) {
619 auto BO = dyn_cast<BinaryOperator>(use);
620 if (BO == nullptr)
621 continue;
622 if (BO->getOpcode() != BinaryOperator::Add)
623 continue;
624 if (use == Increment)
625 continue;
626
627 Value *toadd = nullptr;
628 if (BO->getOperand(0) == CanonicalIV) {
629 toadd = BO->getOperand(1);
630 } else {
631 assert(BO->getOperand(1) == CanonicalIV);
632 toadd = BO->getOperand(0);
633 }
634 if (auto CI = dyn_cast<ConstantInt>(toadd)) {
635 if (!CI->isOne())
636 continue;
637 BO->replaceAllUsesWith(Increment);
638 toErase.push_back(BO);
639 } else {
640 continue;
641 }
642 }
643 for (auto BO : toErase)
644 eraser(BO);
645}
646
647void CanonicalizeLatches(const Loop *L, BasicBlock *Header,
648 BasicBlock *Preheader, PHINode *CanonicalIV,
650 Instruction *Increment,
651 ArrayRef<BasicBlock *> latches) {
652 // Attempt to explicitly rewrite the latch
653 if (latches.size() == 1 && isConditionalBranch(latches[0]->getTerminator()))
654 for (auto use : CanonicalIV->users()) {
655 if (auto cmp = dyn_cast<ICmpInst>(use)) {
656 if (getBranchCondition(latches[0]->getTerminator()) != cmp)
657 continue;
658 // Force i to be on LHS
659 if (cmp->getOperand(0) != CanonicalIV) {
660 // Below also swaps predicate correctly
661 cmp->swapOperands();
662 }
663 assert(cmp->getOperand(0) == CanonicalIV);
664
665 auto scv = SE.getSCEVAtScope(cmp->getOperand(1), L);
666 if (cmp->isUnsigned() ||
667 (scv != SE.getCouldNotCompute() && SE.isKnownNonNegative(scv))) {
668
669 // valid replacements (since unsigned comparison and i starts at 0
670 // counting up)
671
672 // * i < n => i != n, valid since first time i >= n occurs at i == n
673 if (cmp->getPredicate() == ICmpInst::ICMP_ULT ||
674 cmp->getPredicate() == ICmpInst::ICMP_SLT) {
675 cmp->setPredicate(ICmpInst::ICMP_NE);
676 goto cend;
677 }
678
679 // * i <= n => i != n+1, valid since first time i > n occurs at i ==
680 // n+1 [ which we assert is in bitrange as not infinite loop ]
681 if (cmp->getPredicate() == ICmpInst::ICMP_ULE ||
682 cmp->getPredicate() == ICmpInst::ICMP_SLE) {
683 IRBuilder<> builder(Preheader->getTerminator());
684 if (auto inst = dyn_cast<Instruction>(cmp->getOperand(1))) {
685 builder.SetInsertPoint(inst->getNextNode());
686 }
687 cmp->setOperand(
688 1,
689 builder.CreateNUWAdd(
690 cmp->getOperand(1),
691 ConstantInt::get(cmp->getOperand(1)->getType(), 1, false)));
692 cmp->setPredicate(ICmpInst::ICMP_NE);
693 goto cend;
694 }
695
696 // * i >= n => i == n, valid since first time i >= n occurs at i == n
697 if (cmp->getPredicate() == ICmpInst::ICMP_UGE ||
698 cmp->getPredicate() == ICmpInst::ICMP_SGE) {
699 cmp->setPredicate(ICmpInst::ICMP_EQ);
700 goto cend;
701 }
702
703 // * i > n => i == n+1, valid since first time i > n occurs at i ==
704 // n+1 [ which we assert is in bitrange as not infinite loop ]
705 if (cmp->getPredicate() == ICmpInst::ICMP_UGT ||
706 cmp->getPredicate() == ICmpInst::ICMP_SGT) {
707 IRBuilder<> builder(Preheader->getTerminator());
708 if (auto inst = dyn_cast<Instruction>(cmp->getOperand(1))) {
709 builder.SetInsertPoint(inst->getNextNode());
710 }
711 cmp->setOperand(
712 1,
713 builder.CreateNUWAdd(
714 cmp->getOperand(1),
715 ConstantInt::get(cmp->getOperand(1)->getType(), 1, false)));
716 cmp->setPredicate(ICmpInst::ICMP_EQ);
717 goto cend;
718 }
719 }
720 cend:;
721 if (cmp->getPredicate() == ICmpInst::ICMP_NE) {
722 }
723 }
724 }
725
726 // Replace previous increment usage with new increment value
727 if (Increment) {
728 Increment->moveAfter(getFirstNonPHI(CanonicalIV->getParent()));
729
730 if (latches.size() == 1 && isConditionalBranch(latches[0]->getTerminator()))
731 for (auto use : Increment->users()) {
732 if (auto cmp = dyn_cast<ICmpInst>(use)) {
733 if (getBranchCondition(latches[0]->getTerminator()) != cmp)
734 continue;
735
736 // Force i+1 to be on LHS
737 if (cmp->getOperand(0) != Increment) {
738 // Below also swaps predicate correctly
739 cmp->swapOperands();
740 }
741 assert(cmp->getOperand(0) == Increment);
742
743 auto scv = SE.getSCEVAtScope(cmp->getOperand(1), L);
744 if (cmp->isUnsigned() ||
745 (scv != SE.getCouldNotCompute() && SE.isKnownNonNegative(scv))) {
746
747 // valid replacements (since unsigned comparison and i starts at 0
748 // counting up)
749
750 // * i+1 < n => i+1 != n, valid since first time i+1 >= n occurs at
751 // i+1 == n
752 if (cmp->getPredicate() == ICmpInst::ICMP_ULT ||
753 cmp->getPredicate() == ICmpInst::ICMP_SLT) {
754 cmp->setPredicate(ICmpInst::ICMP_NE);
755 continue;
756 }
757
758 // * i+1 <= n => i != n, valid since first time i+1 > n occurs at
759 // i+1 == n+1 => i == n
760 if (cmp->getPredicate() == ICmpInst::ICMP_ULE ||
761 cmp->getPredicate() == ICmpInst::ICMP_SLE) {
762 cmp->setOperand(0, CanonicalIV);
763 cmp->setPredicate(ICmpInst::ICMP_NE);
764 continue;
765 }
766
767 // * i+1 >= n => i+1 == n, valid since first time i+1 >= n occurs at
768 // i+1 == n
769 if (cmp->getPredicate() == ICmpInst::ICMP_UGE ||
770 cmp->getPredicate() == ICmpInst::ICMP_SGE) {
771 cmp->setPredicate(ICmpInst::ICMP_EQ);
772 continue;
773 }
774
775 // * i+1 > n => i == n, valid since first time i+1 > n occurs at i+1
776 // == n+1 => i == n
777 if (cmp->getPredicate() == ICmpInst::ICMP_UGT ||
778 cmp->getPredicate() == ICmpInst::ICMP_SGT) {
779 cmp->setOperand(0, CanonicalIV);
780 cmp->setPredicate(ICmpInst::ICMP_EQ);
781 continue;
782 }
783 }
784 }
785 }
786 }
787}
788
789llvm::AllocaInst *CacheUtility::getDynamicLoopLimit(llvm::Loop *L,
790 bool ReverseLimit) {
791 assert(L);
792 assert(loopContexts.find(L) != loopContexts.end());
793 auto &found = loopContexts[L];
794 assert(found.dynamic);
795 if (found.trueLimit)
796 return cast<AllocaInst>(&*found.trueLimit);
797
798 LimitContext lctx(ReverseLimit,
799 ReverseLimit ? found.preheader : &newFunc->getEntryBlock());
800 AllocaInst *LimitVar =
801 createCacheForScope(lctx, found.var->getType(), "loopLimit",
802 /*shouldfree*/ true);
803
804 for (auto ExitBlock : found.exitBlocks) {
805 IRBuilder<> B(ExitBlock, ExitBlock->begin());
806 auto Limit = B.CreatePHI(found.var->getType(), 1);
807
808 for (BasicBlock *Pred : predecessors(ExitBlock)) {
809 if (L->contains(Pred)) {
810 Limit->addIncoming(found.var, Pred);
811 } else {
812 Limit->addIncoming(UndefValue::get(found.var->getType()), Pred);
813 }
814 }
815
816 storeInstructionInCache(lctx, Limit, LimitVar);
817 }
818 found.trueLimit = LimitVar;
819 return LimitVar;
820}
821
822/// Compute the exact backedge-taken count of L (CouldNotCompute if it is not
823/// statically known) and the maximum number of iterations, ignoring exits that
824/// are guaranteed to reach unreachable.
825std::pair<const SCEV *, const SCEV *> CacheUtility::computeLoopLimit(Loop *L) {
826 const SCEV *MaxIterations = nullptr;
827 const SCEV *MayExitMaxBECount = nullptr;
828
829 SmallVector<BasicBlock *, 8> ExitingBlocks;
830 L->getExitingBlocks(ExitingBlocks);
831
832 // Remove all exiting blocks that are guaranteed
833 // to result in unreachable
834 for (auto &ExitingBlock : ExitingBlocks) {
835 BasicBlock *Exit = nullptr;
836 for (auto *SBB : successors(ExitingBlock)) {
837 if (!L->contains(SBB)) {
838 if (SE.GuaranteedUnreachable.count(SBB))
839 continue;
840 Exit = SBB;
841 break;
842 }
843 }
844 if (!Exit)
845 ExitingBlock = nullptr;
846 }
847 ExitingBlocks.erase(
848 std::remove(ExitingBlocks.begin(), ExitingBlocks.end(), nullptr),
849 ExitingBlocks.end());
850
851 // Compute the exit in the scenarios where an unreachable
852 // is not hit
853 for (BasicBlock *ExitingBlock : ExitingBlocks) {
854 assert(L->contains(ExitingBlock));
855
856 ScalarEvolution::ExitLimit EL =
857 SE.computeExitLimit(L, ExitingBlock, /*AllowPredicates*/ true);
858
859 bool seenHeaders = false;
860 SmallPtrSet<BasicBlock *, 4> Seen;
861 std::deque<BasicBlock *> Todo = {ExitingBlock};
862 while (Todo.size()) {
863 auto cur = Todo.front();
864 Todo.pop_front();
865 if (Seen.count(cur))
866 continue;
867 if (!L->contains(cur))
868 continue;
869 if (cur == L->getHeader()) {
870 seenHeaders = true;
871 break;
872 }
873 for (auto S : successors(cur)) {
874 Todo.push_back(S);
875 }
876 }
877 if (seenHeaders) {
878 if (MaxIterations == nullptr ||
879 MaxIterations == SE.getCouldNotCompute()) {
880 MaxIterations = EL.ExactNotTaken;
881 }
882 if (MaxIterations != SE.getCouldNotCompute()) {
883 if (EL.ExactNotTaken != SE.getCouldNotCompute()) {
884 MaxIterations =
885 SE.getUMaxFromMismatchedTypes(MaxIterations, EL.ExactNotTaken);
886 }
887 }
888
889 if (MayExitMaxBECount == nullptr ||
890 EL.ExactNotTaken == SE.getCouldNotCompute())
891 MayExitMaxBECount = EL.ExactNotTaken;
892
893 if (EL.ExactNotTaken != MayExitMaxBECount) {
894 MayExitMaxBECount = SE.getCouldNotCompute();
895 }
896 }
897 }
898 if (MayExitMaxBECount == nullptr) {
899 MayExitMaxBECount = SE.getCouldNotCompute();
900 }
901 if (MaxIterations == nullptr) {
902 MaxIterations = SE.getCouldNotCompute();
903 }
904 return std::make_pair(MayExitMaxBECount, MaxIterations);
905}
906
907bool CacheUtility::getContext(BasicBlock *BB, LoopContext &loopContext,
908 bool ReverseLimit) {
909 assert(BB->getParent() == newFunc);
910 Loop *L = LI.getLoopFor(BB);
911
912 // Not inside a loop
913 if (L == nullptr)
914 return false;
915
916 // Previously handled this loop
917 if (auto found = findInMap(loopContexts, L)) {
918 loopContext = *found;
919 return true;
920 }
921
922 // Need to canonicalize
923 loopContexts[L].parent = L->getParentLoop();
924
925 loopContexts[L].header = L->getHeader();
926 assert(loopContexts[L].header && "loop must have header");
927
928 loopContexts[L].preheader = L->getLoopPreheader();
929 if (!L->getLoopPreheader()) {
930 llvm::errs() << "fn: " << *L->getHeader()->getParent() << "\n";
931 llvm::errs() << "L: " << *L << "\n";
932 }
933 assert(loopContexts[L].preheader && "loop must have preheader");
934 getExitBlocks(L, loopContexts[L].exitBlocks);
935
936 loopContexts[L].offset = nullptr;
937 loopContexts[L].allocLimit = nullptr;
938 // A precisely matching canonical IV shouldve been run during preprocessing.
939 auto pair = FindCanonicalIV(L, Type::getInt64Ty(BB->getContext()));
940 PHINode *CanonicalIV = pair.first;
941 auto incVar = pair.second;
942 assert(CanonicalIV);
943 loopContexts[L].var = CanonicalIV;
944 loopContexts[L].incvar = incVar;
945 CanonicalizeLatches(L, loopContexts[L].header, loopContexts[L].preheader,
946 CanonicalIV, SE, *this, incVar,
947 getLatches(L, loopContexts[L].exitBlocks));
948 loopContexts[L].antivaralloc =
949 IRBuilder<>(inversionAllocs)
950 .CreateAlloca(CanonicalIV->getType(), nullptr,
951 CanonicalIV->getName() + "'ac");
952 loopContexts[L].antivaralloc->setAlignment(
953 Align(cast<IntegerType>(CanonicalIV->getType())->getBitWidth() / 8));
954
955 const SCEV *Limit = nullptr;
956 const SCEV *MaxIterations = nullptr;
957 std::tie(Limit, MaxIterations) = computeLoopLimit(L);
958 assert(Limit);
959 Value *LimitVar = nullptr;
960
961 if (SE.getCouldNotCompute() != Limit) {
962
963 if (CanonicalIV == nullptr) {
964 report_fatal_error("Couldn't get canonical IV.");
965 }
966
967 // A loop over the chunk of an OpenMP worksharing loop assigned to this
968 // thread runs from the lower to the upper bound __kmpc_for_static_init
969 // stored for it. Size its cache for the iterations of all threads, as
970 // computable before the parallel region, and offset each thread's part
971 // by where its chunk starts. A loop whose limit was derived from these
972 // bounds otherwise (e.g. vectorized, or the remainder of a vectorized
973 // loop) runs at most as many iterations as its chunk has, so the same
974 // offset keeps the parts of different threads disjoint.
975 {
976 SmallVector<const SCEV *, 4> Todo = {Limit};
977 SmallPtrSet<const SCEV *, 8> Seen;
978 CallInst *ompInit = nullptr;
979 LoadInst *boundLoad = nullptr;
980 while (Todo.size() && !ompInit) {
981 auto S = Todo.pop_back_val();
982 if (!Seen.insert(S).second)
983 continue;
984 auto U = dyn_cast<SCEVUnknown>(S);
985 if (!U) {
986 // SCEV::operands() needs LLVM 16.
987 if (auto N = dyn_cast<SCEVNAryExpr>(S))
988 for (auto op : N->operands())
989 Todo.push_back(op);
990 else if (auto C = dyn_cast<SCEVCastExpr>(S))
991 Todo.push_back(C->getOperand());
992 else if (auto D = dyn_cast<SCEVUDivExpr>(S)) {
993 Todo.push_back(D->getLHS());
994 Todo.push_back(D->getRHS());
995 }
996 continue;
997 }
998 auto LI = dyn_cast<LoadInst>(U->getValue());
999 if (!LI)
1000 continue;
1001 auto AI = dyn_cast<AllocaInst>(LI->getPointerOperand());
1002 if (!AI)
1003 continue;
1004 for (auto u : AI->users()) {
1005 auto call = dyn_cast<CallInst>(u);
1006 if (!call)
1007 continue;
1008 Function *F = call->getCalledFunction();
1009 if (!F)
1010 continue;
1011 if ((F->getName() == "__kmpc_for_static_init_4" ||
1012 F->getName() == "__kmpc_for_static_init_4u" ||
1013 F->getName() == "__kmpc_for_static_init_8" ||
1014 F->getName() == "__kmpc_for_static_init_8u") &&
1015 (call->getArgOperand(4) == AI || call->getArgOperand(5) == AI)) {
1016 ompInit = call;
1017 boundLoad = LI;
1018 break;
1019 }
1020 }
1021 }
1022 if (ompInit) {
1023 auto storedValue = [](Value *ptr) -> Value * {
1024 for (auto u : ptr->users())
1025 if (auto si = dyn_cast<StoreInst>(u))
1026 if (si->getPointerOperand() == ptr)
1027 return si->getValueOperand();
1028 return nullptr;
1029 };
1030 Value *lb = storedValue(ompInit->getArgOperand(4));
1031 Value *ub = storedValue(ompInit->getArgOperand(5));
1032 assert(lb);
1033 assert(ub);
1034 // The lower bound of this thread's chunk, as loaded after the call.
1035 Value *omp_lb_post = nullptr;
1036 if (boundLoad->getPointerOperand() == ompInit->getArgOperand(4))
1037 omp_lb_post = boundLoad;
1038 else
1039 for (auto u : ompInit->getArgOperand(4)->users())
1040 if (auto LI = dyn_cast<LoadInst>(u))
1041 if (LI->getParent() == ompInit->getParent() &&
1042 ompInit->comesBefore(LI)) {
1043 omp_lb_post = LI;
1044 break;
1045 }
1046 IRBuilder<> post(ompInit->getNextNode());
1047 if (omp_lb_post)
1048 post.SetInsertPoint(cast<Instruction>(omp_lb_post)->getNextNode());
1049 else
1050 omp_lb_post = post.CreateLoad(
1051 lb->getType(), ompInit->getArgOperand(4), "omp_lb_post");
1052 loopContexts[L].allocLimit = post.CreateZExtOrTrunc(
1053 post.CreateSub(ub, lb), CanonicalIV->getType());
1054 loopContexts[L].offset = post.CreateZExtOrTrunc(
1055 post.CreateSub(omp_lb_post, lb, "", true, true),
1056 CanonicalIV->getType());
1057 }
1058 }
1059
1060 if (Limit->getType() != CanonicalIV->getType()) {
1061 const SCEV *Zero = SE.getZero(Limit->getType());
1062 const Loop *outermost = L;
1063 while (outermost->getParentLoop()) {
1064 outermost = outermost->getParentLoop();
1065 }
1066 BasicBlock *outermostPreheader = outermost->getLoopPreheader();
1067 Instruction *context = outermostPreheader
1068 ? outermostPreheader->getTerminator()
1069 : loopContexts[L].preheader->getTerminator();
1070 if (SE.isKnownPredicateAt(ICmpInst::ICMP_SGE, Limit, Zero, context)) {
1071 Limit = SE.getZeroExtendExpr(Limit, CanonicalIV->getType());
1072 } else {
1073 Limit = SE.getSignExtendExpr(Limit, CanonicalIV->getType());
1074 }
1075 }
1076
1077#if LLVM_VERSION_MAJOR >= 22
1078 SCEVExpander Exp(SE, "enzyme");
1079#else
1080 SCEVExpander Exp(SE, BB->getParent()->getParent()->getDataLayout(),
1081 "enzyme");
1082#endif
1083 LimitVar = Exp.expandCodeFor(Limit, CanonicalIV->getType(),
1084 loopContexts[L].preheader->getTerminator());
1085 loopContexts[L].dynamic = false;
1086 loopContexts[L].maxLimit = LimitVar;
1087 } else {
1088 // TODO if assumeDynamicLoopOfSizeOne(L), only lazily allocate the scope
1089 // cache
1090 DebugLoc loc = L->getHeader()->begin()->getDebugLoc();
1091 for (auto &I : *L->getHeader()) {
1092 if (loc)
1093 break;
1094 loc = I.getDebugLoc();
1095 }
1096 EmitWarning("NoLimit", loc, L->getHeader(),
1097 "SE could not compute loop limit of ",
1098 L->getHeader()->getName(), " of ",
1099 L->getHeader()->getParent()->getName(), "lim: ", *Limit,
1100 " maxlim: ", *MaxIterations);
1101
1102 loopContexts[L].dynamic = true;
1103 loopContexts[L].maxLimit = nullptr;
1104
1106 LimitVar = nullptr;
1107 } else {
1108 LimitVar = getDynamicLoopLimit(L, ReverseLimit);
1109 }
1110 }
1111 loopContexts[L].trueLimit = LimitVar;
1112 if (EfficientMaxCache && loopContexts[L].dynamic &&
1113 SE.getCouldNotCompute() != MaxIterations) {
1114 if (MaxIterations->getType() != CanonicalIV->getType())
1115 MaxIterations =
1116 SE.getZeroExtendExpr(MaxIterations, CanonicalIV->getType());
1117
1118#if LLVM_VERSION_MAJOR >= 22
1119 SCEVExpander Exp(SE, "enzyme");
1120#else
1121 SCEVExpander Exp(SE, BB->getParent()->getParent()->getDataLayout(),
1122 "enzyme");
1123#endif
1124
1125 loopContexts[L].maxLimit =
1126 Exp.expandCodeFor(MaxIterations, CanonicalIV->getType(),
1127 loopContexts[L].preheader->getTerminator());
1128 }
1129 loopContext = loopContexts.find(L)->second;
1130 return true;
1131}
1132
1133/// Caching mechanism: creates a cache of type T in a scope given by ctx
1134/// (where if ctx is in a loop there will be a corresponding number of slots)
1136 StringRef name, bool shouldFree,
1137 bool allocateInternal,
1138 Value *extraSize) {
1139 assert(ctx.Block);
1140 assert(T);
1141
1142 auto sublimits =
1143 getSubLimits(/*inForwardPass*/ true, nullptr, ctx, extraSize);
1144
1145 auto i64 = Type::getInt64Ty(T->getContext());
1146
1147 // List of types stored in the cache for each Loop-Chunk
1148 // This is stored from innner-most chunk to outermost
1149 // Thus it begins with the underlying type, and adds pointers
1150 // to the previous type.
1151 SmallVector<Type *, 4> types = {T};
1152 SmallVector<PointerType *, 4> malloctypes;
1153 bool isi1 = T->isIntegerTy() && cast<IntegerType>(T)->getBitWidth() == 1;
1154 if (EfficientBoolCache && isi1 && sublimits.size() != 0)
1155 types[0] = Type::getInt8Ty(T->getContext());
1156 for (size_t i = 0; i < sublimits.size(); ++i) {
1157 Type *allocType;
1158 {
1159 BasicBlock *BB =
1160 BasicBlock::Create(newFunc->getContext(), "entry", newFunc);
1161 IRBuilder<> B(BB);
1162 auto P = B.CreatePHI(i64, 1);
1163
1164 CallInst *malloccall;
1165 Instruction *Zero;
1166 allocType = cast<PointerType>(CreateAllocation(B, types.back(), P,
1167 "tmpfortypecalc",
1168 &malloccall, &Zero)
1169 ->getType());
1170 malloctypes.push_back(cast<PointerType>(malloccall->getType()));
1171 for (auto &I : make_early_inc_range(reverse(*BB)))
1172 I.eraseFromParent();
1173
1174 BB->eraseFromParent();
1175 }
1176 types.push_back(allocType);
1177 }
1178
1179 // Allocate the outermost type on the stack
1180 IRBuilder<> entryBuilder(inversionAllocs);
1181 entryBuilder.setFastMathFlags(getFast());
1182 AllocaInst *alloc =
1183 entryBuilder.CreateAlloca(types.back(), nullptr, name + "_cache");
1184 {
1185 ConstantInt *byteSizeOfType = ConstantInt::get(
1186 i64, newFunc->getParent()->getDataLayout().getTypeAllocSizeInBits(
1187 types.back()) /
1188 8);
1189 unsigned align =
1190 getCacheAlignment((unsigned)byteSizeOfType->getZExtValue());
1191 alloc->setAlignment(Align(align));
1192 }
1193 auto undef_v = getUndefinedValueForType(*newFunc->getParent(), types.back(),
1194 /*forceZero*/ false);
1195 if (!isa<UndefValue>(undef_v))
1196 scopeInstructions[alloc].push_back(
1197 entryBuilder.CreateStore(undef_v, alloc));
1198
1199 Value *storeInto = alloc;
1200
1201 // Iterating from outermost chunk to innermost chunk
1202 // Allocate and store the requisite memory if needed
1203 // and lookup the next level pointer of the cache
1204 for (int i = sublimits.size() - 1; i >= 0; i--) {
1205 const auto &containedloops = sublimits[i].second;
1206
1207 Type *myType = types[i];
1208
1209 ConstantInt *byteSizeOfType = ConstantInt::get(
1210 Type::getInt64Ty(T->getContext()),
1211 newFunc->getParent()->getDataLayout().getTypeAllocSizeInBits(myType) /
1212 8);
1213
1214 unsigned bsize = (unsigned)byteSizeOfType->getZExtValue();
1215 unsigned alignSize = getCacheAlignment(bsize);
1216
1217 CallInst *malloccall = nullptr;
1218
1219 // Allocate and store the required memory
1220 if (allocateInternal) {
1221
1222 IRBuilder<> allocationBuilder(
1223 &containedloops.back().first.preheader->back());
1224
1225 Value *size = sublimits[i].first;
1226 if (EfficientBoolCache && isi1 && i == 0) {
1227 size = allocationBuilder.CreateLShr(
1228 allocationBuilder.CreateAdd(
1229 size, ConstantInt::get(Type::getInt64Ty(T->getContext()), 7),
1230 "", true),
1231 ConstantInt::get(Type::getInt64Ty(T->getContext()), 3));
1232 }
1233 if (extraSize && i == 0) {
1234 ValueToValueMapTy available;
1235 for (auto &sl : sublimits) {
1236 for (auto &cl : sl.second) {
1237 if (cl.first.var)
1238 available[cl.first.var] = cl.first.var;
1239 }
1240 }
1241 Value *es = unwrapM(extraSize, allocationBuilder, available,
1243 assert(es);
1244 size = allocationBuilder.CreateMul(size, es, "", /*NUW*/ true,
1245 /*NSW*/ true);
1246 }
1247
1248 StoreInst *storealloc = nullptr;
1249 // Statically allocate memory for all iterations if possible
1250 if (sublimits[i].second.back().first.maxLimit) {
1251 Instruction *ZeroInst = nullptr;
1252 Value *firstallocation = CreateAllocation(
1253 allocationBuilder, myType, size, name + "_malloccache", &malloccall,
1254 /*ZeroMem*/ EnzymeZeroCache ? &ZeroInst : nullptr);
1255
1256 if (malloccall) {
1257 auto ident = MDNode::getDistinct(
1258 malloccall->getContext(),
1259 {ConstantAsMetadata::get(
1260 ConstantInt::getFalse(malloccall->getContext()))});
1261 malloccall->setMetadata(
1262 "enzyme_cache_alloc",
1263 MDNode::get(malloccall->getContext(), {ident}));
1264 }
1265
1266 scopeInstructions[alloc].push_back(malloccall);
1267 if (firstallocation != malloccall)
1268 scopeInstructions[alloc].push_back(
1269 cast<Instruction>(firstallocation));
1270
1271 for (auto &actx : sublimits[i].second) {
1272 if (actx.first.offset) {
1273 malloccall->setMetadata("enzyme_ompfor",
1274 MDNode::get(malloccall->getContext(), {}));
1275 break;
1276 }
1277 }
1278
1279 if (ZeroInst) {
1280 if (ZeroInst->getOperand(0) != malloccall) {
1281 scopeInstructions[alloc].push_back(
1282 cast<Instruction>(ZeroInst->getOperand(0)));
1283 }
1284 scopeInstructions[alloc].push_back(ZeroInst);
1285 }
1286 storealloc = allocationBuilder.CreateStore(firstallocation, storeInto);
1287
1288 scopeAllocs[alloc].push_back(malloccall);
1289
1290 // Mark the store as invariant since the allocation is static and
1291 // will not be changed
1292 if (CachePointerInvariantGroups.find(std::make_pair(
1293 (Value *)alloc, i)) == CachePointerInvariantGroups.end()) {
1294 MDNode *invgroup = MDNode::getDistinct(alloc->getContext(), {});
1295 CachePointerInvariantGroups[std::make_pair((Value *)alloc, i)] =
1296 invgroup;
1297 }
1298 storealloc->setMetadata(
1299 LLVMContext::MD_invariant_group,
1300 CachePointerInvariantGroups[std::make_pair((Value *)alloc, i)]);
1301 scopeInstructions[alloc].push_back(storealloc);
1302 for (auto post : PostCacheStore(storealloc, allocationBuilder)) {
1303 scopeInstructions[alloc].push_back(post);
1304 }
1305 } else {
1306 llvm::PointerType *allocType = cast<PointerType>(types[i + 1]);
1307 llvm::PointerType *mallocType = malloctypes[i];
1308
1309 // Reallocate memory dynamically as a fallback
1310 // TODO change this to a power-of-two allocation strategy
1311
1312 auto zerostore = allocationBuilder.CreateStore(
1313 getUndefinedValueForType(*newFunc->getParent(), allocType,
1314 /*forceZero*/ true),
1315 storeInto);
1316 scopeInstructions[alloc].push_back(zerostore);
1317
1318 IRBuilder<> build(containedloops.back().first.incvar->getNextNode());
1319 Value *allocation = build.CreateLoad(allocType, storeInto);
1320
1321 if (allocation->getType() != mallocType) {
1322 auto I =
1323 cast<Instruction>(build.CreateBitCast(allocation, mallocType));
1324 scopeInstructions[alloc].push_back(I);
1325 allocation = I;
1326 }
1327
1328 CallInst *realloccall = nullptr;
1329 auto reallocation = CreateReAllocation(
1330 build, allocation, myType, containedloops.back().first.incvar, size,
1331 name + "_realloccache", &realloccall, EnzymeZeroCache && i == 0);
1332
1333 scopeInstructions[alloc].push_back(cast<Instruction>(reallocation));
1334
1335 if (reallocation->getType() != allocType) {
1336 auto I =
1337 cast<Instruction>(build.CreateBitCast(reallocation, allocType));
1338 scopeInstructions[alloc].push_back(I);
1339 reallocation = I;
1340 }
1341
1342 scopeAllocs[alloc].push_back(realloccall);
1343
1344 storealloc = build.CreateStore(reallocation, storeInto);
1345 // Unlike the static case we can not mark the memory as invariant
1346 // since we are reloading/storing based off the number of loop
1347 // iterations
1348 scopeInstructions[alloc].push_back(storealloc);
1349 for (auto post : PostCacheStore(storealloc, build)) {
1350 scopeInstructions[alloc].push_back(post);
1351 }
1352 }
1353
1354 // Regardless of how allocated (dynamic vs static), mark it
1355 // as having the requisite alignment
1356 storealloc->setAlignment(Align(alignSize));
1357 }
1358
1359 // Free the memory, if requested
1360 if (shouldFree) {
1361 if (CachePointerInvariantGroups.find(std::make_pair((Value *)alloc, i)) ==
1362 CachePointerInvariantGroups.end()) {
1363 MDNode *invgroup = MDNode::getDistinct(alloc->getContext(), {});
1364 CachePointerInvariantGroups[std::make_pair((Value *)alloc, i)] =
1365 invgroup;
1366 }
1367 Type *nextType = types[i + 1];
1368 auto freecall = freeCache(
1369 containedloops.back().first.preheader, sublimits, i, alloc, nextType,
1370 byteSizeOfType, storeInto,
1371 CachePointerInvariantGroups[std::make_pair((Value *)alloc, i)]);
1372 if (freecall) {
1373 auto ident =
1374 MDNode::getDistinct(freecall->getContext(),
1375 {ConstantAsMetadata::get(ConstantInt::getFalse(
1376 freecall->getContext()))});
1377 freecall->setMetadata("enzyme_cache_free",
1378 MDNode::get(freecall->getContext(), {ident}));
1379 }
1380 if (freecall && malloccall) {
1381 auto ident =
1382 MDNode::getDistinct(freecall->getContext(),
1383 {ConstantAsMetadata::get(ConstantInt::getTrue(
1384 freecall->getContext()))});
1385 malloccall->setMetadata("enzyme_cache_alloc",
1386 MDNode::get(malloccall->getContext(), {ident}));
1387 freecall->setMetadata("enzyme_cache_free",
1388 MDNode::get(freecall->getContext(), {ident}));
1389 }
1390 }
1391
1392 // If we are not the final iteration, lookup the next pointer by indexing
1393 // into the relevant location of the current chunk allocation
1394 if (i != 0) {
1395 IRBuilder<> v(&sublimits[i - 1].second.back().first.preheader->back());
1396
1397 Value *idx = computeIndexOfChunk(
1398 /*inForwardPass*/ true, v, containedloops,
1399 /*available*/ ValueToValueMapTy());
1400
1401 storeInto = v.CreateLoad(types[i + 1], storeInto);
1402 cast<LoadInst>(storeInto)->setAlignment(Align(alignSize));
1403 storeInto = v.CreateGEP(types[i], storeInto, idx);
1404 cast<GetElementPtrInst>(storeInto)->setIsInBounds(true);
1405 }
1406 }
1407 return alloc;
1408}
1409
1410Value *CacheUtility::computeIndexOfChunk(
1411 bool inForwardPass, IRBuilder<> &v,
1412 ArrayRef<std::pair<LoopContext, llvm::Value *>> containedloops,
1413 const ValueToValueMapTy &available) {
1414 // List of loop indices in chunk from innermost to outermost
1415 SmallVector<Value *, 3> indices;
1416 // List of cumulative indices in chunk from innermost to outermost
1417 // where limit[i] = prod(loop limit[0..i])
1418 SmallVector<Value *, 3> limits;
1419
1420 // Iterate from innermost loop to outermost loop within a chunk
1421 for (size_t i = 0; i < containedloops.size(); ++i) {
1422 const auto &pair = containedloops[i];
1423
1424 const auto &idx = pair.first;
1425 Value *var = idx.var;
1426
1427 // In the SingleIteration, var may be null (since there's no legal phinode)
1428 // In that case the current iteration is simply the constnat Zero
1429 if (idx.var == nullptr)
1430 var = ConstantInt::get(Type::getInt64Ty(newFunc->getContext()), 0);
1431 else if (available.count(var)) {
1432 var = available.find(var)->second;
1433 } else if (!inForwardPass) {
1434 var = v.CreateLoad(idx.var->getType(), idx.antivaralloc);
1435 } else {
1436 var = idx.var;
1437 }
1438 if (idx.offset) {
1439 var = v.CreateAdd(var, lookupM(idx.offset, v), "", /*NUW*/ true,
1440 /*NSW*/ true);
1441 }
1442
1443 indices.push_back(var);
1444 Value *lim = pair.second;
1445 assert(lim);
1446 if (limits.size() == 0) {
1447 limits.push_back(lim);
1448 } else {
1449 limits.push_back(v.CreateMul(limits.back(), lim, "",
1450 /*NUW*/ true, /*NSW*/ true));
1451 }
1452 }
1453
1454 assert(indices.size() > 0);
1455
1456 // Compute the index into the pointer
1457 Value *idx = indices[0];
1458 for (unsigned ind = 1; ind < indices.size(); ++ind) {
1459 idx = v.CreateAdd(idx,
1460 v.CreateMul(indices[ind], limits[ind - 1], "",
1461 /*NUW*/ true, /*NSW*/ true),
1462 "", /*NUW*/ true, /*NSW*/ true);
1463 }
1464 return idx;
1465}
1466
1467/// Given a LimitContext ctx, representing a location inside a loop nest,
1468/// break each of the loops up into chunks of loops where each chunk's number
1469/// of iterations can be computed at the chunk preheader. Every dynamic loop
1470/// defines the start of a chunk. SubLimitType is a vector of chunk objects.
1471/// More specifically it is a vector of { # iters in a Chunk (sublimit), Chunk }
1472/// Each chunk object is a vector of loops contained within the chunk.
1473/// For every loop, this returns pair of the LoopContext and the limit of that
1474/// loop Both the vector of Chunks and vector of Loops within a Chunk go from
1475/// innermost loop to outermost loop.
1477 IRBuilder<> *RB,
1478 LimitContext ctx,
1479 Value *extraSize) {
1480 // Store the LoopContext's in InnerMost => Outermost order
1481 SmallVector<LoopContext, 4> contexts;
1482
1483 // Given a ``SingleIteration'' Limit Context, return a chunking of
1484 // one loop with size 1, and header/preheader of the BasicBlock
1485 // This is done to create a context for a block outside a loop
1486 // and is part of an experimental mechanism for merging stores
1487 // into a unified memcpy
1488 if (ctx.ForceSingleIteration) {
1489 LoopContext idx;
1490 auto subctx = ctx.Block;
1491 auto zero = ConstantInt::get(Type::getInt64Ty(newFunc->getContext()), 0);
1492 // The iteration count is always zero so we can set it as such
1493 idx.var = nullptr; // = zero;
1494 idx.incvar = nullptr;
1495 idx.antivaralloc = nullptr;
1496 idx.trueLimit = zero;
1497 idx.maxLimit = zero;
1498 idx.header = subctx;
1499 idx.preheader = subctx;
1500 idx.dynamic = false;
1501 idx.parent = nullptr;
1502 idx.exitBlocks = {};
1503 idx.offset = nullptr;
1504 idx.allocLimit = nullptr;
1505 contexts.push_back(idx);
1506 }
1507
1508 for (BasicBlock *blk = ctx.Block; blk != nullptr;) {
1509 LoopContext idx;
1510 if (!getContext(blk, idx, ctx.ReverseLimit)) {
1511 break;
1512 }
1513 contexts.emplace_back(std::move(idx));
1514 blk = idx.preheader;
1515 }
1516
1517 // Legal preheaders for loop i (indexed from inner => outer)
1518 SmallVector<BasicBlock *, 4> allocationPreheaders(contexts.size(), nullptr);
1519 // Limit of loop i (indexed from inner => outer)
1520 SmallVector<Value *, 4> limits(contexts.size(), nullptr);
1521
1522 // Iterate from outermost loop to innermost loop
1523 for (int i = contexts.size() - 1; i >= 0; --i) {
1524 // The outermost loop's preheader is the preheader directly
1525 // outside the loop nest
1526 if ((unsigned)i == contexts.size() - 1) {
1527 allocationPreheaders[i] = contexts[i].preheader;
1528 } else if (!contexts[i].maxLimit) {
1529 // For dynamic loops, the preheader is now forced to be the preheader
1530 // of that loop
1531 allocationPreheaders[i] = contexts[i].preheader;
1532 } else {
1533 // Otherwise try to use the preheader of the loop just outside this
1534 // one to allocate all iterations across both loops together
1535 allocationPreheaders[i] = allocationPreheaders[i + 1];
1536 }
1537
1538 // Dynamic loops are considered to have a limit of one for allocation
1539 // purposes This is because we want to allocate 1 x (# of iterations inside
1540 // chunk) inside every dynamic iteration
1541 if (!contexts[i].maxLimit) {
1542 limits[i] =
1543 ConstantInt::get(Type::getInt64Ty(ctx.Block->getContext()), 1);
1544 } else {
1545 // Map of previous induction variables we are allowed to use as part
1546 // of the computation of the number of iterations in this chunk
1547 ValueToValueMapTy prevMap;
1548
1549 // Iterate from outermost loop down
1550 for (int j = contexts.size() - 1;; --j) {
1551 // If the preheader allocating memory for loop i
1552 // is distinct from this preheader, we are therefore allocating
1553 // memory in a different chunk. We can use induction variables
1554 // from chunks outside us to compute loop bounds so add it to the
1555 // map
1556 if (allocationPreheaders[i] != contexts[j].preheader) {
1557 prevMap[contexts[j].var] = contexts[j].var;
1558 } else {
1559 break;
1560 }
1561 }
1562
1563 IRBuilder<> allocationBuilder(&allocationPreheaders[i]->back());
1564 Value *limitMinus1 = nullptr;
1565
1566 Value *limit = contexts[i].maxLimit;
1567 if (contexts[i].allocLimit)
1568 limit = contexts[i].allocLimit;
1569
1570 // Attempt to compute the limit of this loop at the corresponding
1571 // allocation preheader. This is null if it was not legal to compute
1572 limitMinus1 = unwrapM(limit, allocationBuilder, prevMap,
1574
1575 // We have a loop with static bounds, but whose limit is not available
1576 // to be computed at the current loop preheader (such as the innermost
1577 // loop of triangular iteration domain) Handle this case like a dynamic
1578 // loop and create a new chunk.
1579 if (limitMinus1 == nullptr) {
1580 EmitWarning("NoOuterLimit", *cast<Instruction>(&*limit),
1581 "Could not compute outermost loop limit by moving value ",
1582 *limit, " computed at block", contexts[i].header->getName(),
1583 " function ", contexts[i].header->getParent()->getName());
1584 allocationPreheaders[i] = contexts[i].preheader;
1585 allocationBuilder.SetInsertPoint(&allocationPreheaders[i]->back());
1586 limitMinus1 = unwrapM(limit, allocationBuilder, prevMap,
1588 if (limitMinus1 == nullptr) {
1589 llvm::errs() << *contexts[i].preheader->getParent() << "\n";
1590 llvm::errs() << "block: " << *allocationPreheaders[i] << "\n";
1591 llvm::errs() << "limit: " << *limit << "\n";
1592 }
1593 assert(limitMinus1 != nullptr);
1594 } else if (i == 0 && extraSize &&
1595 unwrapM(extraSize, allocationBuilder, prevMap,
1596 UnwrapMode::AttemptFullUnwrap) == nullptr) {
1598 "NoOuterLimit", *cast<Instruction>(extraSize), newFunc,
1599 cast<Instruction>(extraSize)->getParent(),
1600 "Could not compute outermost loop limit by moving extraSize value ",
1601 *extraSize, " computed at block", contexts[i].header->getName(),
1602 " function ", contexts[i].header->getParent()->getName());
1603 allocationPreheaders[i] = contexts[i].preheader;
1604 allocationBuilder.SetInsertPoint(&allocationPreheaders[i]->back());
1605 }
1606 assert(limitMinus1 != nullptr);
1607
1608 ValueToValueMapTy reverseMap;
1609 // Iterate from outermost loop down
1610 for (int j = contexts.size() - 1;; --j) {
1611 // If the preheader allocating memory for loop i
1612 // is distinct from this preheader, we are therefore allocating
1613 // memory in a different chunk. We can use induction variables
1614 // from chunks outside us to compute loop bounds so add it to the
1615 // map
1616 if (allocationPreheaders[i] != contexts[j].preheader) {
1617 if (!inForwardPass) {
1618 reverseMap[contexts[j].var] = RB->CreateLoad(
1619 contexts[j].var->getType(), contexts[j].antivaralloc);
1620 }
1621 } else {
1622 break;
1623 }
1624 }
1625
1626 // We now need to compute the actual limit as opposed to the limit
1627 // minus one.
1628 if (inForwardPass) {
1629 // For efficiency, avoid doing this multiple times for
1630 // the same <limitMinus1, Block requested at> pair by caching inside
1631 // of LimitCache.
1632 auto &map = LimitCache[limitMinus1];
1633 auto found = map.find(allocationPreheaders[i]);
1634 if (found != map.end() && found->second != nullptr) {
1635 limits[i] = found->second;
1636 } else {
1637 limits[i] = map[allocationPreheaders[i]] =
1638 allocationBuilder.CreateNSWAdd(
1639 limitMinus1, ConstantInt::get(limitMinus1->getType(), 1));
1640 }
1641 } else {
1642 Value *lim = unwrapM(limitMinus1, *RB, reverseMap,
1644 allocationPreheaders[i]);
1645 if (!lim) {
1646 llvm::errs() << *newFunc << "\n";
1647 llvm::errs() << *limitMinus1 << "\n";
1648 }
1649 assert(lim);
1650 limits[i] = RB->CreateNSWAdd(lim, ConstantInt::get(lim->getType(), 1));
1651 }
1652 }
1653 }
1654
1655 SubLimitType sublimits;
1656
1657 // Total number of iterations of current chunk of loops
1658 Value *size = nullptr;
1659 // Loops inside current chunk (stored innermost to outermost)
1660 SmallVector<std::pair<LoopContext, Value *>, 3> lims;
1661
1662 // Iterate from innermost to outermost loops
1663 for (unsigned i = 0; i < contexts.size(); ++i) {
1664 IRBuilder<> allocationBuilder(&allocationPreheaders[i]->back());
1665 lims.push_back(std::make_pair(contexts[i], limits[i]));
1666 // Compute the cumulative size
1667 if (size == nullptr) {
1668 // If starting with no cumulative size, this is the cumulative size
1669 size = limits[i];
1670 } else if (!inForwardPass) {
1671 size = RB->CreateMul(size, limits[i], "",
1672 /*NUW*/ true, /*NSW*/ true);
1673 } else {
1674 // Otherwise new size = old size * limits[i];
1675 auto cidx = std::make_tuple(size, limits[i], allocationPreheaders[i]);
1676 if (SizeCache.find(cidx) == SizeCache.end()) {
1677 SizeCache[cidx] =
1678 allocationBuilder.CreateMul(size, limits[i], "",
1679 /*NUW*/ true, /*NSW*/ true);
1680 }
1681 size = SizeCache[cidx];
1682 }
1683
1684 // If we are starting a new chunk in the next iteration
1685 // push this chunk to sublimits and clear the cumulative calculations
1686 if ((i + 1 < contexts.size()) &&
1687 (allocationPreheaders[i] != allocationPreheaders[i + 1])) {
1688 sublimits.push_back(std::make_pair(size, lims));
1689 size = nullptr;
1690 lims.clear();
1691 }
1692 }
1693
1694 // For any remaining loop chunks, add them to the list
1695 if (size != nullptr) {
1696 sublimits.push_back(std::make_pair(size, lims));
1697 lims.clear();
1698 }
1699
1700 return sublimits;
1701}
1702
1703/// Given an allocation defined at a particular ctx, store the value val
1704/// in the cache at the location defined in the given builder
1705void CacheUtility::storeInstructionInCache(LimitContext ctx,
1706 IRBuilder<> &BuilderM, Value *val,
1707 AllocaInst *cache, MDNode *TBAA) {
1708 assert(BuilderM.GetInsertBlock()->getParent() == newFunc);
1709#ifndef NDEBUG
1710 if (auto inst = dyn_cast<Instruction>(val))
1711 assert(inst->getParent()->getParent() == newFunc);
1712#endif
1713 IRBuilder<> v(BuilderM.GetInsertBlock());
1714 v.SetInsertPoint(BuilderM.GetInsertBlock(), BuilderM.GetInsertPoint());
1715 v.setFastMathFlags(getFast());
1716
1717 // Note for dynamic loops where the allocation is stored somewhere inside
1718 // the loop, we must ensure that we load the allocation after actually
1719 // storing the allocation itself.
1720 // To simplify things and ensure we always store after a
1721 // potential realloc occurs in this loop, we put our store after
1722 // any existing stores in the loop.
1723 // This is okay as there should be no load to the cache in the same block
1724 // where this instruction is defined as we will just use this instruction
1725 // TODO check that the store is actually aliasing/related
1726 if (BuilderM.GetInsertPoint() != BuilderM.GetInsertBlock()->end()) {
1727 for (auto I = BuilderM.GetInsertBlock()->rbegin(),
1728 E = BuilderM.GetInsertBlock()->rend();
1729 I != E; ++I) {
1730 if (&*I == &*BuilderM.GetInsertPoint())
1731 break;
1732 if (auto si = dyn_cast<StoreInst>(&*I)) {
1734 if (ni != nullptr) {
1735 v.SetInsertPoint(ni);
1736 } else {
1737 v.SetInsertPoint(si->getParent());
1738 }
1739 }
1740 }
1741 }
1742
1743 bool isi1 = val->getType()->isIntegerTy() &&
1744 cast<IntegerType>(val->getType())->getBitWidth() == 1;
1745 Value *loc = getCachePointer(val->getType(),
1746 /*inForwardPass*/ true, v, ctx, cache,
1747 /*storeInInstructionsMap*/ true,
1748 /*available*/ llvm::ValueToValueMapTy(),
1749 /*extraSize*/ nullptr);
1750
1751 Value *tostore = val;
1752
1753 // If we are doing the efficient bool cache, the actual value
1754 // we want to store needs to have the existing surrounding bits
1755 // set appropriately
1756 if (EfficientBoolCache && isi1) {
1757 if (auto gep = dyn_cast<GetElementPtrInst>(loc)) {
1758 auto bo = cast<BinaryOperator>(*gep->idx_begin());
1759 assert(bo->getOpcode() == BinaryOperator::LShr);
1760 auto subidx = v.CreateAnd(
1761 v.CreateTrunc(bo->getOperand(0),
1762 Type::getInt8Ty(cache->getContext())),
1763 ConstantInt::get(Type::getInt8Ty(cache->getContext()), 7));
1764 auto mask = v.CreateNot(v.CreateShl(
1765 ConstantInt::get(Type::getInt8Ty(cache->getContext()), 1), subidx));
1766
1767 Value *loadChunk = v.CreateLoad(mask->getType(), loc);
1768 auto cleared = v.CreateAnd(loadChunk, mask);
1769
1770 auto toset = v.CreateShl(
1771 v.CreateZExt(val, Type::getInt8Ty(cache->getContext())), subidx);
1772 tostore = v.CreateOr(cleared, toset);
1773 assert(tostore->getType() == mask->getType());
1774 }
1775 }
1776
1777#if LLVM_VERSION_MAJOR < 17
1778 if (tostore->getContext().supportsTypedPointers()) {
1779 if (tostore->getType() != loc->getType()->getPointerElementType()) {
1780 llvm::errs() << "val: " << *val << "\n";
1781 llvm::errs() << "tostore: " << *tostore << "\n";
1782 llvm::errs() << "loc: " << *loc << "\n";
1783 }
1784 assert(tostore->getType() == loc->getType()->getPointerElementType());
1785 }
1786#endif
1787
1788 StoreInst *storeinst = v.CreateStore(tostore, loc);
1789
1790 // If the value stored doesnt change (per efficient bool cache),
1791 // mark it as invariant
1792 if (tostore == val) {
1793 if (ValueInvariantGroups.find(cache) == ValueInvariantGroups.end()) {
1794 MDNode *invgroup = MDNode::getDistinct(cache->getContext(), {});
1795 ValueInvariantGroups[cache] = invgroup;
1796 }
1797 storeinst->setMetadata(LLVMContext::MD_invariant_group,
1798 ValueInvariantGroups[cache]);
1799 }
1800
1801 // Set alignment
1802 ConstantInt *byteSizeOfType =
1803 ConstantInt::get(Type::getInt64Ty(cache->getContext()),
1804 ctx.Block->getParent()
1805 ->getParent()
1806 ->getDataLayout()
1807 .getTypeAllocSizeInBits(val->getType()) /
1808 8);
1809 unsigned align = getCacheAlignment((unsigned)byteSizeOfType->getZExtValue());
1810 storeinst->setMetadata(LLVMContext::MD_tbaa, TBAA);
1811 storeinst->setAlignment(Align(align));
1812 scopeInstructions[cache].push_back(storeinst);
1813 for (auto post : PostCacheStore(storeinst, v)) {
1814 scopeInstructions[cache].push_back(post);
1815 }
1816}
1817
1818/// Given an allocation defined at a particular ctx, store the instruction
1819/// in the cache right after the instruction is executed
1821 llvm::Instruction *inst,
1822 llvm::AllocaInst *cache,
1823 llvm::MDNode *TBAA) {
1824 assert(ctx.Block);
1825 assert(inst);
1826 assert(cache);
1827
1828 // Find the correct place to issue the store
1829 IRBuilder<> v(inst->getParent());
1830 // If this is a PHINode, we need to store after all phinodes,
1831 // otherwise just after inst sufficies
1832 if (&*inst->getParent()->rbegin() != inst) {
1833 auto pn = dyn_cast<PHINode>(inst);
1834 Instruction *putafter = (pn && pn->getNumIncomingValues() > 0)
1835 ? (getFirstNonPHI(inst->getParent()))
1837 assert(putafter);
1838 v.SetInsertPoint(putafter);
1839 }
1840 v.setFastMathFlags(getFast());
1841 storeInstructionInCache(ctx, v, inst, cache, TBAA);
1842}
1843
1844/// Given an allocation specified by the LimitContext ctx and cache, compute a
1845/// pointer that can hold the underlying type being cached. This value should be
1846/// computed at BuilderM. Optionally, instructions needed to generate this
1847/// pointer can be stored in scopeInstructions
1848Value *CacheUtility::getCachePointer(llvm::Type *T, bool inForwardPass,
1849 IRBuilder<> &BuilderM, LimitContext ctx,
1850 Value *cache, bool storeInInstructionsMap,
1851 const ValueToValueMapTy &available,
1852 Value *extraSize) {
1853 assert(ctx.Block);
1854 assert(cache);
1855 auto sublimits = getSubLimits(inForwardPass, &BuilderM, ctx, extraSize);
1856
1857 Value *next = cache;
1858 assert(next->getType()->isPointerTy());
1859
1860 SmallVector<Type *, 4> types = {T};
1861 bool isi1 = T->isIntegerTy() && cast<IntegerType>(T)->getBitWidth() == 1;
1862 if (EfficientBoolCache && isi1 && sublimits.size() != 0)
1863 types[0] = Type::getInt8Ty(T->getContext());
1864 auto i64 = Type::getInt64Ty(T->getContext());
1865 for (size_t i = 0; i < sublimits.size(); ++i) {
1866 Type *allocType;
1867 {
1868 BasicBlock *BB =
1869 BasicBlock::Create(newFunc->getContext(), "entry", newFunc);
1870 IRBuilder<> B(BB);
1871 auto P = B.CreatePHI(i64, 1);
1872
1873 CallInst *malloccall;
1874 Instruction *Zero;
1875 allocType = cast<PointerType>(CreateAllocation(B, types.back(), P,
1876 "tmpfortypecalc",
1877 &malloccall, &Zero)
1878 ->getType());
1879 for (auto &I : make_early_inc_range(reverse(*BB)))
1880 I.eraseFromParent();
1881
1882 BB->eraseFromParent();
1883 }
1884 types.push_back(allocType);
1885 }
1886
1887 // Iterate from outermost loop to innermost loop
1888 for (int i = sublimits.size() - 1; i >= 0; i--) {
1889 // Lookup the next allocation pointer
1890 next = BuilderM.CreateLoad(types[i + 1], next);
1891 if (storeInInstructionsMap && isa<AllocaInst>(cache))
1892 scopeInstructions[cast<AllocaInst>(cache)].push_back(
1893 cast<Instruction>(next));
1894
1895 if (!next->getType()->isPointerTy()) {
1896 llvm::errs() << *newFunc << "\n";
1897 llvm::errs() << "cache: " << *cache << "\n";
1898 llvm::errs() << "next: " << *next << "\n";
1899 assert(next->getType()->isPointerTy());
1900 }
1901
1902 // Set appropriate invairant lookup flags
1903 if (CachePointerInvariantGroups.find(std::make_pair(cache, i)) ==
1904 CachePointerInvariantGroups.end()) {
1905 MDNode *invgroup = MDNode::getDistinct(cache->getContext(), {});
1906 CachePointerInvariantGroups[std::make_pair(cache, i)] = invgroup;
1907 }
1908 cast<LoadInst>(next)->setMetadata(
1909 LLVMContext::MD_invariant_group,
1910 CachePointerInvariantGroups[std::make_pair(cache, i)]);
1911
1912 // Set dereferenceable and alignment flags
1913 ConstantInt *byteSizeOfType = ConstantInt::get(
1914 Type::getInt64Ty(cache->getContext()),
1915 newFunc->getParent()->getDataLayout().getTypeAllocSizeInBits(
1916 next->getType()) /
1917 8);
1918 cast<LoadInst>(next)->setMetadata(
1919 LLVMContext::MD_dereferenceable,
1920 MDNode::get(
1921 cache->getContext(),
1922 ArrayRef<Metadata *>(ConstantAsMetadata::get(byteSizeOfType))));
1923 unsigned align =
1924 getCacheAlignment((unsigned)byteSizeOfType->getZExtValue());
1925 cast<LoadInst>(next)->setAlignment(Align(align));
1926
1927 const auto &containedloops = sublimits[i].second;
1928
1929 if (containedloops.size() > 0) {
1930 Value *idx = computeIndexOfChunk(inForwardPass, BuilderM, containedloops,
1931 available);
1932 if (EfficientBoolCache && isi1 && i == 0)
1933 idx = BuilderM.CreateLShr(
1934 idx, ConstantInt::get(Type::getInt64Ty(newFunc->getContext()), 3));
1935 if (i == 0 && extraSize) {
1936 Value *es = lookupM(extraSize, BuilderM);
1937 assert(es);
1938 idx = BuilderM.CreateMul(idx, es, "", /*NUW*/ true, /*NSW*/ true);
1939 }
1940 next = BuilderM.CreateGEP(types[i], next, idx);
1941 cast<GetElementPtrInst>(next)->setIsInBounds(true);
1942 if (storeInInstructionsMap && isa<AllocaInst>(cache))
1943 scopeInstructions[cast<AllocaInst>(cache)].push_back(
1944 cast<Instruction>(next));
1945 }
1946 assert(next->getType()->isPointerTy());
1947 }
1948 return next;
1949}
1950
1951/// Perform the final load from the cache, applying requisite invariant
1952/// group and alignment
1954 llvm::IRBuilder<> &BuilderM,
1955 llvm::Value *cptr,
1956 llvm::Value *cache) {
1957 // Retrieve the actual result
1958 auto result = BuilderM.CreateLoad(T, cptr);
1959
1960 // Apply requisite invariant, alignment, etc
1961 if (ValueInvariantGroups.find(cache) == ValueInvariantGroups.end()) {
1962 MDNode *invgroup = MDNode::getDistinct(cache->getContext(), {});
1963 ValueInvariantGroups[cache] = invgroup;
1964 }
1965 CacheLookups.insert(result);
1966 result->setMetadata(LLVMContext::MD_invariant_group,
1967 ValueInvariantGroups[cache]);
1968 ConstantInt *byteSizeOfType = ConstantInt::get(
1969 Type::getInt64Ty(cache->getContext()),
1970 newFunc->getParent()->getDataLayout().getTypeAllocSizeInBits(
1971 result->getType()) /
1972 8);
1973 unsigned align = getCacheAlignment((unsigned)byteSizeOfType->getZExtValue());
1974 result->setAlignment(Align(align));
1975
1976 return result;
1977}
1978
1979/// Given an allocation specified by the LimitContext ctx and cache, lookup the
1980/// underlying cached value.
1982 Type *T, bool inForwardPass, IRBuilder<> &BuilderM, LimitContext ctx,
1983 Value *cache, bool isi1, const ValueToValueMapTy &available,
1984 Value *extraSize, Value *extraOffset) {
1985 // Get the underlying cache pointer
1986 auto cptr =
1987 getCachePointer(T, inForwardPass, BuilderM, ctx, cache,
1988 /*storeInInstructionsMap*/ false, available, extraSize);
1989
1990 // Optionally apply the additional offset
1991 if (extraOffset) {
1992 cptr = BuilderM.CreateGEP(T, cptr, extraOffset);
1993 cast<GetElementPtrInst>(cptr)->setIsInBounds(true);
1994 }
1995
1996 Value *result = loadFromCachePointer(T, BuilderM, cptr, cache);
1997
1998 // If using the efficient bool cache, do the corresponding
1999 // mask and shift to retrieve the actual value
2000 if (EfficientBoolCache && isi1) {
2001 if (auto gep = dyn_cast<GetElementPtrInst>(cptr)) {
2002 auto bo = cast<BinaryOperator>(*gep->idx_begin());
2003 assert(bo->getOpcode() == BinaryOperator::LShr);
2004 Value *res = BuilderM.CreateLShr(
2005 result,
2006 BuilderM.CreateAnd(
2007 BuilderM.CreateTrunc(bo->getOperand(0),
2008 Type::getInt8Ty(cache->getContext())),
2009 ConstantInt::get(Type::getInt8Ty(cache->getContext()), 7)));
2010 return BuilderM.CreateTrunc(res, Type::getInt1Ty(result->getContext()));
2011 }
2012 }
2013 return result;
2014}
static RegisterPass< ActivityAnalysisPrinter > X("print-activity-analysis", "Print Activity Analysis Results")
llvm::cl::opt< bool > EfficientMaxCache("enzyme-max-cache", cl::init(false), cl::Hidden, cl::desc("Avoid reallocs when possible by potentially overallocating cache"))
std::pair< PHINode *, Instruction * > InsertNewCanonicalIV(Loop *L, Type *Ty, const llvm::Twine &Name)
decltype(std::declval< const SCEVAddRecExpr & >().getNoWrapFlags()) NoWrapFlagsTy
static const SCEV * closedFormOfCountedAccumulator(PHINode *PN, Loop *L, const SCEV *IterationNumber, ScalarEvolution &SE)
PN is a header phi of L that scalar evolution could not classify.
static const SCEV * closedFormOfNegatingRecurrence(PHINode *PN, Loop *L, const SCEV *IterationNumber, ScalarEvolution &SE)
PN is a header phi of L that is negated on every iteration, x_{i+1} = -x_i, such as the alternating s...
void RemoveRedundantIVs(Loop *L, PHINode *CanonicalIV, Instruction *Increment, MustExitScalarEvolution &SE, llvm::function_ref< void(Instruction *, Value *)> replacer, llvm::function_ref< void(Instruction *)> eraser)
void CanonicalizeLatches(const Loop *L, BasicBlock *Header, BasicBlock *Preheader, PHINode *CanonicalIV, MustExitScalarEvolution &SE, CacheUtility &gutils, Instruction *Increment, ArrayRef< BasicBlock * > latches)
llvm::cl::opt< bool > EnzymeRewriteAccumulators("enzyme-rewrite-accumulators", cl::init(true), cl::Hidden, cl::desc("Rewrite a loop-carried counter whose step is an inner loop's " "trip count into a closed form of the induction variable"))
std::pair< PHINode *, Instruction * > FindCanonicalIV(Loop *L, Type *Ty)
llvm::cl::opt< bool > EnzymeZeroCache
llvm::cl::opt< bool > EfficientBoolCache
Pack 8 bools together in a single byte.
@ AttemptFullUnwrapWithLookup
static void getExitBlocks(const llvm::Loop *L, llvm::SmallPtrSetImpl< llvm::BasicBlock * > &ExitBlocks)
static llvm::SmallVector< llvm::BasicBlock *, 3 > getLatches(const llvm::Loop *L, const llvm::SmallPtrSetImpl< llvm::BasicBlock * > &ExitBlocks)
static std::string str(AugmentedStruct c)
Definition EnzymeLogic.h:62
llvm::Value * CreateReAllocation(llvm::IRBuilder<> &B, llvm::Value *prev, llvm::Type *T, llvm::Value *OuterCount, llvm::Value *InnerCount, const llvm::Twine &Name, llvm::CallInst **caller, bool ZeroMem)
Definition Utils.cpp:685
llvm::SmallVector< llvm::Instruction *, 2 > PostCacheStore(llvm::StoreInst *SI, llvm::IRBuilder<> &B)
Definition Utils.cpp:517
Value * CreateAllocation(IRBuilder<> &Builder, llvm::Type *T, Value *Count, const Twine &Name, CallInst **caller, Instruction **ZeroMem, bool isDefault)
Definition Utils.cpp:714
LLVMValueRef(* CustomErrorHandler)(const char *, LLVMValueRef, ErrorType, const void *, LLVMValueRef, LLVMBuilderRef)
Definition Utils.cpp:62
const SCEV * evaluateAtIterationWithoutExt(const SCEVAddRecExpr *AR, const SCEV *It, ScalarEvolution &SE)
Definition Utils.cpp:2801
llvm::FastMathFlags getFast()
Get LLVM fast math flags.
Definition Utils.cpp:4026
llvm::Constant * getUndefinedValueForType(llvm::Module &M, llvm::Type *T, bool forceZero)
Definition Utils.cpp:3918
static llvm::Instruction * getNextNonDebugInstructionOrNull(llvm::Instruction *Z)
Get the next non-debug instruction, if one exists.
Definition Utils.h:462
static V * findInMap(std::map< K, V > &map, K key)
Definition Utils.h:999
void EmitFailure(llvm::StringRef RemarkName, const llvm::DiagnosticLocation &Loc, const llvm::Instruction *CodeRegion, Args &...args)
Definition Utils.h:347
static std::map< K, V >::iterator insert_or_assign2(std::map< K, V > &map, K key, V val)
Insert into a map.
Definition Utils.h:990
void EmitWarning(llvm::StringRef RemarkName, const llvm::DiagnosticLocation &Loc, const llvm::BasicBlock *BB, const Args &...args)
Definition Utils.h:252
static llvm::Instruction * getFirstNonPHI(llvm::BasicBlock *B)
Definition Utils.h:2550
static llvm::Instruction * getNextNonDebugInstruction(llvm::Instruction *Z)
Get the next non-debug instruction, erring if none exists.
Definition Utils.h:471
static bool isConditionalBranch(const llvm::Value *V)
Definition Utils.h:65
static llvm::Value * getBranchCondition(llvm::Value *V)
The condition of a branch isConditionalBranch says yes to.
Definition Utils.h:100
llvm::cl::opt< bool > EnzymePrintPerf
Print additional debug info relevant to performance.
static llvm::Instruction * getFirstNonPHIOrDbg(llvm::BasicBlock *B)
Definition Utils.h:2580
static void moveBeforeInst(llvm::Instruction *I, llvm::Instruction *Before)
Definition Utils.h:2571
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.
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()
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...
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
llvm::SmallPtrSet< llvm::BasicBlock *, 4 > GuaranteedUnreachable
ScalarEvolution::ExitLimit computeExitLimit(const llvm::Loop *L, llvm::BasicBlock *ExitingBlock, bool AllowPredicates)
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
Replace every non-affine recurrence (of degree at most three) inside an expression by its closed form...
const SCEV * visitAddRecExpr(const SCEVAddRecExpr *AR)
NonAffineClosedFormRewriter(ScalarEvolution &SE)