diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -452,6 +452,10 @@ /// so we can sort on them later. void AssignFragment(MCSymbol *Symbol, MCFragment *Fragment); + /// Returns the mnemonic for \p MI, if the streamer has access to a + /// instruction printer and returns an empty string otherwise. + virtual StringRef getMnemonic(MCInst &MI) { return ""; } + /// Emit a label for \p Symbol into the current section. /// /// This corresponds to an assembler statement such as: diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1152,11 +1152,10 @@ int NumInstsInFunction = 0; bool CanDoExtraAnalysis = ORE->allowExtraAnalysis(DEBUG_TYPE); - const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo(); for (auto &MBB : *MF) { // Print a label for the basic block. emitBasicBlockStart(MBB); - DenseMap OpcodeCounts; + DenseMap MnemonicCounts; for (auto &MI : MBB) { // Print the assembly for the instruction. if (!MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() && @@ -1220,7 +1219,10 @@ default: emitInstruction(&MI); if (CanDoExtraAnalysis) { - auto I = OpcodeCounts.insert({MI.getOpcode(), 0u}); + MCInst MCI; + MCI.setOpcode(MI.getOpcode()); + auto Name = OutStreamer->getMnemonic(MCI); + auto I = MnemonicCounts.insert({Name, 0u}); I.first->second++; } break; @@ -1272,24 +1274,25 @@ MachineOptimizationRemarkAnalysis R(DEBUG_TYPE, "InstructionMix", MBB.begin()->getDebugLoc(), &MBB); - // Generate instruction mix remark. First, convert opcodes to string - // names, then sort them in descending order by count and name. - SmallVector, 128> OpcodeCountsVec; - for (auto &KV : OpcodeCounts) { - auto Name = (Twine("INST_") + TII->getName(KV.first)).str(); - OpcodeCountsVec.emplace_back(Name, KV.second); - } - sort(OpcodeCountsVec, [](const std::pair &A, - const std::pair &B) { + // Generate instruction mix remark. First, sort counts in descending order + // by count and name. + SmallVector, 128> MnemonicVec; + for (auto &KV : MnemonicCounts) + MnemonicVec.emplace_back(KV.first, KV.second); + + sort(MnemonicVec, [](const std::pair &A, + const std::pair &B) { if (A.second > B.second) return true; if (A.second == B.second) - return A.first < B.first; + return StringRef(A.first) < StringRef(B.first); return false; }); R << "BasicBlock: " << ore::NV("BasicBlock", MBB.getName()) << "\n"; - for (auto &KV : OpcodeCountsVec) - R << KV.first << ": " << ore::NV(KV.first, KV.second) << "\n"; + for (auto &KV : MnemonicVec) { + auto Name = (Twine("INST_") + KV.first.trim()).str(); + R << KV.first << ": " << ore::NV(Name, KV.second) << "\n"; + } ORE->emit(R); } } diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -144,6 +144,11 @@ const MCSymbol *Aliasee) override; void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override; + + StringRef getMnemonic(MCInst &MI) override { + return InstPrinter->getMnemonic(&MI).first; + } + void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; void emitAssemblerFlag(MCAssemblerFlag Flag) override; diff --git a/llvm/test/CodeGen/AArch64/arm64-instruction-mix-remarks.ll b/llvm/test/CodeGen/AArch64/arm64-instruction-mix-remarks.ll --- a/llvm/test/CodeGen/AArch64/arm64-instruction-mix-remarks.ll +++ b/llvm/test/CodeGen/AArch64/arm64-instruction-mix-remarks.ll @@ -3,19 +3,24 @@ ; CHECK-LABEL: %entry ; CHECK-NEXT: ldr w8, [x0] +; CHECK-NEXT: mov w10, #16959 +; CHECK-NEXT: movk w10, #15, lsl #16 ; CHECK-NEXT: add w8, w8, w1 -; CHECK-NEXT: cmp w8, #100 +; CHECK-NEXT: add x9, x8, x2 +; CHECK-NEXT: cmp x9, x10 ; CHECK-NEXT: b.ne LBB0_2 ; YAML: Name: InstructionMix ; YAML-NEXT: DebugLoc: { File: arm64-instruction-mix-remarks.ll, Line: 10, Column: 10 } ; YAML-NEXT: Function: foo ; YAML-NEXT: Args: -; YAML: - BasicBlock: entry -; YAML: - INST_ADDWrs: '1' -; YAML: - INST_Bcc: '1' -; YAML: - INST_LDRWui: '1' -; YAML: - INST_SUBSWri: '1' +; YAML: - BasicBlock: entry +; YAML: - INST_add: '2' +; YAML: - INST_b.: '1' +; YAML: - INST_ldr: '1' +; YAML: - INST_movk: '1' +; YAML: - INST_movz: '1' +; YAML: - INST_subs: '1' ; CHECK-LABEL: %then @@ -26,9 +31,9 @@ ; YAML-NEXT: DebugLoc: { File: arm64-instruction-mix-remarks.ll, Line: 20, Column: 20 } ; YAML-NEXT: Function: foo ; YAML-NEXT: Args: -; YAML: - BasicBlock: then -; YAML: - INST_ORRWrs: '1' -; YAML: - INST_RET: '1' +; YAML: - BasicBlock: then +; YAML: - INST_orr: '1' +; YAML: - INST_ret: '1' ; CHECK-LABEL: %else ; CHECK-NEXT: mul w8, w8, w1 @@ -42,16 +47,18 @@ ; YAML-NEXT: DebugLoc: { File: arm64-instruction-mix-remarks.ll, Line: 30, Column: 30 } ; YAML-NEXT: Function: foo ; YAML-NEXT: Args: -; YAML: - BasicBlock: else -; YAML: - INST_MADDWrrr: '2' -; YAML: - INST_ORRWrs: '1' -; YAML: - INST_RET: '1' -; YAML: - INST_STRWui: '1' -define i32 @foo(i32* %ptr, i32 %x) !dbg !3 { +; YAML: - BasicBlock: else +; YAML: - INST_madd: '2' +; YAML: - INST_orr: '1' +; YAML: - INST_ret: '1' +; YAML: - INST_str: '1' +define i32 @foo(i32* %ptr, i32 %x, i64 %y) !dbg !3 { entry: %l = load i32, i32* %ptr, !dbg !4 %add = add i32 %l, %x, !dbg !4 - %c = icmp eq i32 %add, 100, !dbg !4 + %add.ext = zext i32 %add to i64, !dbg !4 + %add.64 = add i64 %add.ext, %y, !dbg !4 + %c = icmp eq i64 %add.64, 999999, !dbg !4 br i1 %c, label %then, label %else, !dbg !4 then: