diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index d6e36927e73ef..38bab6a588f09 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1328,7 +1328,8 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD, AsmWriterContext &WriterCtx, - bool FromValue = false); + bool FromValue = false, + bool AsOperand = false); static void WriteOptimizationInfo(raw_ostream &Out, const User *U) { if (const FPMathOperator *FPO = dyn_cast(U)) @@ -2447,7 +2448,7 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, if (auto *MD = dyn_cast(V)) { WriteAsOperandInternal(Out, MD->getMetadata(), WriterCtx, - /* FromValue */ true); + /* FromValue */ true, /* AsOperand */ true); return; } @@ -2492,8 +2493,8 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, } static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD, - AsmWriterContext &WriterCtx, - bool FromValue) { + AsmWriterContext &WriterCtx, bool FromValue, + bool AsOperand) { // Write DIExpressions and DIArgLists inline when used as a value. Improves // readability of debug info intrinsics. if (const DIExpression *Expr = dyn_cast(MD)) { @@ -2506,6 +2507,12 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD, } if (const MDNode *N = dyn_cast(MD)) { + // Write empty metadata tuples wrapped in MetadataAsValue inline. + if (isa(N) && !N->getNumOperands() && AsOperand) { + WriteMDNodeBodyInternal(Out, N, WriterCtx); + return; + } + std::unique_ptr MachineStorage; SaveAndRestore SARMachine(WriterCtx.Machine); if (!WriterCtx.Machine) { @@ -4874,7 +4881,8 @@ static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD, WriterCtx = std::make_unique(&TypePrinter, MST.getMachine(), M); - WriteAsOperandInternal(OS, &MD, *WriterCtx, /* FromValue */ true); + WriteAsOperandInternal(OS, &MD, *WriterCtx, /* FromValue */ true, + OnlyAsOperand); auto *N = dyn_cast(&MD); if (OnlyAsOperand || !N || isa(MD) || isa(MD)) diff --git a/llvm/test/DebugInfo/Generic/empty-metadata-roundtrip.ll b/llvm/test/DebugInfo/Generic/empty-metadata-roundtrip.ll new file mode 100644 index 0000000000000..88a0e0538d648 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/empty-metadata-roundtrip.ll @@ -0,0 +1,42 @@ +; RUN: opt -passes=verify %s -o - | opt -S -o - | FileCheck %s + +;; Check that an empty metadata node is printed inline when wrapped in +;; MetadataAsValue. +;; We still get a numbered metadata entry for the node even though it's not +;; used elsewhere. This is a purely cosmetic result of reducing the complexity +;; of the printing functions; it's not a requirement so it is okay to update +;; this part of the test if that changes in the future. + +; CHECK: call void @llvm.dbg.declare(metadata !{}, +; CHECK: ![[#]] = !{} + +define dso_local void @fun() local_unnamed_addr #0 !dbg !9 { +entry: + call void @llvm.dbg.declare(metadata !{}, metadata !13, metadata !DIExpression()), !dbg !15 + ret void, !dbg !16 +} + +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7} +!llvm.ident = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 16.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{!"clang version 16.0.0"} +!9 = distinct !DISubprogram(name: "fun", scope: !1, file: !1, line: 1, type: !10, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12) +!10 = !DISubroutineType(types: !11) +!11 = !{null} +!12 = !{!13} +!13 = !DILocalVariable(name: "a", scope: !9, file: !1, line: 1, type: !14) +!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!15 = !DILocation(line: 1, column: 18, scope: !9) +!16 = !DILocation(line: 1, column: 21, scope: !9) + diff --git a/llvm/test/Transforms/GlobalOpt/localize-constexpr-debuginfo.ll b/llvm/test/Transforms/GlobalOpt/localize-constexpr-debuginfo.ll index 18dc038fce66a..612a0be25ab17 100644 --- a/llvm/test/Transforms/GlobalOpt/localize-constexpr-debuginfo.ll +++ b/llvm/test/Transforms/GlobalOpt/localize-constexpr-debuginfo.ll @@ -11,8 +11,8 @@ define i32 @main(i32 %argc, ptr %argv) norecurse !dbg !18 { ; CHECK: alloca ptr ; Make sure the metadata is sane. Currently, we just drop the metadata, ; so it points to nothing. -; CHECK: call void @llvm.dbg.value(metadata !2, -; CHECK: !2 = !{} +; CHECK: call void @llvm.dbg.value(metadata !{}, + entry: call void @llvm.dbg.value(metadata i32 %argc, metadata !22, metadata !23), !dbg !24 call void @llvm.dbg.value(metadata ptr %argv, metadata !25, metadata !23), !dbg !26 diff --git a/llvm/test/Transforms/GlobalOpt/metadata.ll b/llvm/test/Transforms/GlobalOpt/metadata.ll index 3b6e121d7ce6e..8dda0be7452a2 100644 --- a/llvm/test/Transforms/GlobalOpt/metadata.ll +++ b/llvm/test/Transforms/GlobalOpt/metadata.ll @@ -18,7 +18,7 @@ define void @foo(i32 %x) { ; null, the ValueAsMetadata instance gets replaced by metadata !{}, or ; MDNode::get({}). call void @llvm.foo(metadata ptr @G, metadata i32 %x) -; CHECK: call void @llvm.foo(metadata ![[EMPTY:[0-9]+]], metadata i32 %x) +; CHECK: call void @llvm.foo(metadata !{}, metadata i32 %x) ret void } @@ -29,4 +29,3 @@ declare void @llvm.foo(metadata, metadata) nounwind readnone !0 = !{ptr @G} ; CHECK-DAG: ![[NULL]] = distinct !{null} -; CHECK-DAG: ![[EMPTY]] = !{} diff --git a/llvm/test/Transforms/LoopIdiom/debug-line.ll b/llvm/test/Transforms/LoopIdiom/debug-line.ll index 017d63d0c14a5..7b565a1360e7e 100644 --- a/llvm/test/Transforms/LoopIdiom/debug-line.ll +++ b/llvm/test/Transforms/LoopIdiom/debug-line.ll @@ -18,7 +18,7 @@ define void @foo(ptr nocapture %a) nounwind ssp !dbg !0 { ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVAR_NEXT]], 1000 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]], !dbg [[DBG15]] ; CHECK: for.end: -; CHECK-NEXT: tail call void @llvm.dbg.value(metadata [[META3:![0-9]+]], metadata [[META11]], metadata !DIExpression()), !dbg [[DBG17:![0-9]+]] +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata !{}, metadata [[META11]], metadata !DIExpression()), !dbg [[DBG17:![0-9]+]] ; CHECK-NEXT: ret void, !dbg [[DBG18:![0-9]+]] ; entry: diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp index 5342360109d0d..fa559b4c050d8 100644 --- a/llvm/unittests/IR/MetadataTest.cpp +++ b/llvm/unittests/IR/MetadataTest.cpp @@ -390,18 +390,20 @@ TEST_F(MDNodeTest, PrintFromMetadataAsValue) { EXPECT_PRINTER_EQ("!0 = distinct !{}", MAV0->print(OS)); EXPECT_PRINTER_EQ("!1 = distinct !{}", MAV1->print(OS)); - EXPECT_PRINTER_EQ("!0", MAV0->printAsOperand(OS, false)); - EXPECT_PRINTER_EQ("!1", MAV1->printAsOperand(OS, false)); - EXPECT_PRINTER_EQ("metadata !0", MAV0->printAsOperand(OS, true)); - EXPECT_PRINTER_EQ("metadata !1", MAV1->printAsOperand(OS, true)); + EXPECT_PRINTER_EQ("distinct !{}", MAV0->printAsOperand(OS, false)); + EXPECT_PRINTER_EQ("distinct !{}", MAV1->printAsOperand(OS, false)); + EXPECT_PRINTER_EQ("metadata distinct !{}", MAV0->printAsOperand(OS, true)); + EXPECT_PRINTER_EQ("metadata distinct !{}", MAV1->printAsOperand(OS, true)); ModuleSlotTracker MST(&M); EXPECT_PRINTER_EQ("!0 = distinct !{}", MAV0->print(OS, MST)); EXPECT_PRINTER_EQ("!1 = distinct !{}", MAV1->print(OS, MST)); - EXPECT_PRINTER_EQ("!0", MAV0->printAsOperand(OS, false, MST)); - EXPECT_PRINTER_EQ("!1", MAV1->printAsOperand(OS, false, MST)); - EXPECT_PRINTER_EQ("metadata !0", MAV0->printAsOperand(OS, true, MST)); - EXPECT_PRINTER_EQ("metadata !1", MAV1->printAsOperand(OS, true, MST)); + EXPECT_PRINTER_EQ("distinct !{}", MAV0->printAsOperand(OS, false, MST)); + EXPECT_PRINTER_EQ("distinct !{}", MAV1->printAsOperand(OS, false, MST)); + EXPECT_PRINTER_EQ("metadata distinct !{}", + MAV0->printAsOperand(OS, true, MST)); + EXPECT_PRINTER_EQ("metadata distinct !{}", + MAV1->printAsOperand(OS, true, MST)); } TEST_F(MDNodeTest, PrintWithDroppedCallOperand) {