diff --git a/Core/MIPS/IR/IRInst.cpp b/Core/MIPS/IR/IRInst.cpp index 376f9951b2a8..191ab8b2f7f8 100644 --- a/Core/MIPS/IR/IRInst.cpp +++ b/Core/MIPS/IR/IRInst.cpp @@ -1,6 +1,7 @@ #include "Common/CommonFuncs.h" #include "Core/MIPS/IR/IRInst.h" #include "Core/MIPS/MIPSDebugInterface.h" +#include "Core/HLE/ReplaceTables.h" // Legend // ====================== @@ -13,6 +14,7 @@ // 2 = FPR register, Vec2 (uncommon) // v = Vec4Init constant, chosen by immediate // s = Shuffle immediate (4 2-bit fields, choosing a xyzw shuffle) +// r = Replacement function (in constant field) static const IRMeta irMeta[] = { { IROp::Nop, "Nop", "" }, @@ -165,7 +167,7 @@ static const IRMeta irMeta[] = { { IROp::Break, "Break", "", IRFLAG_EXIT }, { IROp::SetPC, "SetPC", "_G" }, { IROp::SetPCConst, "SetPC", "_C" }, - { IROp::CallReplacement, "CallRepl", "GC", IRFLAG_BARRIER }, + { IROp::CallReplacement, "CallRepl", "Gr", IRFLAG_BARRIER }, { IROp::Breakpoint, "Breakpoint", "_C", IRFLAG_BARRIER }, { IROp::MemoryCheck, "MemoryCheck", "IGC", IRFLAG_BARRIER }, @@ -306,6 +308,16 @@ void DisassembleParam(char *buf, int bufSize, u8 param, char type, u32 constant) case 's': snprintf(buf, bufSize, "%c%c%c%c", xyzw[param & 3], xyzw[(param >> 2) & 3], xyzw[(param >> 4) & 3], xyzw[(param >> 6) & 3]); break; + case 'r': + { + const ReplacementTableEntry *entry = GetReplacementFunc(constant); + if (entry) { + snprintf(buf, bufSize, "%s", entry->name); + } else { + snprintf(buf, bufSize, "(unkn. repl %d)", constant); + } + break; + } case '_': case '\0': buf[0] = 0; diff --git a/Core/MIPS/IR/IRJit.cpp b/Core/MIPS/IR/IRJit.cpp index 07c7a5416208..6815c941ed25 100644 --- a/Core/MIPS/IR/IRJit.cpp +++ b/Core/MIPS/IR/IRJit.cpp @@ -465,7 +465,6 @@ void IRBlockCache::ComputeStats(BlockCacheStats &bcStats) const { bcStats.maxBloatBlock = origAddr; } totalBloat += bloat; - bcStats.bloatMap[bloat] = origAddr; } bcStats.numBlocks = (int)blocks_.size(); bcStats.minBloat = minBloat; diff --git a/Core/MIPS/IR/IRNativeCommon.cpp b/Core/MIPS/IR/IRNativeCommon.cpp index e0a0b4d09927..c3253230bce9 100644 --- a/Core/MIPS/IR/IRNativeCommon.cpp +++ b/Core/MIPS/IR/IRNativeCommon.cpp @@ -801,7 +801,6 @@ void IRNativeBlockCacheDebugInterface::ComputeStats(BlockCacheStats &bcStats) co bcStats.maxBloatBlock = origAddr; } totalBloat += bloat; - bcStats.bloatMap[(float)bloat] = origAddr; } bcStats.numBlocks = numBlocks; bcStats.minBloat = (float)minBloat; diff --git a/Core/MIPS/JitCommon/JitBlockCache.cpp b/Core/MIPS/JitCommon/JitBlockCache.cpp index 120207eb60f9..cf1838951b2c 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.cpp +++ b/Core/MIPS/JitCommon/JitBlockCache.cpp @@ -681,7 +681,6 @@ void JitBlockCache::ComputeStats(BlockCacheStats &bcStats) const { bcStats.maxBloatBlock = b->originalAddress; } totalBloat += bloat; - bcStats.bloatMap[(float)bloat] = b->originalAddress; } bcStats.numBlocks = num_blocks_; bcStats.minBloat = (float)minBloat; @@ -710,6 +709,5 @@ JitBlockDebugInfo JitBlockCache::GetBlockDebugInfo(int blockNum) const { #elif PPSSPP_ARCH(RISCV64) debugInfo.targetDisasm = DisassembleRV64(block->normalEntry, block->codeSize); #endif - return debugInfo; } diff --git a/Core/MIPS/JitCommon/JitBlockCache.h b/Core/MIPS/JitCommon/JitBlockCache.h index cfd363b69e00..16457b0b066f 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.h +++ b/Core/MIPS/JitCommon/JitBlockCache.h @@ -42,7 +42,6 @@ struct BlockCacheStats { u32 minBloatBlock; float maxBloat; u32 maxBloatBlock; - std::map bloatMap; }; enum class DestroyType { diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 4b909c2d0308..f864191b108e 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -188,7 +188,7 @@ static const MIPSInstruction tableSpecial[64] = // 000000 ..... ..... ..... .... INSTR("jalr", JITFUNC(Comp_JumpReg), Dis_JumpRegType, Int_JumpRegType, IS_JUMP|IN_RS|OUT_RD|DELAYSLOT), INSTR("movz", JITFUNC(Comp_RType3), Dis_RType3, Int_RType3, OUT_RD|IN_RS|IN_RT|IS_CONDMOVE|CONDTYPE_EQ), INSTR("movn", JITFUNC(Comp_RType3), Dis_RType3, Int_RType3, OUT_RD|IN_RS|IN_RT|IS_CONDMOVE|CONDTYPE_NE), - INSTR("syscall", JITFUNC(Comp_Syscall), Dis_Syscall, Int_Syscall, IN_MEM|IN_OTHER|OUT_MEM|OUT_OTHER), + INSTR("syscall", JITFUNC(Comp_Syscall), Dis_Syscall, Int_Syscall, IN_MEM|IN_OTHER|OUT_MEM|OUT_OTHER|IS_SYSCALL), INSTR("break", JITFUNC(Comp_Break), Dis_Generic, Int_Break, 0), INVALID, INSTR("sync", JITFUNC(Comp_DoNothing), Dis_Generic, Int_Sync, 0), diff --git a/Core/MIPS/MIPSTables.h b/Core/MIPS/MIPSTables.h index 9c53a07ea011..905c69d6beac 100644 --- a/Core/MIPS/MIPSTables.h +++ b/Core/MIPS/MIPSTables.h @@ -92,6 +92,8 @@ #define OUT_VD 0x100000000000ULL +#define IS_SYSCALL 0x200000000000ULL + #ifndef CDECL #define CDECL #endif diff --git a/UI/JitCompareScreen.cpp b/UI/JitCompareScreen.cpp index 1d1630dd14e9..f14ddfa908b8 100644 --- a/UI/JitCompareScreen.cpp +++ b/UI/JitCompareScreen.cpp @@ -9,19 +9,34 @@ #include "Core/MIPS/JitCommon/JitState.h" JitCompareScreen::JitCompareScreen() : UIDialogScreenWithBackground() { + JitBlockCacheDebugInterface *blockCacheDebug = MIPSComp::jit->GetBlockCacheDebugInterface(); + // The only defaults that make sense. + if (blockCacheDebug->SupportsProfiling()) { + listSort_ = ListSort::TIME_SPENT; + } else { + listSort_ = ListSort::BLOCK_LENGTH_DESC; + } FillBlockList(); } void JitCompareScreen::Flip() { using namespace UI; + // If we add more, let's convert to a for loop. switch (viewMode_) { case ViewMode::DISASM: comparisonView_->SetVisibility(V_VISIBLE); blockListView_->SetVisibility(V_GONE); + statsView_->SetVisibility(V_GONE); break; case ViewMode::BLOCK_LIST: comparisonView_->SetVisibility(V_GONE); blockListView_->SetVisibility(V_VISIBLE); + statsView_->SetVisibility(V_GONE); + break; + case ViewMode::STATS: + comparisonView_->SetVisibility(V_GONE); + blockListView_->SetVisibility(V_GONE); + statsView_->SetVisibility(V_VISIBLE); break; } } @@ -123,6 +138,13 @@ void JitCompareScreen::CreateViews() { ScrollView *blockScroll = blockListView_->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f))); blockListContainer_ = blockScroll->Add(new LinearLayout(ORIENT_VERTICAL)); + statsView_ = root_->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f))); + statsView_->SetVisibility(V_GONE); + + LinearLayout *statsTopBar = statsView_->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + ScrollView *statsScroll = statsView_->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f))); + statsContainer_ = statsScroll->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + // leftColumn->Add(new Choice(dev->T("By Address")))->OnClick.Handle(this, &JitCompareScreen::OnSelectBlock); leftColumn->Add(new Choice(dev->T("All")))->OnClick.Add([=](UI::EventParams &e) { listType_ = ListType::ALL_BLOCKS; @@ -151,6 +173,9 @@ void JitCompareScreen::CreateViews() { void JitCompareScreen::FillBlockList() { JitBlockCacheDebugInterface *blockCacheDebug = MIPSComp::jit->GetBlockCacheDebugInterface(); blockList_.clear(); + int64_t sumTotalNanos = 0; + int64_t sumExecutions = 0; + bool profiling = blockCacheDebug->SupportsProfiling(); for (int i = 0; i < blockCacheDebug->GetNumBlocks(); i++) { if (!blockCacheDebug->IsValidBlock(i)) { continue; @@ -163,12 +188,15 @@ void JitCompareScreen::FillBlockList() { case ListType::FPU_BLOCKS: case ListType::VFPU_BLOCKS: { - const int flags = listType_ == ListType::FPU_BLOCKS ? IS_FPU : IS_VFPU; + const uint64_t flags = listType_ == ListType::FPU_BLOCKS ? IS_FPU : IS_VFPU; + // const uint64_t antiFlags = IS_SYSCALL; + const uint64_t antiFlags = 0; JitBlockMeta meta = blockCacheDebug->GetBlockMeta(i); if (meta.valid) { for (u32 addr = meta.addr; addr < meta.addr + meta.sizeInBytes; addr += 4) { MIPSOpcode opcode = Memory::Read_Instruction(addr); - if (MIPSGetInfo(opcode) & flags) { + MIPSInfo info = MIPSGetInfo(opcode); + if ((info & flags) && !(info & antiFlags)) { blockList_.push_back(i); break; } @@ -178,8 +206,17 @@ void JitCompareScreen::FillBlockList() { default: break; } + + if (profiling) { + JitBlockProfileStats stats = blockCacheDebug->GetBlockProfileStats(i); + sumTotalNanos += stats.totalNanos; + sumExecutions += stats.executions; + } } + sumTotalNanos_ = sumTotalNanos; + sumExecutions_ = sumExecutions; + if (listSort_ == ListSort::BLOCK_NUM) { // Already sorted, effectively. return; @@ -273,19 +310,30 @@ void JitCompareScreen::UpdateDisasm() { int numMips = leftDisasm_->GetNumSubviews(); int numHost = rightDisasm_->GetNumSubviews(); - snprintf(temp, sizeof(temp), "%d to %d : %d%%", numMips, numHost, 100 * numHost / numMips); + double bloat = 100.0 * numHost / numMips; + if (blockCacheDebug->SupportsProfiling()) { + JitBlockProfileStats stats = blockCacheDebug->GetBlockProfileStats(blockNum); + int execs = (int)stats.executions; + double us = (double)stats.totalNanos / 1000000.0; + double percentage = 100.0 * (double)stats.totalNanos / (double)sumTotalNanos_; + snprintf(temp, sizeof(temp), "%d runs, %0.2f ms, %0.2f%%, bloat: %0.1f%%", execs, us, percentage, bloat); + } else { + snprintf(temp, sizeof(temp), "bloat: %0.1f%%", bloat); + } blockStats_->SetText(temp); - } else { + } else if (viewMode_ == ViewMode::BLOCK_LIST) { blockListContainer_->Clear(); + bool profiling = blockCacheDebug->SupportsProfiling(); for (int i = 0; i < std::min(100, (int)blockList_.size()); i++) { int blockNum = blockList_[i]; JitBlockMeta meta = blockCacheDebug->GetBlockMeta(blockNum); char temp[512], small[512]; - if (blockCacheDebug->SupportsProfiling()) { + if (profiling) { JitBlockProfileStats stats = blockCacheDebug->GetBlockProfileStats(blockNum); int execs = (int)stats.executions; - double us = (double)stats.totalNanos / 1000.0; - snprintf(temp, sizeof(temp), "%08x: %d instrs (%d exec, %0.2f us)", meta.addr, meta.sizeInBytes / 4, execs, us); + double us = (double)stats.totalNanos / 1000000.0; + double percentage = 100.0 * (double)stats.totalNanos / (double)sumTotalNanos_; + snprintf(temp, sizeof(temp), "%08x: %d instrs (%d runs, %0.2f ms, %0.2f%%)", meta.addr, meta.sizeInBytes / 4, execs, us, percentage); } else { snprintf(temp, sizeof(temp), "%08x: %d instrs", meta.addr, meta.sizeInBytes / 4); } @@ -293,6 +341,24 @@ void JitCompareScreen::UpdateDisasm() { Choice *blockChoice = blockListContainer_->Add(new Choice(temp, small)); blockChoice->OnClick.Handle(this, &JitCompareScreen::OnBlockClick); } + } else { // viewMode_ == ViewMode::STATS + statsContainer_->Clear(); + + BlockCacheStats bcStats; + blockCacheDebug->ComputeStats(bcStats); + + char stats[1024]; + snprintf(stats, sizeof(stats), + "Num blocks: %d\n" + "Average Bloat: %0.2f%%\n" + "Min Bloat: %0.2f%% (%08x)\n" + "Max Bloat: %0.2f%% (%08x)\n", + blockCacheDebug->GetNumBlocks(), + 100.0 * bcStats.avgBloat, + 100.0 * bcStats.minBloat, bcStats.minBloatBlock, + 100.0 * bcStats.maxBloat, bcStats.maxBloatBlock); + + statsContainer_->Add(new TextView(stats)); } } @@ -332,26 +398,8 @@ UI::EventReturn JitCompareScreen::OnShowStats(UI::EventParams &e) { return UI::EVENT_DONE; } - JitBlockCacheDebugInterface *blockCache = MIPSComp::jit->GetBlockCacheDebugInterface(); - if (!blockCache) - return UI::EVENT_DONE; - - BlockCacheStats bcStats; - blockCache->ComputeStats(bcStats); - NOTICE_LOG(JIT, "Num blocks: %i", bcStats.numBlocks); - NOTICE_LOG(JIT, "Average Bloat: %0.2f%%", 100 * bcStats.avgBloat); - NOTICE_LOG(JIT, "Min Bloat: %0.2f%% (%08x)", 100 * bcStats.minBloat, bcStats.minBloatBlock); - NOTICE_LOG(JIT, "Max Bloat: %0.2f%% (%08x)", 100 * bcStats.maxBloat, bcStats.maxBloatBlock); - - int ctr = 0, sz = (int)bcStats.bloatMap.size(); - for (auto iter : bcStats.bloatMap) { - if (ctr < 10 || ctr > sz - 10) { - NOTICE_LOG(JIT, "%08x: %f", iter.second, iter.first); - } else if (ctr == 10) { - NOTICE_LOG(JIT, "..."); - } - ctr++; - } + viewMode_ = ViewMode::STATS; + UpdateDisasm(); return UI::EVENT_DONE; } diff --git a/UI/JitCompareScreen.h b/UI/JitCompareScreen.h index 03403343f8f0..8a3828f1e435 100644 --- a/UI/JitCompareScreen.h +++ b/UI/JitCompareScreen.h @@ -17,9 +17,15 @@ class JitCompareScreen : public UIDialogScreenWithBackground { void FillBlockList(); UI::LinearLayout *comparisonView_; + UI::LinearLayout *leftDisasm_; + UI::LinearLayout *rightDisasm_; + UI::LinearLayout *blockListView_; UI::LinearLayout *blockListContainer_; + UI::LinearLayout *statsView_; + UI::LinearLayout *statsContainer_; + UI::EventReturn OnSelectBlock(UI::EventParams &e); UI::EventReturn OnBlockAddress(UI::EventParams &e); UI::EventReturn OnAddressChange(UI::EventParams &e); @@ -30,6 +36,7 @@ class JitCompareScreen : public UIDialogScreenWithBackground { enum class ViewMode { BLOCK_LIST, DISASM, + STATS, }; enum class ListType { ALL_BLOCKS, @@ -46,17 +53,16 @@ class JitCompareScreen : public UIDialogScreenWithBackground { }; ViewMode viewMode_ = ViewMode::BLOCK_LIST; ListType listType_ = ListType::ALL_BLOCKS; - ListSort listSort_ = ListSort::BLOCK_LENGTH_DESC; + ListSort listSort_ = ListSort::TIME_SPENT; int currentBlock_ = -1; // For DISASM mode + int64_t sumTotalNanos_ = 0; + int64_t sumExecutions_ = 0; std::vector blockList_; // for BLOCK_LIST mode UI::TextView *blockName_; UI::TextEdit *blockAddr_; UI::TextView *blockStats_; - - UI::LinearLayout *leftDisasm_; - UI::LinearLayout *rightDisasm_; }; class AddressPromptScreen : public PopupScreen {