add insn-histogram.py from bug #532
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 24 Nov 2020 00:44:29 +0000 (00:44 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 24 Nov 2020 00:44:32 +0000 (00:44 +0000)
https://bugs.libre-soc.org/show_bug.cgi?id=532

openpower/sv/insn-histogram.py [new file with mode: 0644]

diff --git a/openpower/sv/insn-histogram.py b/openpower/sv/insn-histogram.py
new file mode 100644 (file)
index 0000000..48b1409
--- /dev/null
@@ -0,0 +1,95 @@
+#! /bin/env python3
+
+# Feed this script the output of:
+# powerpc64le-gnu-objdump -d -M raw --no-show-raw-insn ppc-prog
+
+# It will print the occurrence count of each opcode,
+# and under it, indented by one character,
+# the occurrence count of each operand.
+
+# Registers used as operands or as base addresses are counted
+# separately; immediates and offsets are grouped per bit length;
+# branch target offsets are grouped by range bit length.
+
+import sys
+import re
+
+insn = re.compile('\s+(?P<addr>[0-9a-f]+):\s+(?P<opcode>[^ \n]+) *(?P<operands>.*)[\n]?')
+
+opkind = re.compile('(?P<immediate>-?[0-9]+)|(?P<branch>[0-9a-f]+)(?: <.*>)?|(?P<offset>-?[0-9]+)\((?P<basereg>r[0-9]+)\)')
+
+histogram = {}
+
+def count(ops, op):
+    match = opkind.fullmatch(op)
+
+    if match is None:
+        op = op
+    elif match['immediate'] is not None:
+        op = "%i-bit" % int (op).bit_length ()
+    elif match['branch'] is not None:
+        op = "%i-bit range" % (int (match['branch'], 16) - 
+                               int(addr, 16)).bit_length ()
+    elif match['offset'] is not None:
+        count(ops, match['offset'])
+        op = match['basereg']
+    else:
+        raise "unrecognized operand kind"
+
+    if op not in ops:
+        ops[op] = 1
+    else:
+        ops[op] += 1
+
+for line in sys.stdin:
+    match = insn.fullmatch(line)
+    if match is None:
+        continue
+
+    addr = match['addr']
+    opcode = match['opcode']
+    operands = match['operands']
+
+    if opcode not in histogram:
+        ops = {}
+        histogram[opcode] = [1,ops]
+    else:
+        histogram[opcode][0] += 1
+        ops = histogram[opcode][1]
+
+    if len(operands) > 0:
+        for operand in operands.split(','):
+            count(ops, operand)
+
+hist = list(histogram.items())
+hist.sort(key = (lambda x : x[1][0]))
+for x in hist:
+    print('%6i %s:' % (x[1][0], x[0]))
+    ops = list(x[1][1].items())
+    ops.sort(key = (lambda x : x[1]))
+    # split out "-bit" from "-bit range" from "regs"
+    # first "rNs" or "anything-weird"
+    for x in ops:
+        if '-bit' in x[0]:
+            continue
+        if x[0].startswith('cr'):
+            continue
+        print('\t%6i %s' % (x[1], x[0]))
+    print()
+    # now Condition Registers
+    for x in ops:
+        if '-bit' in x[0]:
+            continue
+        if x[0].startswith('cr'):
+            print('\t%6i %s' % (x[1], x[0]))
+    print()
+    # now "N-bit immediates"
+    for x in ops:
+        if x[0].endswith('-bit'):
+            print('\t%6i %s' % (x[1], x[0]))
+    print()
+    # finally "bit-range" immediates
+    for x in ops:
+        if '-bit range' in x[0]:
+            print('\t%6i %s' % (x[1], x[0]))
+    print()