Skip to content

feature: redesign Proteus's lambda JIT compilation interface and pipeline - #467

Open
johnbowen42 wants to merge 55 commits into
mainfrom
feature/bowen/lambda-analysis-redesign
Open

feature: redesign Proteus's lambda JIT compilation interface and pipeline#467
johnbowen42 wants to merge 55 commits into
mainfrom
feature/bowen/lambda-analysis-redesign

Conversation

@johnbowen42

@johnbowen42 johnbowen42 commented Apr 14, 2026

Copy link
Copy Markdown
Collaborator

This feature restructures Proteus's lambda support so that a device module containing multiple calls of a lambda with different runtime constants can be correctly JIT compiled. This feature makes Proteus's support of JIT compiled lambdas closer to supporting all possible C++ lambda syntax, instead of the narrow syntax often used by parallel programming abstraction layers. Concretely

  • Add a functor wrapper to Proteus lambdas so that lambda callsites can be transparently tracked
  • Add LambdaPass which runs at the start of the pipeline and (1) handles jit_variable callsite analysis on less-simplified IR (before InstCombine can cause indirection at callsite (2) instruments lambda runtime constant registration for host lambda callsites and (3) generates manifests of lambda constants registered to device lambda callsite. Also LambdaPass removes global annotations on lambda functor operator callsites and attaches them as metadata nodes
  • Change ProteusPass so that (1) it consumes the LambdaPass manifests and then (2) uses them to build lambda registration functions, which are executed right before kernel launch
  • Change the runtime to look for lambda callsites in a device module containing metadata nodes, use that metadata as a key for lookup, and specialize each callsite based on the result lookup.

@ggeorgakoudis ggeorgakoudis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great and will solve our lambda issues.

I made a first pass and left comments on things we need to restructure.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think installing and using a separate pass is quirky. We already register ProteusPass in multiple places (early-simplifications and LTO), so we can register it also at pipeline-start and just do the lambda analysis

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you expand on this? How else would be run an early LambdaAnalysis pass and Proteuspass later?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Register ProteusPass at pipeline-start and pass an argument when you construct it to indicate the insert point. Check how we do it for early-simplifications and LTO. Apparently state is not true-false anymore, if there are 3 possible insert points.

Comment thread include/proteus/Frontend/TypeTraits.h
Comment thread include/proteus/JitInterface.h Outdated
Comment thread scripts/setup-rocm.sh Outdated
Comment thread src/include/proteus/impl/Cloning.h Outdated
Comment thread src/include/proteus/impl/Cloning.h
Comment thread src/include/proteus/impl/GlobalAnnotations.h Outdated
Comment thread src/include/proteus/impl/CompilationTask.h Outdated
@johnbowen42
johnbowen42 force-pushed the feature/bowen/lambda-analysis-redesign branch from 2cf03a2 to d5b97c4 Compare April 17, 2026 22:16
@johnbowen42
johnbowen42 marked this pull request as ready for review April 17, 2026 22:16
@johnbowen42
johnbowen42 force-pushed the feature/bowen/lambda-analysis-redesign branch from d5b97c4 to a56679a Compare April 17, 2026 22:17
@johnbowen42

Copy link
Copy Markdown
Collaborator Author

all tests are passing for me locally on Tioga with rocm 6.4.2

@johnbowen42
johnbowen42 force-pushed the feature/bowen/lambda-analysis-redesign branch from c3d3d2e to 5daef48 Compare May 11, 2026 21:30
@johnbowen42
johnbowen42 force-pushed the feature/bowen/lambda-analysis-redesign branch from 4441506 to 3202250 Compare June 18, 2026 19:00
@johnbowen42

johnbowen42 commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator Author

This analysis is now compatible with RAJA launch, kernel, and forall LLVM IR shapes
llnl/RAJA#2052

@johnbowen42
johnbowen42 force-pushed the feature/bowen/lambda-analysis-redesign branch from 8e43319 to f0ed85a Compare July 2, 2026 20:39
@johnbowen42
johnbowen42 requested a review from ggeorgakoudis July 6, 2026 16:22
@johnbowen42
johnbowen42 force-pushed the feature/bowen/lambda-analysis-redesign branch 2 times, most recently from f3e5a08 to f59b51e Compare July 8, 2026 16:08
@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

johnbowen42 and others added 13 commits July 9, 2026 09:51
remove jit var analysis from later pass

tmp

update tests

check point: all lambda tests GPU passing

add wrapper functors

Lambda redeisgn: add functors.  This commit builds but the runtime needs work

delete plugin

get tests working

Refactor tests and track lambdas by global annotations

Remove changes to type traits

Get rid of storing things in llvm.global.annotations.  Fix lambda CPU test

All lambda unit tests passing.  Fixed cloning bug in ProteusPass

delete xfail compile test

remove script change

Fix all unit tests
johnbowen42 and others added 28 commits July 9, 2026 09:51
… expecting jit_variable schema for every lambda
@johnbowen42
johnbowen42 force-pushed the feature/bowen/lambda-analysis-redesign branch from f59b51e to c462791 Compare July 9, 2026 16:53

@ZwFink ZwFink left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great work. I have mostly minor things.
Because this PR is so big and has been so long in the works, I don't want to hold it up for any of these things.
I am concerned that we would perpetually run around in bike-shedding circles, all the while this important feature is held up. Anything you choose not to resolve should be opened as an issue for follow-up.

Comment on lines +122 to +125
// We need collect any kernel host stubs to pass to parse annotations, used
// in forced annotations.
const auto StubToKernelMap = getKernelHostStubs(M);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy-paste artifact from ProteusPass? This is never used here. Can be removed along with getKernelHostStubs.

Comment on lines +476 to +477
DenseMap<Value *, GlobalVariable *> getKernelHostStubs(Module &M) {
DenseMap<Value *, GlobalVariable *> StubToKernelMap;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove

Comment on lines +198 to +199
Value *getStubGV([[maybe_unused]] Value *Operand) {
// NOTE: when called by isDeviceKernelHostStub, Operand may not be a global

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove

Comment on lines +852 to +853
bool hasDeviceLaunchKernelCalls(Module &M) {
Function *LaunchKernelFn = nullptr;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove


DenseMap<StructType *, SmallVector<LambdaJitVariableInfo, 16>>
LambdaStorageTypeToJitIndices;
DenseMap<Type *, GlobalVariable *> LambdaTypeToGlobalName;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not used

Comment on lines +126 to +132
DenseMap<StructType *, SmallVector<LambdaJitVariableInfo, 16>>
LambdaStorageTypeToJitIndices;
DenseMap<Type *, GlobalVariable *> LambdaTypeToGlobalName;
DenseSet<StructType *> RegisteredLambdaStorageClasses;
DenseMap<StructType *, StructType *> FunctorTypeToLambdaTypeMap;
DenseMap<uint64_t, StructType *> FunctorIDToLambdaTypeMap;
DenseMap<uint64_t, StructType *> FunctorIDToFunctorTypeMap;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are all declared here but used only for host compilation?

Comment on lines +579 to +581
KernelFunction = FirstAnalysis->KernelFunction;
AnalysisSuccess = true;
AnalysisFailed = false;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you also need to set KernelArg, Offset, and ChangedRC?

Comment on lines +537 to +544
for (User *U : F->users()) {
auto *CB = dyn_cast<CallBase>(U);
if (!CB)
continue;
DEBUG(Logger::logs("proteus-pass")
<< "Analysis crossed interprocedural boundary at "
<< *CB->getArgOperand(ArgNum) << "\n");
WorkList.push_back({CB->getArgOperand(ArgNum), CB});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be context sensitive?

Comment on lines +615 to +631
std::optional<RuntimeConstantType> getRCTypeForLLVMType(Type *Ty) {
if (Ty->isIntegerTy(1))
return RuntimeConstantType::BOOL;
if (Ty->isIntegerTy(8))
return RuntimeConstantType::INT8;
if (Ty->isIntegerTy(32))
return RuntimeConstantType::INT32;
if (Ty->isIntegerTy(64))
return RuntimeConstantType::INT64;
if (Ty->isFloatTy())
return RuntimeConstantType::FLOAT;
if (Ty->isDoubleTy())
return RuntimeConstantType::DOUBLE;
if (Ty->isPointerTy())
return RuntimeConstantType::PTR;
return std::nullopt;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regression: long double is dropped

Comment thread src/pass/ProteusPass.cpp
Comment on lines 1879 to 1886
// Legacy PM implementation.
struct LegacyProteusPass : public ModulePass {
static char ID;
LegacyProteusPass() : ModulePass(ID) {}
bool runOnModule(Module &M) override {
ProteusPassImpl PPI{M};
bool Changed = PPI.run(M, false);
return Changed;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the lambda analysis be run here too?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants