[clang] [llvm] [dwarf] make dwarf fission compatible with RISCV relaxations (PR #164128)

via cfe-commits cfe-commits at lists.llvm.org
Sat Oct 18 14:02:14 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-debuginfo

@llvm/pr-subscribers-backend-risc-v

Author: None (dlav-sc)

<details>
<summary>Changes</summary>

Currently, `-gsplit-dwarf` and `-mrelax` are incompatible options in
Clang. The issue is that `.dwo` files should not contain any
relocations, as they are not processed by the linker. However, relaxable
code emits relocations in DWARF for debug ranges that reside in the
`.dwo` file when DWARF fission is enabled.

This patch makes DWARF fission compatible with RISC-V relaxations. It
uses the `StartxEndx` DWARF forms in `.debug_rnglists.dwo`, which
allow referencing addresses from `.debug_addr` instead of using absolute
addresses. This approach eliminates relocations from `.dwo` files.

---

Patch is 23.06 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/164128.diff


8 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticDriverKinds.td (-3) 
- (modified) clang/lib/Driver/ToolChains/Arch/RISCV.cpp (+2-9) 
- (modified) clang/test/Driver/riscv-features.c (-7) 
- (modified) llvm/include/llvm/MC/MCSymbol.h (+2) 
- (modified) llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (+5-3) 
- (modified) llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (+112-35) 
- (modified) llvm/lib/MC/MCSymbol.cpp (+19-3) 
- (added) llvm/test/DebugInfo/RISCV/relax_dwo_ranges.ll (+155) 


``````````diff
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 0581bf353d936..fe29424d8f914 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -833,9 +833,6 @@ def warn_drv_sarif_format_unstable : Warning<
   "diagnostic formatting in SARIF mode is currently unstable">,
   InGroup<DiagGroup<"sarif-format-unstable">>;
 
-def err_drv_riscv_unsupported_with_linker_relaxation : Error<
-  "%0 is unsupported with RISC-V linker relaxation (-mrelax)">;
-
 def warn_drv_loongarch_conflicting_implied_val : Warning<
   "ignoring '%0' as it conflicts with that implied by '%1' (%2)">,
   InGroup<OptionIgnored>;
diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
index f2e79e71f93d4..549a8b712c602 100644
--- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -130,17 +130,10 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
 #undef RESERVE_REG
 
   // -mrelax is default, unless -mno-relax is specified.
-  if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true)) {
+  if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
     Features.push_back("+relax");
-    // -gsplit-dwarf -mrelax requires DW_AT_high_pc/DW_AT_ranges/... indexing
-    // into .debug_addr, which is currently not implemented.
-    Arg *A;
-    if (getDebugFissionKind(D, Args, A) != DwarfFissionKind::None)
-      D.Diag(clang::diag::err_drv_riscv_unsupported_with_linker_relaxation)
-          << A->getAsString(Args);
-  } else {
+  else
     Features.push_back("-relax");
-  }
 
   // If -mstrict-align, -mno-strict-align, -mscalar-strict-align, or
   // -mno-scalar-strict-align is passed, use it. Otherwise, the
diff --git a/clang/test/Driver/riscv-features.c b/clang/test/Driver/riscv-features.c
index 1c8b52bd31997..97736ff81c799 100644
--- a/clang/test/Driver/riscv-features.c
+++ b/clang/test/Driver/riscv-features.c
@@ -68,13 +68,6 @@
 // DEFAULT-LINUX-SAME: "-target-feature" "+d"
 // DEFAULT-LINUX-SAME: "-target-feature" "+c"
 
-// RUN: not %clang -c --target=riscv64-linux-gnu -gsplit-dwarf %s 2>&1 | FileCheck %s --check-prefix=ERR-SPLIT-DWARF
-// RUN: not %clang -c --target=riscv64 -gsplit-dwarf=single %s 2>&1 | FileCheck %s --check-prefix=ERR-SPLIT-DWARF
-// RUN: %clang -### -c --target=riscv64 -mno-relax -g -gsplit-dwarf %s 2>&1 | FileCheck %s --check-prefix=SPLIT-DWARF
-
-// ERR-SPLIT-DWARF: error: -gsplit-dwarf{{.*}} is unsupported with RISC-V linker relaxation (-mrelax)
-// SPLIT-DWARF:     "-split-dwarf-file"
-
 // RUN: %clang -mabi=lp64d --target=riscv64-unknown-fuchsia -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=FUCHSIA
 // FUCHSIA: "-target-feature" "+m"
 // FUCHSIA-SAME: "-target-feature" "+a"
