-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[Utils][mlir] Fix interaction between CodeExtractor and OpenMPIRBuilder #145051
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
Changes from 2 commits
de6e916
10ed535
53eab2c
70dad6d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -777,7 +777,7 @@ ModuleTranslation::ModuleTranslation(Operation *module, | |
| } | ||
|
|
||
| ModuleTranslation::~ModuleTranslation() { | ||
| if (ompBuilder) | ||
| if (ompBuilder && !ompBuilder->isFinalized()) | ||
| ompBuilder->finalize(); | ||
| } | ||
|
|
||
|
|
@@ -2332,6 +2332,10 @@ mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext, | |
| // beforehand. | ||
| translator.debugTranslation->addModuleFlagsIfNotPresent(); | ||
|
|
||
| // Call the OpenMP IR Builder callbacks prior to verifying the module | ||
| if (auto *ompBuilder = translator.getOpenMPBuilder()) | ||
| ompBuilder->finalize(); | ||
|
|
||
| if (!disableVerification && | ||
| llvm::verifyModule(*translator.llvmModule, &llvm::errs())) | ||
| return nullptr; | ||
|
Comment on lines
+2335
to
2340
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can move module verification to
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could do this, but then we'd have to change the signature of
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think leaving it here makes more sense indeed. Thanks for looking into it. |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| // RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s | ||
| // This tests the fix for https://github.com/llvm/llvm-project/issues/138102 | ||
| // We are only interested in ensuring that the -mlir-to-llvmir pass doesn't crash | ||
|
|
||
| // CHECK-LABEL: define internal void @_QQmain..omp_par | ||
|
|
||
| omp.private {type = private} @_QFEi_private_i32 : i32 | ||
| omp.private {type = firstprivate} @_QFEc_firstprivate_i32 : i32 copy { | ||
| ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr): | ||
| %0 = llvm.load %arg0 : !llvm.ptr -> i32 | ||
| llvm.store %0, %arg1 : i32, !llvm.ptr | ||
| omp.yield(%arg1 : !llvm.ptr) | ||
| } | ||
| llvm.func @_QQmain() { | ||
| %0 = llvm.mlir.constant(1 : i64) : i64 | ||
| %1 = llvm.alloca %0 x i32 {bindc_name = "i"} : (i64) -> !llvm.ptr | ||
| %2 = llvm.mlir.constant(1 : i64) : i64 | ||
| %3 = llvm.alloca %2 x i32 {bindc_name = "c"} : (i64) -> !llvm.ptr | ||
| %4 = llvm.mlir.constant(10 : index) : i64 | ||
| %5 = llvm.mlir.constant(0 : index) : i64 | ||
| %6 = llvm.mlir.constant(10000 : index) : i64 | ||
| %7 = llvm.mlir.constant(1 : index) : i64 | ||
| %8 = llvm.mlir.constant(1 : i64) : i64 | ||
| %9 = llvm.mlir.addressof @_QFECchunksz : !llvm.ptr | ||
| %10 = llvm.mlir.constant(1 : i64) : i64 | ||
| %11 = llvm.trunc %7 : i64 to i32 | ||
| llvm.br ^bb1(%11, %4 : i32, i64) | ||
| ^bb1(%12: i32, %13: i64): // 2 preds: ^bb0, ^bb2 | ||
| %14 = llvm.icmp "sgt" %13, %5 : i64 | ||
| llvm.store %12, %3 : i32, !llvm.ptr | ||
| omp.task private(@_QFEc_firstprivate_i32 %3 -> %arg0 : !llvm.ptr) { | ||
| %19 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = "i"} | ||
| %20 = omp.map.info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = "c"} | ||
| %21 = omp.map.info var_ptr(%9 : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = "chunksz"} | ||
| omp.target map_entries(%19 -> %arg1, %20 -> %arg2, %21 -> %arg3 : !llvm.ptr, !llvm.ptr, !llvm.ptr) { | ||
| %22 = llvm.mlir.constant(9999 : i32) : i32 | ||
| %23 = llvm.mlir.constant(1 : i32) : i32 | ||
| omp.parallel { | ||
| %24 = llvm.load %arg2 : !llvm.ptr -> i32 | ||
| %25 = llvm.add %24, %22 : i32 | ||
| omp.wsloop private(@_QFEi_private_i32 %arg1 -> %arg4 : !llvm.ptr) { | ||
| omp.loop_nest (%arg5) : i32 = (%24) to (%25) inclusive step (%23) { | ||
| llvm.store %arg5, %arg4 : i32, !llvm.ptr | ||
| omp.yield | ||
| } | ||
| } | ||
| omp.terminator | ||
| } | ||
| omp.terminator | ||
| } | ||
| omp.terminator | ||
| } | ||
| llvm.return | ||
| } | ||
| llvm.mlir.global internal constant @_QFECchunksz() {addr_space = 0 : i32} : i32 { | ||
| %0 = llvm.mlir.constant(10000 : i32) : i32 | ||
| llvm.return %0 : i32 | ||
| } | ||
| llvm.mlir.global internal constant @_QFECn() {addr_space = 0 : i32} : i32 { | ||
| %0 = llvm.mlir.constant(100000 : i32) : i32 | ||
| llvm.return %0 : i32 | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AllocationBlockis assigned on construction of theCodeExtractorobject. Should we instead make sure that we pass a suitable basic block when we construct the code extractor object?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we go up the chain, the problem originates over here:
llvm-project/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
Line 501 in fccab5d
findAllocaInsertPointdoes a stackWalk to find a preexisting alloca insert point, and it does find it - but it's in a different function. We could put a check here to make sure that we only use it if it's in the same function asbuilder.getInsertBlock()?This would fix the issue, but fixing it inside CodeExtractor would make it it more robust for other cases when a wrong block might be passed on accident. I think I'd lean towards keeping it as-is on that account, but if other people have strong preferences or arguments to the contrary then I am happy to change it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it should be fixed in the stack walk and have an assertion added to the code extractor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good way to do it, thanks for the suggestion - done :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update.
Sorry to be difficult but looking at this change gave me an idea: I think this situation just shouldn't ever happen.
Say we have something like this
If the lowering for omp.op2 is trying to put allocas in the alloca region for op1 then yes both of those could be outlined to different functions. But I don't think this should ever happen. If omp.op2 is expecting to be outlined, I think it should define its own alloca insertion point on the alloca stack.
I suspect one of the operations in your test needs to add an insertion point to the stack.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whenever things are saved on that stack, the thing being saved is what was previously returned by findAllocaInsertPoint. E.g.:
llvm-project/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
Line 2265 in fccab5d
The specific call which finds the block in a different function during the stack walk is inside convertOmpTarget, here:
llvm-project/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
Line 5555 in fccab5d
findAllocaInsertPoint defines its own insert point if it can't already find one, hence adding that extra check fixes the problem at hand. In this case the outer op - task - does add the alloca insertion point to the stack like it should, but that insertion point is inside of main as opposed to the outlined function for task.
That is to say - I don't think there are missing SaveStack operations at the point where it's relevant for this specific case.
targetdoes not save the alloca point it finds (maybe it should?) but by the time target would be saving it, the block that was found is already wrong.