[llvm] [Analysis] Improve KernelInfo debug location handling for compiler-generated code (PR #145603)

Miguel Cárdenas via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 24 14:50:49 PDT 2025


https://github.com/miguelcsx created https://github.com/llvm/llvm-project/pull/145603

## Problem

The KernelInfo analysis pass was emitting optimization remarks with `<unknown>:0:0` source locations for compiler-generated intrinsic calls, particularly those generated during OpenMP target offloading. This made it difficult for users to understand which part of their source code these remarks related to.

For example, intrinsics like:
- `@llvm.nvvm.read.ptx.sreg.tid.x` 
- `@llvm.nvvm.read.ptx.sreg.ntid.x`
- `@llvm.nvvm.barrier.cta.sync.aligned.all`

Would show up as:

![image](https://github.com/user-attachments/assets/a93e0f59-9763-4cbb-bf67-0f3d3b1c5b57)


## Solution

This PR introduces a fallback mechanism that:

• **Preserves existing behavior** for instructions that already have debug locations
• **Falls back to function debug info** when instruction debug info is missing  

The fix ensures that instead of `<unknown>:0:0`, users see meaningful source locations derived from the containing function's debug information.

## Changes

• Add `getRemarkLocation()` helper function for centralized location resolution
• Update `remarkCall()`, `remarkFlatAddrspaceAccess()`, `remarkAlloca()`, and `remarkProperty()` to use improved location handling
• Maintain backward compatibility for all existing functionality

## Testing

Tested with OpenMP target offloading code that previously showed unknown locations. The remarks now properly show function-level source locations instead of `<unknown>:0:0`.

>From c1b0977d0ba3d80b5d5e896307a98a816f4efcd7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miguel=20C=C3=A1rdenas?= <miguelecsx at gmail.com>
Date: Tue, 24 Jun 2025 23:24:40 +0200
Subject: [PATCH] [analysis] fix unknown source locations in KernelInfo

The fix provides meaningful source locations by falling back to the
containing function's subprogram information instead of showing unknown
locations.
---
 llvm/lib/Analysis/KernelInfo.cpp | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Analysis/KernelInfo.cpp b/llvm/lib/Analysis/KernelInfo.cpp
index 93dd7cecb32e1..33a84452d1527 100644
--- a/llvm/lib/Analysis/KernelInfo.cpp
+++ b/llvm/lib/Analysis/KernelInfo.cpp
@@ -77,6 +77,14 @@ class KernelInfo {
 
 } // end anonymous namespace
 
+static DiagnosticLocation getRemarkLocation(const Instruction &I) {
+  if (DebugLoc DL = I.getDebugLoc())
+    return DiagnosticLocation(DL);
+  if (auto *SP = I.getFunction()->getSubprogram())
+    return DiagnosticLocation(SP);
+  return DiagnosticLocation();
+}
+
 static void identifyCallee(OptimizationRemark &R, const Module *M,
                            const Value *V, StringRef Kind = "") {
   SmallString<100> Name; // might be function name or asm expression
@@ -105,16 +113,19 @@ static void remarkAlloca(OptimizationRemarkEmitter &ORE, const Function &Caller,
                          TypeSize::ScalarTy StaticSize) {
   ORE.emit([&] {
     StringRef DbgName;
-    DebugLoc Loc;
+    DebugLoc DL;
     bool Artificial = false;
     auto DVRs = findDVRDeclares(&const_cast<AllocaInst &>(Alloca));
     if (!DVRs.empty()) {
       const DbgVariableRecord &DVR = **DVRs.begin();
       DbgName = DVR.getVariable()->getName();
-      Loc = DVR.getDebugLoc();
+      DL = DVR.getDebugLoc();
       Artificial = DVR.Variable->isArtificial();
     }
-    OptimizationRemark R(DEBUG_TYPE, "Alloca", DiagnosticLocation(Loc),
+
+    OptimizationRemark R(DEBUG_TYPE, "Alloca",
+                         DL ? DiagnosticLocation(DL)
+                            : getRemarkLocation(Alloca),
                          Alloca.getParent());
     R << "in ";
     identifyFunction(R, Caller);
@@ -142,7 +153,8 @@ static void remarkCall(OptimizationRemarkEmitter &ORE, const Function &Caller,
                        const CallBase &Call, StringRef CallKind,
                        StringRef RemarkKind) {
   ORE.emit([&] {
-    OptimizationRemark R(DEBUG_TYPE, RemarkKind, &Call);
+    OptimizationRemark R(DEBUG_TYPE, RemarkKind, getRemarkLocation(Call),
+                         Call.getParent());
     R << "in ";
     identifyFunction(R, Caller);
     R << ", " << CallKind << ", callee is ";
@@ -155,7 +167,8 @@ static void remarkFlatAddrspaceAccess(OptimizationRemarkEmitter &ORE,
                                       const Function &Caller,
                                       const Instruction &Inst) {
   ORE.emit([&] {
-    OptimizationRemark R(DEBUG_TYPE, "FlatAddrspaceAccess", &Inst);
+    OptimizationRemark R(DEBUG_TYPE, "FlatAddrspaceAccess",
+                         getRemarkLocation(Inst), Inst.getParent());
     R << "in ";
     identifyFunction(R, Caller);
     if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(&Inst)) {
@@ -265,7 +278,11 @@ void KernelInfo::updateForBB(const BasicBlock &BB,
 static void remarkProperty(OptimizationRemarkEmitter &ORE, const Function &F,
                            StringRef Name, int64_t Value) {
   ORE.emit([&] {
-    OptimizationRemark R(DEBUG_TYPE, Name, &F);
+    DiagnosticLocation DL = F.getSubprogram()
+                                ? DiagnosticLocation(F.getSubprogram())
+                                : DiagnosticLocation();
+    OptimizationRemark R(DEBUG_TYPE, Name, DL,
+                         !F.empty() ? &F.front() : nullptr);
     R << "in ";
     identifyFunction(R, F);
     R << ", " << Name << " = " << itostr(Value);



More information about the llvm-commits mailing list