[flang] [llvm] [mlir] [OpenMPIRBuilder] Don't drop debug info for target region. (PR #80692)

via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 7 08:20:01 PST 2024


https://github.com/abidh updated https://github.com/llvm/llvm-project/pull/80692

>From 116741bde587b001e2e2a456cb9e14b08db3a538 Mon Sep 17 00:00:00 2001
From: Abid Qadeer <haqadeer at amd.com>
Date: Fri, 2 Feb 2024 12:16:52 -0600
Subject: [PATCH 1/3] [OpenMPIRBuilder] Don't drop debug info for target
 region.

When an outlined function is generated for omp target region,
a corresponding DISubprogram was not being generated. This resulted in
all the debug information for the target region being dropped.

This commit adds DISubprogram for the outlined function if there is one
available for the parent function. It also updates the current debug
location so that the right scope is used for the entries in the outlined
function.

With this change in place, I can set source line breakpoint in target
region and run to them in debugger.
---
 flang/test/Lower/OpenMP/target-debug.f90      | 18 ++++++++++
 llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp     | 36 +++++++++++++++++--
 .../Frontend/OpenMPIRBuilderTest.cpp          |  4 +++
 3 files changed, 56 insertions(+), 2 deletions(-)
 create mode 100644 flang/test/Lower/OpenMP/target-debug.f90

