[llvm] b2bec7c - [AsmPrinter] Add per BB instruction mix remark.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 26 02:26:22 PDT 2020


Author: Florian Hahn
Date: 2020-10-26T09:25:45Z
New Revision: b2bec7cece9bb7d17799ac0af65a770cab4397ee

URL: https://github.com/llvm/llvm-project/commit/b2bec7cece9bb7d17799ac0af65a770cab4397ee
DIFF: https://github.com/llvm/llvm-project/commit/b2bec7cece9bb7d17799ac0af65a770cab4397ee.diff

LOG: [AsmPrinter] Add per BB instruction mix remark.

This patch adds a remarks that provides counts for each opcode per basic block.

An snippet of the generated information can be seen below.

The current implementation uses the target specific opcode for the counts. For example, on AArch64 this means we currently get 2 entries for `add` instructions if the block contains 32 and 64 bit adds. Similarly, immediate version are treated differently.

Unfortunately there seems to be no convenient way to get only the mnemonic part of the instruction as a string AFAIK. This could be improved in the future.

```
--- !Analysis
Pass:            asm-printer
Name:            InstructionMix
DebugLoc:        { File: arm64-instruction-mix-remarks.ll, Line: 30, Column: 30 }
Function:        foo
Args:
  - String:          'BasicBlock: '
  - BasicBlock:      else
  - String:          "\n"
  - String:          INST_MADDWrrr
  - String:          ': '
  - INST_MADDWrrr:   '2'
  - String:          "\n"
  - String:          INST_MOVZWi
  - String:          ': '
  - INST_MOVZWi:     '1'
```

Reviewed By: anemet, thegameg, paquette

Differential Revision: https://reviews.llvm.org/D89892

Added: 
    llvm/test/CodeGen/AArch64/arm64-instruction-mix-remarks.ll

Modified: 
    llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 97236a5872bc..f491fb137427 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1134,9 +1134,12 @@ void AsmPrinter::emitFunctionBody() {
   bool HasAnyRealCode = false;
   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<unsigned, unsigned> OpcodeCounts;
     for (auto &MI : MBB) {
       // Print the assembly for the instruction.
       if (!MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() &&
@@ -1202,6 +1205,10 @@ void AsmPrinter::emitFunctionBody() {
         break;
       default:
         emitInstruction(&MI);
+        if (CanDoExtraAnalysis) {
+          auto I = OpcodeCounts.insert({MI.getOpcode(), 0u});
+          I.first->second++;
+        }
         break;
       }
 
@@ -1245,6 +1252,35 @@ void AsmPrinter::emitFunctionBody() {
       }
     }
     emitBasicBlockEnd(MBB);
+
+    if (CanDoExtraAnalysis) {
+      // Skip empty blocks.
+      if (MBB.empty())
+        continue;
+
+      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<std::pair<std::string, unsigned>, 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<std::string, unsigned> &A,
+                               const std::pair<std::string, unsigned> &B) {
+        if (A.second > B.second)
+          return true;
+        if (A.second == B.second)
+          return A.first < 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";
+      ORE->emit(R);
+    }
   }
 
   EmittedInsts += NumInstsInFunction;

diff  --git a/llvm/test/CodeGen/AArch64/arm64-instruction-mix-remarks.ll b/llvm/test/CodeGen/AArch64/arm64-instruction-mix-remarks.ll
new file mode 100644
index 000000000000..f56d0d2d0372
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/arm64-instruction-mix-remarks.ll
@@ -0,0 +1,75 @@
+; RUN: llc -mtriple=arm64-apple-ios7.0 -pass-remarks-output=%t -pass-remarks=asm-printer -o - %s | FileCheck %s
+; RUN: FileCheck --input-file=%t --check-prefix=YAML %s
+
+; CHECK-LABEL: %entry
+; CHECK-NEXT:   ldr w8, [x0]
+; CHECK-NEXT:   add w8, w8, w1
+; CHECK-NEXT:   cmp w8, #100
+; 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'
+
+
+; CHECK-LABEL: %then
+; CHECK-NEXT:    mov w0, w8
+; CHECK-NEXT:    ret
+
+; YAML:      Name:            InstructionMix
+; 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'
+
+; CHECK-LABEL: %else
+; CHECK-NEXT:    mul w8, w8, w1
+; CHECK-NEXT:    mov w9, #10
+; CHECK-NEXT:    mul w8, w8, w1
+; CHECK-NEXT:    str w9, [x0]
+; CHECK-NEXT:    mov w0, w8
+; CHECK-NEXT:    ret
+
+; YAML:      Name:            InstructionMix
+; 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 {
+entry:
+  %l = load i32, i32* %ptr, !dbg !4
+  %add = add i32 %l, %x, !dbg !4
+  %c = icmp eq i32 %add, 100, !dbg !4
+  br i1 %c, label %then, label %else, !dbg !4
+
+then:
+  ret i32 %add, !dbg !5
+
+else:
+  store i32 10, i32* %ptr, !dbg !6
+  %res = mul i32 %add, %x, !dbg !6
+  %res.2 = mul i32 %res, %x, !dbg !6
+  ret i32 %res.2, !dbg !6
+}
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1)
+!1 = !DIFile(filename: "arm64-instruction-mix-remarks.ll", directory: "")
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 5, scopeLine: 5, unit: !0)
+!4 = distinct !DILocation(line: 10, column: 10, scope: !3)
+!5 = distinct !DILocation(line: 20, column: 20, scope: !3)
+!6 = distinct !DILocation(line: 30, column: 30, scope: !3)


        


More information about the llvm-commits mailing list