diff --git a/llvm/include/llvm/MC/MCSymbol.h b/llvm/include/llvm/MC/MCSymbol.h
index e31d0374baf4a..eef248354b70f 100644
--- a/llvm/include/llvm/MC/MCSymbol.h
+++ b/llvm/include/llvm/MC/MCSymbol.h
@@ -383,6 +383,8 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) {
   return OS;
 }
 
+bool isRangeRelaxable(const MCSymbol *Begin, const MCSymbol *End);
+
 } // end namespace llvm
 
 #endif // LLVM_MC_MCSYMBOL_H
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 518121e200190..12ad5c18e9600 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -493,10 +493,12 @@ void DwarfCompileUnit::attachLowHighPC(DIE &D, const MCSymbol *Begin,
   assert(End->isDefined() && "Invalid end label");
 
   addLabelAddress(D, dwarf::DW_AT_low_pc, Begin);
-  if (DD->getDwarfVersion() < 4)
-    addLabelAddress(D, dwarf::DW_AT_high_pc, End);
-  else
+  if (DD->getDwarfVersion() >= 4 &&
+      (!isDwoUnit() || !llvm::isRangeRelaxable(Begin, End))) {
     addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin);
+    return;
+  }
+  addLabelAddress(D, dwarf::DW_AT_high_pc, End);
 }
 
 // Add info for Wasm-global-based relocation.
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 433877f3a8b98..4ba35953d196c 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -3275,34 +3275,70 @@ static MCSymbol *emitLoclistsTableHeader(AsmPrinter *Asm,
   return TableEnd;
 }
 