diff --git a/flang/test/Lower/OpenMP/target-debug.f90 b/flang/test/Lower/OpenMP/target-debug.f90
new file mode 100644
index 00000000000000..c9843eba391d7c
--- /dev/null
+++ b/flang/test/Lower/OpenMP/target-debug.f90
@@ -0,0 +1,18 @@
+!RUN: %flang_fc1 -triple amdgcn-amd-amdhsa %s -debug-info-kind=line-tables-only -fopenmp -fopenmp-is-target-device -emit-llvm -o - | FileCheck %s
+program test
+implicit none
+
+  integer(kind = 4) :: a, b, c, d
+
+  !$omp target map(tofrom: a, b, c, d)
+  a = a + 1
+  ! CHECK: !DILocation(line: [[@LINE-1]]
+  b = a + 2
+  ! CHECK: !DILocation(line: [[@LINE-1]]
+  c = a + 3
+  ! CHECK: !DILocation(line: [[@LINE-1]]
+  d = a + 4
+  ! CHECK: !DILocation(line: [[@LINE-1]]
+  !$omp end target
+
+end program test
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 02b333e9ccd567..f0f26c5b8d8b7b 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -31,6 +31,7 @@
 #include "llvm/IR/CallingConv.h"
 #include "llvm/IR/Constant.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Function.h"
@@ -5025,10 +5026,41 @@ static Function *createOutlinedFunction(
       ParameterTypes.push_back(Arg->getType());
   }
 
+  auto BB = Builder.GetInsertBlock();
+  auto M = BB->getModule();
   auto FuncType = FunctionType::get(Builder.getVoidTy(), ParameterTypes,
                                     /*isVarArg*/ false);
-  auto Func = Function::Create(FuncType, GlobalValue::InternalLinkage, FuncName,
-                               Builder.GetInsertBlock()->getModule());
+  auto Func =
+      Function::Create(FuncType, GlobalValue::InternalLinkage, FuncName, M);
+
+  // If there's a DISubprogram associated with current function, then
+  // generate one for the outlined function.
+  if (Function *parentFunc = BB->getParent()) {
+    if (DISubprogram *SP = parentFunc->getSubprogram()) {
+      DICompileUnit *CU = SP->getUnit();
+      DIBuilder DB(*M, true, CU);
+      DebugLoc DL = Builder.getCurrentDebugLocation();
+      // TODO: We are using nullopt for arguments at the moment. This will need
+      // to be updated when debug data is being generated for variables.
+      DISubroutineType *Ty =
+          DB.createSubroutineType(DB.getOrCreateTypeArray(std::nullopt));
+      DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagDefinition |
+                                        DISubprogram::SPFlagOptimized |
+                                        DISubprogram::SPFlagLocalToUnit;
+
+      DISubprogram *OutlinedSP = DB.createFunction(
+          CU, FuncName, FuncName, SP->getFile(), DL.getLine(), Ty, DL.getLine(),
+          DINode::DIFlags::FlagArtificial, SPFlags);
+
+      // Attach subprogram to the function.
+      Func->setSubprogram(OutlinedSP);
+      // Update the CurrentDebugLocation in the builder so that right scope
+      // is used for things inside outlined function.
+      Builder.SetCurrentDebugLocation(
+          DILocation::get(Func->getContext(), DL.getLine(), DL.getCol(),
+                          OutlinedSP, DL.getInlinedAt()));
+    }
+  }
 
   // Save insert point.
   auto OldInsertPoint = Builder.saveIP();
diff --git a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
index e79d0bb2f65aea..c5b5d12840c4de 100644
--- a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
+++ b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
@@ -5827,6 +5827,10 @@ TEST_F(OpenMPIRBuilderTest, TargetRegion) {
   BasicBlock *FallbackBlock = Branch->getSuccessor(0);
   Iter = FallbackBlock->rbegin();
   CallInst *FCall = dyn_cast<CallInst>(&*(++Iter));
+  // 'F' has a dummy DISubprogram which causes OutlinedFunc to also
+  // have a DISubprogram. In this case, the call to OutlinedFunc needs
+  // to have a debug loc, otherwise verifier will complain.
+  FCall->setDebugLoc(DL);
   EXPECT_NE(FCall, nullptr);
 
   // Check that the correct aguments are passed in

>From 746a12cc7f57b85cbc8c9976ac4cb4674d7f858e Mon Sep 17 00:00:00 2001
From: Abid Qadeer <haqadeer at amd.com>
Date: Wed, 7 Feb 2024 10:07:11 -0600
Subject: [PATCH 2/3] Move the test into MLIR.

The original f90 ->llvmir test has been removed.
 I have added an MLIR -> llvmir test as per review comments.
---
 flang/test/Lower/OpenMP/target-debug.f90     | 18 -----
 mlir/test/Target/LLVMIR/omptarget-debug.mlir | 72 ++++++++++++++++++++
 2 files changed, 72 insertions(+), 18 deletions(-)
 delete mode 100644 flang/test/Lower/OpenMP/target-debug.f90
 create mode 100644 mlir/test/Target/LLVMIR/omptarget-debug.mlir

diff --git a/flang/test/Lower/OpenMP/target-debug.f90 b/flang/test/Lower/OpenMP/target-debug.f90
deleted file mode 100644
index c9843eba391d7c..00000000000000
--- a/flang/test/Lower/OpenMP/target-debug.f90
+++ /dev/null
@@ -1,18 +0,0 @@
-!RUN: %flang_fc1 -triple amdgcn-amd-amdhsa %s -debug-info-kind=line-tables-only -fopenmp -fopenmp-is-target-device -emit-llvm -o - | FileCheck %s
-program test
-implicit none
-
-  integer(kind = 4) :: a, b, c, d
-
-  !$omp target map(tofrom: a, b, c, d)
-  a = a + 1
-  ! CHECK: !DILocation(line: [[@LINE-1]]
-  b = a + 2
-  ! CHECK: !DILocation(line: [[@LINE-1]]
-  c = a + 3
-  ! CHECK: !DILocation(line: [[@LINE-1]]
-  d = a + 4
-  ! CHECK: !DILocation(line: [[@LINE-1]]
-  !$omp end target
-
-end program test
diff --git a/mlir/test/Target/LLVMIR/omptarget-debug.mlir b/mlir/test/Target/LLVMIR/omptarget-debug.mlir
new file mode 100644
index 00000000000000..4d061eb25082be
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/omptarget-debug.mlir
@@ -0,0 +1,72 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+module attributes {omp.is_target_device = true} {
+  llvm.func @_QQmain() {
+    %0 = llvm.mlir.constant(1 : i64) : i64
+    %1 = llvm.alloca %0 x i32 : (i64) -> !llvm.ptr<5>
+    %2 = llvm.addrspacecast %1 : !llvm.ptr<5> to !llvm.ptr
+    %3 = llvm.mlir.constant(1 : i64) : i64
+    %4 = llvm.alloca %3 x i32 : (i64) -> !llvm.ptr<5>
+    %5 = llvm.addrspacecast %4 : !llvm.ptr<5> to !llvm.ptr
+    %6 = llvm.mlir.constant(1 : i64) : i64
+    %7 = llvm.alloca %6 x i32 : (i64) -> !llvm.ptr<5>
+    %8 = llvm.addrspacecast %7 : !llvm.ptr<5> to !llvm.ptr
+    %9 = omp.map_info var_ptr(%2 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
+    %10 = omp.map_info var_ptr(%5 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
+    omp.target map_entries(%9 -> %arg0, %10 -> %arg1 : !llvm.ptr, !llvm.ptr) {
+    ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+      %12 = llvm.mlir.constant(2 : i32) : i32
+      %13 = llvm.mlir.constant(1 : i32) : i32
+      %14 = llvm.load %arg0 : !llvm.ptr -> i32 loc(#loc2)
+      %15 = llvm.add %14, %13  : i32 loc(#loc2)
+      llvm.store %15, %arg0 : i32, !llvm.ptr loc(#loc2)
+      %16 = llvm.load %arg0 : !llvm.ptr -> i32 loc(#loc3)
+      %17 = llvm.add %16, %12  : i32 loc(#loc3)
+      llvm.store %17, %arg1 : i32, !llvm.ptr loc(#loc3)
+      omp.terminator
+    }
+    %11 = omp.map_info var_ptr(%8 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
+    omp.target map_entries(%11 -> %arg0 : !llvm.ptr) {
+    ^bb0(%arg0: !llvm.ptr):
+      %12 = llvm.mlir.constant(1 : i32) : i32
+      omp.parallel {
+        %13 = llvm.load %arg0 : !llvm.ptr -> i32 loc(#loc4)
+        %14 = llvm.add %13, %12  : i32 loc(#loc4)
+        llvm.store %14, %arg0 : i32, !llvm.ptr loc(#loc4)
+        omp.terminator
+      }
+      omp.terminator
+    }
+    llvm.return
+  } loc(#loc5)
+} loc(#loc)
+#di_basic_type = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "void", encoding = DW_ATE_address>
+#di_file = #llvm.di_file<"target.f90" in "">
+#loc = loc("target.f90":0:0)
+#loc1 = loc("target.f90":1:1)
+#loc2 = loc("target.f90":9:3)
+#loc3 = loc("target.f90":10:3)
+#loc4 = loc("target.f90":14:3)
+#di_compile_unit = #llvm.di_compile_unit<id = distinct[0]<>, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "Flang", isOptimized = false, emissionKind = LineTablesOnly>
+#di_subroutine_type = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, types = #di_basic_type, #di_basic_type>
+#di_subprogram = #llvm.di_subprogram<id = distinct[1]<>, compileUnit = #di_compile_unit, scope = #di_file, name = "_QQmain", linkageName = "_QQmain", file = #di_file, line = 1, scopeLine = 1, subprogramFlags = "Definition|Optimized", type = #di_subroutine_type>
+#loc5 = loc(fused<#di_subprogram>[#loc1])
+
+// 8:  !$omp target map(tofrom: a, b)
+// 9:  a = a + 1
+//10:  b = a + 2
+//11:  !$omp end target
+
+//13:  !$omp target parallel map(tofrom: a, b)
+//14:  c = c + 1
+//15:  !$omp end target parallel
+
+// CHECK-DAG: [[FILE:.*]] = !DIFile(filename: "target.f90", directory: "")
+// CHECK-DAG: [[CU:.*]] = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: [[FILE]], {{.*}})
+
+// CHECK: [[SP1:.*]] = distinct !DISubprogram(name: "__omp_offloading_{{.*}}", {{.*}}, unit: [[CU]])
+// CHECK-DAG: !DILocation(line: 9, column: 3, scope: [[SP1]])
+// CHECK-DAG: !DILocation(line: 10, column: 3, scope: [[SP1]])
+
+// CHECK: [[SP2:.*]] = distinct !DISubprogram(name: "__omp_offloading_{{.*}}omp_par", {{.*}}, unit: [[CU]])
+// CHECK: !DILocation(line: 14, column: 3, scope: [[SP2]])

>From a989a442d2e5f830f5ab30efc63253dcc6ec1b40 Mon Sep 17 00:00:00 2001
From: Abid Qadeer <haqadeer at amd.com>
Date: Wed, 7 Feb 2024 10:08:08 -0600
Subject: [PATCH 3/3] Correct the case on variable name.

---
 llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index f0f26c5b8d8b7b..2002de2e54fc64 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -5035,8 +5035,8 @@ static Function *createOutlinedFunction(
 
   // If there's a DISubprogram associated with current function, then
   // generate one for the outlined function.
-  if (Function *parentFunc = BB->getParent()) {
-    if (DISubprogram *SP = parentFunc->getSubprogram()) {
+  if (Function *ParentFunc = BB->getParent()) {
+    if (DISubprogram *SP = ParentFunc->getSubprogram()) {
       DICompileUnit *CU = SP->getUnit();
       DIBuilder DB(*M, true, CU);
       DebugLoc DL = Builder.getCurrentDebugLocation();



More information about the llvm-commits mailing list