[llvm] [mlir] [OpenMP][MLIR][OMPIRBuilder] Add a small optional constant alloca raise function pass to finalize, utilised in convertTarget (PR #78818)

via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 19 07:18:46 PST 2024


================
@@ -0,0 +1,43 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// A small condensed version of a problem requiring constant alloca raising in
+// Target Region Entries for user injected code, found in an issue in the Flang
+// compiler. Certain LLVM IR optimisation passes will perform runtime breaking 
+// transformations on allocations not found to be in the entry block, current
+// OpenMP dialect lowering of TargetOp's will inject user allocations after
+// compiler generated entry code, in a seperate block, this test checks that
+// a small function which attempts to raise some of these (specifically 
+// constant sized) allocations performs its task reasonably in these 
+// scenarios. 
+
+module attributes {omp.is_target_device = true} {
+  llvm.func @_QQmain() attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>} {
+    %1 = llvm.mlir.constant(1 : i64) : i64
+    %2 = llvm.alloca %1 x !llvm.struct<(ptr)> : (i64) -> !llvm.ptr
+    %3 = omp.map_info var_ptr(%2 : !llvm.ptr, !llvm.struct<(ptr)>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr
+    omp.target map_entries(%3 -> %arg0 : !llvm.ptr) {
+    ^bb0(%arg0: !llvm.ptr):
+      %4 = llvm.mlir.constant(1 : i32) : i32
+      %5 = llvm.alloca %4 x !llvm.struct<(ptr)> {alignment = 8 : i64} : (i32) -> !llvm.ptr
+      %6 = llvm.mlir.constant(50 : i32) : i32
+      %7 = llvm.mlir.constant(1 : i64) : i64
+      %8 = llvm.alloca %7 x i32 : (i64) -> !llvm.ptr
+      llvm.store %6, %8 : i32, !llvm.ptr
+      %9 = llvm.mlir.undef : !llvm.struct<(ptr)>
+      %10 = llvm.insertvalue %8, %9[0] : !llvm.struct<(ptr)> 
+      llvm.store %10, %5 : !llvm.struct<(ptr)>, !llvm.ptr
+      %88 = llvm.call @_ExternalCall(%arg0, %5) : (!llvm.ptr, !llvm.ptr) -> !llvm.struct<()>
----------------
agozillon wrote:

> > From a Fortran perspective (as someone who is still very bad at writing Fortran) I am not sure a user can inject an alloca directly into the `TargetOp`, from my understanding you can only declare a variable at the top of a function or in a module. So you can't quite do what you can in C++ where as an example you declare an integer directly in the OpenMP target region which will become an alloca.
> 
> There is a block construct in Fortran 2008 that can be used for this.
> 

Thank you Kiran! I can give this a shot then (provided it currently works in a target region, not tested it myself directly, so I am a little interested in that). Sorry that my Fortran knowledge is rather lacking in areas and thank you for introducing me to new stuff! 

> Also we have passes that can convert to Allocs to Allocas.
> 
> https://github.com/llvm/llvm-project/blob/2d0137dd64017c34101f8a763fd8958c20acd6bb/flang/lib/Optimizer/Transforms/StackArrays.cpp#L187

I'll have a look into the pass, it could be quite useful in the future. I did notice it when I was looking around for other possible solutions and it caught my eye, but I wasn't quite sure if we needed to look into an extensive solution just yet. While I don't think the pass would solve the issue (perhaps I am incorrect with my thinking however), it would be a good basis to create a pass that might. 

However, I think if we wanted to do this pass at an MLIR level we'd have to enforce an entry block for Target regions, and I believe it may be unnecessary to be a pass at that point, during the lowering to LLVM Dialect I think we try to move all allocas into the Target (or any) entry block, and if we make sure we have or generate an explicit entry block at this point, I think all allocas should hopefully end up naturally in the entry block where it's possible at least.

https://github.com/llvm/llvm-project/pull/78818


More information about the llvm-commits mailing list