[flang-commits] [flang] [flang][cuda] Rewrite predefined variable in acc.parallel with inlined cuf function (PR #206205)
Valentin Clement バレンタイン クレメン via flang-commits
flang-commits at lists.llvm.org
Fri Jun 26 21:22:24 PDT 2026
https://github.com/clementval updated https://github.com/llvm/llvm-project/pull/206205
>From 6112ee122d8a0a4ba901d2b9b9fd37393929e6e8 Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Fri, 26 Jun 2026 16:08:00 -0700
Subject: [PATCH 1/2] [flang][cuda] Rewrite predefined variable in acc.parallel
with inlined cuf function
---
.../Transforms/CUDA/CUFPredefinedVarToGPU.cpp | 8 +-
flang/test/Fir/CUDA/predefined-variables.mlir | 100 ++++++++++++++++++
2 files changed, 106 insertions(+), 2 deletions(-)
diff --git a/flang/lib/Optimizer/Transforms/CUDA/CUFPredefinedVarToGPU.cpp b/flang/lib/Optimizer/Transforms/CUDA/CUFPredefinedVarToGPU.cpp
index 2dd332488269d..5a2fae4ab0756 100644
--- a/flang/lib/Optimizer/Transforms/CUDA/CUFPredefinedVarToGPU.cpp
+++ b/flang/lib/Optimizer/Transforms/CUDA/CUFPredefinedVarToGPU.cpp
@@ -10,6 +10,7 @@
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
#include "mlir/Dialect/LLVMIR/NVVMDialect.h"
+#include "mlir/Dialect/OpenACC/OpenACC.h"
#include "mlir/Pass/Pass.h"
namespace fir {
@@ -171,11 +172,14 @@ struct CUFPredefinedVarToGPU
if (rewrittenWholeFunction)
return;
- // Host functions containing cuf.kernel regions can still carry predefined
- // vars in the kernel body. Rewrite them in-place as well.
+ // Host functions containing cuf.kernel or acc.parallel regions can still
+ // carry predefined vars in the kernel body. Rewrite them in-place as well.
funcOp.walk([&](cuf::KernelOp kernelOp) {
rewritePredefinedVars(kernelOp.getRegion(), kernelOp.getLoc());
});
+ funcOp.walk([&](mlir::acc::ParallelOp parallelOp) {
+ rewritePredefinedVars(parallelOp.getRegion(), parallelOp.getLoc());
+ });
}
};
diff --git a/flang/test/Fir/CUDA/predefined-variables.mlir b/flang/test/Fir/CUDA/predefined-variables.mlir
index 50f269e4c65db..ce9ec0a62855a 100644
--- a/flang/test/Fir/CUDA/predefined-variables.mlir
+++ b/flang/test/Fir/CUDA/predefined-variables.mlir
@@ -318,3 +318,103 @@ func.func @surviving_predefined_vars(%arg0: i32, %arg1: i32, %arg2: i32) {
// CHECK-NOT: _QM__fortran_builtinsE__builtin_griddim
// CHECK-NOT: _QM__fortran_builtinsE__builtin_threadidx
// CHECK: nvvm.read.ptx.sreg.tid.x
+
+// -----
+
+func.func @_QMoutermodPouter(%arg0: !fir.ref<!fir.array<?x?xf64>> {fir.bindc_name = "a"}, %arg1: !fir.ref<!fir.array<?x?xf64>> {fir.bindc_name = "b"}, %arg2: i32 {fir.bindc_name = "stride"}, %arg3: i32 {fir.bindc_name = "n"}) attributes {no_inline} {
+ %c1 = arith.constant 1 : index
+ %cst = arith.constant 2.000000e+00 : f64
+ %c1_i32 = arith.constant 1 : i32
+ %c0 = arith.constant 0 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.alloca i32
+ fir.store %arg2 to %1 : !fir.ref<i32>
+ %2 = fir.declare %1 dummy_scope %0 arg 3 {fortran_attrs = #fir.var_attrs<intent_in, value>, uniq_name = "_QMoutermodFouterEstride"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+ %3 = fir.alloca i32
+ fir.store %arg3 to %3 : !fir.ref<i32>
+ %4 = fir.declare %3 dummy_scope %0 arg 4 {fortran_attrs = #fir.var_attrs<intent_in, value>, uniq_name = "_QMoutermodFouterEn"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+ %5 = fir.alloca i32 {bindc_name = "j", uniq_name = "_QMoutermodFouterEj"}
+ %6 = fir.declare %5 {uniq_name = "_QMoutermodFouterEj"} : (!fir.ref<i32>) -> !fir.ref<i32>
+ %7 = fir.load %2 : !fir.ref<i32>
+ %8 = fir.convert %7 : (i32) -> index
+ %9 = arith.maxsi %8, %c0 : index
+ %10 = fir.load %4 : !fir.ref<i32>
+ %11 = fir.convert %10 : (i32) -> index
+ %12 = arith.maxsi %11, %c0 : index
+ %13 = fir.shape %9, %12 : (index, index) -> !fir.shape<2>
+ %14 = fir.declare %arg0(%13) dummy_scope %0 arg 1 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QMoutermodFouterEa"} : (!fir.ref<!fir.array<?x?xf64>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<?x?xf64>>
+ %15 = fir.embox %14(%13) : (!fir.ref<!fir.array<?x?xf64>>, !fir.shape<2>) -> !fir.box<!fir.array<?x?xf64>>
+ %16 = fir.declare %arg1(%13) dummy_scope %0 arg 2 {fortran_attrs = #fir.var_attrs<intent_out>, uniq_name = "_QMoutermodFouterEb"} : (!fir.ref<!fir.array<?x?xf64>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<?x?xf64>>
+ %17 = fir.embox %16(%13) : (!fir.ref<!fir.array<?x?xf64>>, !fir.shape<2>) -> !fir.box<!fir.array<?x?xf64>>
+ %18 = acc.present var(%15 : !fir.box<!fir.array<?x?xf64>>) -> !fir.box<!fir.array<?x?xf64>> {name = "a"}
+ %19 = acc.present var(%17 : !fir.box<!fir.array<?x?xf64>>) -> !fir.box<!fir.array<?x?xf64>> {name = "b"}
+ acc.parallel combined(loop) dataOperands(%18, %19 : !fir.box<!fir.array<?x?xf64>>, !fir.box<!fir.array<?x?xf64>>) {
+ %20 = fir.box_addr %18 : (!fir.box<!fir.array<?x?xf64>>) -> !fir.ref<!fir.array<?x?xf64>>
+ %21 = fir.dummy_scope : !fir.dscope
+ %22 = fir.declare %20(%13) dummy_scope %21 arg 1 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QMoutermodFouterEa"} : (!fir.ref<!fir.array<?x?xf64>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<?x?xf64>>
+ %23 = fir.box_addr %19 : (!fir.box<!fir.array<?x?xf64>>) -> !fir.ref<!fir.array<?x?xf64>>
+ %24 = fir.declare %23(%13) dummy_scope %21 arg 2 {fortran_attrs = #fir.var_attrs<intent_out>, uniq_name = "_QMoutermodFouterEb"} : (!fir.ref<!fir.array<?x?xf64>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<?x?xf64>>
+ %25 = fir.load %4 : !fir.ref<i32>
+ %26 = acc.private varPtr(%6 : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "j"}
+ %27 = fir.load %2 : !fir.ref<i32>
+ %28 = fir.address_of(@_QM__fortran_builtinsE__builtin_blockdim) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>
+ %29 = fir.address_of(@_QM__fortran_builtinsE__builtin_blockidx) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>
+ %30 = fir.address_of(@_QM__fortran_builtinsE__builtin_griddim) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>
+ %31 = fir.address_of(@_QM__fortran_builtinsE__builtin_threadidx) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>
+ %32 = fir.assumed_size_extent : index
+ %33 = fir.convert %c1 : (index) -> i32
+ acc.loop combined(parallel) gang vector private(%26 : !fir.ref<i32>) control(%arg4 : i32) = (%c1_i32 : i32) to (%25 : i32) step (%c1_i32 : i32) {
+ %34 = fir.alloca i32
+ %35 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QMoutermodFinner_loopEi"}
+ %36 = fir.alloca i32
+ %37 = fir.alloca i32 {bindc_name = "warpsize", uniq_name = "_QMcudadeviceECwarpsize"}
+ %38 = fir.declare %26 {uniq_name = "_QMoutermodFouterEj"} : (!fir.ref<i32>) -> !fir.ref<i32>
+ fir.store %arg4 to %38 : !fir.ref<i32>
+ %39 = fir.load %38 : !fir.ref<i32>
+ %40 = fir.dummy_scope : !fir.dscope
+ fir.store %27 to %34 : !fir.ref<i32>
+ %41 = fir.declare %34 dummy_scope %40 arg 3 {fortran_attrs = #fir.var_attrs<intent_in, value>, uniq_name = "_QMoutermodFinner_loopEstride"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+ %42 = fir.declare %28 {uniq_name = "_QM__fortran_builtinsE__builtin_blockdim"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>
+ %43 = fir.declare %29 {uniq_name = "_QM__fortran_builtinsE__builtin_blockidx"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>
+ %44 = fir.declare %30 {uniq_name = "_QM__fortran_builtinsE__builtin_griddim"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>
+ %45 = fir.declare %35 {uniq_name = "_QMoutermodFinner_loopEi"} : (!fir.ref<i32>) -> !fir.ref<i32>
+ fir.store %39 to %36 : !fir.ref<i32>
+ %46 = fir.declare %36 dummy_scope %40 arg 4 {fortran_attrs = #fir.var_attrs<intent_in, value>, uniq_name = "_QMoutermodFinner_loopEj"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+ %47 = fir.declare %31 {uniq_name = "_QM__fortran_builtinsE__builtin_threadidx"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>
+ %48 = fir.declare %37 {uniq_name = "_QMcudadeviceECwarpsize"} : (!fir.ref<i32>) -> !fir.ref<i32>
+ %49 = fir.load %41 : !fir.ref<i32>
+ %50 = fir.convert %49 : (i32) -> index
+ %51 = arith.maxsi %50, %c0 : index
+ %52 = fir.shape %51, %32 : (index, index) -> !fir.shape<2>
+ %53 = fir.declare %22(%52) dummy_scope %40 arg 1 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QMoutermodFinner_loopEa"} : (!fir.ref<!fir.array<?x?xf64>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<?x?xf64>>
+ %54 = fir.declare %24(%52) dummy_scope %40 arg 2 {fortran_attrs = #fir.var_attrs<intent_out>, uniq_name = "_QMoutermodFinner_loopEb"} : (!fir.ref<!fir.array<?x?xf64>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<?x?xf64>>
+ %55 = fir.load %46 : !fir.ref<i32>
+ %56 = fir.convert %55 : (i32) -> i64
+ %57 = fir.do_loop %arg5 = %c1 to %50 step %c1 iter_args(%arg6 = %33) -> (i32) {
+ fir.store %arg6 to %45 : !fir.ref<i32>
+ %58 = fir.load %45 : !fir.ref<i32>
+ %59 = fir.convert %58 : (i32) -> i64
+ %60 = fir.array_coor %53(%52) %59, %56 : (!fir.ref<!fir.array<?x?xf64>>, !fir.shape<2>, i64, i64) -> !fir.ref<f64>
+ %61 = fir.load %60 : !fir.ref<f64>
+ %62 = arith.mulf %61, %cst fastmath<reassoc,contract> : f64
+ %63 = fir.array_coor %54(%52) %59, %56 : (!fir.ref<!fir.array<?x?xf64>>, !fir.shape<2>, i64, i64) -> !fir.ref<f64>
+ fir.store %62 to %63 : !fir.ref<f64>
+ %64 = fir.load %45 : !fir.ref<i32>
+ %65 = arith.addi %64, %33 overflow<nsw> : i32
+ fir.result %65 : i32
+ }
+ fir.store %57 to %45 : !fir.ref<i32>
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]}
+ acc.yield
+ }
+ acc.delete accVar(%18 : !fir.box<!fir.array<?x?xf64>>) {dataClause = #acc<data_clause acc_present>, name = "a"}
+ acc.delete accVar(%19 : !fir.box<!fir.array<?x?xf64>>) {dataClause = #acc<data_clause acc_present>, name = "b"}
+ return
+}
+
+// CHECK-LABEL: _QMoutermodPouter
+// CHECK-NOT: _QM__fortran_builtinsE__builtin_blockdim
+// CHECK-NOT: _QM__fortran_builtinsE__builtin_blockidx
+// CHECK-NOT: _QM__fortran_builtinsE__builtin_griddim
+// CHECK-NOT: _QM__fortran_builtinsE__builtin_threadidx
>From f944a486e2ed2ebb9312c3b1e4b403c949a295fc Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Fri, 26 Jun 2026 21:22:01 -0700
Subject: [PATCH 2/2] Support acc compute construct
---
.../Optimizer/Transforms/CUDA/CUFPredefinedVarToGPU.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/flang/lib/Optimizer/Transforms/CUDA/CUFPredefinedVarToGPU.cpp b/flang/lib/Optimizer/Transforms/CUDA/CUFPredefinedVarToGPU.cpp
index 5a2fae4ab0756..699f0a7b33a6f 100644
--- a/flang/lib/Optimizer/Transforms/CUDA/CUFPredefinedVarToGPU.cpp
+++ b/flang/lib/Optimizer/Transforms/CUDA/CUFPredefinedVarToGPU.cpp
@@ -172,13 +172,13 @@ struct CUFPredefinedVarToGPU
if (rewrittenWholeFunction)
return;
- // Host functions containing cuf.kernel or acc.parallel regions can still
- // carry predefined vars in the kernel body. Rewrite them in-place as well.
+ // Host functions containing cuf.kernel or OpenACC compute regions can
+ // still carry predefined vars in the kernel body. Rewrite them in-place.
funcOp.walk([&](cuf::KernelOp kernelOp) {
rewritePredefinedVars(kernelOp.getRegion(), kernelOp.getLoc());
});
- funcOp.walk([&](mlir::acc::ParallelOp parallelOp) {
- rewritePredefinedVars(parallelOp.getRegion(), parallelOp.getLoc());
+ funcOp.walk([&](mlir::acc::ComputeRegionOpInterface computeOp) {
+ rewritePredefinedVars(computeOp->getRegion(0), computeOp->getLoc());
});
}
};
More information about the flang-commits
mailing list