-
Notifications
You must be signed in to change notification settings - Fork 13k
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
[Flang][MLIR][OpenMP] Fix Target Data if (present(...)) causing LLVM-IR branching error #123771
Conversation
…IR branching error Currently if we generate code for the below target data map that uses an optional mapping: !$omp target data if(present(a)) map(alloc:a) do i = 1, 10 a(i) = i end do !$omp end target data We yield an LLVM-IR error as the branch for the else path is not generated. This occurs because we enter the NoDupPriv path of the call back function when generating the else branch, however, the emitBranch function needs to be set to a block for it to functionally generate and link in a follow up branch. The NoDupPriv path currently doesn't do this, while it's not supposed to generate anything (as far as I am aware) we still need to at least set the builders placement back so that it emits the appropriate follow up branch. This avoids the missing terminator LLVM-IR verification error by correctly generating the follow up branch.
@llvm/pr-subscribers-mlir-llvm @llvm/pr-subscribers-flang-openmp Author: None (agozillon) ChangesCurrently if we generate code for the below target data map that uses an optional mapping:
We yield an LLVM-IR error as the branch for the else path is not generated. This occurs because we enter the NoDupPriv path of the call back function when generating the else branch, however, the emitBranch function needs to be set to a block for it to functionally generate and link in a follow up branch. The NoDupPriv path currently doesn't do this, while it's not supposed to generate anything (as far as I am aware) we still need to at least set the builders placement back so that it emits the appropriate follow up branch. This avoids the missing terminator LLVM-IR verification error by correctly generating the follow up branch. Full diff: https://github.com/llvm/llvm-project/pull/123771.diff 2 Files Affected:
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index e776722a818d7d..c3d87e25ab12d2 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -3727,6 +3727,9 @@ convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder,
}
break;
case BodyGenTy::DupNoPriv:
+ // We must always restoreIP regardless of doing anything the caller
+ // does not restore it, leading to incorrect (no) branch generation.
+ builder.restoreIP(codeGenIP);
break;
case BodyGenTy::NoPriv:
// If device info is available then region has already been generated
diff --git a/offload/test/offloading/fortran/target-data-map-if-present.f90 b/offload/test/offloading/fortran/target-data-map-if-present.f90
new file mode 100644
index 00000000000000..c181573cd7a1c1
--- /dev/null
+++ b/offload/test/offloading/fortran/target-data-map-if-present.f90
@@ -0,0 +1,29 @@
+! Offloading test that tests that if(present(a)) compiles and executes without
+! causing any compilation errors, primarily a regression test that does not
+! yield interesting results.
+! REQUIRES: flang, amdgpu
+
+! RUN: %libomptarget-compile-fortran-run-and-check-generic
+module mod
+ implicit none
+contains
+ subroutine routine(a)
+ implicit none
+ real, dimension(:), optional :: a
+ integer :: i
+ !$omp target data if(present(a)) map(alloc:a)
+ do i = 1, 10
+ a(i) = i
+ end do
+ !$omp end target data
+ end subroutine routine
+end module mod
+
+program main
+ use mod
+ real :: a(10)
+ call routine(a)
+ print *, a
+end program main
+
+! CHECK: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
|
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.
Thank you, just one comment from me.
@@ -3727,6 +3727,9 @@ convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder, | |||
} | |||
break; | |||
case BodyGenTy::DupNoPriv: | |||
// We must always restoreIP regardless of doing anything the caller | |||
// does not restore it, leading to incorrect (no) branch generation. | |||
builder.restoreIP(codeGenIP); |
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.
I see that this is done based on whether info.DevicePtrInfoMap
is empty at the moment for the other cases. Can that result in similar problems that perhaps are addressed by moving this call right before the switch
or do we actually want to make it conditional in the other cases?
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.
It doesn't from what I can tell with testing and actually causes runtime errors as opposed to compile time errors! :-) I believe it likely comes from the fact that the lambda is called in a different manner by the OMPIRBuilder based on a variable amount of conditions, so I'd be loathe to change it further without good reason/a reproducer (if there happens to be one) so that I can find a solution that'd make all paths happy!
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.
Setting and restoring the IPs and AllocalIPs is really complicated. It would be nice to have a better approach maybe generate code using regions.
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.
LGTM.
@@ -3727,6 +3727,9 @@ convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder, | |||
} | |||
break; | |||
case BodyGenTy::DupNoPriv: | |||
// We must always restoreIP regardless of doing anything the caller | |||
// does not restore it, leading to incorrect (no) branch generation. | |||
builder.restoreIP(codeGenIP); |
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.
Setting and restoring the IPs and AllocalIPs is really complicated. It would be nice to have a better approach maybe generate code using regions.
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.
LGTM.
@@ -3727,6 +3727,9 @@ convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder, | |||
} | |||
break; | |||
case BodyGenTy::DupNoPriv: | |||
// We must always restoreIP regardless of doing anything the caller | |||
// does not restore it, leading to incorrect (no) branch generation. | |||
builder.restoreIP(codeGenIP); |
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.
I had encountered and passively fixed this issue in #124746.
I think the better fix would be to raise the restoreIP call to just before or after the assert, basically immediately after entering CodeGenCB and get rid of the restoreIP calls inside the switch case.
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.
Thank you @TIFitis I'll leave the better fix to you then in your PR and just land this in the meantime to address the current reproducer!
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/73/builds/12741 Here is the relevant piece of the build log for the reference
|
Seems to be a sporadic failure of the test (and a few others) on that particular buildbot that occurs fairly frequently across all the test builds, at least for the past few days. So it seems unrelated and ignorable. |
Currently if we generate code for the below target data map that uses an optional mapping:
We yield an LLVM-IR error as the branch for the else path is not generated. This occurs because we enter the NoDupPriv path of the call back function when generating the else branch, however, the emitBranch function needs to be set to a block for it to functionally generate and link in a follow up branch. The NoDupPriv path currently doesn't do this, while it's not supposed to generate anything (as far as I am aware) we still need to at least set the builders placement back so that it emits the appropriate follow up branch. This avoids the missing terminator LLVM-IR verification error by correctly generating the follow up branch.