Skip to content

[flang][OpenMP] Process omp.atomic.update while translating scopes for target device #132165

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5323,6 +5323,20 @@ convertTargetOpsInNest(Operation *op, llvm::IRBuilderBase &builder,
if (auto blockArgsIface =
dyn_cast<omp::BlockArgOpenMPOpInterface>(oper))
forwardArgs(moduleTranslation, blockArgsIface);
else {
// Here we map entry block arguments of
// non-BlockArgOpenMPOpInterface ops if they can be encountered
// inside of a function and they define any of these arguments.
if (isa<mlir::omp::AtomicUpdateOp>(oper))
for (auto [operand, arg] :
llvm::zip_equal(oper->getOperands(),
oper->getRegion(0).getArguments())) {
moduleTranslation.mapValue(
arg, builder.CreateLoad(
moduleTranslation.convertType(arg.getType()),
moduleTranslation.lookupValue(operand)));
}
}

if (auto loopNest = dyn_cast<omp::LoopNestOp>(oper)) {
assert(builder.GetInsertBlock() &&
Expand All @@ -5340,9 +5354,10 @@ convertTargetOpsInNest(Operation *op, llvm::IRBuilderBase &builder,
// translation of the OpenMP construct being converted (e.g. no
// OpenMP runtime calls will be generated). We just need this to
// prepare the kernel invocation args.
SmallVector<llvm::PHINode *> phis;
auto result = convertOmpOpRegions(
region, oper->getName().getStringRef().str() + ".fake.region",
builder, moduleTranslation);
builder, moduleTranslation, &phis);
Copy link
Member

Choose a reason for hiding this comment

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

I see phis isn't used. Does passing the vector on its own cause a behavior change?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, since omp.atomic.update yields values (which are not used in this context), convertOmpOpRegions asserts unless we pass a vector to collect the phis.

Copy link
Member

Choose a reason for hiding this comment

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

Ah I see, and I guess not using these PHI nodes later doesn't cause issues. Thanks for the explanation!

if (failed(handleError(result, *oper)))
return WalkResult::interrupt();

Expand Down
21 changes: 21 additions & 0 deletions mlir/test/Target/LLVMIR/openmp-target-nesting-in-host-ops.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,20 @@ module attributes {llvm.target_triple = "amdgcn-amd-amdhsa", omp.is_gpu = true,
llvm.return
}

llvm.func @test_target_and_atomic_update(%x: !llvm.ptr, %expr : i32) {
omp.target {
omp.terminator
}

omp.atomic.update %x : !llvm.ptr {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}

llvm.return
}

// CHECK-LABEL: define void @test_nested_target_in_parallel_with_private({{.*}}) {
// CHECK: br label %omp.parallel.fake.region
// CHECK: omp.parallel.fake.region:
Expand Down Expand Up @@ -132,4 +146,11 @@ module attributes {llvm.target_triple = "amdgcn-amd-amdhsa", omp.is_gpu = true,
// CHECK: call void @__kmpc_target_deinit()
// CHECK: ret void
// CHECK: }

// CHECK-LABEL: define {{.*}} amdgpu_kernel void @__omp_offloading_{{.*}}_test_target_and_atomic_update_{{.*}} {
// CHECK: call i32 @__kmpc_target_init
// CHECK: user_code.entry:
// CHECK: call void @__kmpc_target_deinit()
// CHECK: ret void
// CHECK: }
}