[llvm] 0e34347 - [llvm-mca] Compare multiple files

Djordje Todorovic via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 21 02:57:07 PST 2021


Author: Djordje Todorovic
Date: 2021-12-21T11:56:18+01:00
New Revision: 0e343479a7ea9cabac8c467cd24bc3ed463b8786

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

LOG: [llvm-mca] Compare multiple files

Script (llvm-mca-compare.py) uses llvm-mca tool to print
statistics in console for multiple files.
Script requires specified --llvm-mca-binary option (specified
relative path to binary of llvm-mca).
Options: --args [="-option1=<arg> -option2=<arg> ..."], -v or -h can also be used.

The script is used as follows:
$ llvm-project/llvm/utils/llvm-mca-compare.py file1.s --llvm-mca-binary=build/bin/llvm-mca

Patch by Milica Matic <Milica.Matic at syrmia.com>

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

Added: 
    llvm/utils/llvm-mca-compare.py

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/llvm/utils/llvm-mca-compare.py b/llvm/utils/llvm-mca-compare.py
new file mode 100755
index 0000000000000..72c875d424422
--- /dev/null
+++ b/llvm/utils/llvm-mca-compare.py
@@ -0,0 +1,279 @@
+#!/usr/bin/env python3
+
+import argparse
+import sys
+from json import loads
+from subprocess import Popen, PIPE
+
+# Holds code regions statistics.
+class Summary:
+    def __init__(
+        self,
+        name,
+        block_rthroughput,
+        dispatch_width,
+        ipc,
+        instructions,
+        iterations,
+        total_cycles,
+        total_uops,
+        uops_per_cycle,
+        iteration_resource_pressure,
+        name_target_info_resources,
+    ):
+        self.name = name
+        self.block_rthroughput = block_rthroughput
+        self.dispatch_width = dispatch_width
+        self.ipc = ipc
+        self.instructions = instructions
+        self.iterations = iterations
+        self.total_cycles = total_cycles
+        self.total_uops = total_uops
+        self.uops_per_cycle = uops_per_cycle
+        self.iteration_resource_pressure = iteration_resource_pressure
+        self.name_target_info_resources = name_target_info_resources
+
+
+# Parse the program arguments.
+def parse_program_args(parser):
+    parser.add_argument(
+        "file_names",
+        nargs="+",
+        type=str,
+        help="Names of files which llvm-mca tool process.",
+    )
+    parser.add_argument(
+        "--llvm-mca-binary",
+        nargs=1,
+        required=True,
+        type=str,
+        action="store",
+        metavar="[=<path to llvm-mca>]",
+        help="Specified relative path to binary of llvm-mca.",
+    )
+    parser.add_argument(
+        "--args",
+        nargs=1,
+        type=str,
+        action="store",
+        metavar="[='-option1=<arg> -option2=<arg> ...']",
+        default=["-"],
+        help="Forward options to lvm-mca tool.",
+    )
+    parser.add_argument(
+        "-v",
+        action="store_true",
+        default=False,
+        help="More details about the running lvm-mca tool.",
+    )
+    return parser.parse_args()
+
+
+# Returns the name of the file to be analyzed from the path it is on.
+def get_filename_from_path(path):
+    index_of_slash = path.rfind("/")
+    return path[(index_of_slash + 1) : len(path)]
+
+
+# Returns the results of the running llvm-mca tool for the input file.
+def run_llvm_mca_tool(opts, file_name):
+    # Get the path of the llvm-mca binary file.
+    llvm_mca_cmd = opts.llvm_mca_binary[0]
+
+    # The statistics llvm-mca options.
+    if opts.args[0] != "-":
+        llvm_mca_cmd += " " + opts.args[0]
+    llvm_mca_cmd += " -json"
+
+    # Set file which llvm-mca tool will process.
+    llvm_mca_cmd += " " + file_name
+
+    if opts.v:
+        print("run: $ " + llvm_mca_cmd + "\n")
+
+    # Generate the stats with the llvm-mca.
+    subproc = Popen(
+        llvm_mca_cmd.split(" "),
+        stdin=PIPE,
+        stdout=PIPE,
+        stderr=PIPE,
+        universal_newlines=True,
+    )
+
+    cmd_stdout, cmd_stderr = subproc.communicate()
+
+    try:
+        json_parsed = loads(cmd_stdout)
+    except:
+        print("error: No valid llvm-mca statistics found.")
+        print(cmd_stderr)
+        sys.exit(1)
+
+    if opts.v:
+        print("Simulation Parameters: ")
+        simulation_parameters = json_parsed["SimulationParameters"]
+        for key in simulation_parameters:
+            print(key, ":", simulation_parameters[key])
+        print("\n")
+
+    code_regions_len = len(json_parsed["CodeRegions"])
+    array_of_code_regions = [None] * code_regions_len
+
+    for i in range(code_regions_len):
+        code_region_instructions_len = len(
+            json_parsed["CodeRegions"][i]["Instructions"]
+        )
+        target_info_resources_len = len(json_parsed["TargetInfo"]["Resources"])
+        iteration_resource_pressure = ["-" for k in range(target_info_resources_len)]
+        resource_pressure_info = json_parsed["CodeRegions"][i]["ResourcePressureView"][
+            "ResourcePressureInfo"
+        ]
+
+        name_target_info_resources = [" "] + json_parsed["TargetInfo"]["Resources"]
+
+        for s in range(len(resource_pressure_info)):
+            obj_of_resource_pressure_info = resource_pressure_info[s]
+            if (
+                obj_of_resource_pressure_info["InstructionIndex"]
+                == code_region_instructions_len
+            ):
+                iteration_resource_pressure[
+                    obj_of_resource_pressure_info["ResourceIndex"]
+                ] = str(round(obj_of_resource_pressure_info["ResourceUsage"], 2))
+
+        array_of_code_regions[i] = Summary(
+            file_name,
+            json_parsed["CodeRegions"][i]["SummaryView"]["BlockRThroughput"],
+            json_parsed["CodeRegions"][i]["SummaryView"]["DispatchWidth"],
+            json_parsed["CodeRegions"][i]["SummaryView"]["IPC"],
+            json_parsed["CodeRegions"][i]["SummaryView"]["Instructions"],
+            json_parsed["CodeRegions"][i]["SummaryView"]["Iterations"],
+            json_parsed["CodeRegions"][i]["SummaryView"]["TotalCycles"],
+            json_parsed["CodeRegions"][i]["SummaryView"]["TotaluOps"],
+            json_parsed["CodeRegions"][i]["SummaryView"]["uOpsPerCycle"],
+            iteration_resource_pressure,
+            name_target_info_resources,
+        )
+
+    return array_of_code_regions
+
+
+# Print statistics in console for single file or for multiple files.
+def console_print_results(matrix_of_code_regions, opts):
+    try:
+        import termtables as tt
+    except ImportError:
+        print("error: termtables not found.")
+        sys.exit(1)
+
+    headers_names = [None] * (len(opts.file_names) + 1)
+    headers_names[0] = " "
+
+    max_code_regions = 0
+
+    print("Input files:")
+    for i in range(len(matrix_of_code_regions)):
+        if max_code_regions < len(matrix_of_code_regions[i]):
+            max_code_regions = len(matrix_of_code_regions[i])
+        print("[f" + str(i + 1) + "]: " + get_filename_from_path(opts.file_names[i]))
+        headers_names[i + 1] = "[f" + str(i + 1) + "]: "
+
+    print("\nITERATIONS: " + str(matrix_of_code_regions[0][0].iterations) + "\n")
+
+    for i in range(max_code_regions):
+
+        print(
+            "\n-----------------------------------------\nCode region: "
+            + str(i + 1)
+            + "\n"
+        )
+
+        table_values = [
+            [[None] for i in range(len(matrix_of_code_regions) + 1)] for j in range(7)
+        ]
+
+        table_values[0][0] = "Instructions: "
+        table_values[1][0] = "Total Cycles: "
+        table_values[2][0] = "Total uOps: "
+        table_values[3][0] = "Dispatch Width: "
+        table_values[4][0] = "uOps Per Cycle: "
+        table_values[5][0] = "IPC: "
+        table_values[6][0] = "Block RThroughput: "
+
+        for j in range(len(matrix_of_code_regions)):
+            if len(matrix_of_code_regions[j]) > i:
+                table_values[0][j + 1] = str(matrix_of_code_regions[j][i].instructions)
+                table_values[1][j + 1] = str(matrix_of_code_regions[j][i].total_cycles)
+                table_values[2][j + 1] = str(matrix_of_code_regions[j][i].total_uops)
+                table_values[3][j + 1] = str(
+                    matrix_of_code_regions[j][i].dispatch_width
+                )
+                table_values[4][j + 1] = str(
+                    round(matrix_of_code_regions[j][i].uops_per_cycle, 2)
+                )
+                table_values[5][j + 1] = str(round(matrix_of_code_regions[j][i].ipc, 2))
+                table_values[6][j + 1] = str(
+                    round(matrix_of_code_regions[j][i].block_rthroughput, 2)
+                )
+            else:
+                table_values[0][j + 1] = "-"
+                table_values[1][j + 1] = "-"
+                table_values[2][j + 1] = "-"
+                table_values[3][j + 1] = "-"
+                table_values[4][j + 1] = "-"
+                table_values[5][j + 1] = "-"
+                table_values[6][j + 1] = "-"
+
+        tt.print(
+            table_values,
+            header=headers_names,
+            style=tt.styles.ascii_thin_double,
+            padding=(0, 1),
+        )
+
+        print("\nResource pressure per iteration: \n")
+
+        table_values = [
+            [
+                [None]
+                for i in range(
+                    len(matrix_of_code_regions[0][0].iteration_resource_pressure) + 1
+                )
+            ]
+            for j in range(len(matrix_of_code_regions) + 1)
+        ]
+
+        table_values[0] = matrix_of_code_regions[0][0].name_target_info_resources
+
+        for j in range(len(matrix_of_code_regions)):
+            if len(matrix_of_code_regions[j]) > i:
+                table_values[j + 1] = [
+                    "[f" + str(j + 1) + "]: "
+                ] + matrix_of_code_regions[j][i].iteration_resource_pressure
+            else:
+                table_values[j + 1] = ["[f" + str(j + 1) + "]: "] + len(
+                    matrix_of_code_regions[0][0].iteration_resource_pressure
+                ) * ["-"]
+
+        tt.print(
+            table_values,
+            style=tt.styles.ascii_thin_double,
+            padding=(0, 1),
+        )
+        print("\n")
+
+
+def Main():
+    parser = argparse.ArgumentParser()
+    opts = parse_program_args(parser)
+
+    matrix_of_code_regions = [None] * len(opts.file_names)
+
+    for i in range(len(opts.file_names)):
+        matrix_of_code_regions[i] = run_llvm_mca_tool(opts, opts.file_names[i])
+    console_print_results(matrix_of_code_regions, opts)
+
+
+if __name__ == "__main__":
+    Main()
+    sys.exit(0)


        


More information about the llvm-commits mailing list