Files
TheRock/rocm-systems/projects/rocprof-trace-decoder/markers/SQTTNamedMarkers.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

153 lines
5.6 KiB
C++

// MIT License
//
// Copyright (c) 2026 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "SQTTPass.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/IR/Constants.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
namespace
{
enum MarkerFlag : uint8_t
{
MarkerEnter = 1,
MarkerExit = 2,
MarkerPoint = 4,
MarkerPayload = 8
};
uint8_t markerFlags(const CallInst* call)
{
const Function* callee = call ? call->getCalledFunction() : nullptr;
return callee ? StringSwitch<uint8_t>(callee->getName())
.Case("__sqtt_named_marker_enter", MarkerEnter)
.Case("__sqtt_named_marker_exit", MarkerExit)
.Case("__sqtt_named_marker_point", MarkerPoint)
.Case("__sqtt_named_marker_data", MarkerPoint | MarkerPayload)
.Default(0)
: 0;
}
} // namespace
uint32_t SQTTInstrumentPass::resolveMarkerString(CallInst* CI, uint8_t flags)
{
Value* Arg = CI->getArgOperand(0)->stripPointerCasts();
auto* GV = dyn_cast<GlobalVariable>(Arg);
if (!GV || !GV->hasInitializer()) return 0;
auto* CDA = dyn_cast<ConstantDataArray>(GV->getInitializer());
if (!CDA || !CDA->isString()) return 0;
// Exit just pops the top of the marker stack — the name string is
// unused at the trace level, so no ID/funcmap entry is needed.
if (flags & MarkerExit) return FLAG_EXIT_PREV; // value 1: pop top scope
std::string Name = CDA->getAsString().str();
if (!Name.empty() && Name.back() == '\0') Name.pop_back();
bool isPoint = flags & MarkerPoint;
uint32_t extraPayloadCount = (flags & MarkerPayload) ? 1 : 0;
std::string key = std::string(isPoint ? "P:" : "U:") + std::to_string(extraPayloadCount) + ":" + Name;
auto [it, inserted] = UserMarkerMap.try_emplace(key, NextEventID);
uint32_t id = it->second;
if (inserted)
{
++NextEventID;
Markers.push_back({id, isPoint ? MarkerKind::Point : MarkerKind::UserScope, Name, {}, 0, extraPayloadCount});
}
bool enter = flags & MarkerEnter;
return encodeMarker(id, enter, false); // enter or point
}
// Early emits bare traces and leaves unresolved calls for late processing.
// Late emits scoped/bounded traces and warns for unresolved calls.
bool SQTTInstrumentPass::processMarkerCalls(Function& F, GfxGen gen, bool useBareTrace)
{
SmallVector<CallInst*, 8> Calls;
for (auto& BB : F)
for (auto& I : BB)
if (auto* CI = dyn_cast<CallInst>(&I); markerFlags(CI)) Calls.push_back(CI);
if (Calls.empty()) return false;
Module* M = F.getParent();
bool Changed = false;
auto emit = [&](IRBuilder<>& B, uint32_t encoded, Value* payload = nullptr)
{
if (useBareTrace)
{
CallInst* header = emitBareTrace(B, encoded, M, gen);
if (payload) emitRawTracePayload(B, payload, M, header);
}
else
insertTraceMarker(B, encoded, F, gen, payload);
};
for (unsigned i = 0; i < Calls.size(); i++)
{
CallInst* CI = Calls[i];
uint8_t flags = markerFlags(CI);
// Fuse only directly adjacent exit+enter pairs. A marker boundary
// must not absorb work between the calls.
if (flags == MarkerExit && i + 1 < Calls.size())
{
CallInst* NextCI = Calls[i + 1];
if (markerFlags(NextCI) == MarkerEnter && CI->getNextNode() == NextCI)
{
uint32_t enterEncoded = resolveMarkerString(NextCI, MarkerEnter);
if (enterEncoded)
{
uint32_t id = enterEncoded >> 2;
uint32_t fused = encodeMarker(id, true, true);
IRBuilder<> B(CI);
emit(B, fused);
CI->eraseFromParent();
NextCI->eraseFromParent();
Changed = true;
i++;
continue;
}
}
}
uint32_t encoded = resolveMarkerString(CI, flags);
if (!encoded)
{
if (useBareTrace) continue; // not resolvable yet, leave for late pass
errs() << "SQTT: warning: sqtt_marker_enter/exit/point/data() "
"argument is not a string literal, skipping\n";
CI->eraseFromParent();
continue;
}
IRBuilder<> B(CI);
emit(B, encoded, flags & MarkerPayload ? CI->getArgOperand(1) : nullptr);
CI->eraseFromParent();
Changed = true;
}
return Changed || !useBareTrace;
}