[flang-commits] [flang] [flang][cuda] Synchronize context before finalization (PR #223058)
via flang-commits
flang-commits at lists.llvm.org
Fri Sep 11 13:53:23 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: Valentin Clement (バレンタイン クレメン) (clementval)
<details>
<summary>Changes</summary>
When switching to custom allocator like a pool allocator, cudaFree is not called anymore. This was implicitly synchronizing the context for the user. Adding explicit synchronization before the CUDA Fortran finalization sequence.
---
Full diff: https://github.com/llvm/llvm-project/pull/223058.diff
6 Files Affected:
- (added) flang/include/flang/Optimizer/Builder/Runtime/CUDA/Support.h (+27)
- (modified) flang/lib/Lower/Bridge.cpp (+5-1)
- (modified) flang/lib/Optimizer/Builder/CMakeLists.txt (+1)
- (added) flang/lib/Optimizer/Builder/Runtime/CUDA/Support.cpp (+33)
- (modified) flang/test/Lower/CUDA/cuda-return01.cuf (+1)
- (modified) flang/test/Lower/CUDA/cuda-return02.cuf (+3)
``````````diff
diff --git a/flang/include/flang/Optimizer/Builder/Runtime/CUDA/Support.h b/flang/include/flang/Optimizer/Builder/Runtime/CUDA/Support.h
new file mode 100644
index 0000000000000..c22b61b854017
--- /dev/null
+++ b/flang/include/flang/Optimizer/Builder/Runtime/CUDA/Support.h
@@ -0,0 +1,27 @@
+//===-- Support.h - CUDA support runtime functions --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_OPTIMIZER_BUILDER_RUNTIME_CUDA_SUPPORT_H_
+#define FORTRAN_OPTIMIZER_BUILDER_RUNTIME_CUDA_SUPPORT_H_
+
+namespace mlir {
+class Location;
+} // namespace mlir
+
+namespace fir {
+class FirOpBuilder;
+}
+
+namespace fir::runtime::cuda {
+
+/// Generate runtime call to synchronize the CUDA device.
+void getCUDADeviceSynchronize(fir::FirOpBuilder &builder, mlir::Location loc);
+
+} // namespace fir::runtime::cuda
+
+#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_CUDA_SUPPORT_H_
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 5ea1850669297..b6b8b03073ce3 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -39,6 +39,7 @@
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Builder/Runtime/Assign.h"
#include "flang/Optimizer/Builder/Runtime/CUDA/Descriptor.h"
+#include "flang/Optimizer/Builder/Runtime/CUDA/Support.h"
#include "flang/Optimizer/Builder/Runtime/Character.h"
#include "flang/Optimizer/Builder/Runtime/Derived.h"
#include "flang/Optimizer/Builder/Runtime/EnvironmentDefaults.h"
@@ -2005,7 +2006,10 @@ class FirConverter : public Fortran::lower::AbstractConverter {
mlir::Value active =
fir::runtime::cuda::genDeviceIsActive(*builder, loc);
builder->genIfThen(loc, active)
- .genThen([&]() { bridge.cudaCleanupCtx().finalizeAndKeep(); })
+ .genThen([&]() {
+ fir::runtime::cuda::getCUDADeviceSynchronize(*builder, loc);
+ bridge.cudaCleanupCtx().finalizeAndKeep();
+ })
.end();
}
bridge.fctCtx().finalizeAndKeep();
diff --git a/flang/lib/Optimizer/Builder/CMakeLists.txt b/flang/lib/Optimizer/Builder/CMakeLists.txt
index b77e21d40476c..190b16d659338 100644
--- a/flang/lib/Optimizer/Builder/CMakeLists.txt
+++ b/flang/lib/Optimizer/Builder/CMakeLists.txt
@@ -22,6 +22,7 @@ add_flang_library(FIRBuilder
Runtime/Character.cpp
Runtime/Command.cpp
Runtime/CUDA/Descriptor.cpp
+ Runtime/CUDA/Support.cpp
Runtime/Derived.cpp
Runtime/EnvironmentDefaults.cpp
Runtime/Exceptions.cpp
diff --git a/flang/lib/Optimizer/Builder/Runtime/CUDA/Support.cpp b/flang/lib/Optimizer/Builder/Runtime/CUDA/Support.cpp
new file mode 100644
index 0000000000000..4fc5fa8e3c090
--- /dev/null
+++ b/flang/lib/Optimizer/Builder/Runtime/CUDA/Support.cpp
@@ -0,0 +1,33 @@
+//===-- Support.cpp -- Lowering helper for CUDA runtime functions ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Optimizer/Builder/Runtime/CUDA/Support.h"
+#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
+
+using namespace fir::runtime::cuda;
+
+static constexpr llvm::StringRef kCudaDeviceSynchronizeName = "_QPcudadevicesynchronize";
+
+void fir::runtime::cuda::getCUDADeviceSynchronize(fir::FirOpBuilder &builder,
+ mlir::Location loc) {
+ mlir::func::FuncOp func = builder.getNamedFunction(kCudaDeviceSynchronizeName);
+ if (!func) {
+ mlir::FunctionType funcType = mlir::FunctionType::get(builder.getContext(), {}, {builder.getI32Type()});
+ func = builder.createFunction(loc, kCudaDeviceSynchronizeName, funcType);
+ func->setAttr(fir::getFortranProcedureFlagsAttrName(), fir::FortranProcedureFlagsEnumAttr::get(builder.getContext(), fir::FortranProcedureFlagsEnum::intrinsic));
+ func.setPrivate();
+ }
+ auto call = fir::CallOp::create(builder, loc, func, mlir::ValueRange{});
+ call.setProcedureAttrsAttr(fir::FortranProcedureFlagsEnumAttr::get(builder.getContext(), fir::FortranProcedureFlagsEnum::intrinsic));
+}
+
+
+// %1315 = fir.call @_QPcudadevicesynchronize() proc_attrs<intrinsic> fastmath<contract> : () -> i32
+
+// func.func private @_QPcudadevicesynchronize() -> i32 attributes {fir.proc_attrs = #fir.proc_attrs<intrinsic>}
diff --git a/flang/test/Lower/CUDA/cuda-return01.cuf b/flang/test/Lower/CUDA/cuda-return01.cuf
index 9ea5ce1538081..847a22cc18229 100644
--- a/flang/test/Lower/CUDA/cuda-return01.cuf
+++ b/flang/test/Lower/CUDA/cuda-return01.cuf
@@ -43,6 +43,7 @@ end
! CHECK: %[[PTR:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFEp"}
! CHECK: %[[ACTIVE:.*]] = fir.call @_FortranACUFDeviceIsActive() {{.*}} : () -> i1
! CHECK-NEXT: fir.if %[[ACTIVE]] {
+! CHECK-NEXT: fir.call @_QPcudadevicesynchronize()
! CHECK-NEXT: cuf.free %[[PTR]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>{{.*}}
! CHECK: cuf.deallocate
! CHECK: cuf.free{{.*}}
diff --git a/flang/test/Lower/CUDA/cuda-return02.cuf b/flang/test/Lower/CUDA/cuda-return02.cuf
index b45635c219202..aa82cd5039cb2 100644
--- a/flang/test/Lower/CUDA/cuda-return02.cuf
+++ b/flang/test/Lower/CUDA/cuda-return02.cuf
@@ -19,12 +19,14 @@ end
! CHECK-NEXT: ^bb1:
! CHECK-NEXT: %[[ACTIVE1:.*]] = fir.call @_FortranACUFDeviceIsActive()
! CHECK-NEXT: fir.if %[[ACTIVE1]] {
+! CHECK-NEXT: fir.call @_QPcudadevicesynchronize() proc_attrs<intrinsic> fastmath<contract> : () -> i32
! CHECK-NEXT: cuf.free %[[DECL]]#0 : !fir.ref<!fir.array<10xi32>>{{.*}}
! CHECK-NEXT: }
! CHECK-NEXT: return
! CHECK-NEXT: ^bb2:
! CHECK-NEXT: %[[ACTIVE2:.*]] = fir.call @_FortranACUFDeviceIsActive()
! CHECK-NEXT: fir.if %[[ACTIVE2]] {
+! CHECK-NEXT: fir.call @_QPcudadevicesynchronize() proc_attrs<intrinsic> fastmath<contract> : () -> i32
! CHECK-NEXT: cuf.free %[[DECL]]#0 : !fir.ref<!fir.array<10xi32>>{{.*}}
! CHECK-NEXT: }
! CHECK-NEXT: return
@@ -52,6 +54,7 @@ end
! CHECK: ^bb3:
! CHECK-NEXT: %[[SUB_ACTIVE:.*]] = fir.call @_FortranACUFDeviceIsActive()
! CHECK-NEXT: fir.if %[[SUB_ACTIVE]] {
+! CHECK-NEXT: fir.call @_QPcudadevicesynchronize() proc_attrs<intrinsic> fastmath<contract> : () -> i32
! CHECK-NEXT: cuf.free %[[DECL]]#0 : !fir.ref<!fir.array<10xi32>>{{.*}}
! CHECK-NEXT: }
! CHECK-NEXT: return
``````````
</details>
https://github.com/llvm/llvm-project/pull/223058
More information about the flang-commits
mailing list