[lld] [llvm] [DTLTO] Add DTLTO-specific LTO input handling time-trace scopes (PR #175799)
Ben Dunbobbin via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 13 09:28:25 PST 2026
https://github.com/bd1976bris created https://github.com/llvm/llvm-project/pull/175799
Add time-trace scopes to the DTLTO-specific input handling code to improve observability and debugging.
These scopes are tested via LLD, as the primary purpose of this code is to support member files of non-thin archives as DTLTO inputs. `llvm-lto2` does not currently support archives. Adding archive support to `llvm-lto2` solely for testing these scopes does not appear to be worthwhile.
SIE internal tracker: TOOLCHAIN-21021
>From cdd4d9907f0dfbd8c58fafe70bb10d5bb232768c Mon Sep 17 00:00:00 2001
From: Ben <ben.dunbobbin at sony.com>
Date: Tue, 13 Jan 2026 11:04:35 +0000
Subject: [PATCH] [DTLTO] Add DTLTO-specific LTO input handling time-trace
scopes
Add time-trace scopes to the DTLTO-specific input handling code to
improve observability and debugging.
These scopes are tested via LLD, as the primary purpose of this code
is to support member files of non-thin archives as DTLTO inputs.
`llvm-lto2` does not currently support archives. Adding archive
support to `llvm-lto2` solely for testing these scopes does not appear
to be worthwhile.
SIE internal tracker: TOOLCHAIN-21021
---
lld/test/ELF/dtlto/timetrace.test | 67 +++++++++++++++++++++++++++++++
llvm/lib/DTLTO/DTLTO.cpp | 6 ++-
2 files changed, 72 insertions(+), 1 deletion(-)
create mode 100644 lld/test/ELF/dtlto/timetrace.test
diff --git a/lld/test/ELF/dtlto/timetrace.test b/lld/test/ELF/dtlto/timetrace.test
new file mode 100644
index 0000000000000..f2b988de119ab
--- /dev/null
+++ b/lld/test/ELF/dtlto/timetrace.test
@@ -0,0 +1,67 @@
+REQUIRES: x86
+
+## Test that DTLTO-specific LTO input file handling time-trace output is
+## produced as expected.
+
+RUN: rm -rf %t && split-file %s %t && cd %t
+
+RUN: sed 's/@t1/@t2/g' t1.ll > t2.ll
+
+## Generate ThinLTO bitcode files.
+RUN: opt -thinlto-bc t1.ll -o t1.bc
+RUN: opt -thinlto-bc t2.ll -o t2.bc
+
+## Create archives.
+RUN: llvm-ar rcs t1.a t1.bc
+RUN: llvm-ar rcsT t2.thin.a t2.bc
+
+## Generate object files for mock.py to return.
+RUN: llc t1.ll --filetype=obj -o t1.o
+RUN: llc t2.ll --filetype=obj -o t2.o
+
+## Link and generate a time-trace.
+## Note: mock.py doesn't compile; it copies the specified object files to the
+## outputs in job order.
+RUN: ld.lld --whole-archive t1.a t2.thin.a -o my.elf \
+RUN: --thinlto-distributor=%python \
+RUN: --thinlto-distributor-arg=%llvm_src_root/utils/dtlto/mock.py \
+RUN: --thinlto-distributor-arg=t1.o --thinlto-distributor-arg=t2.o \
+RUN: --time-trace-granularity=0 --time-trace=%t.json
+RUN: %python filter_order_and_pprint.py %t.json | FileCheck %s
+
+## Check that DTLTO add input file events are recorded.
+CHECK: "name": "Add input for DTLTO"
+CHECK-SAME: "detail": "t1.a(t1.bc at [[T1_ARCHIVE_OFFSET:[0-9]+]])"
+CHECK: "name": "Add input for DTLTO"
+CHECK-SAME: "detail": "t2.thin.a(t2.bc at [[T2_ARCHIVE_OFFSET:[0-9]+]])"
+CHECK: "name": "Remove DTLTO temporary files"
+CHECK: "name": "Save input archive member for DTLTO"
+CHECK-SAME: "detail": "t1.a(t1.bc at [[T1_ARCHIVE_OFFSET]]).1.[[PID:[a-fA-F0-9]+]].o"
+CHECK: "name": "Total Add input for DTLTO"
+CHECK-SAME: "count": 2,
+CHECK: "name": "Total Remove DTLTO temporary files"
+CHECK-SAME: "count": 1,
+CHECK: "name": "Total Save input archive member for DTLTO"
+CHECK-SAME: "count": 1,
+
+#--- t1.ll
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @t1() {
+ ret void
+}
+
+#--- filter_order_and_pprint.py
+import json, sys
+
+data = json.load(open(sys.argv[1], "r", encoding="utf-8"))
+
+# Get DTLTO events.
+events = [e for e in data["traceEvents"] if "DTLTO" in e["name"]]
+events.sort(key=lambda e: (e["name"], str(e.get("args", {}).get("detail", ""))))
+
+# Print an event per line. Ensure 'name' is the first key.
+for ev in events:
+ name = ev.pop("name")
+ print(json.dumps({"name": name, **ev}))
diff --git a/llvm/lib/DTLTO/DTLTO.cpp b/llvm/lib/DTLTO/DTLTO.cpp
index 7ba4bfd80b6ab..6ba4407bae742 100644
--- a/llvm/lib/DTLTO/DTLTO.cpp
+++ b/llvm/lib/DTLTO/DTLTO.cpp
@@ -25,6 +25,7 @@
#include "llvm/Support/MemoryBufferRef.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
+#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/raw_ostream.h"
#include <iostream>
@@ -119,6 +120,7 @@ Expected<bool> lto::DTLTO::isThinArchive(const StringRef ArchivePath) {
// Removes any temporary regular archive member files that were created during
// processing.
void lto::DTLTO::removeTempFiles() {
+ TimeTraceScope TimeScope("Remove temporary inputs for DTLTO");
for (auto &Input : InputFiles) {
if (Input->isMemberOfArchive())
sys::fs::remove(Input->getName(), /*IgnoreNonExisting=*/true);
@@ -133,12 +135,13 @@ void lto::DTLTO::removeTempFiles() {
// 4. Updates the bitcode module's identifier.
Expected<std::shared_ptr<lto::InputFile>>
lto::DTLTO::addInput(std::unique_ptr<lto::InputFile> InputPtr) {
+ StringRef ModuleId = InputPtr->getName();
+ TimeTraceScope TimeScope("Add input for DTLTO", ModuleId);
// Add the input file to the LTO object.
InputFiles.emplace_back(InputPtr.release());
std::shared_ptr<lto::InputFile> &Input = InputFiles.back();
- StringRef ModuleId = Input->getName();
StringRef ArchivePath = Input->getArchivePath();
// Only process archive members.
@@ -180,6 +183,7 @@ lto::DTLTO::addInput(std::unique_ptr<lto::InputFile> InputPtr) {
Error lto::DTLTO::saveInputArchiveMember(lto::InputFile *Input) {
StringRef ModuleId = Input->getName();
if (Input->isMemberOfArchive()) {
+ TimeTraceScope TimeScope("Save input archive member for DTLTO", ModuleId);
MemoryBufferRef MemoryBufferRef = Input->getFileBuffer();
if (Error EC = saveBuffer(MemoryBufferRef.getBuffer(), ModuleId))
return EC;
More information about the llvm-commits
mailing list