Skip to content

[OpenMP][LLVM] Clone omp.private op in the parent module #96024

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 9 commits into from
Jun 23, 2024
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 @@ -1304,7 +1304,26 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder,
// region. The privatizer is processed in-place (see below) before it
// gets inlined in the parallel region and therefore processing the
// original op is dangerous.
return {privVar, privatizer.clone()};

MLIRContext &context = moduleTranslation.getContext();
mlir::IRRewriter opCloner(&context);
opCloner.setInsertionPoint(privatizer);
auto clone = llvm::cast<mlir::omp::PrivateClauseOp>(
opCloner.clone(*privatizer));

// Unique the clone name to avoid clashes in the symbol table.
unsigned counter = 0;
SmallString<256> cloneName = SymbolTable::generateSymbolName<256>(
privatizer.getSymName(),
[&](llvm::StringRef candidate) {
return SymbolTable::lookupNearestSymbolFrom(
opInst, StringAttr::get(&context, candidate)) !=
nullptr;
},
counter);

clone.setSymName(cloneName);
return {privVar, clone};
}
}

Expand Down
44 changes: 44 additions & 0 deletions mlir/test/Target/LLVMIR/openmp-private.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,47 @@ omp.private {type = private} @multi_block.privatizer : !llvm.ptr alloc {
llvm.store %1, %arg2 : f32, !llvm.ptr
omp.yield(%arg2 : !llvm.ptr)
}

// Tests fix for Fujitsu test suite test: 0007_0019.f90: the
// `llvm.mlir.addressof` op needs access to the parent module when lowering
// from the LLVM dialect to LLVM IR. If such op is used inside an `omp.private`
// op instance that was not created/cloned inside the module, we would get a
// seg fault due to trying to access a null pointer.

// CHECK-LABEL: define internal void @lower_region_with_addressof..omp_par
// CHECK: omp.par.region:
// CHECK: br label %[[PAR_REG_BEG:.*]]
// CHECK: [[PAR_REG_BEG]]:
// CHECK: %[[PRIVATIZER_GEP:.*]] = getelementptr double, ptr @_QQfoo, i64 111
// CHECK: call void @bar(ptr %[[PRIVATIZER_GEP]])
// CHECK: call void @bar(ptr getelementptr (double, ptr @_QQfoo, i64 222))
llvm.func @lower_region_with_addressof() {
%0 = llvm.mlir.constant(1 : i64) : i64
%1 = llvm.alloca %0 x f64 {bindc_name = "u1"} : (i64) -> !llvm.ptr
omp.parallel private(@_QFlower_region_with_addressof_privatizer %1 -> %arg0 : !llvm.ptr) {
%c0 = llvm.mlir.constant(111 : i64) : i64
%2 = llvm.getelementptr %arg0[%c0] : (!llvm.ptr, i64) -> !llvm.ptr, f64
llvm.call @bar(%2) : (!llvm.ptr) -> ()

%c1 = llvm.mlir.constant(222 : i64) : i64
%3 = llvm.mlir.addressof @_QQfoo: !llvm.ptr
%4 = llvm.getelementptr %3[%c1] : (!llvm.ptr, i64) -> !llvm.ptr, f64
llvm.call @bar(%4) : (!llvm.ptr) -> ()
omp.terminator
}

llvm.return
}

omp.private {type = private} @_QFlower_region_with_addressof_privatizer : !llvm.ptr alloc {
^bb0(%arg0: !llvm.ptr):
%0 = llvm.mlir.addressof @_QQfoo: !llvm.ptr
omp.yield(%0 : !llvm.ptr)
}

llvm.mlir.global linkonce constant @_QQfoo() {addr_space = 0 : i32} : !llvm.array<3 x i8> {
%0 = llvm.mlir.constant("foo") : !llvm.array<3 x i8>
llvm.return %0 : !llvm.array<3 x i8>
}

llvm.func @bar(!llvm.ptr)
Loading