@@ -534,10 +534,64 @@ UpgradeAllocasToMallocs(Function *NewF, DerivativeMode mode,
534534 }
535535 }
536536
537+ #if LLVM_VERSION_MAJOR >= 22
538+ Function *start_lifetime = nullptr ;
539+ Function *end_lifetime = nullptr ;
540+ #endif
541+
537542 for (auto AI : ToConvert) {
538543 std::string nam = AI->getName ().str ();
539544 AI->setName (" " );
540545
546+ #if LLVM_VERSION_MAJOR >= 22
547+ for (auto U : llvm::make_early_inc_range (AI->users ())) {
548+ if (auto II = dyn_cast<IntrinsicInst>(U)) {
549+ if (II->getIntrinsicID () == Intrinsic::lifetime_start) {
550+ if (!start_lifetime) {
551+ start_lifetime = cast<Function>(
552+ NewF->getParent ()
553+ ->getOrInsertFunction (
554+ " llvm.enzyme.lifetime_start" ,
555+ FunctionType::get (Type::getVoidTy (NewF->getContext ()),
556+ {}, true ))
557+ .getCallee ());
558+ }
559+ IRBuilder<> B (II);
560+ SmallVector<Value *, 2 > args (II->arg_size ());
561+ for (unsigned i = 0 ; i < II->arg_size (); ++i) {
562+ args[i] = II->getArgOperand (i);
563+ }
564+ auto newI = B.CreateCall (start_lifetime, args);
565+ newI->takeName (II);
566+ newI->setDebugLoc (II->getDebugLoc ());
567+ II->eraseFromParent ();
568+ continue ;
569+ }
570+ if (II->getIntrinsicID () == Intrinsic::lifetime_end) {
571+ if (!end_lifetime) {
572+ end_lifetime = cast<Function>(
573+ NewF->getParent ()
574+ ->getOrInsertFunction (
575+ " llvm.enzyme.lifetime_end" ,
576+ FunctionType::get (Type::getVoidTy (NewF->getContext ()),
577+ {}, true ))
578+ .getCallee ());
579+ }
580+ IRBuilder<> B (II);
581+ SmallVector<Value *, 2 > args (II->arg_size ());
582+ for (unsigned i = 0 ; i < II->arg_size (); ++i) {
583+ args[i] = II->getArgOperand (i);
584+ }
585+ auto newI = B.CreateCall (end_lifetime, args);
586+ newI->takeName (II);
587+ newI->setDebugLoc (II->getDebugLoc ());
588+ II->eraseFromParent ();
589+ continue ;
590+ }
591+ }
592+ }
593+ #endif
594+
541595 // Ensure we insert the malloc after the allocas
542596 Instruction *insertBefore = AI;
543597 while (isa<AllocaInst>(insertBefore->getNextNode ())) {
@@ -884,6 +938,45 @@ void PreProcessCache::LowerAllocAddr(Function *NewF) {
884938#endif
885939 RecursivelyReplaceAddressSpace (T, AIV, /* legal*/ true );
886940 }
941+
942+ #if LLVM_VERSION_MAJOR >= 22
943+ {
944+ auto start_lifetime =
945+ NewF->getParent ()->getFunction (" llvm.enzyme.lifetime_start" );
946+ auto end_lifetime =
947+ NewF->getParent ()->getFunction (" llvm.enzyme.lifetime_end" );
948+
949+ SmallVector<CallInst *, 1 > Todo;
950+ for (auto &BB : *NewF) {
951+ for (auto &I : BB) {
952+ if (auto CB = dyn_cast<CallInst>(&I)) {
953+ if (!CB->getCalledFunction ())
954+ continue ;
955+ if (CB->getCalledFunction () == start_lifetime ||
956+ CB->getCalledFunction () == end_lifetime) {
957+ Todo.push_back (CB);
958+ }
959+ }
960+ }
961+ }
962+
963+ for (auto CB : Todo) {
964+ if (!isa<AllocaInst>(CB->getArgOperand (1 ))) {
965+ CB->eraseFromParent ();
966+ continue ;
967+ }
968+ IRBuilder<> B (CB);
969+ if (CB->getCalledFunction () == start_lifetime) {
970+ B.CreateLifetimeStart (CB->getArgOperand (1 ),
971+ cast<ConstantInt>(CB->getArgOperand (0 )));
972+ } else {
973+ B.CreateLifetimeEnd (CB->getArgOperand (1 ),
974+ cast<ConstantInt>(CB->getArgOperand (0 )));
975+ }
976+ CB->eraseFromParent ();
977+ }
978+ }
979+ #endif
887980}
888981
889982// / Calls to realloc with an appropriate implementation
@@ -7300,6 +7393,9 @@ Constraints::InnerTy Constraints::make_compare(const SCEV *v, bool isEqual,
73007393 ConstraintContext ctx2 (ctx.SE , ctx.loopToSolve , noassumption, ctx.DT );
73017394 for (auto I : ctx.Assumptions ) {
73027395 bool legal = true ;
7396+ if (I->getParent ()->getParent () !=
7397+ ctx.loopToSolve ->getHeader ()->getParent ())
7398+ continue ;
73037399 auto parsedCond = getSparseConditions (legal, I->getOperand (0 ),
73047400 Constraints::none (), nullptr , ctx2);
73057401 bool dominates = ctx.DT .dominates (I, ctx.loopToSolve ->getHeader ());
0 commit comments