26#if LLVM_VERSION_MAJOR >= 16
28#include "llvm/Analysis/ScalarEvolution.h"
29#include "llvm/Transforms/Utils/ScalarEvolutionExpander.h"
32#include "SCEV/ScalarEvolution.h"
33#include "SCEV/ScalarEvolutionExpander.h"
38#include "EnzymeLogic.h"
39#include "GradientUtils.h"
41#if LLVM_VERSION_MAJOR >= 16
42#include "llvm/Analysis/TargetLibraryInfo.h"
44#include "SCEV/TargetLibraryInfo.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"
55#include "llvm/IR/LegacyPassManager.h"
56#include "llvm/Transforms/IPO/Attributor.h"
58#define addAttribute addAttributeAtIndex
59#define removeAttribute removeAttributeAtIndex
60#define getAttribute getAttributeAtIndex
61#define hasAttribute hasAttributeAtIndex
65TargetLibraryInfo
eunwrap(LLVMTargetLibraryInfoRef P) {
66 return TargetLibraryInfo(*
reinterpret_cast<TargetLibraryInfoImpl *
>(P));
108 llvm_unreachable(
"Unknown concrete type to unwrap");
113 for (
size_t i = 0; i < IL.
size; i++) {
114 v.push_back((
int)IL.
data[i]);
120 for (
size_t i = 0; i < IL.
size; i++) {
121 v.insert((int64_t)IL.
data[i]);
131 if (flt->isFloatTy())
133 if (flt->isDoubleTy())
135 if (flt->isX86_FP80Ty())
137 if (flt->isBFloatTy())
139 if (flt->isFP128Ty())
152 llvm_unreachable(
"Illegal conversion of concretetype");
155 llvm_unreachable(
"Illegal conversion of concretetype");
160 IL.
size = offsets.size();
162 for (
size_t i = 0; i < offsets.size(); i++) {
163 IL.
data[i] = offsets[i];
178 for (
auto &arg : F->args()) {
189 auto cl = (llvm::cl::opt<bool> *)ptr;
190 cl->setValue((
bool)val);
194 auto cl = (llvm::cl::opt<bool> *)ptr;
195 return (uint8_t)(bool)cl->getValue();
199 auto cl = (llvm::cl::opt<int> *)ptr;
200 cl->setValue((
int)val);
204 auto cl = (llvm::cl::opt<int> *)ptr;
205 return (int64_t)cl->getValue();
209 if (
auto *clopt =
static_cast<cl::opt<std::string> *
>(ptr))
210 clopt->setValue(val);
218 eunwrap(Ref).ExternalContext = ExternalContext;
222 return eunwrap(Ref).ExternalContext;
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))));
257 unwrap(interface), cast<Function>(unwrap(F))));
264 for (
const auto &pair : Logic.PPC.cache)
265 pair.second->eraseFromParent();
275 char **customRuleNames,
280 for (
size_t i = 0; i < numRules; i++) {
283 [=](
int direction,
TypeTree &returnTree, ArrayRef<TypeTree> argTrees,
284 ArrayRef<std::set<int64_t>> knownValues, CallBase *call,
289 for (
size_t i = 0; i < argTrees.size(); ++i) {
291 kvs[i].
size = knownValues[i].size();
292 kvs[i].
data =
new int64_t[kvs[i].
size];
294 for (
auto val : knownValues[i]) {
295 kvs[i].data[j] = val;
299 uint8_t result = rule(direction, creturnTree, cargs, kvs, argTrees.
size(),
302 for (
size_t i = 0; i < argTrees.size(); ++i) {
303 delete[] kvs[i].
data;
326 return (
void *)((
TypeAnalysis *)TAR)->analyzeFunction(FTI).analyzer;
338 return G->
erase(cast<Instruction>(unwrap(I)));
341 LLVMValueRef orig, uint8_t erase) {
343 cast<Instruction>(unwrap(orig)),
344 "_replacementABI", erase != 0);
355 ArrayRef<Value *>
Args,
357 SmallVector<LLVMValueRef, 3> refs;
359 refs.push_back(wrap(a));
361 AHandle(wrap(&B), wrap(CI),
Args.size(), refs.data(), gutils));
365 Value *ToFree) -> llvm::CallInst * {
366 return cast_or_null<CallInst>(unwrap(FHandle(wrap(&B), wrap(ToFree))));
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);
381 FwdHandle(wrap(&B), wrap(CI), &gutils, &normalR, &shadowR, &tapeR);
382 normalReturn = unwrap(normalR);
383 shadowReturn = unwrap(shadowR);
384 tape = unwrap(tapeR);
389 RevHandle(wrap(&B), wrap(CI), &gutils, wrap(tape));
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);
409 pair = [=](
const CallInst *CI,
const GradientUtils *gutils,
const Value *arg,
411 uint8_t useDefaultC = 0;
412 uint8_t noMod = Handle(wrap(CI), gutils, wrap(arg), isshadow,
414 useDefault = useDefaultC != 0;
459 auto orig = cast<Instruction>(unwrap(origC));
460 auto rep = cast<Instruction>(unwrap(repC));
463 auto newCall = found->second;
475 uint8_t foreignFunction) {
486 uint8_t *needsPrimal,
487 uint8_t *needsShadow,
492 unwrap(oval), &needsPrimalB, &needsShadowB, (
DerivativeMode)mode));
494 *needsPrimal = needsPrimalB;
496 *needsShadow = needsShadowB;
503 return cast<Instruction>(unwrap(val))
505 cast<Instruction>(unwrap(orig))->getDebugLoc()));
509 LLVMValueRef val2,
unsigned *sz, int64_t length,
511 return wrap(unwrap(B)->CreateInsertValue(
512 unwrap(val), unwrap(val2), ArrayRef<unsigned>(sz, sz + length), name));
517 return wrap(gutils->
lookupM(unwrap(val), *unwrap(B)));
527 LLVMValueRef val, LLVMBuilderRef B) {
528 return wrap(gutils->
diffe(unwrap(val), *unwrap(B)));
532 LLVMValueRef diffe, LLVMBuilderRef B,
534 gutils->
addToDiffe(unwrap(val), unwrap(diffe), *unwrap(B), unwrap(T));
539 LLVMTypeRef addingType,
unsigned start,
unsigned size, LLVMValueRef origptr,
540 LLVMValueRef dif, LLVMBuilderRef BuilderM,
unsigned align,
544 align2 = MaybeAlign(align);
545 auto inst = cast_or_null<Instruction>(unwrap(orig));
547 start, size, unwrap(origptr), unwrap(dif),
548 *unwrap(BuilderM), align2, unwrap(mask));
553 CTypeTreeRef vd,
unsigned LoadSize, LLVMValueRef origptr,
554 LLVMValueRef prediff, LLVMBuilderRef BuilderM,
unsigned align,
555 LLVMValueRef premask) {
558 align2 = MaybeAlign(align);
559 auto inst = cast_or_null<Instruction>(unwrap(orig));
561 LoadSize, unwrap(origptr), unwrap(prediff),
562 *unwrap(BuilderM), align2, unwrap(premask));
566 LLVMValueRef diffe, LLVMBuilderRef B) {
567 gutils->
setDiffe(unwrap(val), unwrap(diffe), *unwrap(B));
585 LLVMValueRef orig, uint8_t *data,
594 CallInst *call = cast<CallInst>(unwrap(orig));
599 llvm::errs() <<
" oldFunc " << *gutils->
oldFunc <<
"\n";
601 llvm::errs() <<
" + " << *pair.first <<
"\n";
603 llvm::errs() <<
" could not find call orig in overwritten_args_map_ptr "
608 const std::vector<bool> &overwritten_args = found->second.second;
610 if (size != overwritten_args.size()) {
611 llvm::errs() <<
" orig: " << *call <<
"\n";
612 llvm::errs() <<
" size: " << size
613 <<
" overwritten_args.size(): " << overwritten_args.size()
616 assert(size == overwritten_args.size());
617 for (uint64_t i = 0; i < size; i++) {
618 data[i] = overwritten_args[i];
625 auto v = unwrap(val);
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);
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);
653 LLVMBasicBlockRef block,
657 return wrap(gutils->
addReverseBlock(cast<BasicBlock>(unwrap(block)), name,
662 LLVMBasicBlockRef block) {
663 auto endBlock = cast<BasicBlock>(unwrap(block));
668 vec.push_back(endBlock);
672 EnzymeLogicRef Logic, LLVMValueRef request_req, LLVMBuilderRef request_ip,
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,
680 SmallVector<DIFFE_TYPE, 4> nconstant_args((
DIFFE_TYPE *)constant_args,
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]);
688 return wrap(
eunwrap(Logic).CreateForwardDiff(
691 cast<Function>(unwrap(todiff)), (
DIFFE_TYPE)retType, nconstant_args,
693 runtimeActivity, strongZero, width, unwrap(additionalArg),
694 eunwrap(typeInfo, cast<Function>(unwrap(todiff))),
695 subsequent_calls_may_write, overwritten_args,
eunwrap(augmented)));
698 EnzymeLogicRef Logic, LLVMValueRef request_req, LLVMBuilderRef request_ip,
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,
707 std::vector<DIFFE_TYPE> nconstant_args((
DIFFE_TYPE *)constant_args,
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]);
715 return wrap(
eunwrap(Logic).CreatePrimalAndGradient(
719 .todiff = cast<Function>(unwrap(todiff)),
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,
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},
738 EnzymeLogicRef Logic, LLVMValueRef request_req, LLVMBuilderRef request_ip,
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,
748 SmallVector<DIFFE_TYPE, 4> nconstant_args((
DIFFE_TYPE *)constant_args,
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]);
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]);
761 auto F = cast<Function>(unwrap(todiff));
766 shadowReturnUsed,
eunwrap(typeInfo, F), subsequent_calls_may_write,
767 overwritten_args, nowrite_shadows, forceAnonymousTape, runtimeActivity,
768 strongZero, width, AtomicAdd));
772 LLVMBuilderRef request_ip, LLVMValueRef tobatch,
776 return wrap(
eunwrap(Logic).CreateBatch(
779 cast<Function>(unwrap(tobatch)), width,
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,
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])));
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])));
803 StringSet<> ActiveRandomVariables;
804 for (
size_t i = 0; i < active_random_variables_size; i++) {
805 ActiveRandomVariables.insert(active_random_variables[i]);
808 return wrap(
eunwrap(Logic).CreateTrace(
811 cast<Function>(unwrap(totrace)), SampleFunctions, ObserveFunctions,
812 ActiveRandomVariables, (
ProbProgMode)mode, (
bool)autodiff,
825 return wrap(AR->tapeType);
832 if (found == AR->returns.end()) {
833 return wrap((Type *)
nullptr);
835 if (found->second == -1) {
836 return wrap(AR->fn->getReturnType());
839 cast<StructType>(AR->fn->getReturnType())->getTypeAtIndex(found->second));
842 uint8_t *existed,
size_t len) {
847 for (
size_t i = 0; i < len; i++) {
848 auto found = AR->returns.find(todo[i]);
849 if (found != AR->returns.end()) {
851 data[i] = (int64_t)found->second;
859 Metadata *MD = MAV->getMetadata();
860 assert((isa<MDNode>(MD) || isa<ConstantAsMetadata>(MD)) &&
861 "Expected a metadata node or a canonicalized constant");
863 if (MDNode *N = dyn_cast<MDNode>(MD))
866 return MDNode::get(MAV->getContext(), MD);
871 MDNode *N = Val ?
extractMDNode(unwrap<MetadataAsValue>(Val)) :
nullptr;
877 auto MD = ((
TypeTree *)CTR)->toMD(*unwrap(ctx));
878 return wrap(MetadataAsValue::get(MD->getContext(), MD));
900 ->checkedOrIn(*(
TypeTree *)src,
false, legal);
918 ((
TypeTree *)CTT)->CanonicalizeInPlace(size, DataLayout(dl));
926 int64_t offset, int64_t maxSize,
927 uint64_t addOffset) {
928 DataLayout DL(datalayout);
930 ((
TypeTree *)CTT)->ShiftIndices(DL, offset, maxSize, addOffset);
934 std::vector<int> seq;
935 for (
size_t i = 0; i < len; i++) {
936 seq.push_back(indices[i]);
941 std::string tmp = ((
TypeTree *)src)->str();
942 char *cstr =
new char[tmp.length() + 1];
943 std::strcpy(cstr, tmp.c_str());
954 raw_string_ostream ss(
str);
957 char *cstr =
new char[
str.length() + 1];
958 std::strcpy(cstr,
str.c_str());
970 raw_string_ostream ss(
str);
972 ss <<
"available inversion for " << *z.first <<
" of " << *z.second <<
"\n";
975 char *cstr =
new char[
str.length() + 1];
976 std::strcpy(cstr,
str.c_str());
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,
985 auto orig = cast<CallInst>(unwrap(orig_vr));
987 ArrayRef<ValueType> ar((
ValueType *)valTys, valTys_size);
989 IRBuilder<> &BR = *unwrap(B);
993 SmallVector<Value *, 1> args;
994 for (
size_t i = 0; i < args_size; i++) {
995 args.push_back(unwrap(args_vr[i]));
998 auto callval = unwrap(func);
1001 BR.CreateCall(cast<FunctionType>(unwrap(funcTy)), callval, args, Defs);
1009 Instruction *I1 = cast<Instruction>(unwrap(inst1));
1010 Instruction *I2 = cast<Instruction>(unwrap(inst2));
1013 IRBuilder<> &BR = *unwrap(B);
1014 if (I1->getIterator() == BR.GetInsertPoint()) {
1015 if (I2->getNextNode() ==
nullptr)
1016 BR.SetInsertPoint(I1->getParent());
1018 BR.SetInsertPoint(I1->getNextNode());
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);
1031 cast<GlobalVariable>(V)->setMetadata(Kind, N);
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));
1043 Instruction *I1 = cast<Instruction>(unwrap(inst1));
1044 I1->setMetadata(
"enzyme_mustcache", MDNode::get(I1->getContext(), {}));
1048 Instruction *I1 = cast<Instruction>(unwrap(inst1));
1053 auto &OldFunc = *cast<Function>(unwrap(F));
1054 auto &NewFunc = *cast<Function>(unwrap(NF));
1055 auto OldSP = OldFunc.getSubprogram();
1058 DIBuilder DIB(*OldFunc.getParent(),
false,
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 0, SPType, 0, DINode::FlagZero, SPFlags);
1067 NewFunc.setSubprogram(NewSP);
1068 DIB.finalizeSubprogram(NewSP);
1081 llvm::errs() << *unwrap(M) <<
"\n";
1089 SetVector<Function *> &Functions,
1091 CallGraphUpdater &CGUpdater,
1092 bool DeleteFns,
bool IsModulePass) {
1093 if (Functions.empty())
1098 AttributorConfig AC(CGUpdater);
1099 AC.RewriteSignatures =
false;
1100 AC.IsModulePass = IsModulePass;
1101 AC.DeleteFns = DeleteFns;
1102 Attributor A(Functions, InfoCache, AC);
1104 for (Function *F : Functions) {
1107 A.identifyDefaultAbstractAttributes(*F);
1110 ChangeStatus Changed = A.run();
1112 return Changed == ChangeStatus::CHANGED;
1116 auto &M = *unwrap(M0);
1118 SetVector<Function *> Functions;
1119 for (Function &F : M)
1120 Functions.insert(&F);
1122 CallGraphUpdater CGUpdater;
1123 BumpPtrAllocator Allocator;
1124 InformationCache InfoCache(M, AG, Allocator,
nullptr);
1140 SetVector<Function *> Functions;
1141 for (Function &F : M)
1142 Functions.insert(&F);
1144 CallGraphUpdater CGUpdater;
1145 BumpPtrAllocator Allocator;
1146 InformationCache InfoCache(M, AG, Allocator,
nullptr);
1154 AU.addRequired<TargetLibraryInfoWrapperPass>();
1163 auto M = cast<MDNode>(unwrap(MD));
1164 if (M->getNumOperands() != 4)
1166 auto CAM = dyn_cast<ConstantAsMetadata>(M->getOperand(3));
1169 if (!CAM->getValue()->isOneValue())
1171 SmallVector<Metadata *, 4> MDs;
1172 for (
auto &M : M->operands())
1175 ConstantAsMetadata::get(ConstantInt::get(CAM->getValue()->getType(), 0));
1176 return wrap(MDNode::get(M->getContext(), MDs));
1179 cast<Instruction>(unwrap(inst1))
1180 ->copyMetadata(*cast<Instruction>(unwrap(inst2)));
1183 cast<AllocaInst>(unwrap(inst1))
1184 ->setAlignment(cast<AllocaInst>(unwrap(inst2))->getAlign());
1187 unwrap(inst1)->takeName(unwrap(inst2));
1191 LLVMContextRef ctx) {
1192 MDBuilder MDB(*unwrap(ctx));
1193 MDNode *scope = MDB.createAnonymousAliasScopeDomain(
str);
1198 auto dom = cast<MDNode>(unwrap(domain));
1199 MDBuilder MDB(dom->getContext());
1200 MDNode *scope = MDB.createAnonymousAliasScope(dom,
str);
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;
1218 if (CI->getType() == F->getReturnType()) {
1219 for (
auto attr : Attrs.getAttributes(AttributeList::ReturnIndex))
1220 NewAttrs = NewAttrs.addAttribute(F->getContext(),
1221 AttributeList::ReturnIndex, attr);
1223 for (
auto attr : Attrs.getAttributes(AttributeList::FunctionIndex))
1224 NewAttrs = NewAttrs.addAttribute(F->getContext(),
1225 AttributeList::FunctionIndex, attr);
1227 size_t argremsz = 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]) {
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));
1243 assert(argremsz == num_argrem);
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);
1253 if (CI->getType() == F->getReturnType())
1254 CI->replaceAllUsesWith(NC);
1256 if (!NC->getType()->isVoidTy())
1258 NC->setCallingConv(CI->getCallingConv());
1259 CI->eraseFromParent();
1264 uint8_t keepReturnU,
1266 uint64_t num_argrem) {
1267 auto F = cast<Function>(unwrap(FC));
1268 auto FT = F->getFunctionType();
1269 bool keepReturn = keepReturnU != 0;
1271 size_t argremsz = 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]) {
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));
1290 for (
auto attr : Attrs.getAttributes(AttributeList::ReturnIndex))
1291 NewAttrs = NewAttrs.addAttribute(F->getContext(),
1292 AttributeList::ReturnIndex, attr);
1294 for (
auto attr : Attrs.getAttributes(AttributeList::FunctionIndex))
1295 NewAttrs = NewAttrs.addAttribute(F->getContext(),
1296 AttributeList::FunctionIndex, attr);
1298 FunctionType *FTy = FunctionType::get(
1299 keepReturn ? F->getReturnType() : Type::getVoidTy(F->getContext()), types,
1303 Function *NewF = Function::Create(FTy, F->getLinkage(), F->getAddressSpace(),
1304 F->getName(), F->getParent());
1306 ValueToValueMapTy VMap;
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());
1319 DestI->setName(I.getName());
1320 VMap[&I] = &*DestI++;
1323 SmallVector<ReturnInst *, 8> Returns;
1324 CloneFunctionInto(NewF, F, VMap, CloneFunctionChangeType::LocalChangesOnly,
1325 Returns,
"",
nullptr);
1329 for (
auto &B : *NewF) {
1330 if (
auto RI = dyn_cast<ReturnInst>(B.getTerminator())) {
1332 auto NRI = B.CreateRetVoid();
1333 NRI->copyMetadata(*RI);
1334 RI->eraseFromParent();
1338 NewF->setAttributes(NewAttrs);
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);
1348 NewF->setCallingConv(F->getCallingConv());
1350 NewF->addFnAttr(
"enzyme_retremove",
"");
1353 SmallVector<uint64_t, 1> previdx;
1354 if (Attrs.hasAttribute(AttributeList::FunctionIndex,
"enzyme_parmremove")) {
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) {
1362 bool b = s.getAsInteger(10, ival);
1365 previdx.push_back(ival);
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);
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]);
1382 out.push_back(nextidx[nextcnt] + prevcnt);
1386 while (prevcnt < previdx.size()) {
1387 out.push_back(previdx[prevcnt]);
1390 while (nextcnt < nextidx.size()) {
1391 out.push_back(nextidx[nextcnt] + prevcnt);
1396 for (
auto arg : out) {
1399 remstr += std::to_string(arg);
1402 NewF->addFnAttr(
"enzyme_parmremove", remstr);
1407 return wrap(cast<AllocaInst>(unwrap(V))->getAllocatedType());
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();
1420#if LLVM_VERSION_MAJOR >= 20
1421 SmallMapVector<Value *, APInt, 4> VariableOffsets;
1423 MapVector<Value *, APInt> VariableOffsets;
1425 APInt Offset(width, 0);
1426 bool success =
collectOffset(gep, DL, width, VariableOffsets, Offset);
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)));
1440 unsigned *Index,
unsigned Size,
1442 return wrap(unwrap(B)->CreateExtractValue(
1443 unwrap(AggVal), ArrayRef<unsigned>(Index, Size), Name));
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));
int64_t EnzymeGetCLInteger(void *ptr)
void EnzymeGradientUtilsAddToInvertedPointerDiffeTT(DiffeGradientUtils *gutils, LLVMValueRef orig, LLVMValueRef origVal, CTypeTreeRef vd, unsigned LoadSize, LLVMValueRef origptr, LLVMValueRef prediff, LLVMBuilderRef BuilderM, unsigned align, LLVMValueRef premask)
EnzymeTypeAnalysisRef EnzymeGetTypeAnalysisFromTypeAnalyzer(void *TAR)
void EnzymeAttributeKnownFunctions(LLVMValueRef FC)
void EnzymeTypeTreeLookupEq(CTypeTreeRef CTT, int64_t size, const char *dl)
LLVMMetadataRef EnzymeAnonymousAliasScopeDomain(const char *str, LLVMContextRef ctx)
void * EnzymeGradientUtilsGetExternalContext(GradientUtils *gutils)
uint8_t EnzymeGradientUtilsIsConstantValue(GradientUtils *gutils, LLVMValueRef val)
LLVMValueRef EnzymeInsertValue(LLVMBuilderRef B, LLVMValueRef val, LLVMValueRef val2, unsigned *sz, int64_t length, const char *name)
void EnzymeSetCalledFunction(LLVMValueRef C_CI, LLVMValueRef C_F, uint64_t *argrem, uint64_t num_argrem)
CDIFFE_TYPE EnzymeGradientUtilsGetReturnDiffeType(GradientUtils *G, LLVMValueRef oval, uint8_t *needsPrimal, uint8_t *needsShadow, CDerivativeMode mode)
void EnzymeStringFree(const char *cstr)
void EnzymeCopyAlignment(LLVMValueRef inst1, LLVMValueRef inst2)
void EnzymeAddAttributorLegacyPass(LLVMPassManagerRef PM)
CTypeTreeRef EnzymeNewTypeTreeTR(CTypeTreeRef CTR)
void FreeTypeAnalysis(EnzymeTypeAnalysisRef TAR)
const char * EnzymeGradientUtilsInvertedPointersToString(GradientUtils *gutils, void *src)
LLVMBasicBlockRef EnzymeGradientUtilsAddReverseBlock(GradientUtils *gutils, LLVMBasicBlockRef block, const char *name, uint8_t forkCache, uint8_t push)
void EnzymeTakeName(LLVMValueRef inst1, LLVMValueRef inst2)
void EnzymeTypeTreeData0Eq(CTypeTreeRef CTT)
EnzymeTraceInterfaceRef CreateEnzymeDynamicTraceInterface(LLVMValueRef interface, LLVMValueRef F)
static bool runAttributorOnFunctions(InformationCache &InfoCache, SetVector< Function * > &Functions, AnalysisGetter &AG, CallGraphUpdater &CGUpdater, bool DeleteFns, bool IsModulePass)
LLVMValueRef EnzymeGetStringMD(LLVMValueRef Inst, const char *Kind)
void EnzymeFreeTypeTree(CTypeTreeRef CTT)
EnzymeTraceInterfaceRef FindEnzymeStaticTraceInterface(LLVMModuleRef M)
static MDNode * extractMDNode(MetadataAsValue *MAV)
LLVMTypeRef EnzymeExtractUnderlyingTapeTypeFromAugmentation(EnzymeAugmentedReturnPtr ret)
void EnzymeSetCLInteger(void *ptr, int64_t val)
void ClearTypeAnalysis(EnzymeTypeAnalysisRef TAR)
CConcreteType EnzymeTypeTreeInner0(CTypeTreeRef CTT)
void EnzymeTypeTreeToStringFree(const char *cstr)
uint8_t EnzymeGradientUtilsGetAugmentedPrimalReturnUsed(GradientUtils *G, LLVMValueRef oval)
EnzymeLogicRef CreateEnzymeLogic(uint8_t PostOpt)
void EnzymeRegisterFwdCallHandler(char *Name, CustomFunctionForward FwdHandle)
uint8_t EnzymeGetCLBool(void *ptr)
void EnzymeDumpValueRef(LLVMValueRef M)
void FreeEnzymeLogic(EnzymeLogicRef Ref)
void EnzymeGradientUtilsSetDebugLocFromOriginal(GradientUtils *gutils, LLVMValueRef val, LLVMValueRef orig)
LLVMValueRef EnzymeGradientUtilsLookup(GradientUtils *gutils, LLVMValueRef val, LLVMBuilderRef B)
const char * EnzymeTypeAnalyzerToString(void *src)
CDIFFE_TYPE EnzymeGradientUtilsGetDiffeType(GradientUtils *G, LLVMValueRef oval, uint8_t foreignFunction)
uint8_t EnzymeLowerSparsification(LLVMValueRef F, uint8_t replaceAll)
LLVMMetadataRef EnzymeAnonymousAliasScope(LLVMMetadataRef domain, const char *str)
void EnzymeReplaceOriginalToNew(GradientUtils *gutils, LLVMValueRef origC, LLVMValueRef repC)
void EnzymeSetStringMD(LLVMValueRef Inst, const char *Kind, LLVMValueRef Val)
uint8_t EnzymeGradientUtilsGetAtomicAdd(GradientUtils *gutils)
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)
void EnzymeDetectReadonlyOrThrow(LLVMModuleRef M)
LLVMValueRef EnzymeBuildExtractValue(LLVMBuilderRef B, LLVMValueRef AggVal, unsigned *Index, unsigned Size, const char *Name)
void EnzymeLogicSetExternalContext(EnzymeLogicRef Ref, void *ExternalContext)
LLVMValueRef EnzymeGradientUtilsNewFromOriginal(GradientUtils *gutils, LLVMValueRef val)
void EnzymeTypeTreeInsertEq(CTypeTreeRef CTT, const int64_t *indices, size_t len, CConcreteType ct, LLVMContextRef ctx)
uint8_t EnzymeGradientUtilsGetRuntimeActivity(GradientUtils *gutils)
void EnzymeDumpTypeRef(LLVMTypeRef M)
void EnzymeCloneFunctionDISubprogramInto(LLVMValueRef NF, LLVMValueRef F)
void FreeTraceInterface(EnzymeTraceInterfaceRef Ref)
void EnzymeLogicErasePreprocessedFunctions(EnzymeLogicRef Ref)
CTypeTreeRef EnzymeNewTypeTree()
void EnzymeGradientUtilsSetReverseBlock(GradientUtils *gutils, LLVMBasicBlockRef block)
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)
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)
void * EnzymeGradientUtilsTypeAnalyzer(GradientUtils *G)
uint8_t EnzymeGradientUtilsIsConstantInstruction(GradientUtils *gutils, LLVMValueRef val)
LLVMTypeRef EnzymeGradientUtilsGetShadowType(GradientUtils *gutils, LLVMTypeRef T)
void RunAttributorOnModule(LLVMModuleRef M0)
void EnzymeRegisterCallHandler(const char *Name, CustomAugmentedFunctionForward FwdHandle, CustomFunctionReverse RevHandle)
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)
void EnzymeGradientUtilsDumpTypeResults(GradientUtils *gutils)
uint8_t EnzymeSetTypeTree(CTypeTreeRef dst, CTypeTreeRef src)
uint8_t EnzymeGradientUtilsGetStrongZero(GradientUtils *gutils)
EnzymeLogicRef EnzymeTypeAnalysisGetLogic(EnzymeTypeAnalysisRef TAR)
LLVMBasicBlockRef EnzymeGradientUtilsAllocationBlock(GradientUtils *gutils)
void EnzymeGradientUtilsAddToDiffe(DiffeGradientUtils *gutils, LLVMValueRef val, LLVMValueRef diffe, LLVMBuilderRef B, LLVMTypeRef T)
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)
uint8_t EnzymeGradientUtilsGetUncacheableArgs(GradientUtils *gutils, LLVMValueRef orig, uint8_t *data, uint64_t size)
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)
void EnzymeTypeTreeOnlyEq(CTypeTreeRef CTT, int64_t x)
TargetLibraryInfo eunwrap(LLVMTargetLibraryInfoRef P)
LLVMValueRef EnzymeComputeByteOffsetOfGEP(LLVMBuilderRef B_r, LLVMValueRef V_r, LLVMTypeRef T_r)
void EnzymeSetMustCache(LLVMValueRef inst1)
void EnzymeDumpModuleRef(LLVMModuleRef M)
void EnzymeGradientUtilsEraseWithPlaceholder(GradientUtils *G, LLVMValueRef I, LLVMValueRef orig, uint8_t erase)
LLVMTypeRef EnzymeExtractTapeTypeFromAugmentation(EnzymeAugmentedReturnPtr ret)
CTypeTreeRef EnzymeTypeTreeFromMD(LLVMValueRef Val)
CDerivativeMode EnzymeGradientUtilsGetMode(GradientUtils *gutils)
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)
LLVMValueRef EnzymeGradientUtilsDiffe(DiffeGradientUtils *gutils, LLVMValueRef val, LLVMBuilderRef B)
EnzymeAugmentedReturnPtr ewrap(const AugmentedReturn &AR)
CTypeTreeRef EnzymeNewTypeTreeCT(CConcreteType CT, LLVMContextRef ctx)
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)
void EnzymeGradientUtilsAddToInvertedPointerDiffe(DiffeGradientUtils *gutils, LLVMValueRef orig, LLVMValueRef origVal, LLVMTypeRef addingType, unsigned start, unsigned size, LLVMValueRef origptr, LLVMValueRef dif, LLVMBuilderRef BuilderM, unsigned align, LLVMValueRef mask)
uint8_t EnzymeMergeTypeTree(CTypeTreeRef dst, CTypeTreeRef src)
LLVMValueRef EnzymeBuildInsertValue(LLVMBuilderRef B, LLVMValueRef AggVal, LLVMValueRef EltVal, unsigned *Index, unsigned Size, const char *Name)
void EnzymeGradientUtilsErase(GradientUtils *G, LLVMValueRef I)
uint8_t EnzymeHasFromStack(LLVMValueRef inst1)
EnzymeTypeAnalysisRef CreateTypeAnalysis(EnzymeLogicRef Log, char **customRuleNames, CustomRuleType *customRules, size_t numRules)
EnzymeLogicRef EnzymeGradientUtilsGetLogic(GradientUtils *gutils)
LLVMValueRef EnzymeTypeTreeToMD(CTypeTreeRef CTR, LLVMContextRef ctx)
void * EnzymeAnalyzeTypes(EnzymeTypeAnalysisRef TAR, CFnTypeInfo CTI, LLVMValueRef F)
LLVMMetadataRef EnzymeMakeNonConstTBAA(LLVMMetadataRef MD)
void EnzymeGradientUtilsSetDiffe(DiffeGradientUtils *gutils, LLVMValueRef val, LLVMValueRef diffe, LLVMBuilderRef B)
void EnzymeSetCLBool(void *ptr, uint8_t val)
LLVMValueRef EnzymeExtractFunctionFromAugmentation(EnzymeAugmentedReturnPtr ret)
LLVMValueRef EnzymeGradientUtilsInvertPointer(GradientUtils *gutils, LLVMValueRef val, LLVMBuilderRef B)
void EnzymeSetCLString(void *ptr, const char *val)
std::set< int64_t > eunwrap64(IntList IL)
void EnzymeExtractReturnInfo(EnzymeAugmentedReturnPtr ret, int64_t *data, uint8_t *existed, size_t len)
CTypeTreeRef EnzymeGradientUtilsAllocAndGetTypeTree(GradientUtils *gutils, LLVMValueRef val)
void EnzymeGradientUtilsReplaceAWithB(GradientUtils *G, LLVMValueRef A, LLVMValueRef B)
void EnzymeTypeTreeShiftIndiciesEq(CTypeTreeRef CTT, const char *datalayout, int64_t offset, int64_t maxSize, uint64_t addOffset)
void EnzymeCopyMetadata(LLVMValueRef inst1, LLVMValueRef inst2)
uint8_t EnzymeCheckedMergeTypeTree(CTypeTreeRef dst, CTypeTreeRef src, uint8_t *legalP)
void * EnzymeLogicGetExternalContext(EnzymeLogicRef Ref)
void EnzymeReplaceFunctionImplementation(LLVMModuleRef M)
void EnzymeTypeTreeCanonicalizeInPlace(CTypeTreeRef CTT, int64_t size, const char *dl)
void EnzymeRegisterDiffUseCallHandler(char *Name, CustomFunctionDiffUse Handle)
const char * EnzymeTypeTreeToString(CTypeTreeRef src)
EnzymeLogicRef EnzymeTypeAnalyzerGetLogic(void *src)
void EnzymeRegisterAllocationHandler(char *Name, CustomShadowAlloc AHandle, CustomShadowFree FHandle)
uint64_t EnzymeGradientUtilsGetWidth(GradientUtils *gutils)
LLVMValueRef EnzymeCloneFunctionWithoutReturnOrArgs(LLVMValueRef FC, uint8_t keepReturnU, uint64_t *argrem, uint64_t num_argrem)
LLVMTypeRef EnzymeGetShadowType(uint64_t width, LLVMTypeRef T)
LLVMTypeRef EnzymeAllocaType(LLVMValueRef V)
void ClearEnzymeLogic(EnzymeLogicRef Ref)
void EnzymeMoveBefore(LLVMValueRef inst1, LLVMValueRef inst2, LLVMBuilderRef B)
uint8_t(* CustomFunctionForward)(LLVMBuilderRef, LLVMValueRef, GradientUtils *, LLVMValueRef *, LLVMValueRef *)
struct EnzymeOpaqueTypeAnalysis * EnzymeTypeAnalysisRef
struct EnzymeOpaqueTraceInterface * EnzymeTraceInterfaceRef
struct EnzymeTypeTree * CTypeTreeRef
uint8_t(* CustomAugmentedFunctionForward)(LLVMBuilderRef, LLVMValueRef, GradientUtils *, LLVMValueRef *, LLVMValueRef *, LLVMValueRef *)
uint8_t(* CustomRuleType)(int, CTypeTreeRef, CTypeTreeRef *, struct IntList *, size_t, LLVMValueRef, void *)
uint8_t(* CustomFunctionDiffUse)(LLVMValueRef, const GradientUtils *, LLVMValueRef, uint8_t, CDerivativeMode, uint8_t *)
void(* CustomFunctionReverse)(LLVMBuilderRef, LLVMValueRef, DiffeGradientUtils *, LLVMValueRef)
LLVMValueRef(* CustomShadowFree)(LLVMBuilderRef, LLVMValueRef)
struct EnzymeOpaqueLogic * EnzymeLogicRef
LLVMValueRef(* CustomShadowAlloc)(LLVMBuilderRef, LLVMValueRef, size_t, LLVMValueRef *, GradientUtils *)
struct EnzymeOpaqueAugmentedReturn * EnzymeAugmentedReturnPtr
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)
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)
bool collectOffset(GEPOperator *gep, const DataLayout &DL, unsigned BitWidth, MapVector< Value *, APInt > &VariableOffsets, APInt &ConstantOffset)
@ 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.
static void resetClonedGUID(llvm::Function *F)
ValueType
Classification of value as an original program variable, a derivative variable, neither,...
static void moveBeforeInst(llvm::Instruction *I, llvm::Instruction *Before)
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.
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)
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
std::map< llvm::BasicBlock *, llvm::SmallVector< llvm::BasicBlock *, 4 > > reverseBlocks
Map of primal block to corresponding block(s) in reverse.
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.
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.
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.
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.
void insertFromMD(llvm::MDNode *md, const std::vector< int > &prev={})
struct IntList * KnownValues
The specific constant(s) known to represented by an argument, if constant.
CTypeTreeRef * Arguments
Types of arguments, assumed of size len(Arguments)
CTypeTreeRef Return
Type of return.
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.
void getAnalysisUsage(AnalysisUsage &AU) const override
bool runOnModule(Module &M) override
todiff is the function to differentiate retType is the activity info of the return.