-template <typename Ranges, typename PayloadEmitter>
-static void emitRangeList(
-    DwarfDebug &DD, AsmPrinter *Asm, MCSymbol *Sym, const Ranges &R,
-    const DwarfCompileUnit &CU, unsigned BaseAddressx, unsigned OffsetPair,
-    unsigned StartxLength, unsigned EndOfList,
-    StringRef (*StringifyEnum)(unsigned),
-    bool ShouldUseBaseAddress,
-    PayloadEmitter EmitPayload) {
+namespace {
+
+struct DebugLocSpanList {
+  MCSymbol *Label;
+  const DwarfCompileUnit *CU;
+  llvm::ArrayRef<llvm::DebugLocStream::Entry> Ranges;
+};
+
+template <typename DWARFSpanList> struct DwarfRangeListTraits {};
+
+template <> struct DwarfRangeListTraits<DebugLocSpanList> {
+  static constexpr unsigned BaseAddressx = dwarf::DW_LLE_base_addressx;
+  static constexpr unsigned OffsetPair = dwarf::DW_LLE_offset_pair;
+  static constexpr unsigned StartxLength = dwarf::DW_LLE_startx_length;
+  static constexpr unsigned StartxEndx = dwarf::DW_LLE_startx_endx;
+  static constexpr unsigned EndOfList = dwarf::DW_LLE_end_of_list;
+
+  static StringRef StringifyRangeKind(unsigned Encoding) {
+    return llvm::dwarf::LocListEncodingString(Encoding);
+  }
+};
+
+template <> struct DwarfRangeListTraits<RangeSpanList> {
+  static constexpr unsigned BaseAddressx = dwarf::DW_RLE_base_addressx;
+  static constexpr unsigned OffsetPair = dwarf::DW_RLE_offset_pair;
+  static constexpr unsigned StartxLength = dwarf::DW_RLE_startx_length;
+  static constexpr unsigned StartxEndx = dwarf::DW_RLE_startx_endx;
+  static constexpr unsigned EndOfList = dwarf::DW_RLE_end_of_list;
+
+  static StringRef StringifyRangeKind(unsigned Encoding) {
+    return llvm::dwarf::RangeListEncodingString(Encoding);
+  }
+};
+
+} // namespace
+
+template <
+    typename Ranges, typename PayloadEmitter,
+    std::enable_if_t<DwarfRangeListTraits<Ranges>::BaseAddressx, bool> = true>
+static void emitRangeList(DwarfDebug &DD, AsmPrinter *Asm, const Ranges &R,
+                          bool ShouldUseBaseAddress,
+                          PayloadEmitter EmitPayload) {
 
   auto Size = Asm->MAI->getCodePointerSize();
   bool UseDwarf5 = DD.getDwarfVersion() >= 5;
 
   // Emit our symbol so we can find the beginning of the range.
-  Asm->OutStreamer->emitLabel(Sym);
+  Asm->OutStreamer->emitLabel(R.Label);
 
   // Gather all the ranges that apply to the same section so they can share
   // a base address entry.
-  SmallMapVector<const MCSection *, std::vector<decltype(&*R.begin())>, 16>
+  SmallMapVector<const MCSection *, std::vector<decltype(&*R.Ranges.begin())>,
+                 16>
       SectionRanges;
 
-  for (const auto &Range : R)
+  for (const auto &Range : R.Ranges)
     SectionRanges[&Range.Begin->getSection()].push_back(&Range);
 
-  const MCSymbol *CUBase = CU.getBaseAddress();
+  const MCSymbol *CUBase = R.CU->getBaseAddress();
   bool BaseIsSet = false;
   for (const auto &P : SectionRanges) {
     auto *Base = CUBase;
-    if ((Asm->TM.getTargetTriple().isNVPTX() && DD.tuneForGDB())) {
+    if ((Asm->TM.getTargetTriple().isNVPTX() && DD.tuneForGDB()) ||
+        (DD.useSplitDwarf() && P.first->isLinkerRelaxable())) {
       // PTX does not support subtracting labels from the code section in the
       // debug_loc section.  To work around this, the NVPTX backend needs the
       // compile unit to have no low_pc in order to have a zero base_address
@@ -3327,8 +3363,10 @@ static void emitRangeList(
         //  * or, there's more than one entry to share the base address
         Base = NewBase;
         BaseIsSet = true;
-        Asm->OutStreamer->AddComment(StringifyEnum(BaseAddressx));
-        Asm->emitInt8(BaseAddressx);
+        Asm->OutStreamer->AddComment(
+            DwarfRangeListTraits<Ranges>::StringifyRangeKind(
+                DwarfRangeListTraits<Ranges>::BaseAddressx));
+        Asm->emitInt8(DwarfRangeListTraits<Ranges>::BaseAddressx);
         Asm->OutStreamer->AddComment("  base address index");
         Asm->emitULEB128(DD.getAddressPool().getIndex(Base));
       }
@@ -3339,7 +3377,46 @@ static void emitRangeList(
       Asm->OutStreamer->emitIntValue(0, Size);
     }
 
-    for (const auto *RS : P.second) {
+    if (DD.useSplitDwarf() && UseDwarf5) {
+      // In .dwo files, we must ensure no relocations are present. For
+      // .debug_ranges.dwo. this means that if there is at least one
+      // relocation between the start and end of a range, we must
+      // represent the range boundaries using indirect addresses from
+      // the .debug_addr section.
+      //
+      // The DWARFv5 specification (section 2.17.3) does not require
+      // range entries to be ordered. Therefore, we emit such range
+      // entries here to allow using more optimal formats (e.g.
+      // StartxLength) for other ranges.
+
+      auto RelaxableRanges = llvm::make_filter_range(P.second, [](auto &&RS) {
+        return llvm::isRangeRelaxable(RS->Begin, RS->End);
+      });
+
+      for (auto &&RS : RelaxableRanges) {
+        const auto *Begin = RS->Begin;
+        const auto *End = RS->End;
+        Asm->OutStreamer->AddComment(
+            DwarfRangeListTraits<Ranges>::StringifyRangeKind(
+                DwarfRangeListTraits<Ranges>::StartxEndx));
+        Asm->emitInt8(DwarfRangeListTraits<Ranges>::StartxEndx);
+        Asm->OutStreamer->AddComment("  start index");
+        Asm->emitULEB128(DD.getAddressPool().getIndex(Begin));
+        Asm->OutStreamer->AddComment("  end index");
+        Asm->emitULEB128(DD.getAddressPool().getIndex(End));
+        EmitPayload(*RS);
+      }
+    }
+
+    auto NonRelaxableRanges = llvm::make_filter_range(
+        P.second,
+        [HasRelaxableRanges = DD.useSplitDwarf() && UseDwarf5](auto &&RS) {
+          if (!HasRelaxableRanges)
+            return true;
+          return !llvm::isRangeRelaxable(RS->Begin, RS->End);
+        });
+
+    for (const auto *RS : NonRelaxableRanges) {
       const MCSymbol *Begin = RS->Begin;
       const MCSymbol *End = RS->End;
       assert(Begin && "Range without a begin symbol?");
@@ -3347,8 +3424,10 @@ static void emitRangeList(
       if (Base) {
         if (UseDwarf5) {
           // Emit offset_pair when we have a base.
-          Asm->OutStreamer->AddComment(StringifyEnum(OffsetPair));
-          Asm->emitInt8(OffsetPair);
+          Asm->OutStreamer->AddComment(
+              DwarfRangeListTraits<Ranges>::StringifyRangeKind(
+                  DwarfRangeListTraits<Ranges>::OffsetPair));
+          Asm->emitInt8(DwarfRangeListTraits<Ranges>::OffsetPair);
           Asm->OutStreamer->AddComment("  starting offset");
           Asm->emitLabelDifferenceAsULEB128(Begin, Base);
           Asm->OutStreamer->AddComment("  ending offset");
@@ -3358,8 +3437,10 @@ static void emitRangeList(
           Asm->emitLabelDifference(End, Base, Size);
         }
       } else if (UseDwarf5) {
-        Asm->OutStreamer->AddComment(StringifyEnum(StartxLength));
-        Asm->emitInt8(StartxLength);
+        Asm->OutStreamer->AddComment(
+            DwarfRangeListTraits<Ranges>::StringifyRangeKind(
+                DwarfRangeListTraits<Ranges>::StartxLength));
+        Asm->emitInt8(DwarfRangeListTraits<Ranges>::StartxLength);
         Asm->OutStreamer->AddComment("  start index");
         Asm->emitULEB128(DD.getAddressPool().getIndex(Begin));
         Asm->OutStreamer->AddComment("  length");
@@ -3373,8 +3454,10 @@ static void emitRangeList(
   }
 
   if (UseDwarf5) {
-    Asm->OutStreamer->AddComment(StringifyEnum(EndOfList));
-    Asm->emitInt8(EndOfList);
+    Asm->OutStreamer->AddComment(
+        DwarfRangeListTraits<Ranges>::StringifyRangeKind(
+            DwarfRangeListTraits<Ranges>::EndOfList));
+    Asm->emitInt8(DwarfRangeListTraits<Ranges>::EndOfList);
   } else {
     // Terminate the list with two 0 values.
     Asm->OutStreamer->emitIntValue(0, Size);
@@ -3384,11 +3467,9 @@ static void emitRangeList(
 
 // Handles emission of both debug_loclist / debug_loclist.dwo
 static void emitLocList(DwarfDebug &DD, AsmPrinter *Asm, const DebugLocStream::List &List) {
-  emitRangeList(DD, Asm, List.Label, DD.getDebugLocs().getEntries(List),
-                *List.CU, dwarf::DW_LLE_base_addressx,
-                dwarf::DW_LLE_offset_pair, dwarf::DW_LLE_startx_length,
-                dwarf::DW_LLE_end_of_list, llvm::dwarf::LocListEncodingString,
-                /* ShouldUseBaseAddress */ true,
+  DebugLocSpanList Ranges = {List.Label, List.CU,
+                             DD.getDebugLocs().getEntries(List)};
+  emitRangeList(DD, Asm, Ranges, /* ShouldUseBaseAddress */ true,
                 [&](const DebugLocStream::Entry &E) {
                   DD.emitDebugLocEntryLocation(E, List.CU);
                 });
@@ -3413,10 +3494,9 @@ void DwarfDebug::emitDebugLocImpl(MCSection *Sec) {
 
 // Emit locations into the .debug_loc/.debug_loclists section.
 void DwarfDebug::emitDebugLoc() {
-  emitDebugLocImpl(
-      getDwarfVersion() >= 5
-          ? Asm->getObjFileLowering().getDwarfLoclistsSection()
-          : Asm->getObjFileLowering().getDwarfLocSection());
+  emitDebugLocImpl(getDwarfVersion() >= 5
+                       ? Asm->getObjFileLowering().getDwarfLoclistsSection()
+                       : Asm->getObjFileLowering().getDwarfLocSection());
 }
 
 // Emit locations into the .debug_loc.dwo/.debug_loclists.dwo section.
@@ -3611,10 +3691,7 @@ void DwarfDebug::emitDebugARanges() {
 /// Emit a single range list. We handle both DWARF v5 and earlier.
 static void emitRangeList(DwarfDebug &DD, AsmPrinter *Asm,
                           const RangeSpanList &List) {
-  emitRangeList(DD, Asm, List.Label, List.Ranges, *List.CU,
-                dwarf::DW_RLE_base_addressx, dwarf::DW_RLE_offset_pair,
-                dwarf::DW_RLE_startx_length, dwarf::DW_RLE_end_of_list,
-                llvm::dwarf::RangeListEncodingString,
+  emitRangeList(DD, Asm, List,
                 List.CU->getCUNode()->getRangesBaseAddress() ||
                     DD.getDwarfVersion() >= 5,
                 [](auto) {});
diff --git a/llvm/lib/MC/MCSymbol.cpp b/llvm/lib/MC/MCSymbol.cpp
index b86873824cb00..e95c714ed003c 100644
--- a/llvm/lib/MC/MCSymbol.cpp
+++ b/llvm/lib/MC/MCSymbol.cpp
@@ -83,8 +83,24 @@ void MCSymbol::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
   OS << '"';
 }
 
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void MCSymbol::dump() const {
-  dbgs() << *this;
+bool llvm::isRangeRelaxable(const MCSymbol *Begin, const MCSymbol *End) {
+  assert(Begin && "Range without a begin symbol?");
+  assert(End && "Range without an end symbol?");
+  llvm::SmallVector<const MCFragment *> RangeFragments{};
+  for (const auto *Fragment = Begin->getFragment();
+       Fragment != End->getFragment(); Fragment = Fragment->getNext()) {
+    assert(Fragment);
+    RangeFragments.push_back(Fragment);
+  }
+  assert(End->getFragment());
+  RangeFragments.push_back(End->getFragment());
+
+  bool IsRelaxableRange = llvm::any_of(RangeFragments, [](auto &&Fragment) {
+    return Fragment->isLinkerRelaxable();
+  });
+  return IsRelaxableRange;
 }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void MCSymbol::dump() const { dbgs() << *this; }
 #endif
diff --git a/llvm/test/DebugInfo/RISCV/relax_dwo_ranges.ll b/llvm/test/DebugInfo/RISCV/relax_dwo_ranges.ll
new file mode 100644
index 0000000000000..759177b2a376f
--- /dev/null
+++ b/llvm/test/DebugInfo/RISCV/relax_dwo_ranges.ll
@@ -0,0 +1,155 @@
+; RUN: llc -dwarf-version=5 -split-dwarf-file=foo.dwo -O0 %s -mtriple=riscv64-unknown-linux-gnu -filetype=obj -o %t
+; RUN: llvm-dwarfdump -v %t | FileCheck %s
+
+; In the RISC-V architecture, the .text section is subject to
+; relaxation, meaning the start address of each function can change
+; during the linking process. Therefore, the .debug_rnglists.dwo
+; section must obtain function's start addresses from the .debug_addr
+; section.
+
+; Generally, a function's body can be relaxed (for example, the
+; square() and main() functions in this test, which contain call
+; instructions). For such code ranges, the linker must place the
+; start and end addresses into the .debug_addr section and use
+; the DW_RLE_startx_endx entry form in the .debug_rnglists.dwo
+; section within the .dwo file.
+
+; However, some functions may not contain any relaxable instructions
+; (for example, the boo() function in this test). In these cases,
+; it is possible to use the more space-efficient DW_RLE_startx_length
+; range entry form.
+
+; From the code:
+
+; __attribute__((noinline)) int boo();
+
+; int square(int num) {
+;   int num1 = boo();
+;   return num1 * num;
+; }
+
+; __attribute__((noinline)) int boo() {
+;   return 8;
+; }
+
+; int main() {
+;   int a = 10;
+;   int squared = square(a);
+;   return squared;
+; }
+
+; compiled with
+
+; clang -g -S -gsplit-dwarf --target=riscv64 -march=rv64gc -O0 relax_dwo_ranges.cpp
+
+; Ensure that 'square()' function uses indexed start and end addresses
+; CHECK: .debug_info.dwo contents:
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT_low_pc [DW_FORM_addrx]    (indexed (00000000) address = 0x0000000000000000 ".text")
+; CHECK-NEXT: DW_AT_high_pc [DW_FORM_addrx]   (indexed (00000001) address = 0x0000000000000044 ".text")
+; CHECK: DW_AT_name {{.*}} "square") 
+; CHECK: DW_TAG_formal_parameter
+
+; Ensure there is no unnecessary addresses in .o file
+; CHECK: .debug_addr contents:
+; CHECK: Addrs: [
+; CHECK-NEXT: 0x0000000000000000
+; CHECK-NEXT: 0x0000000000000044
+; CHECK-NEXT: 0x0000000000000046
+; CHECK-NEXT: 0x000000000000006c
+; CHECK-NEXT: 0x00000000000000b0
+; CHECK-NEXT: ]
+
+; Ensure that 'boo()' and 'main()' use DW_RLE_startx_length and DW_RLE_startx_endx
+; entries respectively
+; CHECK: .debug_rnglists.dwo contents:
+; CHECK: ranges:
+; CHECK-NEXT: 0x00000014: [DW_RLE_startx_length]:  0x0000000000000002, 0x0000000000000024 => [0x0000000000000046, 0x000000000000006a)
+; CHECK-NEXT: 0x00000017: [DW_RLE_end_of_list  ]
+; CHECK-NEXT: 0x00000018: [DW_RLE_startx_endx  ]:  0x0000000000000003, 0x0000000000000004 => [0x000000000000006c, 0x00000000000000b0)
+; CHECK-NEXT: 0x0000001b: [DW_RLE_end_of_list  ]
+; CHECK-EMPTY:
+
+
+; Function Attrs: mustprogress noinline optnone
+define dso_local noundef signext i32 @_Z6squarei(i32 noundef signext %0) #0 !dbg !11 {
+  %2 = alloca i32, align 4
+  %3 = alloca i32, align 4
+  store i32 %0, ptr %2, align 4
+    #dbg_declare(ptr %2, !16, !DIExpression(), !17)
+    #dbg_declare(ptr %3, !18, !DIExpression(), !19)
+  %4 = call noundef signext i32 @_Z3boov(), !dbg !20
+  store i32 %4, ptr %3, align 4, !dbg !19
+  %5 = load i32, ptr %3, align 4, !dbg !21
+  %6 = load i32, ptr %2, align 4, !dbg !22
+  %7 = mul nsw i32 %5, %6, !dbg !23
+  ret i32 %7, !dbg !24
+}
+
+; Function Attrs: mustprogress noinline nounwind optnone
+define dso_local noundef signext i32 @_Z3boov() #1 !dbg !25 {
+  ret i32 8, !dbg !28
+}
+
+; Function Attrs: mustprogress noinline norecurse optnone
+define dso_local noundef signext i32 @main() #2 !dbg !29 {
+  %1 = alloca i32, align 4
+  %2 = alloca i32, align 4
+  %3 = alloca i32, align 4
+  store i32 0, ptr %1, align 4
+    #dbg_declare(ptr %2, !30, !DIExpression(), !31)
+  store i32 10, ptr %2, align 4, !dbg !31
+    #dbg_declare(ptr %3, !32, !DIExpression(), !33)
+  %4 = load i32, ptr %2, align 4, !dbg !34
+  %5 = call noundef signext i32 @_Z6squarei(i32 noundef signext %4), !dbg !35
+  store i32 %5, ptr %3, align 4, !dbg !33
+  %6 = load i32, ptr %3, align 4, !dbg !36
+  ret i32 %6, !dbg !37
+}
+
+attributes #0 = { mustprogress noinline optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv64" "target-features"="+64bit,+relax,+f,+d" }
+attributes #1 = { mustprogress noinline nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv64" "target-features"="+64bit,+relax,+f,+d" }
+attributes #2 = { must...
[truncated]

``````````

</details>


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


More information about the cfe-commits mailing list