Enzyme main
Loading...
Searching...
No Matches
CApi.cpp
Go to the documentation of this file.
1//===- CApi.cpp - Enzyme API exported to C for external use -----------===//
2//
3// Enzyme Project
4//
5// Part of the Enzyme Project, under the Apache License v2.0 with LLVM
6// Exceptions. See https://llvm.org/LICENSE.txt for license information.
7// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8//
9// If using this code in an academic setting, please cite the following:
10// @incollection{enzymeNeurips,
11// title = {Instead of Rewriting Foreign Code for Machine Learning,
12// Automatically Synthesize Fast Gradients},
13// author = {Moses, William S. and Churavy, Valentin},
14// booktitle = {Advances in Neural Information Processing Systems 33},
15// year = {2020},
16// note = {To appear in},
17// }
18//
19//===----------------------------------------------------------------------===//
20//
21// This file defines various utility functions of Enzyme for access via C
22//
23//===----------------------------------------------------------------------===//
24#include "CApi.h"
25#include "Utils.h"
26#if LLVM_VERSION_MAJOR >= 16
27#define private public
28#include "llvm/Analysis/ScalarEvolution.h"
29#include "llvm/Transforms/Utils/ScalarEvolutionExpander.h"
30#undef private
31#else
32#include "SCEV/ScalarEvolution.h"
33#include "SCEV/ScalarEvolutionExpander.h"
34#endif
35
36#include "DiffeGradientUtils.h"
38#include "EnzymeLogic.h"
39#include "GradientUtils.h"
40#include "LibraryFuncs.h"
41#if LLVM_VERSION_MAJOR >= 16
42#include "llvm/Analysis/TargetLibraryInfo.h"
43#else
44#include "SCEV/TargetLibraryInfo.h"
45#endif
46#include "TraceInterface.h"
47
48// #include "llvm/ADT/Triple.h"
49#include "llvm/Analysis/CallGraph.h"
50#include "llvm/Analysis/GlobalsModRef.h"
51#include "llvm/IR/DIBuilder.h"
52#include "llvm/IR/MDBuilder.h"
53#include "llvm/Transforms/Utils/Cloning.h"
54
55#include "llvm/IR/LegacyPassManager.h"
56#include "llvm/Transforms/IPO/Attributor.h"
57
58#define addAttribute addAttributeAtIndex
59#define removeAttribute removeAttributeAtIndex
60#define getAttribute getAttributeAtIndex
61#define hasAttribute hasAttributeAtIndex
62
63using namespace llvm;
64
65TargetLibraryInfo eunwrap(LLVMTargetLibraryInfoRef P) {
66 return TargetLibraryInfo(*reinterpret_cast<TargetLibraryInfoImpl *>(P));
67}
68
70
74
84
85ConcreteType eunwrap(CConcreteType CDT, llvm::LLVMContext &ctx) {
86 switch (CDT) {
87 case DT_Anything:
88 return BaseType::Anything;
89 case DT_Integer:
90 return BaseType::Integer;
91 case DT_Pointer:
92 return BaseType::Pointer;
93 case DT_Half:
94 return ConcreteType(llvm::Type::getHalfTy(ctx));
95 case DT_Float:
96 return ConcreteType(llvm::Type::getFloatTy(ctx));
97 case DT_Double:
98 return ConcreteType(llvm::Type::getDoubleTy(ctx));
99 case DT_X86_FP80:
100 return ConcreteType(llvm::Type::getX86_FP80Ty(ctx));
101 case DT_BFloat16:
102 return ConcreteType(llvm::Type::getBFloatTy(ctx));
103 case DT_FP128:
104 return ConcreteType(llvm::Type::getFP128Ty(ctx));
105 case DT_Unknown:
106 return BaseType::Unknown;
107 }
108 llvm_unreachable("Unknown concrete type to unwrap");
109}
110
111std::vector<int> eunwrap(IntList IL) {
112 std::vector<int> v;
113 for (size_t i = 0; i < IL.size; i++) {
114 v.push_back((int)IL.data[i]);
115 }
116 return v;
117}
118std::set<int64_t> eunwrap64(IntList IL) {
119 std::set<int64_t> v;
120 for (size_t i = 0; i < IL.size; i++) {
121 v.insert((int64_t)IL.data[i]);
122 }
123 return v;
124}
125TypeTree eunwrap(CTypeTreeRef CTT) { return *(TypeTree *)CTT; }
126
128 if (auto flt = CT.isFloat()) {
129 if (flt->isHalfTy())
130 return DT_Half;
131 if (flt->isFloatTy())
132 return DT_Float;
133 if (flt->isDoubleTy())
134 return DT_Double;
135 if (flt->isX86_FP80Ty())
136 return DT_X86_FP80;
137 if (flt->isBFloatTy())
138 return DT_BFloat16;
139 if (flt->isFP128Ty())
140 return DT_FP128;
141 } else {
142 switch (CT.SubTypeEnum) {
144 return DT_Integer;
146 return DT_Pointer;
148 return DT_Anything;
150 return DT_Unknown;
151 case BaseType::Float:
152 llvm_unreachable("Illegal conversion of concretetype");
153 }
154 }
155 llvm_unreachable("Illegal conversion of concretetype");
156}
157
158IntList ewrap(const std::vector<int> &offsets) {
159 IntList IL;
160 IL.size = offsets.size();
161 IL.data = new int64_t[IL.size];
162 for (size_t i = 0; i < offsets.size(); i++) {
163 IL.data[i] = offsets[i];
164 }
165 return IL;
166}
167
169 return (CTypeTreeRef)(new TypeTree(TT));
170}
171
172FnTypeInfo eunwrap(CFnTypeInfo CTI, llvm::Function *F) {
173 FnTypeInfo FTI(F);
174 // auto &ctx = F->getContext();
175 FTI.Return = eunwrap(CTI.Return);
176
177 size_t argnum = 0;
178 for (auto &arg : F->args()) {
179 FTI.Arguments[&arg] = eunwrap(CTI.Arguments[argnum]);
180 FTI.KnownValues[&arg] = eunwrap64(CTI.KnownValues[argnum]);
181 argnum++;
182 }
183 return FTI;
184}
185
186extern "C" {
187
188void EnzymeSetCLBool(void *ptr, uint8_t val) {
189 auto cl = (llvm::cl::opt<bool> *)ptr;
190 cl->setValue((bool)val);
191}
192
193uint8_t EnzymeGetCLBool(void *ptr) {
194 auto cl = (llvm::cl::opt<bool> *)ptr;
195 return (uint8_t)(bool)cl->getValue();
196}
197
198void EnzymeSetCLInteger(void *ptr, int64_t val) {
199 auto cl = (llvm::cl::opt<int> *)ptr;
200 cl->setValue((int)val);
201}
202
203int64_t EnzymeGetCLInteger(void *ptr) {
204 auto cl = (llvm::cl::opt<int> *)ptr;
205 return (int64_t)cl->getValue();
206}
207
208void EnzymeSetCLString(void *ptr, const char *val) {
209 if (auto *clopt = static_cast<cl::opt<std::string> *>(ptr))
210 clopt->setValue(val);
211}
212
214 return (EnzymeLogicRef)(new EnzymeLogic((bool)PostOpt));
215}
216
217void EnzymeLogicSetExternalContext(EnzymeLogicRef Ref, void *ExternalContext) {
218 eunwrap(Ref).ExternalContext = ExternalContext;
219}
220
222 return eunwrap(Ref).ExternalContext;
223}
224
228
230 LLVMContextRef C, LLVMValueRef getTraceFunction,
231 LLVMValueRef getChoiceFunction, LLVMValueRef insertCallFunction,
232 LLVMValueRef insertChoiceFunction, LLVMValueRef insertArgumentFunction,
233 LLVMValueRef insertReturnFunction, LLVMValueRef insertFunctionFunction,
234 LLVMValueRef insertChoiceGradientFunction,
235 LLVMValueRef insertArgumentGradientFunction, LLVMValueRef newTraceFunction,
236 LLVMValueRef freeTraceFunction, LLVMValueRef hasCallFunction,
237 LLVMValueRef hasChoiceFunction) {
239 *unwrap(C), cast<Function>(unwrap(getTraceFunction)),
240 cast<Function>(unwrap(getChoiceFunction)),
241 cast<Function>(unwrap(insertCallFunction)),
242 cast<Function>(unwrap(insertChoiceFunction)),
243 cast<Function>(unwrap(insertArgumentFunction)),
244 cast<Function>(unwrap(insertReturnFunction)),
245 cast<Function>(unwrap(insertFunctionFunction)),
246 cast<Function>(unwrap(insertChoiceGradientFunction)),
247 cast<Function>(unwrap(insertArgumentGradientFunction)),
248 cast<Function>(unwrap(newTraceFunction)),
249 cast<Function>(unwrap(freeTraceFunction)),
250 cast<Function>(unwrap(hasCallFunction)),
251 cast<Function>(unwrap(hasChoiceFunction))));
252};
253
255CreateEnzymeDynamicTraceInterface(LLVMValueRef interface, LLVMValueRef F) {
257 unwrap(interface), cast<Function>(unwrap(F))));
258}
259
260void ClearEnzymeLogic(EnzymeLogicRef Ref) { eunwrap(Ref).clear(); }
261
263 auto &Logic = eunwrap(Ref);
264 for (const auto &pair : Logic.PPC.cache)
265 pair.second->eraseFromParent();
266}
267
268void FreeEnzymeLogic(EnzymeLogicRef Ref) { delete (EnzymeLogic *)Ref; }
269
273
275 char **customRuleNames,
276 CustomRuleType *customRules,
277 size_t numRules) {
278 EnzymeLogic &Logic = eunwrap(Log);
279 TypeAnalysis *TA = new TypeAnalysis(Logic);
280 for (size_t i = 0; i < numRules; i++) {
281 CustomRuleType rule = customRules[i];
282 TA->CustomRules[customRuleNames[i]] =
283 [=](int direction, TypeTree &returnTree, ArrayRef<TypeTree> argTrees,
284 ArrayRef<std::set<int64_t>> knownValues, CallBase *call,
285 TypeAnalyzer *TA) -> uint8_t {
286 CTypeTreeRef creturnTree = (CTypeTreeRef)(&returnTree);
287 CTypeTreeRef *cargs = new CTypeTreeRef[argTrees.size()];
288 IntList *kvs = new IntList[argTrees.size()];
289 for (size_t i = 0; i < argTrees.size(); ++i) {
290 cargs[i] = (CTypeTreeRef)(&(argTrees[i]));
291 kvs[i].size = knownValues[i].size();
292 kvs[i].data = new int64_t[kvs[i].size];
293 size_t j = 0;
294 for (auto val : knownValues[i]) {
295 kvs[i].data[j] = val;
296 j++;
297 }
298 }
299 uint8_t result = rule(direction, creturnTree, cargs, kvs, argTrees.size(),
300 wrap(call), TA);
301 delete[] cargs;
302 for (size_t i = 0; i < argTrees.size(); ++i) {
303 delete[] kvs[i].data;
304 }
305 delete[] kvs;
306 return result;
307 };
308 }
309 return (EnzymeTypeAnalysisRef)TA;
310}
311
313
315 TypeAnalysis *TA = (TypeAnalysis *)TAR;
316 delete TA;
317}
318
322
324 LLVMValueRef F) {
325 FnTypeInfo FTI(eunwrap(CTI, cast<Function>(unwrap(F))));
326 return (void *)((TypeAnalysis *)TAR)->analyzeFunction(FTI).analyzer;
327}
328
330 return (void *)&G->TR.analyzer;
331}
332
336
337void EnzymeGradientUtilsErase(GradientUtils *G, LLVMValueRef I) {
338 return G->erase(cast<Instruction>(unwrap(I)));
339}
341 LLVMValueRef orig, uint8_t erase) {
342 return G->eraseWithPlaceholder(cast<Instruction>(unwrap(I)),
343 cast<Instruction>(unwrap(orig)),
344 "_replacementABI", erase != 0);
345}
346
348 LLVMValueRef B) {
349 return G->replaceAWithB(unwrap(A), unwrap(B));
350}
351
353 CustomShadowFree FHandle) {
354 shadowHandlers[Name] = [=](IRBuilder<> &B, CallInst *CI,
355 ArrayRef<Value *> Args,
356 GradientUtils *gutils) -> llvm::Value * {
357 SmallVector<LLVMValueRef, 3> refs;
358 for (auto a : Args)
359 refs.push_back(wrap(a));
360 return unwrap(
361 AHandle(wrap(&B), wrap(CI), Args.size(), refs.data(), gutils));
362 };
363 if (FHandle)
364 shadowErasers[Name] = [=](IRBuilder<> &B,
365 Value *ToFree) -> llvm::CallInst * {
366 return cast_or_null<CallInst>(unwrap(FHandle(wrap(&B), wrap(ToFree))));
367 };
368}
369
370void EnzymeRegisterCallHandler(const char *Name,
372 CustomFunctionReverse RevHandle) {
373 auto &pair = customCallHandlers[Name];
374 pair.first = [=](IRBuilder<> &B, CallInst *CI, GradientUtils &gutils,
375 Value *&normalReturn, Value *&shadowReturn,
376 Value *&tape) -> bool {
377 LLVMValueRef normalR = wrap(normalReturn);
378 LLVMValueRef shadowR = wrap(shadowReturn);
379 LLVMValueRef tapeR = wrap(tape);
380 uint8_t noMod =
381 FwdHandle(wrap(&B), wrap(CI), &gutils, &normalR, &shadowR, &tapeR);
382 normalReturn = unwrap(normalR);
383 shadowReturn = unwrap(shadowR);
384 tape = unwrap(tapeR);
385 return noMod != 0;
386 };
387 pair.second = [=](IRBuilder<> &B, CallInst *CI, DiffeGradientUtils &gutils,
388 Value *tape) {
389 RevHandle(wrap(&B), wrap(CI), &gutils, wrap(tape));
390 };
391}
392
394 auto &pair = customFwdCallHandlers[Name];
395 pair = [=](IRBuilder<> &B, CallInst *CI, GradientUtils &gutils,
396 Value *&normalReturn, Value *&shadowReturn) -> bool {
397 LLVMValueRef normalR = wrap(normalReturn);
398 LLVMValueRef shadowR = wrap(shadowReturn);
399 uint8_t noMod = FwdHandle(wrap(&B), wrap(CI), &gutils, &normalR, &shadowR);
400 normalReturn = unwrap(normalR);
401 shadowReturn = unwrap(shadowR);
402 return noMod != 0;
403 };
404}
405
407 CustomFunctionDiffUse Handle) {
408 auto &pair = customDiffUseHandlers[Name];
409 pair = [=](const CallInst *CI, const GradientUtils *gutils, const Value *arg,
410 bool isshadow, DerivativeMode mode, bool &useDefault) -> bool {
411 uint8_t useDefaultC = 0;
412 uint8_t noMod = Handle(wrap(CI), gutils, wrap(arg), isshadow,
413 (CDerivativeMode)(mode), &useDefaultC);
414 useDefault = useDefaultC != 0;
415 return noMod != 0;
416 };
417}
418
420 return gutils->runtimeActivity;
421}
422
426
428 return gutils->strongZero;
429}
430
432 return gutils->AtomicAdd;
433}
434
436 return gutils->getWidth();
437}
438
442
444 LLVMTypeRef T) {
445 return wrap(gutils->getShadowType(unwrap(T)));
446}
447
448LLVMTypeRef EnzymeGetShadowType(uint64_t width, LLVMTypeRef T) {
449 return wrap(GradientUtils::getShadowType(unwrap(T), width));
450}
451
453 LLVMValueRef val) {
454 return wrap(gutils->getNewFromOriginal(unwrap(val)));
455}
456
457void EnzymeReplaceOriginalToNew(GradientUtils *gutils, LLVMValueRef origC,
458 LLVMValueRef repC) {
459 auto orig = cast<Instruction>(unwrap(origC));
460 auto rep = cast<Instruction>(unwrap(repC));
461 auto found = gutils->originalToNewFn.find(orig);
462 assert(found != gutils->originalToNewFn.end());
463 auto newCall = found->second;
464 gutils->originalToNewFn[orig] = rep;
465 gutils->newToOriginalFn.erase(newCall);
466 gutils->newToOriginalFn[rep] = orig;
467}
468
472
475 uint8_t foreignFunction) {
476 return (CDIFFE_TYPE)(G->getDiffeType(unwrap(oval), foreignFunction != 0));
477}
478
480 LLVMValueRef oval) {
481 return G->augmentedPrimalReturnUsed(unwrap(oval));
482}
483
486 uint8_t *needsPrimal,
487 uint8_t *needsShadow,
488 CDerivativeMode mode) {
489 bool needsPrimalB;
490 bool needsShadowB;
491 auto res = (CDIFFE_TYPE)(G->getReturnDiffeType(
492 unwrap(oval), &needsPrimalB, &needsShadowB, (DerivativeMode)mode));
493 if (needsPrimal)
494 *needsPrimal = needsPrimalB;
495 if (needsShadow)
496 *needsShadow = needsShadowB;
497 return res;
498}
499
501 LLVMValueRef val,
502 LLVMValueRef orig) {
503 return cast<Instruction>(unwrap(val))
504 ->setDebugLoc(gutils->getNewFromOriginal(
505 cast<Instruction>(unwrap(orig))->getDebugLoc()));
506}
507
508LLVMValueRef EnzymeInsertValue(LLVMBuilderRef B, LLVMValueRef val,
509 LLVMValueRef val2, unsigned *sz, int64_t length,
510 const char *name) {
511 return wrap(unwrap(B)->CreateInsertValue(
512 unwrap(val), unwrap(val2), ArrayRef<unsigned>(sz, sz + length), name));
513}
514
515LLVMValueRef EnzymeGradientUtilsLookup(GradientUtils *gutils, LLVMValueRef val,
516 LLVMBuilderRef B) {
517 return wrap(gutils->lookupM(unwrap(val), *unwrap(B)));
518}
519
521 LLVMValueRef val,
522 LLVMBuilderRef B) {
523 return wrap(gutils->invertPointerM(unwrap(val), *unwrap(B)));
524}
525
527 LLVMValueRef val, LLVMBuilderRef B) {
528 return wrap(gutils->diffe(unwrap(val), *unwrap(B)));
529}
530
532 LLVMValueRef diffe, LLVMBuilderRef B,
533 LLVMTypeRef T) {
534 gutils->addToDiffe(unwrap(val), unwrap(diffe), *unwrap(B), unwrap(T));
535}
536
538 DiffeGradientUtils *gutils, LLVMValueRef orig, LLVMValueRef origVal,
539 LLVMTypeRef addingType, unsigned start, unsigned size, LLVMValueRef origptr,
540 LLVMValueRef dif, LLVMBuilderRef BuilderM, unsigned align,
541 LLVMValueRef mask) {
542 MaybeAlign align2;
543 if (align)
544 align2 = MaybeAlign(align);
545 auto inst = cast_or_null<Instruction>(unwrap(orig));
546 gutils->addToInvertedPtrDiffe(inst, unwrap(origVal), unwrap(addingType),
547 start, size, unwrap(origptr), unwrap(dif),
548 *unwrap(BuilderM), align2, unwrap(mask));
549}
550
552 DiffeGradientUtils *gutils, LLVMValueRef orig, LLVMValueRef origVal,
553 CTypeTreeRef vd, unsigned LoadSize, LLVMValueRef origptr,
554 LLVMValueRef prediff, LLVMBuilderRef BuilderM, unsigned align,
555 LLVMValueRef premask) {
556 MaybeAlign align2;
557 if (align)
558 align2 = MaybeAlign(align);
559 auto inst = cast_or_null<Instruction>(unwrap(orig));
560 gutils->addToInvertedPtrDiffe(inst, unwrap(origVal), *(TypeTree *)vd,
561 LoadSize, unwrap(origptr), unwrap(prediff),
562 *unwrap(BuilderM), align2, unwrap(premask));
563}
564
565void EnzymeGradientUtilsSetDiffe(DiffeGradientUtils *gutils, LLVMValueRef val,
566 LLVMValueRef diffe, LLVMBuilderRef B) {
567 gutils->setDiffe(unwrap(val), unwrap(diffe), *unwrap(B));
568}
569
571 LLVMValueRef val) {
572 return gutils->isConstantValue(unwrap(val));
573}
574
576 LLVMValueRef val) {
577 return gutils->isConstantInstruction(cast<Instruction>(unwrap(val)));
578}
579
581 return wrap(gutils->inversionAllocs);
582}
583
585 LLVMValueRef orig, uint8_t *data,
586 uint64_t size) {
587 if (gutils->mode == DerivativeMode::ForwardMode ||
589 return 0;
590
591 if (!gutils->overwritten_args_map_ptr)
592 return 0;
593
594 CallInst *call = cast<CallInst>(unwrap(orig));
595
596 assert(gutils->overwritten_args_map_ptr);
597 auto found = gutils->overwritten_args_map_ptr->find(call);
598 if (found == gutils->overwritten_args_map_ptr->end()) {
599 llvm::errs() << " oldFunc " << *gutils->oldFunc << "\n";
600 for (auto &pair : *gutils->overwritten_args_map_ptr) {
601 llvm::errs() << " + " << *pair.first << "\n";
602 }
603 llvm::errs() << " could not find call orig in overwritten_args_map_ptr "
604 << *call << "\n";
605 }
606 assert(found != gutils->overwritten_args_map_ptr->end());
607
608 const std::vector<bool> &overwritten_args = found->second.second;
609
610 if (size != overwritten_args.size()) {
611 llvm::errs() << " orig: " << *call << "\n";
612 llvm::errs() << " size: " << size
613 << " overwritten_args.size(): " << overwritten_args.size()
614 << "\n";
615 }
616 assert(size == overwritten_args.size());
617 for (uint64_t i = 0; i < size; i++) {
618 data[i] = overwritten_args[i];
619 }
620 return 1;
621}
622
624 LLVMValueRef val) {
625 auto v = unwrap(val);
626 TypeTree *pTT = new TypeTree(gutils->TR.query(v));
627 return (CTypeTreeRef)pTT;
628}
629
631 gutils->TR.dump();
632}
633
635 GradientUtils *gutils, CDerivativeMode mode, LLVMTypeRef secretty,
636 uint64_t intrinsic, uint64_t dstAlign, uint64_t srcAlign, uint64_t offset,
637 uint8_t dstConstant, LLVMValueRef shadow_dst, LLVMValueRef primal_dst,
638 uint8_t srcConstant, LLVMValueRef shadow_src, LLVMValueRef primal_src,
639 LLVMValueRef length, LLVMValueRef isVolatile, LLVMValueRef MTI,
640 uint8_t allowForward, uint8_t shadowsLookedUp) {
641 auto orig = unwrap(MTI);
642 assert(orig);
643 SubTransferHelper(gutils, (DerivativeMode)mode, unwrap(secretty),
644 (Intrinsic::ID)intrinsic, (unsigned)dstAlign,
645 (unsigned)srcAlign, (unsigned)offset, (bool)dstConstant,
646 unwrap(shadow_dst), unwrap(primal_dst), (bool)srcConstant,
647 unwrap(shadow_src), unwrap(primal_src), unwrap(length),
648 unwrap(isVolatile), cast<CallInst>(orig),
649 (bool)allowForward, (bool)shadowsLookedUp);
650}
651
653 LLVMBasicBlockRef block,
654 const char *name,
655 uint8_t forkCache,
656 uint8_t push) {
657 return wrap(gutils->addReverseBlock(cast<BasicBlock>(unwrap(block)), name,
658 forkCache, push));
659}
660
662 LLVMBasicBlockRef block) {
663 auto endBlock = cast<BasicBlock>(unwrap(block));
664 auto found = gutils->reverseBlockToPrimal.find(endBlock);
665 assert(found != gutils->reverseBlockToPrimal.end());
666 auto &vec = gutils->reverseBlocks[found->second];
667 assert(vec.size());
668 vec.push_back(endBlock);
669}
670
672 EnzymeLogicRef Logic, LLVMValueRef request_req, LLVMBuilderRef request_ip,
673 LLVMValueRef todiff, CDIFFE_TYPE retType, CDIFFE_TYPE *constant_args,
674 size_t constant_args_size, EnzymeTypeAnalysisRef TA, uint8_t returnValue,
675 CDerivativeMode mode, uint8_t freeMemory, uint8_t runtimeActivity,
676 uint8_t strongZero, unsigned width, LLVMTypeRef additionalArg,
677 CFnTypeInfo typeInfo, uint8_t subsequent_calls_may_write,
678 uint8_t *_overwritten_args, size_t overwritten_args_size,
679 EnzymeAugmentedReturnPtr augmented) {
680 SmallVector<DIFFE_TYPE, 4> nconstant_args((DIFFE_TYPE *)constant_args,
681 (DIFFE_TYPE *)constant_args +
682 constant_args_size);
683 std::vector<bool> overwritten_args;
684 assert(overwritten_args_size == cast<Function>(unwrap(todiff))->arg_size());
685 for (uint64_t i = 0; i < overwritten_args_size; i++) {
686 overwritten_args.push_back(_overwritten_args[i]);
687 }
688 return wrap(eunwrap(Logic).CreateForwardDiff(
689 RequestContext(cast_or_null<Instruction>(unwrap(request_req)),
690 unwrap(request_ip)),
691 cast<Function>(unwrap(todiff)), (DIFFE_TYPE)retType, nconstant_args,
692 eunwrap(TA), returnValue, (DerivativeMode)mode, freeMemory,
693 runtimeActivity, strongZero, width, unwrap(additionalArg),
694 eunwrap(typeInfo, cast<Function>(unwrap(todiff))),
695 subsequent_calls_may_write, overwritten_args, eunwrap(augmented)));
696}
698 EnzymeLogicRef Logic, LLVMValueRef request_req, LLVMBuilderRef request_ip,
699 LLVMValueRef todiff, CDIFFE_TYPE retType, CDIFFE_TYPE *constant_args,
700 size_t constant_args_size, EnzymeTypeAnalysisRef TA, uint8_t returnValue,
701 uint8_t dretUsed, CDerivativeMode mode, uint8_t runtimeActivity,
702 uint8_t strongZero, unsigned width, uint8_t freeMemory,
703 LLVMTypeRef additionalArg, uint8_t forceAnonymousTape, CFnTypeInfo typeInfo,
704 uint8_t subsequent_calls_may_write, uint8_t *_overwritten_args,
705 size_t overwritten_args_size, EnzymeAugmentedReturnPtr augmented,
706 uint8_t AtomicAdd) {
707 std::vector<DIFFE_TYPE> nconstant_args((DIFFE_TYPE *)constant_args,
708 (DIFFE_TYPE *)constant_args +
709 constant_args_size);
710 std::vector<bool> overwritten_args;
711 assert(overwritten_args_size == cast<Function>(unwrap(todiff))->arg_size());
712 for (uint64_t i = 0; i < overwritten_args_size; i++) {
713 overwritten_args.push_back(_overwritten_args[i]);
714 }
715 return wrap(eunwrap(Logic).CreatePrimalAndGradient(
716 RequestContext(cast_or_null<Instruction>(unwrap(request_req)),
717 unwrap(request_ip)),
719 .todiff = cast<Function>(unwrap(todiff)),
720 .retType = (DIFFE_TYPE)retType,
721 .constant_args = nconstant_args,
722 .subsequent_calls_may_write = (bool)subsequent_calls_may_write,
723 .overwritten_args = overwritten_args,
724 .returnUsed = (bool)returnValue,
725 .shadowReturnUsed = (bool)dretUsed,
726 .mode = (DerivativeMode)mode,
727 .width = width,
728 .freeMemory = (bool)freeMemory,
729 .AtomicAdd = (bool)AtomicAdd,
730 .additionalType = unwrap(additionalArg),
731 .forceAnonymousTape = (bool)forceAnonymousTape,
732 .typeInfo = eunwrap(typeInfo, cast<Function>(unwrap(todiff))),
733 .runtimeActivity = (bool)runtimeActivity,
734 .strongZero = (bool)strongZero},
735 eunwrap(TA), eunwrap(augmented)));
736}
738 EnzymeLogicRef Logic, LLVMValueRef request_req, LLVMBuilderRef request_ip,
739 LLVMValueRef todiff, CDIFFE_TYPE retType, CDIFFE_TYPE *constant_args,
740 size_t constant_args_size, EnzymeTypeAnalysisRef TA, uint8_t returnUsed,
741 uint8_t shadowReturnUsed, CFnTypeInfo typeInfo,
742 uint8_t subsequent_calls_may_write, uint8_t *_overwritten_args,
743 size_t overwritten_args_size, uint8_t *_nowrite_shadows,
744 size_t nowrite_shadows_size, uint8_t forceAnonymousTape,
745 uint8_t runtimeActivity, uint8_t strongZero, unsigned width,
746 uint8_t AtomicAdd) {
747
748 SmallVector<DIFFE_TYPE, 4> nconstant_args((DIFFE_TYPE *)constant_args,
749 (DIFFE_TYPE *)constant_args +
750 constant_args_size);
751 std::vector<bool> overwritten_args;
752 assert(overwritten_args_size == cast<Function>(unwrap(todiff))->arg_size());
753 for (uint64_t i = 0; i < overwritten_args_size; i++) {
754 overwritten_args.push_back(_overwritten_args[i]);
755 }
756 std::vector<bool> nowrite_shadows;
757 assert(nowrite_shadows_size == cast<Function>(unwrap(todiff))->arg_size());
758 for (uint64_t i = 0; i < nowrite_shadows_size; i++) {
759 nowrite_shadows.push_back(_nowrite_shadows[i]);
760 }
761 auto F = cast<Function>(unwrap(todiff));
762 return ewrap(eunwrap(Logic).CreateAugmentedPrimal(
763 RequestContext(cast_or_null<Instruction>(unwrap(request_req)),
764 unwrap(request_ip)),
765 F, (DIFFE_TYPE)retType, nconstant_args, eunwrap(TA), returnUsed,
766 shadowReturnUsed, eunwrap(typeInfo, F), subsequent_calls_may_write,
767 overwritten_args, nowrite_shadows, forceAnonymousTape, runtimeActivity,
768 strongZero, width, AtomicAdd));
769}
770
771LLVMValueRef EnzymeCreateBatch(EnzymeLogicRef Logic, LLVMValueRef request_req,
772 LLVMBuilderRef request_ip, LLVMValueRef tobatch,
773 unsigned width, CBATCH_TYPE *arg_types,
774 size_t arg_types_size, CBATCH_TYPE retType) {
775
776 return wrap(eunwrap(Logic).CreateBatch(
777 RequestContext(cast_or_null<Instruction>(unwrap(request_req)),
778 unwrap(request_ip)),
779 cast<Function>(unwrap(tobatch)), width,
780 ArrayRef<BATCH_TYPE>((BATCH_TYPE *)arg_types,
781 (BATCH_TYPE *)arg_types + arg_types_size),
782 (BATCH_TYPE)retType));
783}
784
785LLVMValueRef EnzymeCreateTrace(
786 EnzymeLogicRef Logic, LLVMValueRef request_req, LLVMBuilderRef request_ip,
787 LLVMValueRef totrace, LLVMValueRef *sample_functions,
788 size_t sample_functions_size, LLVMValueRef *observe_functions,
789 size_t observe_functions_size, const char *active_random_variables[],
790 size_t active_random_variables_size, CProbProgMode mode, uint8_t autodiff,
791 EnzymeTraceInterfaceRef interface) {
792
793 SmallPtrSet<Function *, 4> SampleFunctions;
794 for (size_t i = 0; i < sample_functions_size; i++) {
795 SampleFunctions.insert(cast<Function>(unwrap(sample_functions[i])));
796 }
797
798 SmallPtrSet<Function *, 4> ObserveFunctions;
799 for (size_t i = 0; i < observe_functions_size; i++) {
800 ObserveFunctions.insert(cast<Function>(unwrap(observe_functions[i])));
801 }
802
803 StringSet<> ActiveRandomVariables;
804 for (size_t i = 0; i < active_random_variables_size; i++) {
805 ActiveRandomVariables.insert(active_random_variables[i]);
806 }
807
808 return wrap(eunwrap(Logic).CreateTrace(
809 RequestContext(cast_or_null<Instruction>(unwrap(request_req)),
810 unwrap(request_ip)),
811 cast<Function>(unwrap(totrace)), SampleFunctions, ObserveFunctions,
812 ActiveRandomVariables, (ProbProgMode)mode, (bool)autodiff,
813 eunwrap(interface)));
814}
815
816LLVMValueRef
818 auto AR = (AugmentedReturn *)ret;
819 return wrap(AR->fn);
820}
821
822LLVMTypeRef
824 auto AR = (AugmentedReturn *)ret;
825 return wrap(AR->tapeType);
826}
827
828LLVMTypeRef
830 auto AR = (AugmentedReturn *)ret;
831 auto found = AR->returns.find(AugmentedStruct::Tape);
832 if (found == AR->returns.end()) {
833 return wrap((Type *)nullptr);
834 }
835 if (found->second == -1) {
836 return wrap(AR->fn->getReturnType());
837 }
838 return wrap(
839 cast<StructType>(AR->fn->getReturnType())->getTypeAtIndex(found->second));
840}
842 uint8_t *existed, size_t len) {
843 assert(len == 3);
844 auto AR = (AugmentedReturn *)ret;
847 for (size_t i = 0; i < len; i++) {
848 auto found = AR->returns.find(todo[i]);
849 if (found != AR->returns.end()) {
850 existed[i] = true;
851 data[i] = (int64_t)found->second;
852 } else {
853 existed[i] = false;
854 }
855 }
856}
857
858static MDNode *extractMDNode(MetadataAsValue *MAV) {
859 Metadata *MD = MAV->getMetadata();
860 assert((isa<MDNode>(MD) || isa<ConstantAsMetadata>(MD)) &&
861 "Expected a metadata node or a canonicalized constant");
862
863 if (MDNode *N = dyn_cast<MDNode>(MD))
864 return N;
865
866 return MDNode::get(MAV->getContext(), MD);
867}
868
870 TypeTree *Ret = new TypeTree();
871 MDNode *N = Val ? extractMDNode(unwrap<MetadataAsValue>(Val)) : nullptr;
872 Ret->insertFromMD(N);
873 return (CTypeTreeRef)N;
874}
875
876LLVMValueRef EnzymeTypeTreeToMD(CTypeTreeRef CTR, LLVMContextRef ctx) {
877 auto MD = ((TypeTree *)CTR)->toMD(*unwrap(ctx));
878 return wrap(MetadataAsValue::get(MD->getContext(), MD));
879}
880
883 return (CTypeTreeRef)(new TypeTree(eunwrap(CT, *unwrap(ctx))));
884}
888void EnzymeFreeTypeTree(CTypeTreeRef CTT) { delete (TypeTree *)CTT; }
890 return *(TypeTree *)dst = *(TypeTree *)src;
891}
893 return ((TypeTree *)dst)->orIn(*(TypeTree *)src, /*PointerIntSame*/ false);
894}
896 uint8_t *legalP) {
897 bool legal = true;
898 bool res =
899 ((TypeTree *)dst)
900 ->checkedOrIn(*(TypeTree *)src, /*PointerIntSame*/ false, legal);
901 *legalP = legal;
902 return res;
903}
904
905void EnzymeTypeTreeOnlyEq(CTypeTreeRef CTT, int64_t x) {
906 // TODO only inst
907 *(TypeTree *)CTT = ((TypeTree *)CTT)->Only(x, nullptr);
908}
910 *(TypeTree *)CTT = ((TypeTree *)CTT)->Data0();
911}
912
913void EnzymeTypeTreeLookupEq(CTypeTreeRef CTT, int64_t size, const char *dl) {
914 *(TypeTree *)CTT = ((TypeTree *)CTT)->Lookup(size, DataLayout(dl));
915}
917 const char *dl) {
918 ((TypeTree *)CTT)->CanonicalizeInPlace(size, DataLayout(dl));
919}
920
922 return ewrap(((TypeTree *)CTT)->Inner0());
923}
924
925void EnzymeTypeTreeShiftIndiciesEq(CTypeTreeRef CTT, const char *datalayout,
926 int64_t offset, int64_t maxSize,
927 uint64_t addOffset) {
928 DataLayout DL(datalayout);
929 *(TypeTree *)CTT =
930 ((TypeTree *)CTT)->ShiftIndices(DL, offset, maxSize, addOffset);
931}
932void EnzymeTypeTreeInsertEq(CTypeTreeRef CTT, const int64_t *indices,
933 size_t len, CConcreteType ct, LLVMContextRef ctx) {
934 std::vector<int> seq;
935 for (size_t i = 0; i < len; i++) {
936 seq.push_back(indices[i]);
937 }
938 ((TypeTree *)CTT)->insert(seq, eunwrap(ct, *unwrap(ctx)));
939}
941 std::string tmp = ((TypeTree *)src)->str();
942 char *cstr = new char[tmp.length() + 1];
943 std::strcpy(cstr, tmp.c_str());
944
945 return cstr;
946}
947
948// TODO deprecated
949void EnzymeTypeTreeToStringFree(const char *cstr) { delete[] cstr; }
950
951const char *EnzymeTypeAnalyzerToString(void *src) {
952 auto TA = (TypeAnalyzer *)src;
953 std::string str;
954 raw_string_ostream ss(str);
955 TA->dump(ss);
956 ss.str();
957 char *cstr = new char[str.length() + 1];
958 std::strcpy(cstr, str.c_str());
959 return cstr;
960}
961
963 auto TA = (TypeAnalyzer *)src;
964 return (EnzymeLogicRef)&TA->interprocedural.Logic;
965}
966
968 void *src) {
969 std::string str;
970 raw_string_ostream ss(str);
971 for (auto z : gutils->invertedPointers) {
972 ss << "available inversion for " << *z.first << " of " << *z.second << "\n";
973 }
974 ss.str();
975 char *cstr = new char[str.length() + 1];
976 std::strcpy(cstr, str.c_str());
977 return cstr;
978}
979
981 GradientUtils *gutils, LLVMValueRef func, LLVMTypeRef funcTy,
982 LLVMValueRef *args_vr, uint64_t args_size, LLVMValueRef orig_vr,
983 CValueType *valTys, uint64_t valTys_size, LLVMBuilderRef B,
984 uint8_t lookup) {
985 auto orig = cast<CallInst>(unwrap(orig_vr));
986
987 ArrayRef<ValueType> ar((ValueType *)valTys, valTys_size);
988
989 IRBuilder<> &BR = *unwrap(B);
990
991 auto Defs = gutils->getInvertedBundles(orig, ar, BR, lookup != 0);
992
993 SmallVector<Value *, 1> args;
994 for (size_t i = 0; i < args_size; i++) {
995 args.push_back(unwrap(args_vr[i]));
996 }
997
998 auto callval = unwrap(func);
999
1000 auto res =
1001 BR.CreateCall(cast<FunctionType>(unwrap(funcTy)), callval, args, Defs);
1002 return wrap(res);
1003}
1004
1005void EnzymeStringFree(const char *cstr) { delete[] cstr; }
1006
1007void EnzymeMoveBefore(LLVMValueRef inst1, LLVMValueRef inst2,
1008 LLVMBuilderRef B) {
1009 Instruction *I1 = cast<Instruction>(unwrap(inst1));
1010 Instruction *I2 = cast<Instruction>(unwrap(inst2));
1011 if (I1 != I2) {
1012 if (B != nullptr) {
1013 IRBuilder<> &BR = *unwrap(B);
1014 if (I1->getIterator() == BR.GetInsertPoint()) {
1015 if (I2->getNextNode() == nullptr)
1016 BR.SetInsertPoint(I1->getParent());
1017 else
1018 BR.SetInsertPoint(I1->getNextNode());
1019 }
1020 }
1021 moveBeforeInst(I1, I2);
1022 }
1023}
1024
1025void EnzymeSetStringMD(LLVMValueRef Inst, const char *Kind, LLVMValueRef Val) {
1026 MDNode *N = Val ? extractMDNode(unwrap<MetadataAsValue>(Val)) : nullptr;
1027 Value *V = unwrap(Inst);
1028 if (auto I = dyn_cast<Instruction>(V))
1029 I->setMetadata(Kind, N);
1030 else
1031 cast<GlobalVariable>(V)->setMetadata(Kind, N);
1032}
1033
1034LLVMValueRef EnzymeGetStringMD(LLVMValueRef Inst, const char *Kind) {
1035 auto *I = unwrap<Instruction>(Inst);
1036 assert(I && "Expected instruction");
1037 if (auto *MD = I->getMetadata(Kind))
1038 return wrap(MetadataAsValue::get(I->getContext(), MD));
1039 return nullptr;
1040}
1041
1042void EnzymeSetMustCache(LLVMValueRef inst1) {
1043 Instruction *I1 = cast<Instruction>(unwrap(inst1));
1044 I1->setMetadata("enzyme_mustcache", MDNode::get(I1->getContext(), {}));
1045}
1046
1047uint8_t EnzymeHasFromStack(LLVMValueRef inst1) {
1048 Instruction *I1 = cast<Instruction>(unwrap(inst1));
1049 return hasMetadata(I1, "enzyme_fromstack") != 0;
1050}
1051
1052void EnzymeCloneFunctionDISubprogramInto(LLVMValueRef NF, LLVMValueRef F) {
1053 auto &OldFunc = *cast<Function>(unwrap(F));
1054 auto &NewFunc = *cast<Function>(unwrap(NF));
1055 auto OldSP = OldFunc.getSubprogram();
1056 if (!OldSP)
1057 return;
1058 DIBuilder DIB(*OldFunc.getParent(), /*AllowUnresolved=*/false,
1059 OldSP->getUnit());
1060 auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray({}));
1061 DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagDefinition |
1062 DISubprogram::SPFlagOptimized |
1063 DISubprogram::SPFlagLocalToUnit;
1064 auto NewSP = DIB.createFunction(
1065 OldSP->getUnit(), NewFunc.getName(), NewFunc.getName(), OldSP->getFile(),
1066 /*LineNo=*/0, SPType, /*ScopeLine=*/0, DINode::FlagZero, SPFlags);
1067 NewFunc.setSubprogram(NewSP);
1068 DIB.finalizeSubprogram(NewSP);
1069 return;
1070}
1071
1074}
1075
1076void EnzymeDetectReadonlyOrThrow(LLVMModuleRef M) {
1077 DetectReadonlyOrThrow(*unwrap(M));
1078}
1079
1080void EnzymeDumpModuleRef(LLVMModuleRef M) {
1081 llvm::errs() << *unwrap(M) << "\n";
1082}
1083
1084void EnzymeDumpValueRef(LLVMValueRef M) { llvm::errs() << *unwrap(M) << "\n"; }
1085
1086void EnzymeDumpTypeRef(LLVMTypeRef M) { llvm::errs() << *unwrap(M) << "\n"; }
1087
1088static bool runAttributorOnFunctions(InformationCache &InfoCache,
1089 SetVector<Function *> &Functions,
1090 AnalysisGetter &AG,
1091 CallGraphUpdater &CGUpdater,
1092 bool DeleteFns, bool IsModulePass) {
1093 if (Functions.empty())
1094 return false;
1095
1096 // Create an Attributor and initially empty information cache that is filled
1097 // while we identify default attribute opportunities.
1098 AttributorConfig AC(CGUpdater);
1099 AC.RewriteSignatures = false;
1100 AC.IsModulePass = IsModulePass;
1101 AC.DeleteFns = DeleteFns;
1102 Attributor A(Functions, InfoCache, AC);
1103
1104 for (Function *F : Functions) {
1105 // Populate the Attributor with abstract attribute opportunities in the
1106 // function and the information cache with IR information.
1107 A.identifyDefaultAbstractAttributes(*F);
1108 }
1109
1110 ChangeStatus Changed = A.run();
1111
1112 return Changed == ChangeStatus::CHANGED;
1113}
1114
1115extern "C" void RunAttributorOnModule(LLVMModuleRef M0) {
1116 auto &M = *unwrap(M0);
1117 AnalysisGetter AG;
1118 SetVector<Function *> Functions;
1119 for (Function &F : M)
1120 Functions.insert(&F);
1121
1122 CallGraphUpdater CGUpdater;
1123 BumpPtrAllocator Allocator;
1124 InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ nullptr);
1125 runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater,
1126 /* DeleteFns*/ true,
1127 /* IsModulePass */ true);
1128}
1129
1131 static char ID;
1132
1134
1135 bool runOnModule(Module &M) override {
1136 if (skipModule(M))
1137 return false;
1138
1139 AnalysisGetter AG;
1140 SetVector<Function *> Functions;
1141 for (Function &F : M)
1142 Functions.insert(&F);
1143
1144 CallGraphUpdater CGUpdater;
1145 BumpPtrAllocator Allocator;
1146 InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ nullptr);
1147 return runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater,
1148 /* DeleteFns*/ true,
1149 /* IsModulePass */ true);
1150 }
1151
1152 void getAnalysisUsage(AnalysisUsage &AU) const override {
1153 // FIXME: Think about passes we will preserve and add them here.
1154 AU.addRequired<TargetLibraryInfoWrapperPass>();
1155 }
1156};
1157extern "C++" char MyAttributorLegacyPass::ID = 0;
1158void EnzymeAddAttributorLegacyPass(LLVMPassManagerRef PM) {
1159 unwrap(PM)->add(new MyAttributorLegacyPass());
1160}
1161
1162LLVMMetadataRef EnzymeMakeNonConstTBAA(LLVMMetadataRef MD) {
1163 auto M = cast<MDNode>(unwrap(MD));
1164 if (M->getNumOperands() != 4)
1165 return MD;
1166 auto CAM = dyn_cast<ConstantAsMetadata>(M->getOperand(3));
1167 if (!CAM)
1168 return MD;
1169 if (!CAM->getValue()->isOneValue())
1170 return MD;
1171 SmallVector<Metadata *, 4> MDs;
1172 for (auto &M : M->operands())
1173 MDs.push_back(M);
1174 MDs[3] =
1175 ConstantAsMetadata::get(ConstantInt::get(CAM->getValue()->getType(), 0));
1176 return wrap(MDNode::get(M->getContext(), MDs));
1177}
1178void EnzymeCopyMetadata(LLVMValueRef inst1, LLVMValueRef inst2) {
1179 cast<Instruction>(unwrap(inst1))
1180 ->copyMetadata(*cast<Instruction>(unwrap(inst2)));
1181}
1182void EnzymeCopyAlignment(LLVMValueRef inst1, LLVMValueRef inst2) {
1183 cast<AllocaInst>(unwrap(inst1))
1184 ->setAlignment(cast<AllocaInst>(unwrap(inst2))->getAlign());
1185}
1186void EnzymeTakeName(LLVMValueRef inst1, LLVMValueRef inst2) {
1187 unwrap(inst1)->takeName(unwrap(inst2));
1188}
1189
1190LLVMMetadataRef EnzymeAnonymousAliasScopeDomain(const char *str,
1191 LLVMContextRef ctx) {
1192 MDBuilder MDB(*unwrap(ctx));
1193 MDNode *scope = MDB.createAnonymousAliasScopeDomain(str);
1194 return wrap(scope);
1195}
1196LLVMMetadataRef EnzymeAnonymousAliasScope(LLVMMetadataRef domain,
1197 const char *str) {
1198 auto dom = cast<MDNode>(unwrap(domain));
1199 MDBuilder MDB(dom->getContext());
1200 MDNode *scope = MDB.createAnonymousAliasScope(dom, str);
1201 return wrap(scope);
1202}
1203uint8_t EnzymeLowerSparsification(LLVMValueRef F, uint8_t replaceAll) {
1204 return LowerSparsification(cast<Function>(unwrap(F)), replaceAll != 0);
1205}
1206
1207void EnzymeAttributeKnownFunctions(LLVMValueRef FC) {
1208 attributeKnownFunctions(*cast<Function>(unwrap(FC)));
1209}
1210
1211void EnzymeSetCalledFunction(LLVMValueRef C_CI, LLVMValueRef C_F,
1212 uint64_t *argrem, uint64_t num_argrem) {
1213 auto CI = cast<CallInst>(unwrap(C_CI));
1214 auto F = cast<Function>(unwrap(C_F));
1215 auto Attrs = CI->getAttributes();
1216 AttributeList NewAttrs;
1217
1218 if (CI->getType() == F->getReturnType()) {
1219 for (auto attr : Attrs.getAttributes(AttributeList::ReturnIndex))
1220 NewAttrs = NewAttrs.addAttribute(F->getContext(),
1221 AttributeList::ReturnIndex, attr);
1222 }
1223 for (auto attr : Attrs.getAttributes(AttributeList::FunctionIndex))
1224 NewAttrs = NewAttrs.addAttribute(F->getContext(),
1225 AttributeList::FunctionIndex, attr);
1226
1227 size_t argremsz = 0;
1228 size_t nexti = 0;
1229 SmallVector<Value *, 1> vals;
1230 for (size_t i = 0, end = CI->arg_size(); i < end; i++) {
1231 if (argremsz < num_argrem) {
1232 if (i == argrem[argremsz]) {
1233 argremsz++;
1234 continue;
1235 }
1236 }
1237 for (auto attr : Attrs.getAttributes(AttributeList::FirstArgIndex + i))
1238 NewAttrs = NewAttrs.addAttribute(
1239 F->getContext(), AttributeList::FirstArgIndex + nexti, attr);
1240 vals.push_back(CI->getArgOperand(i));
1241 nexti++;
1242 }
1243 assert(argremsz == num_argrem);
1244
1245 IRBuilder<> B(CI);
1246 SmallVector<OperandBundleDef, 1> Bundles;
1247 for (unsigned I = 0, E = CI->getNumOperandBundles(); I != E; ++I)
1248 Bundles.emplace_back(CI->getOperandBundleAt(I));
1249 auto NC = B.CreateCall(F, vals, Bundles);
1250 NC->setAttributes(NewAttrs);
1251 NC->copyMetadata(*CI);
1252
1253 if (CI->getType() == F->getReturnType())
1254 CI->replaceAllUsesWith(NC);
1255
1256 if (!NC->getType()->isVoidTy())
1257 NC->takeName(CI);
1258 NC->setCallingConv(CI->getCallingConv());
1259 CI->eraseFromParent();
1260}
1261
1262// clones a function to now miss the return or args
1263LLVMValueRef EnzymeCloneFunctionWithoutReturnOrArgs(LLVMValueRef FC,
1264 uint8_t keepReturnU,
1265 uint64_t *argrem,
1266 uint64_t num_argrem) {
1267 auto F = cast<Function>(unwrap(FC));
1268 auto FT = F->getFunctionType();
1269 bool keepReturn = keepReturnU != 0;
1270
1271 size_t argremsz = 0;
1272 size_t nexti = 0;
1273 SmallVector<Type *, 1> types;
1274 auto Attrs = F->getAttributes();
1275 AttributeList NewAttrs;
1276 for (size_t i = 0, end = FT->getNumParams(); i < end; i++) {
1277 if (argremsz < num_argrem) {
1278 if (i == argrem[argremsz]) {
1279 argremsz++;
1280 continue;
1281 }
1282 }
1283 for (auto attr : Attrs.getAttributes(AttributeList::FirstArgIndex + i))
1284 NewAttrs = NewAttrs.addAttribute(
1285 F->getContext(), AttributeList::FirstArgIndex + nexti, attr);
1286 types.push_back(F->getFunctionType()->getParamType(i));
1287 nexti++;
1288 }
1289 if (keepReturn) {
1290 for (auto attr : Attrs.getAttributes(AttributeList::ReturnIndex))
1291 NewAttrs = NewAttrs.addAttribute(F->getContext(),
1292 AttributeList::ReturnIndex, attr);
1293 }
1294 for (auto attr : Attrs.getAttributes(AttributeList::FunctionIndex))
1295 NewAttrs = NewAttrs.addAttribute(F->getContext(),
1296 AttributeList::FunctionIndex, attr);
1297
1298 FunctionType *FTy = FunctionType::get(
1299 keepReturn ? F->getReturnType() : Type::getVoidTy(F->getContext()), types,
1300 FT->isVarArg());
1301
1302 // Create the new function
1303 Function *NewF = Function::Create(FTy, F->getLinkage(), F->getAddressSpace(),
1304 F->getName(), F->getParent());
1305
1306 ValueToValueMapTy VMap;
1307 // Loop over the arguments, copying the names of the mapped arguments over...
1308 nexti = 0;
1309 argremsz = 0;
1310 Function::arg_iterator DestI = NewF->arg_begin();
1311 for (const Argument &I : F->args()) {
1312 if (argremsz < num_argrem) {
1313 if (I.getArgNo() == argrem[argremsz]) {
1314 VMap[&I] = UndefValue::get(I.getType());
1315 argremsz++;
1316 continue;
1317 }
1318 }
1319 DestI->setName(I.getName()); // Copy the name over...
1320 VMap[&I] = &*DestI++; // Add mapping to VMap
1321 }
1322
1323 SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
1324 CloneFunctionInto(NewF, F, VMap, CloneFunctionChangeType::LocalChangesOnly,
1325 Returns, "", nullptr);
1326 resetClonedGUID(NewF);
1327
1328 if (!keepReturn) {
1329 for (auto &B : *NewF) {
1330 if (auto RI = dyn_cast<ReturnInst>(B.getTerminator())) {
1331 IRBuilder<> B(RI);
1332 auto NRI = B.CreateRetVoid();
1333 NRI->copyMetadata(*RI);
1334 RI->eraseFromParent();
1335 }
1336 }
1337 }
1338 NewF->setAttributes(NewAttrs);
1339 if (!keepReturn)
1340 for (auto &Arg : NewF->args())
1341 Arg.removeAttr(Attribute::Returned);
1342 SmallVector<std::pair<unsigned, MDNode *>, 1> MD;
1343 F->getAllMetadata(MD);
1344 for (auto pair : MD)
1345 if (pair.first != LLVMContext::MD_dbg)
1346 NewF->addMetadata(pair.first, *pair.second);
1347 NewF->takeName(F);
1348 NewF->setCallingConv(F->getCallingConv());
1349 if (!keepReturn)
1350 NewF->addFnAttr("enzyme_retremove", "");
1351
1352 if (num_argrem) {
1353 SmallVector<uint64_t, 1> previdx;
1354 if (Attrs.hasAttribute(AttributeList::FunctionIndex, "enzyme_parmremove")) {
1355 auto attr =
1356 Attrs.getAttribute(AttributeList::FunctionIndex, "enzyme_parmremove");
1357 auto prevstr = attr.getValueAsString();
1358 SmallVector<StringRef, 1> sub;
1359 prevstr.split(sub, ",");
1360 for (auto s : sub) {
1361 uint64_t ival;
1362 bool b = s.getAsInteger(10, ival);
1363 (void)b;
1364 assert(!b);
1365 previdx.push_back(ival);
1366 }
1367 }
1368 SmallVector<uint64_t, 1> nextidx;
1369 for (size_t i = 0; i < num_argrem; i++) {
1370 auto val = argrem[i];
1371 nextidx.push_back(val);
1372 }
1373
1374 size_t prevcnt = 0;
1375 size_t nextcnt = 0;
1376 SmallVector<uint64_t, 1> out;
1377 while (prevcnt < previdx.size() && nextcnt < nextidx.size()) {
1378 if (previdx[prevcnt] <= nextidx[nextcnt] + prevcnt) {
1379 out.push_back(previdx[prevcnt]);
1380 prevcnt++;
1381 } else {
1382 out.push_back(nextidx[nextcnt] + prevcnt);
1383 nextcnt++;
1384 }
1385 }
1386 while (prevcnt < previdx.size()) {
1387 out.push_back(previdx[prevcnt]);
1388 prevcnt++;
1389 }
1390 while (nextcnt < nextidx.size()) {
1391 out.push_back(nextidx[nextcnt] + prevcnt);
1392 nextcnt++;
1393 }
1394
1395 std::string remstr;
1396 for (auto arg : out) {
1397 if (remstr.size())
1398 remstr += ",";
1399 remstr += std::to_string(arg);
1400 }
1401
1402 NewF->addFnAttr("enzyme_parmremove", remstr);
1403 }
1404 return wrap(NewF);
1405}
1406LLVMTypeRef EnzymeAllocaType(LLVMValueRef V) {
1407 return wrap(cast<AllocaInst>(unwrap(V))->getAllocatedType());
1408}
1409LLVMValueRef EnzymeComputeByteOffsetOfGEP(LLVMBuilderRef B_r, LLVMValueRef V_r,
1410 LLVMTypeRef T_r) {
1411 IRBuilder<> &B = *unwrap(B_r);
1412 auto T = cast<IntegerType>(unwrap(T_r));
1413 auto width = T->getBitWidth();
1414 auto uw = unwrap(V_r);
1415 GEPOperator *gep = isa<GetElementPtrInst>(uw)
1416 ? cast<GEPOperator>(cast<GetElementPtrInst>(uw))
1417 : cast<GEPOperator>(cast<ConstantExpr>(uw));
1418 auto &DL = B.GetInsertBlock()->getParent()->getParent()->getDataLayout();
1419
1420#if LLVM_VERSION_MAJOR >= 20
1421 SmallMapVector<Value *, APInt, 4> VariableOffsets;
1422#else
1423 MapVector<Value *, APInt> VariableOffsets;
1424#endif
1425 APInt Offset(width, 0);
1426 bool success = collectOffset(gep, DL, width, VariableOffsets, Offset);
1427 (void)success;
1428 assert(success);
1429 Value *start = ConstantInt::get(T, Offset);
1430 for (auto &pair : VariableOffsets)
1431 start = B.CreateAdd(
1432 start, B.CreateMul(pair.first, ConstantInt::get(T, pair.second)));
1433 return wrap(start);
1434}
1435}
1436
1437extern "C" {
1438
1439LLVMValueRef EnzymeBuildExtractValue(LLVMBuilderRef B, LLVMValueRef AggVal,
1440 unsigned *Index, unsigned Size,
1441 const char *Name) {
1442 return wrap(unwrap(B)->CreateExtractValue(
1443 unwrap(AggVal), ArrayRef<unsigned>(Index, Size), Name));
1444}
1445
1446LLVMValueRef EnzymeBuildInsertValue(LLVMBuilderRef B, LLVMValueRef AggVal,
1447 LLVMValueRef EltVal, unsigned *Index,
1448 unsigned Size, const char *Name) {
1449 return wrap(unwrap(B)->CreateInsertValue(
1450 unwrap(AggVal), unwrap(EltVal), ArrayRef<unsigned>(Index, Size), Name));
1451}
1452}
int64_t EnzymeGetCLInteger(void *ptr)
Definition CApi.cpp:203
void EnzymeGradientUtilsAddToInvertedPointerDiffeTT(DiffeGradientUtils *gutils, LLVMValueRef orig, LLVMValueRef origVal, CTypeTreeRef vd, unsigned LoadSize, LLVMValueRef origptr, LLVMValueRef prediff, LLVMBuilderRef BuilderM, unsigned align, LLVMValueRef premask)
Definition CApi.cpp:551
EnzymeTypeAnalysisRef EnzymeGetTypeAnalysisFromTypeAnalyzer(void *TAR)
Definition CApi.cpp:333
void EnzymeAttributeKnownFunctions(LLVMValueRef FC)
Definition CApi.cpp:1207
void EnzymeTypeTreeLookupEq(CTypeTreeRef CTT, int64_t size, const char *dl)
Definition CApi.cpp:913
LLVMMetadataRef EnzymeAnonymousAliasScopeDomain(const char *str, LLVMContextRef ctx)
Definition CApi.cpp:1190
void * EnzymeGradientUtilsGetExternalContext(GradientUtils *gutils)
Definition CApi.cpp:423
uint8_t EnzymeGradientUtilsIsConstantValue(GradientUtils *gutils, LLVMValueRef val)
Definition CApi.cpp:570
LLVMValueRef EnzymeInsertValue(LLVMBuilderRef B, LLVMValueRef val, LLVMValueRef val2, unsigned *sz, int64_t length, const char *name)
Definition CApi.cpp:508
void EnzymeSetCalledFunction(LLVMValueRef C_CI, LLVMValueRef C_F, uint64_t *argrem, uint64_t num_argrem)
Definition CApi.cpp:1211
CDIFFE_TYPE EnzymeGradientUtilsGetReturnDiffeType(GradientUtils *G, LLVMValueRef oval, uint8_t *needsPrimal, uint8_t *needsShadow, CDerivativeMode mode)
Definition CApi.cpp:485
void EnzymeStringFree(const char *cstr)
Definition CApi.cpp:1005
void EnzymeCopyAlignment(LLVMValueRef inst1, LLVMValueRef inst2)
Definition CApi.cpp:1182
void EnzymeAddAttributorLegacyPass(LLVMPassManagerRef PM)
Definition CApi.cpp:1158
CTypeTreeRef EnzymeNewTypeTreeTR(CTypeTreeRef CTR)
Definition CApi.cpp:885
void FreeTypeAnalysis(EnzymeTypeAnalysisRef TAR)
Definition CApi.cpp:314
const char * EnzymeGradientUtilsInvertedPointersToString(GradientUtils *gutils, void *src)
Definition CApi.cpp:967
LLVMBasicBlockRef EnzymeGradientUtilsAddReverseBlock(GradientUtils *gutils, LLVMBasicBlockRef block, const char *name, uint8_t forkCache, uint8_t push)
Definition CApi.cpp:652
void EnzymeTakeName(LLVMValueRef inst1, LLVMValueRef inst2)
Definition CApi.cpp:1186
void EnzymeTypeTreeData0Eq(CTypeTreeRef CTT)
Definition CApi.cpp:909
EnzymeTraceInterfaceRef CreateEnzymeDynamicTraceInterface(LLVMValueRef interface, LLVMValueRef F)
Definition CApi.cpp:255
static bool runAttributorOnFunctions(InformationCache &InfoCache, SetVector< Function * > &Functions, AnalysisGetter &AG, CallGraphUpdater &CGUpdater, bool DeleteFns, bool IsModulePass)
Definition CApi.cpp:1088
LLVMValueRef EnzymeGetStringMD(LLVMValueRef Inst, const char *Kind)
Definition CApi.cpp:1034
void EnzymeFreeTypeTree(CTypeTreeRef CTT)
Definition CApi.cpp:888
EnzymeTraceInterfaceRef FindEnzymeStaticTraceInterface(LLVMModuleRef M)
Definition CApi.cpp:225
static MDNode * extractMDNode(MetadataAsValue *MAV)
Definition CApi.cpp:858
LLVMTypeRef EnzymeExtractUnderlyingTapeTypeFromAugmentation(EnzymeAugmentedReturnPtr ret)
Definition CApi.cpp:823
void EnzymeSetCLInteger(void *ptr, int64_t val)
Definition CApi.cpp:198
void ClearTypeAnalysis(EnzymeTypeAnalysisRef TAR)
Definition CApi.cpp:312
CConcreteType EnzymeTypeTreeInner0(CTypeTreeRef CTT)
Definition CApi.cpp:921
void EnzymeTypeTreeToStringFree(const char *cstr)
Definition CApi.cpp:949
uint8_t EnzymeGradientUtilsGetAugmentedPrimalReturnUsed(GradientUtils *G, LLVMValueRef oval)
Definition CApi.cpp:479
EnzymeLogicRef CreateEnzymeLogic(uint8_t PostOpt)
Definition CApi.cpp:213
void EnzymeRegisterFwdCallHandler(char *Name, CustomFunctionForward FwdHandle)
Definition CApi.cpp:393
uint8_t EnzymeGetCLBool(void *ptr)
Definition CApi.cpp:193
void EnzymeDumpValueRef(LLVMValueRef M)
Definition CApi.cpp:1084
void FreeEnzymeLogic(EnzymeLogicRef Ref)
Definition CApi.cpp:268
void EnzymeGradientUtilsSetDebugLocFromOriginal(GradientUtils *gutils, LLVMValueRef val, LLVMValueRef orig)
Definition CApi.cpp:500
LLVMValueRef EnzymeGradientUtilsLookup(GradientUtils *gutils, LLVMValueRef val, LLVMBuilderRef B)
Definition CApi.cpp:515
const char * EnzymeTypeAnalyzerToString(void *src)
Definition CApi.cpp:951
CDIFFE_TYPE EnzymeGradientUtilsGetDiffeType(GradientUtils *G, LLVMValueRef oval, uint8_t foreignFunction)
Definition CApi.cpp:474
uint8_t EnzymeLowerSparsification(LLVMValueRef F, uint8_t replaceAll)
Definition CApi.cpp:1203
LLVMMetadataRef EnzymeAnonymousAliasScope(LLVMMetadataRef domain, const char *str)
Definition CApi.cpp:1196
void EnzymeReplaceOriginalToNew(GradientUtils *gutils, LLVMValueRef origC, LLVMValueRef repC)
Definition CApi.cpp:457
void EnzymeSetStringMD(LLVMValueRef Inst, const char *Kind, LLVMValueRef Val)
Definition CApi.cpp:1025
uint8_t EnzymeGradientUtilsGetAtomicAdd(GradientUtils *gutils)
Definition CApi.cpp:431
LLVMValueRef EnzymeGradientUtilsCallWithInvertedBundles(GradientUtils *gutils, LLVMValueRef func, LLVMTypeRef funcTy, LLVMValueRef *args_vr, uint64_t args_size, LLVMValueRef orig_vr, CValueType *valTys, uint64_t valTys_size, LLVMBuilderRef B, uint8_t lookup)
Definition CApi.cpp:980
void EnzymeDetectReadonlyOrThrow(LLVMModuleRef M)
Definition CApi.cpp:1076
LLVMValueRef EnzymeBuildExtractValue(LLVMBuilderRef B, LLVMValueRef AggVal, unsigned *Index, unsigned Size, const char *Name)
Definition CApi.cpp:1439
void EnzymeLogicSetExternalContext(EnzymeLogicRef Ref, void *ExternalContext)
Definition CApi.cpp:217
LLVMValueRef EnzymeGradientUtilsNewFromOriginal(GradientUtils *gutils, LLVMValueRef val)
Definition CApi.cpp:452
void EnzymeTypeTreeInsertEq(CTypeTreeRef CTT, const int64_t *indices, size_t len, CConcreteType ct, LLVMContextRef ctx)
Definition CApi.cpp:932
uint8_t EnzymeGradientUtilsGetRuntimeActivity(GradientUtils *gutils)
Definition CApi.cpp:419
void EnzymeDumpTypeRef(LLVMTypeRef M)
Definition CApi.cpp:1086
void EnzymeCloneFunctionDISubprogramInto(LLVMValueRef NF, LLVMValueRef F)
Definition CApi.cpp:1052
void FreeTraceInterface(EnzymeTraceInterfaceRef Ref)
Definition CApi.cpp:270
void EnzymeLogicErasePreprocessedFunctions(EnzymeLogicRef Ref)
Definition CApi.cpp:262
CTypeTreeRef EnzymeNewTypeTree()
Definition CApi.cpp:881
void EnzymeGradientUtilsSetReverseBlock(GradientUtils *gutils, LLVMBasicBlockRef block)
Definition CApi.cpp:661
LLVMValueRef EnzymeCreateBatch(EnzymeLogicRef Logic, LLVMValueRef request_req, LLVMBuilderRef request_ip, LLVMValueRef tobatch, unsigned width, CBATCH_TYPE *arg_types, size_t arg_types_size, CBATCH_TYPE retType)
Definition CApi.cpp:771
void EnzymeGradientUtilsSubTransferHelper(GradientUtils *gutils, CDerivativeMode mode, LLVMTypeRef secretty, uint64_t intrinsic, uint64_t dstAlign, uint64_t srcAlign, uint64_t offset, uint8_t dstConstant, LLVMValueRef shadow_dst, LLVMValueRef primal_dst, uint8_t srcConstant, LLVMValueRef shadow_src, LLVMValueRef primal_src, LLVMValueRef length, LLVMValueRef isVolatile, LLVMValueRef MTI, uint8_t allowForward, uint8_t shadowsLookedUp)
Definition CApi.cpp:634
void * EnzymeGradientUtilsTypeAnalyzer(GradientUtils *G)
Definition CApi.cpp:329
uint8_t EnzymeGradientUtilsIsConstantInstruction(GradientUtils *gutils, LLVMValueRef val)
Definition CApi.cpp:575
LLVMTypeRef EnzymeGradientUtilsGetShadowType(GradientUtils *gutils, LLVMTypeRef T)
Definition CApi.cpp:443
void RunAttributorOnModule(LLVMModuleRef M0)
Definition CApi.cpp:1115
void EnzymeRegisterCallHandler(const char *Name, CustomAugmentedFunctionForward FwdHandle, CustomFunctionReverse RevHandle)
Definition CApi.cpp:370
LLVMValueRef EnzymeCreateForwardDiff(EnzymeLogicRef Logic, LLVMValueRef request_req, LLVMBuilderRef request_ip, LLVMValueRef todiff, CDIFFE_TYPE retType, CDIFFE_TYPE *constant_args, size_t constant_args_size, EnzymeTypeAnalysisRef TA, uint8_t returnValue, CDerivativeMode mode, uint8_t freeMemory, uint8_t runtimeActivity, uint8_t strongZero, unsigned width, LLVMTypeRef additionalArg, CFnTypeInfo typeInfo, uint8_t subsequent_calls_may_write, uint8_t *_overwritten_args, size_t overwritten_args_size, EnzymeAugmentedReturnPtr augmented)
Definition CApi.cpp:671
void EnzymeGradientUtilsDumpTypeResults(GradientUtils *gutils)
Definition CApi.cpp:630
uint8_t EnzymeSetTypeTree(CTypeTreeRef dst, CTypeTreeRef src)
Definition CApi.cpp:889
uint8_t EnzymeGradientUtilsGetStrongZero(GradientUtils *gutils)
Definition CApi.cpp:427
EnzymeLogicRef EnzymeTypeAnalysisGetLogic(EnzymeTypeAnalysisRef TAR)
Definition CApi.cpp:319
LLVMBasicBlockRef EnzymeGradientUtilsAllocationBlock(GradientUtils *gutils)
Definition CApi.cpp:580
void EnzymeGradientUtilsAddToDiffe(DiffeGradientUtils *gutils, LLVMValueRef val, LLVMValueRef diffe, LLVMBuilderRef B, LLVMTypeRef T)
Definition CApi.cpp:531
LLVMValueRef EnzymeCreatePrimalAndGradient(EnzymeLogicRef Logic, LLVMValueRef request_req, LLVMBuilderRef request_ip, LLVMValueRef todiff, CDIFFE_TYPE retType, CDIFFE_TYPE *constant_args, size_t constant_args_size, EnzymeTypeAnalysisRef TA, uint8_t returnValue, uint8_t dretUsed, CDerivativeMode mode, uint8_t runtimeActivity, uint8_t strongZero, unsigned width, uint8_t freeMemory, LLVMTypeRef additionalArg, uint8_t forceAnonymousTape, CFnTypeInfo typeInfo, uint8_t subsequent_calls_may_write, uint8_t *_overwritten_args, size_t overwritten_args_size, EnzymeAugmentedReturnPtr augmented, uint8_t AtomicAdd)
Definition CApi.cpp:697
uint8_t EnzymeGradientUtilsGetUncacheableArgs(GradientUtils *gutils, LLVMValueRef orig, uint8_t *data, uint64_t size)
Definition CApi.cpp:584
LLVMValueRef EnzymeCreateTrace(EnzymeLogicRef Logic, LLVMValueRef request_req, LLVMBuilderRef request_ip, LLVMValueRef totrace, LLVMValueRef *sample_functions, size_t sample_functions_size, LLVMValueRef *observe_functions, size_t observe_functions_size, const char *active_random_variables[], size_t active_random_variables_size, CProbProgMode mode, uint8_t autodiff, EnzymeTraceInterfaceRef interface)
Definition CApi.cpp:785
void EnzymeTypeTreeOnlyEq(CTypeTreeRef CTT, int64_t x)
Definition CApi.cpp:905
TargetLibraryInfo eunwrap(LLVMTargetLibraryInfoRef P)
Definition CApi.cpp:65
LLVMValueRef EnzymeComputeByteOffsetOfGEP(LLVMBuilderRef B_r, LLVMValueRef V_r, LLVMTypeRef T_r)
Definition CApi.cpp:1409
void EnzymeSetMustCache(LLVMValueRef inst1)
Definition CApi.cpp:1042
void EnzymeDumpModuleRef(LLVMModuleRef M)
Definition CApi.cpp:1080
void EnzymeGradientUtilsEraseWithPlaceholder(GradientUtils *G, LLVMValueRef I, LLVMValueRef orig, uint8_t erase)
Definition CApi.cpp:340
LLVMTypeRef EnzymeExtractTapeTypeFromAugmentation(EnzymeAugmentedReturnPtr ret)
Definition CApi.cpp:829
CTypeTreeRef EnzymeTypeTreeFromMD(LLVMValueRef Val)
Definition CApi.cpp:869
CDerivativeMode EnzymeGradientUtilsGetMode(GradientUtils *gutils)
Definition CApi.cpp:469
EnzymeAugmentedReturnPtr EnzymeCreateAugmentedPrimal(EnzymeLogicRef Logic, LLVMValueRef request_req, LLVMBuilderRef request_ip, LLVMValueRef todiff, CDIFFE_TYPE retType, CDIFFE_TYPE *constant_args, size_t constant_args_size, EnzymeTypeAnalysisRef TA, uint8_t returnUsed, uint8_t shadowReturnUsed, CFnTypeInfo typeInfo, uint8_t subsequent_calls_may_write, uint8_t *_overwritten_args, size_t overwritten_args_size, uint8_t *_nowrite_shadows, size_t nowrite_shadows_size, uint8_t forceAnonymousTape, uint8_t runtimeActivity, uint8_t strongZero, unsigned width, uint8_t AtomicAdd)
Definition CApi.cpp:737
LLVMValueRef EnzymeGradientUtilsDiffe(DiffeGradientUtils *gutils, LLVMValueRef val, LLVMBuilderRef B)
Definition CApi.cpp:526
EnzymeAugmentedReturnPtr ewrap(const AugmentedReturn &AR)
Definition CApi.cpp:81
CTypeTreeRef EnzymeNewTypeTreeCT(CConcreteType CT, LLVMContextRef ctx)
Definition CApi.cpp:882
EnzymeTraceInterfaceRef CreateEnzymeStaticTraceInterface(LLVMContextRef C, LLVMValueRef getTraceFunction, LLVMValueRef getChoiceFunction, LLVMValueRef insertCallFunction, LLVMValueRef insertChoiceFunction, LLVMValueRef insertArgumentFunction, LLVMValueRef insertReturnFunction, LLVMValueRef insertFunctionFunction, LLVMValueRef insertChoiceGradientFunction, LLVMValueRef insertArgumentGradientFunction, LLVMValueRef newTraceFunction, LLVMValueRef freeTraceFunction, LLVMValueRef hasCallFunction, LLVMValueRef hasChoiceFunction)
Definition CApi.cpp:229
void EnzymeGradientUtilsAddToInvertedPointerDiffe(DiffeGradientUtils *gutils, LLVMValueRef orig, LLVMValueRef origVal, LLVMTypeRef addingType, unsigned start, unsigned size, LLVMValueRef origptr, LLVMValueRef dif, LLVMBuilderRef BuilderM, unsigned align, LLVMValueRef mask)
Definition CApi.cpp:537
uint8_t EnzymeMergeTypeTree(CTypeTreeRef dst, CTypeTreeRef src)
Definition CApi.cpp:892
LLVMValueRef EnzymeBuildInsertValue(LLVMBuilderRef B, LLVMValueRef AggVal, LLVMValueRef EltVal, unsigned *Index, unsigned Size, const char *Name)
Definition CApi.cpp:1446
void EnzymeGradientUtilsErase(GradientUtils *G, LLVMValueRef I)
Definition CApi.cpp:337
uint8_t EnzymeHasFromStack(LLVMValueRef inst1)
Definition CApi.cpp:1047
EnzymeTypeAnalysisRef CreateTypeAnalysis(EnzymeLogicRef Log, char **customRuleNames, CustomRuleType *customRules, size_t numRules)
Definition CApi.cpp:274
EnzymeLogicRef EnzymeGradientUtilsGetLogic(GradientUtils *gutils)
Definition CApi.cpp:439
LLVMValueRef EnzymeTypeTreeToMD(CTypeTreeRef CTR, LLVMContextRef ctx)
Definition CApi.cpp:876
void * EnzymeAnalyzeTypes(EnzymeTypeAnalysisRef TAR, CFnTypeInfo CTI, LLVMValueRef F)
Definition CApi.cpp:323
LLVMMetadataRef EnzymeMakeNonConstTBAA(LLVMMetadataRef MD)
Definition CApi.cpp:1162
void EnzymeGradientUtilsSetDiffe(DiffeGradientUtils *gutils, LLVMValueRef val, LLVMValueRef diffe, LLVMBuilderRef B)
Definition CApi.cpp:565
void EnzymeSetCLBool(void *ptr, uint8_t val)
Definition CApi.cpp:188
LLVMValueRef EnzymeExtractFunctionFromAugmentation(EnzymeAugmentedReturnPtr ret)
Definition CApi.cpp:817
LLVMValueRef EnzymeGradientUtilsInvertPointer(GradientUtils *gutils, LLVMValueRef val, LLVMBuilderRef B)
Definition CApi.cpp:520
void EnzymeSetCLString(void *ptr, const char *val)
Definition CApi.cpp:208
std::set< int64_t > eunwrap64(IntList IL)
Definition CApi.cpp:118
void EnzymeExtractReturnInfo(EnzymeAugmentedReturnPtr ret, int64_t *data, uint8_t *existed, size_t len)
Definition CApi.cpp:841
CTypeTreeRef EnzymeGradientUtilsAllocAndGetTypeTree(GradientUtils *gutils, LLVMValueRef val)
Definition CApi.cpp:623
void EnzymeGradientUtilsReplaceAWithB(GradientUtils *G, LLVMValueRef A, LLVMValueRef B)
Definition CApi.cpp:347
void EnzymeTypeTreeShiftIndiciesEq(CTypeTreeRef CTT, const char *datalayout, int64_t offset, int64_t maxSize, uint64_t addOffset)
Definition CApi.cpp:925
void EnzymeCopyMetadata(LLVMValueRef inst1, LLVMValueRef inst2)
Definition CApi.cpp:1178
uint8_t EnzymeCheckedMergeTypeTree(CTypeTreeRef dst, CTypeTreeRef src, uint8_t *legalP)
Definition CApi.cpp:895
void * EnzymeLogicGetExternalContext(EnzymeLogicRef Ref)
Definition CApi.cpp:221
void EnzymeReplaceFunctionImplementation(LLVMModuleRef M)
Definition CApi.cpp:1072
void EnzymeTypeTreeCanonicalizeInPlace(CTypeTreeRef CTT, int64_t size, const char *dl)
Definition CApi.cpp:916
void EnzymeRegisterDiffUseCallHandler(char *Name, CustomFunctionDiffUse Handle)
Definition CApi.cpp:406
const char * EnzymeTypeTreeToString(CTypeTreeRef src)
Definition CApi.cpp:940
EnzymeLogicRef EnzymeTypeAnalyzerGetLogic(void *src)
Definition CApi.cpp:962
void EnzymeRegisterAllocationHandler(char *Name, CustomShadowAlloc AHandle, CustomShadowFree FHandle)
Definition CApi.cpp:352
uint64_t EnzymeGradientUtilsGetWidth(GradientUtils *gutils)
Definition CApi.cpp:435
LLVMValueRef EnzymeCloneFunctionWithoutReturnOrArgs(LLVMValueRef FC, uint8_t keepReturnU, uint64_t *argrem, uint64_t num_argrem)
Definition CApi.cpp:1263
LLVMTypeRef EnzymeGetShadowType(uint64_t width, LLVMTypeRef T)
Definition CApi.cpp:448
LLVMTypeRef EnzymeAllocaType(LLVMValueRef V)
Definition CApi.cpp:1406
void ClearEnzymeLogic(EnzymeLogicRef Ref)
Definition CApi.cpp:260
void EnzymeMoveBefore(LLVMValueRef inst1, LLVMValueRef inst2, LLVMBuilderRef B)
Definition CApi.cpp:1007
uint8_t(* CustomFunctionForward)(LLVMBuilderRef, LLVMValueRef, GradientUtils *, LLVMValueRef *, LLVMValueRef *)
Definition CApi.h:198
struct EnzymeOpaqueTypeAnalysis * EnzymeTypeAnalysisRef
Definition CApi.h:38
struct EnzymeOpaqueTraceInterface * EnzymeTraceInterfaceRef
Definition CApi.h:47
struct EnzymeTypeTree * CTypeTreeRef
Definition CApi.h:87
CValueType
Definition CApi.h:79
uint8_t(* CustomAugmentedFunctionForward)(LLVMBuilderRef, LLVMValueRef, GradientUtils *, LLVMValueRef *, LLVMValueRef *, LLVMValueRef *)
Definition CApi.h:206
CConcreteType
Definition CApi.h:54
@ DT_Integer
Definition CApi.h:56
@ DT_Double
Definition CApi.h:60
@ DT_Anything
Definition CApi.h:55
@ DT_Unknown
Definition CApi.h:61
@ DT_FP128
Definition CApi.h:64
@ DT_BFloat16
Definition CApi.h:63
@ DT_X86_FP80
Definition CApi.h:62
@ DT_Float
Definition CApi.h:59
@ DT_Half
Definition CApi.h:58
@ DT_Pointer
Definition CApi.h:57
uint8_t(* CustomRuleType)(int, CTypeTreeRef, CTypeTreeRef *, struct IntList *, size_t, LLVMValueRef, void *)
Definition CApi.h:147
uint8_t(* CustomFunctionDiffUse)(LLVMValueRef, const GradientUtils *, LLVMValueRef, uint8_t, CDerivativeMode, uint8_t *)
Definition CApi.h:202
CProbProgMode
Definition CApi.h:142
void(* CustomFunctionReverse)(LLVMBuilderRef, LLVMValueRef, DiffeGradientUtils *, LLVMValueRef)
Definition CApi.h:212
CDIFFE_TYPE
Definition CApi.h:120
CDerivativeMode
Definition CApi.h:133
LLVMValueRef(* CustomShadowFree)(LLVMBuilderRef, LLVMValueRef)
Definition CApi.h:193
struct EnzymeOpaqueLogic * EnzymeLogicRef
Definition CApi.h:41
CBATCH_TYPE
Definition CApi.h:131
LLVMValueRef(* CustomShadowAlloc)(LLVMBuilderRef, LLVMValueRef, size_t, LLVMValueRef *, GradientUtils *)
Definition CApi.h:190
struct EnzymeOpaqueAugmentedReturn * EnzymeAugmentedReturnPtr
Definition CApi.h:44
StringMap< std::function< bool(const CallInst *, const GradientUtils *, const Value *, bool, DerivativeMode, bool &)> > customDiffUseHandlers
DIFFE_TYPE
Potential differentiable argument classifications.
void ReplaceFunctionImplementation(Module &M)
bool DetectReadonlyOrThrow(Module &M)
bool LowerSparsification(llvm::Function *F, bool replaceAll)
Lower __enzyme_todense, returning if changed.
static std::string str(AugmentedStruct c)
Definition EnzymeLogic.h:62
AugmentedStruct
Definition EnzymeLogic.h:60
StringMap< std::function< CallInst *(IRBuilder<> &, Value *)> > shadowErasers
StringMap< std::function< Value *(IRBuilder<> &, CallInst *, ArrayRef< Value * >, GradientUtils *)> > shadowHandlers
StringMap< std::pair< std::function< bool(IRBuilder<> &, CallInst *, GradientUtils &, Value *&, Value *&, Value *&)>, std::function< void(IRBuilder<> &, CallInst *, DiffeGradientUtils &, Value *)> > > customCallHandlers
void SubTransferHelper(GradientUtils *gutils, DerivativeMode mode, Type *secretty, Intrinsic::ID intrinsic, unsigned dstalign, unsigned srcalign, unsigned offset, bool dstConstant, Value *shadow_dst, Value *primal_dst, bool srcConstant, Value *shadow_src, Value *primal_src, Value *length, Value *isVolatile, llvm::CallInst *MTI, bool allowForward, bool shadowsLookedUp, bool backwardsShadow)
StringMap< std::function< bool(IRBuilder<> &, CallInst *, GradientUtils &, Value *&, Value *&)> > customFwdCallHandlers
bool attributeKnownFunctions(llvm::Function &F)
Definition Utils.cpp:139
bool collectOffset(GEPOperator *gep, const DataLayout &DL, unsigned BitWidth, MapVector< Value *, APInt > &VariableOffsets, APInt &ConstantOffset)
Definition Utils.cpp:4464
BATCH_TYPE
Definition Utils.h:519
@ Args
Return is a struct of all args.
static llvm::MDNode * hasMetadata(const llvm::GlobalObject *O, llvm::StringRef kind)
Check if a global has metadata.
Definition Utils.h:483
ProbProgMode
Definition Utils.h:533
static void resetClonedGUID(llvm::Function *F)
Definition Utils.h:91
ValueType
Classification of value as an original program variable, a derivative variable, neither,...
Definition Utils.h:543
static void moveBeforeInst(llvm::Instruction *I, llvm::Instruction *Before)
Definition Utils.h:2571
DerivativeMode
Definition Utils.h:524
return structtype if recursive function
llvm::BasicBlock * inversionAllocs
Concrete SubType of a given value.
BaseType SubTypeEnum
Category of underlying type.
llvm::Type * isFloat() const
Return the floating point type, if this is a float.
void addToInvertedPtrDiffe(llvm::Instruction *orig, llvm::Value *origVal, llvm::Type *addingType, unsigned start, unsigned size, llvm::Value *origptr, llvm::Value *dif, llvm::IRBuilder<> &BuilderM, llvm::MaybeAlign align=llvm::MaybeAlign(), llvm::Value *mask=nullptr)
align is the alignment that should be specified for load/store to pointer
llvm::Value * diffe(llvm::Value *val, llvm::IRBuilder<> &BuilderM)
void setDiffe(llvm::Value *val, llvm::Value *toset, llvm::IRBuilder<> &BuilderM)
llvm::SmallVector< llvm::SelectInst *, 4 > addToDiffe(llvm::Value *val, llvm::Value *dif, llvm::IRBuilder<> &BuilderM, llvm::Type *addingType, llvm::ArrayRef< llvm::Value * > idxs={}, llvm::Value *mask=nullptr)
Returns created select instructions, if any.
void * ExternalContext
Provided through the frontend and only used from it.
DerivativeMode mode
llvm::ValueMap< const llvm::Value *, InvertedPointerVH > invertedPointers
llvm::DebugLoc getNewFromOriginal(const llvm::DebugLoc L) const
bool augmentedPrimalReturnUsed(llvm::Value *orig) const
Whether the augmented pass used the primal of orig.
void eraseWithPlaceholder(llvm::Instruction *I, llvm::Instruction *orig, const llvm::Twine &suffix="_replacementA", bool erase=true)
TypeResults TR
llvm::BasicBlock * addReverseBlock(llvm::BasicBlock *currentBlock, llvm::Twine const &name, bool forkCache=true, bool push=true)
const std::map< llvm::CallInst *, std::pair< bool, const std::vector< bool > > > * overwritten_args_map_ptr
unsigned getWidth()
std::map< llvm::BasicBlock *, llvm::SmallVector< llvm::BasicBlock *, 4 > > reverseBlocks
Map of primal block to corresponding block(s) in reverse.
llvm::Function * oldFunc
llvm::SmallVector< llvm::OperandBundleDef, 2 > getInvertedBundles(llvm::CallInst *orig, llvm::ArrayRef< ValueType > types, llvm::IRBuilder<> &Builder2, bool lookup, const llvm::ValueToValueMapTy &available=llvm::ValueToValueMapTy())
void replaceAWithB(llvm::Value *A, llvm::Value *B, bool storeInCache=false) override
Replace this instruction both in LLVM modules and any local data-structures.
EnzymeLogic & Logic
DIFFE_TYPE getDiffeType(llvm::Value *v, bool foreignFunction) const
llvm::Value * lookupM(llvm::Value *val, llvm::IRBuilder<> &BuilderM, const llvm::ValueToValueMapTy &incoming_availalble=llvm::ValueToValueMapTy(), bool tryLegalRecomputeCheck=true, llvm::BasicBlock *scope=nullptr) override
High-level utility to get the value an instruction at a new location specified by BuilderM.
llvm::ValueMap< const llvm::Value *, AssertingReplacingVH > originalToNewFn
llvm::Value * invertPointerM(llvm::Value *val, llvm::IRBuilder<> &BuilderM)
DIFFE_TYPE getReturnDiffeType(llvm::Value *orig, bool *primalReturnUsedP, bool *shadowReturnUsedP, DerivativeMode cmode) const
std::map< llvm::BasicBlock *, llvm::BasicBlock * > reverseBlockToPrimal
Map of block in reverse to corresponding primal block.
bool isConstantInstruction(const llvm::Instruction *inst) const
llvm::ValueMap< const llvm::Value *, AssertingReplacingVH > newToOriginalFn
static llvm::Type * getShadowType(llvm::Type *ty, unsigned width)
bool isConstantValue(llvm::Value *val) const
void erase(llvm::Instruction *I) override
Erase this instruction both from LLVM modules and any local data-structures.
Full interprocedural TypeAnalysis.
llvm::StringMap< std::function< bool(int, TypeTree &, llvm::ArrayRef< TypeTree >, llvm::ArrayRef< std::set< int64_t > >, llvm::CallBase *, TypeAnalyzer *)> > CustomRules
Map of custom function call handlers.
void clear()
Clear existing analyses.
EnzymeLogic & Logic
Helper class that computes the fixed-point type results of a given function.
TypeAnalysis & interprocedural
Calling TypeAnalysis to be used in the case of calls to other functions.
void dump(llvm::raw_ostream &ss=llvm::errs()) const
Prints all known information.
TypeAnalyzer * analyzer
const TypeTree & query(llvm::Value *val) const
The TypeTree of a particular Value.
Class representing the underlying types of values as sequences of offsets to a ConcreteType.
Definition TypeTree.h:72
void insertFromMD(llvm::MDNode *md, const std::vector< int > &prev={})
Definition TypeTree.h:1499
struct IntList * KnownValues
The specific constant(s) known to represented by an argument, if constant.
Definition CApi.h:117
CTypeTreeRef * Arguments
Types of arguments, assumed of size len(Arguments)
Definition CApi.h:110
CTypeTreeRef Return
Type of return.
Definition CApi.h:113
Struct containing all contextual type information for a particular function call.
std::map< llvm::Argument *, TypeTree > Arguments
Types of arguments.
TypeTree Return
Type of return.
std::map< llvm::Argument *, std::set< int64_t > > KnownValues
The specific constant(s) known to represented by an argument, if constant.
Definition CApi.h:49
int64_t * data
Definition CApi.h:50
size_t size
Definition CApi.h:51
void getAnalysisUsage(AnalysisUsage &AU) const override
Definition CApi.cpp:1152
bool runOnModule(Module &M) override
Definition CApi.cpp:1135
todiff is the function to differentiate retType is the activity info of the return.