Skip to content

Commit f0ae0b5

Browse files
committed
PIX: Remove per-instruction disassembly in annotation pass output
1 parent 58a6c44 commit f0ae0b5

2 files changed

Lines changed: 147 additions & 53 deletions

File tree

lib/DxilPIXPasses/DxilAnnotateWithVirtualRegister.cpp

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,7 @@ class DxilAnnotateWithVirtualRegister : public llvm::ModulePass {
8181
void AnnotateAlloca(llvm::AllocaInst *pAlloca);
8282
void AnnotateGeneric(llvm::Instruction *pI);
8383
void AssignNewDxilRegister(llvm::Instruction *pI);
84-
void PrintSingleRegister(llvm::Instruction* pI, uint32_t Register);
8584
void AssignNewAllocaRegister(llvm::AllocaInst* pAlloca, std::uint32_t C);
86-
void PrintAllocaMember(llvm::AllocaInst* pAlloca, uint32_t Base, uint32_t Offset);
8785

8886
hlsl::DxilModule* m_DM;
8987
std::uint32_t m_uVReg;
@@ -406,36 +404,15 @@ void DxilAnnotateWithVirtualRegister::AnnotateGeneric(llvm::Instruction *pI) {
406404
void DxilAnnotateWithVirtualRegister::AssignNewDxilRegister(
407405
llvm::Instruction *pI) {
408406
PixDxilReg::AddMD(m_DM->GetCtx(), pI, m_uVReg);
409-
PrintSingleRegister(pI, m_uVReg);
410407
m_uVReg++;
411408
}
412409

413410
void DxilAnnotateWithVirtualRegister::AssignNewAllocaRegister(
414411
llvm::AllocaInst *pAlloca, std::uint32_t C) {
415412
PixAllocaReg::AddMD(m_DM->GetCtx(), pAlloca, m_uVReg, C);
416-
PrintAllocaMember(pAlloca, m_uVReg, C);
417413
m_uVReg += C;
418414
}
419415

420-
void DxilAnnotateWithVirtualRegister::PrintSingleRegister(
421-
llvm::Instruction* pI, uint32_t Register) {
422-
if (OSOverride != nullptr) {
423-
static constexpr bool DontPrintType = false;
424-
pI->printAsOperand(*OSOverride, DontPrintType, *m_MST.get());
425-
*OSOverride << " dxil " << Register << "\n";
426-
}
427-
}
428-
429-
void DxilAnnotateWithVirtualRegister::PrintAllocaMember(llvm::AllocaInst* pAlloca,
430-
uint32_t Base,
431-
uint32_t Offset) {
432-
if (OSOverride != nullptr) {
433-
static constexpr bool DontPrintType = false;
434-
pAlloca->printAsOperand(*OSOverride, DontPrintType, *m_MST.get());
435-
*OSOverride << " alloca " << Base << " " << Offset << "\n";
436-
}
437-
}
438-
439416
} // namespace
440417

441418
using namespace llvm;

tools/clang/unittests/HLSL/PixTest.cpp

Lines changed: 147 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,144 @@ class PixTest {
728728
std::vector<std::string> lines;
729729
};
730730

731+
std::string ExtractBracedSubstring(std::string const &line) {
732+
auto open = line.find('{');
733+
auto close = line.find('}');
734+
if (open != std::string::npos && close != std::string::npos &&
735+
open + 1 < close) {
736+
return line.substr(open + 1, close - open - 1);
737+
}
738+
return "";
739+
}
740+
741+
int ExtractMetaInt32Value(std::string const &token) {
742+
if (token.substr(0, 5) == " i32 ") {
743+
return atoi(token.c_str() + 5);
744+
}
745+
return -1;
746+
}
747+
748+
std::map<int, std::pair<int, int>>
749+
MetaDataKeyToRegisterNumber(std::vector<std::string> const &lines) {
750+
// Find lines of the exemplary form
751+
// "!249 = !{i32 0, i32 20}" (in the case of a DXIL value)
752+
// "!196 = !{i32 1, i32 5, i32 1}" (in the case of a DXIL alloca reg)
753+
// The first i32 is a tag indicating what type of metadata this is.
754+
// It doesn't matter if we parse poorly and find some data that don't match
755+
// this pattern, as long as we do find all the data that do match (we won't
756+
// be looking up the non-matchers in the resultant map anyway).
757+
758+
constexpr char *valueMetaDataAssignment = "= !{i32 0, ";
759+
constexpr char *allocaMetaDataAssignment = "= !{i32 1, ";
760+
761+
std::map<int, std::pair<int, int>> ret;
762+
for (auto const &line : lines) {
763+
if (line[0] == '!') {
764+
if (line.find(valueMetaDataAssignment) != std::string::npos ||
765+
line.find(allocaMetaDataAssignment) != std::string::npos) {
766+
int key = atoi(line.c_str() + 1);
767+
if (key != 0) {
768+
std::string bitInBraces = ExtractBracedSubstring(line);
769+
if (bitInBraces != "") {
770+
auto tokens = Tokenize(bitInBraces.c_str(), ",");
771+
if (tokens.size() == 2) {
772+
auto value = ExtractMetaInt32Value(tokens[1]);
773+
if (value != -1) {
774+
ret[key] = {value, 1};
775+
}
776+
}
777+
if (tokens.size() == 3) {
778+
auto value0 = ExtractMetaInt32Value(tokens[1]);
779+
if (value0 != -1) {
780+
auto value1 = ExtractMetaInt32Value(tokens[2]);
781+
if (value1 != -1) {
782+
ret[key] = {value0, value1};
783+
}
784+
}
785+
}
786+
}
787+
}
788+
}
789+
}
790+
}
791+
return ret;
792+
}
793+
794+
std::string ExtractValueName(std::string const &line) {
795+
auto foundEquals = line.find('=');
796+
if (foundEquals != std::string::npos && foundEquals > 4) {
797+
return line.substr(2, foundEquals - 3);
798+
}
799+
return "";
800+
}
801+
802+
using DxilRegisterToNameMap = std::map<std::pair<int, int>, std::string>;
803+
804+
void CheckForAndInsertMapEntryIfFound(
805+
DxilRegisterToNameMap &registerToNameMap,
806+
std::map<int, std::pair<int, int>> const &metaDataKeyToValue,
807+
std::string const &line, char const *tag, size_t tagLength) {
808+
auto foundAlloca = line.find(tag);
809+
if (foundAlloca != std::string::npos) {
810+
auto valueName = ExtractValueName(line);
811+
if (valueName != "") {
812+
int key = atoi(line.c_str() + foundAlloca + tagLength);
813+
auto foundKey = metaDataKeyToValue.find(key);
814+
if (foundKey != metaDataKeyToValue.end()) {
815+
registerToNameMap[foundKey->second] = valueName;
816+
}
817+
}
818+
}
819+
}
820+
821+
// Here's some exemplary DXIL to help understand what's going on:
822+
//
823+
// %5 = alloca [1 x float], i32 0, !pix-alloca-reg !196
824+
// %25 = call float @dx.op.loadInput.f32(...), !pix-dxil-reg !255
825+
//
826+
// The %5 is an alloca name, and the %25 is a regular llvm value.
827+
// The meta-data tags !pix-alloca-reg and !pix-dxil-reg denote this,
828+
// and provide keys !196 and !255 respectively.
829+
// Those keys are then given values later on in the DXIL like this:
830+
//
831+
// !196 = !{i32 1, i32 5, i32 1} (5 is the base alloca, 1 is the offset into
832+
// it) !255 = !{i32 0, i32 23}
833+
//
834+
// So the task is first to find all of those key/value pairs and make a map
835+
// from e.g. !196 to, e.g., (5,1), and then to find all of the alloca and reg
836+
// tags and look up the keys in said map to build the map we're actually
837+
// looking for, with key->values like e.g. "%5"->(5,1) and "%25"->(23)
838+
839+
DxilRegisterToNameMap BuildDxilRegisterToNameMap(char const *disassembly) {
840+
DxilRegisterToNameMap ret;
841+
842+
auto lines = Tokenize(disassembly, "\n");
843+
844+
auto metaDataKeyToValue = MetaDataKeyToRegisterNumber(lines);
845+
846+
for (auto const &line : lines) {
847+
if (line[0] == '!') {
848+
// Stop searching for values when we've run into the metadata region of
849+
// the disassembly
850+
break;
851+
}
852+
const char allocaTag[] = "!pix-alloca-reg !";
853+
CheckForAndInsertMapEntryIfFound(ret, metaDataKeyToValue, line, allocaTag,
854+
_countof(allocaTag) - 1);
855+
const char valueTag[] = "!pix-dxil-reg !";
856+
CheckForAndInsertMapEntryIfFound(ret, metaDataKeyToValue, line, valueTag,
857+
_countof(valueTag) - 1);
858+
}
859+
return ret;
860+
}
861+
862+
static std::string ToString(std::wstring from)
863+
{
864+
std::string ret;
865+
ret.assign(from.data(), from.data() + from.size());
866+
return ret;
867+
}
868+
731869
PassOutput RunAnnotationPasses(IDxcBlob * dxil, int startingLineNumber = 0)
732870
{
733871
CComPtr<IDxcOptimizer> pOptimizer;
@@ -752,39 +890,18 @@ class PixTest {
752890
outputText = reinterpret_cast<const char*>(pText->GetBufferPointer());
753891
}
754892

755-
auto lines = Tokenize(outputText, "\n");
893+
auto disasm = ToString(Disassemble(pOptimizedModule));
756894

757-
std::vector<ValueLocation> valueLocations;
895+
auto registerToName = BuildDxilRegisterToNameMap(disasm.c_str());
758896

759-
for (size_t line = 0; line < lines.size(); ++line) {
760-
if (lines[line] == "Begin - dxil values to virtual register mapping") {
761-
for (++line; line < lines.size(); ++line) {
762-
if (lines[line] == "End - dxil values to virtual register mapping") {
763-
break;
764-
}
897+
std::vector<ValueLocation> valueLocations;
765898

766-
auto lineTokens = Tokenize(lines[line], " ");
767-
VERIFY_IS_TRUE(lineTokens.size() >= 2);
768-
if (lineTokens[1] == "dxil")
769-
{
770-
VERIFY_IS_TRUE(lineTokens.size() == 3);
771-
valueLocations.push_back({atoi(lineTokens[2].c_str()), 1});
772-
}
773-
else if (lineTokens[1] == "alloca")
774-
{
775-
VERIFY_IS_TRUE(lineTokens.size() == 4);
776-
valueLocations.push_back(
777-
{atoi(lineTokens[2].c_str()), atoi(lineTokens[3].c_str())});
778-
}
779-
else
780-
{
781-
VERIFY_IS_TRUE(false);
782-
}
783-
}
784-
}
899+
for (auto const& r2n : registerToName)
900+
{
901+
valueLocations.push_back({r2n.first.first, r2n.first.second});
785902
}
786903

787-
return { std::move(pOptimizedModule), std::move(valueLocations), std::move(lines) };
904+
return { std::move(pOptimizedModule), std::move(valueLocations), Tokenize(outputText.c_str(), "\n") };
788905
}
789906

790907
std::wstring Disassemble(IDxcBlob * pProgram)
@@ -2126,10 +2243,10 @@ PixTest::TestableResults PixTest::TestStructAnnotationCase(
21262243
for (ValueLocation const &valueLocation :
21272244
passOutput.valueLocations) // For each allocas and dxil values
21282245
{
2129-
if (CurRegIdx == valueLocation.base) {
2246+
if (CurRegIdx == valueLocation.base &&
2247+
valueLocation.count == cover.countOfMembers) {
21302248
VERIFY_IS_FALSE(found);
21312249
found = true;
2132-
VERIFY_ARE_EQUAL(valueLocation.count, cover.countOfMembers);
21332250
}
21342251
}
21352252
VERIFY_IS_TRUE(found);

0 commit comments

Comments
 (0)