xref: /llvm-project/llvm/utils/llvm-mca-compare.py (revision 402f91bcbb5157a122b92366b0f5f9a917df06a3)
10e343479SDjordje Todorovic#!/usr/bin/env python3
20e343479SDjordje Todorovic
30e343479SDjordje Todorovicimport argparse
40e343479SDjordje Todorovicimport sys
5*402f91bcSMilica Maticimport os
60e343479SDjordje Todorovicfrom json import loads
70e343479SDjordje Todorovicfrom subprocess import Popen, PIPE
80e343479SDjordje Todorovic
90e343479SDjordje Todorovic# Holds code regions statistics.
100e343479SDjordje Todorovicclass Summary:
110e343479SDjordje Todorovic    def __init__(
120e343479SDjordje Todorovic        self,
130e343479SDjordje Todorovic        name,
140e343479SDjordje Todorovic        block_rthroughput,
150e343479SDjordje Todorovic        dispatch_width,
160e343479SDjordje Todorovic        ipc,
170e343479SDjordje Todorovic        instructions,
180e343479SDjordje Todorovic        iterations,
190e343479SDjordje Todorovic        total_cycles,
200e343479SDjordje Todorovic        total_uops,
210e343479SDjordje Todorovic        uops_per_cycle,
220e343479SDjordje Todorovic        iteration_resource_pressure,
230e343479SDjordje Todorovic        name_target_info_resources,
240e343479SDjordje Todorovic    ):
250e343479SDjordje Todorovic        self.name = name
260e343479SDjordje Todorovic        self.block_rthroughput = block_rthroughput
270e343479SDjordje Todorovic        self.dispatch_width = dispatch_width
280e343479SDjordje Todorovic        self.ipc = ipc
290e343479SDjordje Todorovic        self.instructions = instructions
300e343479SDjordje Todorovic        self.iterations = iterations
310e343479SDjordje Todorovic        self.total_cycles = total_cycles
320e343479SDjordje Todorovic        self.total_uops = total_uops
330e343479SDjordje Todorovic        self.uops_per_cycle = uops_per_cycle
340e343479SDjordje Todorovic        self.iteration_resource_pressure = iteration_resource_pressure
350e343479SDjordje Todorovic        self.name_target_info_resources = name_target_info_resources
360e343479SDjordje Todorovic
370e343479SDjordje Todorovic
380e343479SDjordje Todorovic# Parse the program arguments.
390e343479SDjordje Todorovicdef parse_program_args(parser):
400e343479SDjordje Todorovic    parser.add_argument(
410e343479SDjordje Todorovic        "file_names",
420e343479SDjordje Todorovic        nargs="+",
430e343479SDjordje Todorovic        type=str,
440e343479SDjordje Todorovic        help="Names of files which llvm-mca tool process.",
450e343479SDjordje Todorovic    )
460e343479SDjordje Todorovic    parser.add_argument(
470e343479SDjordje Todorovic        "--llvm-mca-binary",
480e343479SDjordje Todorovic        nargs=1,
490e343479SDjordje Todorovic        required=True,
500e343479SDjordje Todorovic        type=str,
510e343479SDjordje Todorovic        action="store",
520e343479SDjordje Todorovic        metavar="[=<path to llvm-mca>]",
530e343479SDjordje Todorovic        help="Specified relative path to binary of llvm-mca.",
540e343479SDjordje Todorovic    )
550e343479SDjordje Todorovic    parser.add_argument(
560e343479SDjordje Todorovic        "--args",
570e343479SDjordje Todorovic        nargs=1,
580e343479SDjordje Todorovic        type=str,
590e343479SDjordje Todorovic        action="store",
600e343479SDjordje Todorovic        metavar="[='-option1=<arg> -option2=<arg> ...']",
610e343479SDjordje Todorovic        default=["-"],
620e343479SDjordje Todorovic        help="Forward options to lvm-mca tool.",
630e343479SDjordje Todorovic    )
640e343479SDjordje Todorovic    parser.add_argument(
65*402f91bcSMilica Matic        "-plot",
66*402f91bcSMilica Matic        action="store_true",
67*402f91bcSMilica Matic        default=False,
68*402f91bcSMilica Matic        help="Draw plots of statistics for input files.",
69*402f91bcSMilica Matic    )
70*402f91bcSMilica Matic    parser.add_argument(
71*402f91bcSMilica Matic        "-plot-resource-pressure",
72*402f91bcSMilica Matic        action="store_true",
73*402f91bcSMilica Matic        default=False,
74*402f91bcSMilica Matic        help="Draw plots of resource pressure per iterations for input files.",
75*402f91bcSMilica Matic    )
76*402f91bcSMilica Matic    parser.add_argument(
77*402f91bcSMilica Matic        "--plot-path",
78*402f91bcSMilica Matic        nargs=1,
79*402f91bcSMilica Matic        type=str,
80*402f91bcSMilica Matic        action="store",
81*402f91bcSMilica Matic        metavar="[=<path>]",
82*402f91bcSMilica Matic        default=["-"],
83*402f91bcSMilica Matic        help="Specify relative path where you want to save the plots.",
84*402f91bcSMilica Matic    )
85*402f91bcSMilica Matic    parser.add_argument(
860e343479SDjordje Todorovic        "-v",
870e343479SDjordje Todorovic        action="store_true",
880e343479SDjordje Todorovic        default=False,
890e343479SDjordje Todorovic        help="More details about the running lvm-mca tool.",
900e343479SDjordje Todorovic    )
910e343479SDjordje Todorovic    return parser.parse_args()
920e343479SDjordje Todorovic
930e343479SDjordje Todorovic
94*402f91bcSMilica Matic# Verify that the program inputs meet the requirements.
95*402f91bcSMilica Maticdef verify_program_inputs(opts):
96*402f91bcSMilica Matic    if opts.plot_path[0] != "-" and not opts.plot and not opts.plot_resource_pressure:
97*402f91bcSMilica Matic        print(
98*402f91bcSMilica Matic            "error: Please specify --plot-path only with the -plot or -plot-resource-pressure options."
99*402f91bcSMilica Matic        )
100*402f91bcSMilica Matic        return False
101*402f91bcSMilica Matic
102*402f91bcSMilica Matic    return True
103*402f91bcSMilica Matic
104*402f91bcSMilica Matic
1050e343479SDjordje Todorovic# Returns the name of the file to be analyzed from the path it is on.
1060e343479SDjordje Todorovicdef get_filename_from_path(path):
1070e343479SDjordje Todorovic    index_of_slash = path.rfind("/")
1080e343479SDjordje Todorovic    return path[(index_of_slash + 1) : len(path)]
1090e343479SDjordje Todorovic
1100e343479SDjordje Todorovic
1110e343479SDjordje Todorovic# Returns the results of the running llvm-mca tool for the input file.
1120e343479SDjordje Todorovicdef run_llvm_mca_tool(opts, file_name):
1130e343479SDjordje Todorovic    # Get the path of the llvm-mca binary file.
1140e343479SDjordje Todorovic    llvm_mca_cmd = opts.llvm_mca_binary[0]
1150e343479SDjordje Todorovic
1160e343479SDjordje Todorovic    # The statistics llvm-mca options.
1170e343479SDjordje Todorovic    if opts.args[0] != "-":
1180e343479SDjordje Todorovic        llvm_mca_cmd += " " + opts.args[0]
1190e343479SDjordje Todorovic    llvm_mca_cmd += " -json"
1200e343479SDjordje Todorovic
1210e343479SDjordje Todorovic    # Set file which llvm-mca tool will process.
1220e343479SDjordje Todorovic    llvm_mca_cmd += " " + file_name
1230e343479SDjordje Todorovic
1240e343479SDjordje Todorovic    if opts.v:
1250e343479SDjordje Todorovic        print("run: $ " + llvm_mca_cmd + "\n")
1260e343479SDjordje Todorovic
1270e343479SDjordje Todorovic    # Generate the stats with the llvm-mca.
1280e343479SDjordje Todorovic    subproc = Popen(
1290e343479SDjordje Todorovic        llvm_mca_cmd.split(" "),
1300e343479SDjordje Todorovic        stdin=PIPE,
1310e343479SDjordje Todorovic        stdout=PIPE,
1320e343479SDjordje Todorovic        stderr=PIPE,
1330e343479SDjordje Todorovic        universal_newlines=True,
1340e343479SDjordje Todorovic    )
1350e343479SDjordje Todorovic
1360e343479SDjordje Todorovic    cmd_stdout, cmd_stderr = subproc.communicate()
1370e343479SDjordje Todorovic
1380e343479SDjordje Todorovic    try:
1390e343479SDjordje Todorovic        json_parsed = loads(cmd_stdout)
1400e343479SDjordje Todorovic    except:
1410e343479SDjordje Todorovic        print("error: No valid llvm-mca statistics found.")
1420e343479SDjordje Todorovic        print(cmd_stderr)
1430e343479SDjordje Todorovic        sys.exit(1)
1440e343479SDjordje Todorovic
1450e343479SDjordje Todorovic    if opts.v:
1460e343479SDjordje Todorovic        print("Simulation Parameters: ")
1470e343479SDjordje Todorovic        simulation_parameters = json_parsed["SimulationParameters"]
1480e343479SDjordje Todorovic        for key in simulation_parameters:
1490e343479SDjordje Todorovic            print(key, ":", simulation_parameters[key])
1500e343479SDjordje Todorovic        print("\n")
1510e343479SDjordje Todorovic
1520e343479SDjordje Todorovic    code_regions_len = len(json_parsed["CodeRegions"])
1530e343479SDjordje Todorovic    array_of_code_regions = [None] * code_regions_len
1540e343479SDjordje Todorovic
1550e343479SDjordje Todorovic    for i in range(code_regions_len):
1560e343479SDjordje Todorovic        code_region_instructions_len = len(
1570e343479SDjordje Todorovic            json_parsed["CodeRegions"][i]["Instructions"]
1580e343479SDjordje Todorovic        )
1590e343479SDjordje Todorovic        target_info_resources_len = len(json_parsed["TargetInfo"]["Resources"])
1600e343479SDjordje Todorovic        iteration_resource_pressure = ["-" for k in range(target_info_resources_len)]
1610e343479SDjordje Todorovic        resource_pressure_info = json_parsed["CodeRegions"][i]["ResourcePressureView"][
1620e343479SDjordje Todorovic            "ResourcePressureInfo"
1630e343479SDjordje Todorovic        ]
1640e343479SDjordje Todorovic
165*402f91bcSMilica Matic        name_target_info_resources = json_parsed["TargetInfo"]["Resources"]
1660e343479SDjordje Todorovic
1670e343479SDjordje Todorovic        for s in range(len(resource_pressure_info)):
1680e343479SDjordje Todorovic            obj_of_resource_pressure_info = resource_pressure_info[s]
1690e343479SDjordje Todorovic            if (
1700e343479SDjordje Todorovic                obj_of_resource_pressure_info["InstructionIndex"]
1710e343479SDjordje Todorovic                == code_region_instructions_len
1720e343479SDjordje Todorovic            ):
1730e343479SDjordje Todorovic                iteration_resource_pressure[
1740e343479SDjordje Todorovic                    obj_of_resource_pressure_info["ResourceIndex"]
1750e343479SDjordje Todorovic                ] = str(round(obj_of_resource_pressure_info["ResourceUsage"], 2))
1760e343479SDjordje Todorovic
1770e343479SDjordje Todorovic        array_of_code_regions[i] = Summary(
1780e343479SDjordje Todorovic            file_name,
1790e343479SDjordje Todorovic            json_parsed["CodeRegions"][i]["SummaryView"]["BlockRThroughput"],
1800e343479SDjordje Todorovic            json_parsed["CodeRegions"][i]["SummaryView"]["DispatchWidth"],
1810e343479SDjordje Todorovic            json_parsed["CodeRegions"][i]["SummaryView"]["IPC"],
1820e343479SDjordje Todorovic            json_parsed["CodeRegions"][i]["SummaryView"]["Instructions"],
1830e343479SDjordje Todorovic            json_parsed["CodeRegions"][i]["SummaryView"]["Iterations"],
1840e343479SDjordje Todorovic            json_parsed["CodeRegions"][i]["SummaryView"]["TotalCycles"],
1850e343479SDjordje Todorovic            json_parsed["CodeRegions"][i]["SummaryView"]["TotaluOps"],
1860e343479SDjordje Todorovic            json_parsed["CodeRegions"][i]["SummaryView"]["uOpsPerCycle"],
1870e343479SDjordje Todorovic            iteration_resource_pressure,
1880e343479SDjordje Todorovic            name_target_info_resources,
1890e343479SDjordje Todorovic        )
1900e343479SDjordje Todorovic
1910e343479SDjordje Todorovic    return array_of_code_regions
1920e343479SDjordje Todorovic
1930e343479SDjordje Todorovic
1940e343479SDjordje Todorovic# Print statistics in console for single file or for multiple files.
1950e343479SDjordje Todorovicdef console_print_results(matrix_of_code_regions, opts):
1960e343479SDjordje Todorovic    try:
1970e343479SDjordje Todorovic        import termtables as tt
1980e343479SDjordje Todorovic    except ImportError:
1990e343479SDjordje Todorovic        print("error: termtables not found.")
2000e343479SDjordje Todorovic        sys.exit(1)
2010e343479SDjordje Todorovic
2020e343479SDjordje Todorovic    headers_names = [None] * (len(opts.file_names) + 1)
2030e343479SDjordje Todorovic    headers_names[0] = " "
2040e343479SDjordje Todorovic
2050e343479SDjordje Todorovic    max_code_regions = 0
2060e343479SDjordje Todorovic
2070e343479SDjordje Todorovic    print("Input files:")
2080e343479SDjordje Todorovic    for i in range(len(matrix_of_code_regions)):
2090e343479SDjordje Todorovic        if max_code_regions < len(matrix_of_code_regions[i]):
2100e343479SDjordje Todorovic            max_code_regions = len(matrix_of_code_regions[i])
2110e343479SDjordje Todorovic        print("[f" + str(i + 1) + "]: " + get_filename_from_path(opts.file_names[i]))
2120e343479SDjordje Todorovic        headers_names[i + 1] = "[f" + str(i + 1) + "]: "
2130e343479SDjordje Todorovic
2140e343479SDjordje Todorovic    print("\nITERATIONS: " + str(matrix_of_code_regions[0][0].iterations) + "\n")
2150e343479SDjordje Todorovic
2160e343479SDjordje Todorovic    for i in range(max_code_regions):
2170e343479SDjordje Todorovic
2180e343479SDjordje Todorovic        print(
2190e343479SDjordje Todorovic            "\n-----------------------------------------\nCode region: "
2200e343479SDjordje Todorovic            + str(i + 1)
2210e343479SDjordje Todorovic            + "\n"
2220e343479SDjordje Todorovic        )
2230e343479SDjordje Todorovic
2240e343479SDjordje Todorovic        table_values = [
2250e343479SDjordje Todorovic            [[None] for i in range(len(matrix_of_code_regions) + 1)] for j in range(7)
2260e343479SDjordje Todorovic        ]
2270e343479SDjordje Todorovic
2280e343479SDjordje Todorovic        table_values[0][0] = "Instructions: "
2290e343479SDjordje Todorovic        table_values[1][0] = "Total Cycles: "
2300e343479SDjordje Todorovic        table_values[2][0] = "Total uOps: "
2310e343479SDjordje Todorovic        table_values[3][0] = "Dispatch Width: "
2320e343479SDjordje Todorovic        table_values[4][0] = "uOps Per Cycle: "
2330e343479SDjordje Todorovic        table_values[5][0] = "IPC: "
2340e343479SDjordje Todorovic        table_values[6][0] = "Block RThroughput: "
2350e343479SDjordje Todorovic
2360e343479SDjordje Todorovic        for j in range(len(matrix_of_code_regions)):
2370e343479SDjordje Todorovic            if len(matrix_of_code_regions[j]) > i:
2380e343479SDjordje Todorovic                table_values[0][j + 1] = str(matrix_of_code_regions[j][i].instructions)
2390e343479SDjordje Todorovic                table_values[1][j + 1] = str(matrix_of_code_regions[j][i].total_cycles)
2400e343479SDjordje Todorovic                table_values[2][j + 1] = str(matrix_of_code_regions[j][i].total_uops)
2410e343479SDjordje Todorovic                table_values[3][j + 1] = str(
2420e343479SDjordje Todorovic                    matrix_of_code_regions[j][i].dispatch_width
2430e343479SDjordje Todorovic                )
2440e343479SDjordje Todorovic                table_values[4][j + 1] = str(
2450e343479SDjordje Todorovic                    round(matrix_of_code_regions[j][i].uops_per_cycle, 2)
2460e343479SDjordje Todorovic                )
2470e343479SDjordje Todorovic                table_values[5][j + 1] = str(round(matrix_of_code_regions[j][i].ipc, 2))
2480e343479SDjordje Todorovic                table_values[6][j + 1] = str(
2490e343479SDjordje Todorovic                    round(matrix_of_code_regions[j][i].block_rthroughput, 2)
2500e343479SDjordje Todorovic                )
2510e343479SDjordje Todorovic            else:
2520e343479SDjordje Todorovic                table_values[0][j + 1] = "-"
2530e343479SDjordje Todorovic                table_values[1][j + 1] = "-"
2540e343479SDjordje Todorovic                table_values[2][j + 1] = "-"
2550e343479SDjordje Todorovic                table_values[3][j + 1] = "-"
2560e343479SDjordje Todorovic                table_values[4][j + 1] = "-"
2570e343479SDjordje Todorovic                table_values[5][j + 1] = "-"
2580e343479SDjordje Todorovic                table_values[6][j + 1] = "-"
2590e343479SDjordje Todorovic
2600e343479SDjordje Todorovic        tt.print(
2610e343479SDjordje Todorovic            table_values,
2620e343479SDjordje Todorovic            header=headers_names,
2630e343479SDjordje Todorovic            style=tt.styles.ascii_thin_double,
2640e343479SDjordje Todorovic            padding=(0, 1),
2650e343479SDjordje Todorovic        )
2660e343479SDjordje Todorovic
2670e343479SDjordje Todorovic        print("\nResource pressure per iteration: \n")
2680e343479SDjordje Todorovic
2690e343479SDjordje Todorovic        table_values = [
2700e343479SDjordje Todorovic            [
2710e343479SDjordje Todorovic                [None]
2720e343479SDjordje Todorovic                for i in range(
2730e343479SDjordje Todorovic                    len(matrix_of_code_regions[0][0].iteration_resource_pressure) + 1
2740e343479SDjordje Todorovic                )
2750e343479SDjordje Todorovic            ]
2760e343479SDjordje Todorovic            for j in range(len(matrix_of_code_regions) + 1)
2770e343479SDjordje Todorovic        ]
2780e343479SDjordje Todorovic
279*402f91bcSMilica Matic        table_values[0] = [" "] + matrix_of_code_regions[0][
280*402f91bcSMilica Matic            0
281*402f91bcSMilica Matic        ].name_target_info_resources
2820e343479SDjordje Todorovic
2830e343479SDjordje Todorovic        for j in range(len(matrix_of_code_regions)):
2840e343479SDjordje Todorovic            if len(matrix_of_code_regions[j]) > i:
2850e343479SDjordje Todorovic                table_values[j + 1] = [
2860e343479SDjordje Todorovic                    "[f" + str(j + 1) + "]: "
2870e343479SDjordje Todorovic                ] + matrix_of_code_regions[j][i].iteration_resource_pressure
2880e343479SDjordje Todorovic            else:
2890e343479SDjordje Todorovic                table_values[j + 1] = ["[f" + str(j + 1) + "]: "] + len(
2900e343479SDjordje Todorovic                    matrix_of_code_regions[0][0].iteration_resource_pressure
2910e343479SDjordje Todorovic                ) * ["-"]
2920e343479SDjordje Todorovic
2930e343479SDjordje Todorovic        tt.print(
2940e343479SDjordje Todorovic            table_values,
2950e343479SDjordje Todorovic            style=tt.styles.ascii_thin_double,
2960e343479SDjordje Todorovic            padding=(0, 1),
2970e343479SDjordje Todorovic        )
2980e343479SDjordje Todorovic        print("\n")
2990e343479SDjordje Todorovic
3000e343479SDjordje Todorovic
301*402f91bcSMilica Matic# Based on the obtained results (summary view) of llvm-mca tool, draws plots for multiple input files.
302*402f91bcSMilica Maticdef draw_plot_files_summary(array_of_summary, opts):
303*402f91bcSMilica Matic    try:
304*402f91bcSMilica Matic        import matplotlib.pyplot as plt
305*402f91bcSMilica Matic    except ImportError:
306*402f91bcSMilica Matic        print("error: matplotlib.pyplot not found.")
307*402f91bcSMilica Matic        sys.exit(1)
308*402f91bcSMilica Matic    try:
309*402f91bcSMilica Matic        from matplotlib.cm import get_cmap
310*402f91bcSMilica Matic    except ImportError:
311*402f91bcSMilica Matic        print("error: get_cmap (matplotlib.cm) not found.")
312*402f91bcSMilica Matic        sys.exit(1)
313*402f91bcSMilica Matic
314*402f91bcSMilica Matic    names = [
315*402f91bcSMilica Matic        "Block RThroughput",
316*402f91bcSMilica Matic        "Dispatch Width",
317*402f91bcSMilica Matic        "IPC",
318*402f91bcSMilica Matic        "uOps Per Cycle",
319*402f91bcSMilica Matic        "Instructions",
320*402f91bcSMilica Matic        "Total Cycles",
321*402f91bcSMilica Matic        "Total uOps",
322*402f91bcSMilica Matic    ]
323*402f91bcSMilica Matic
324*402f91bcSMilica Matic    rows, cols = (len(opts.file_names), 7)
325*402f91bcSMilica Matic
326*402f91bcSMilica Matic    values = [[0 for x in range(cols)] for y in range(rows)]
327*402f91bcSMilica Matic
328*402f91bcSMilica Matic    for i in range(len(opts.file_names)):
329*402f91bcSMilica Matic        values[i][0] = array_of_summary[i].block_rthroughput
330*402f91bcSMilica Matic        values[i][1] = array_of_summary[i].dispatch_width
331*402f91bcSMilica Matic        values[i][2] = array_of_summary[i].ipc
332*402f91bcSMilica Matic        values[i][3] = array_of_summary[i].uops_per_cycle
333*402f91bcSMilica Matic        values[i][4] = array_of_summary[i].instructions
334*402f91bcSMilica Matic        values[i][5] = array_of_summary[i].total_cycles
335*402f91bcSMilica Matic        values[i][6] = array_of_summary[i].total_uops
336*402f91bcSMilica Matic
337*402f91bcSMilica Matic    fig, axs = plt.subplots(4, 2)
338*402f91bcSMilica Matic    fig.suptitle(
339*402f91bcSMilica Matic        "Machine code statistics", fontsize=20, fontweight="bold", color="black"
340*402f91bcSMilica Matic    )
341*402f91bcSMilica Matic    i = 0
342*402f91bcSMilica Matic
343*402f91bcSMilica Matic    for x in range(4):
344*402f91bcSMilica Matic        for y in range(2):
345*402f91bcSMilica Matic            cmap = get_cmap("tab20")
346*402f91bcSMilica Matic            colors = cmap.colors
347*402f91bcSMilica Matic            if not (x == 0 and y == 1) and i < 7:
348*402f91bcSMilica Matic                axs[x][y].grid(True, color="grey", linestyle="--")
349*402f91bcSMilica Matic                maxValue = 0
350*402f91bcSMilica Matic                if i == 0:
351*402f91bcSMilica Matic                    for j in range(len(opts.file_names)):
352*402f91bcSMilica Matic                        if maxValue < values[j][i]:
353*402f91bcSMilica Matic                            maxValue = values[j][i]
354*402f91bcSMilica Matic                        axs[x][y].bar(
355*402f91bcSMilica Matic                            0.3 * j,
356*402f91bcSMilica Matic                            values[j][i],
357*402f91bcSMilica Matic                            width=0.1,
358*402f91bcSMilica Matic                            color=colors[j],
359*402f91bcSMilica Matic                            label=get_filename_from_path(opts.file_names[j]),
360*402f91bcSMilica Matic                        )
361*402f91bcSMilica Matic                else:
362*402f91bcSMilica Matic                    for j in range(len(opts.file_names)):
363*402f91bcSMilica Matic                        if maxValue < values[j][i]:
364*402f91bcSMilica Matic                            maxValue = values[j][i]
365*402f91bcSMilica Matic                        axs[x][y].bar(0.3 * j, values[j][i], width=0.1, color=colors[j])
366*402f91bcSMilica Matic                axs[x][y].set_axisbelow(True)
367*402f91bcSMilica Matic                axs[x][y].set_xlim([-0.3, len(opts.file_names) / 3])
368*402f91bcSMilica Matic                axs[x][y].set_ylim([0, maxValue + (maxValue / 2)])
369*402f91bcSMilica Matic                axs[x][y].set_title(names[i], fontsize=15, fontweight="bold")
370*402f91bcSMilica Matic                axs[x][y].axes.xaxis.set_visible(False)
371*402f91bcSMilica Matic                for j in range(len(opts.file_names)):
372*402f91bcSMilica Matic                    axs[x][y].text(
373*402f91bcSMilica Matic                        0.3 * j,
374*402f91bcSMilica Matic                        values[j][i] + (maxValue / 40),
375*402f91bcSMilica Matic                        s=str(values[j][i]),
376*402f91bcSMilica Matic                        color="black",
377*402f91bcSMilica Matic                        fontweight="bold",
378*402f91bcSMilica Matic                        fontsize=4,
379*402f91bcSMilica Matic                    )
380*402f91bcSMilica Matic                i = i + 1
381*402f91bcSMilica Matic
382*402f91bcSMilica Matic    axs[0][1].set_visible(False)
383*402f91bcSMilica Matic    fig.legend(prop={"size": 15})
384*402f91bcSMilica Matic    figg = plt.gcf()
385*402f91bcSMilica Matic    figg.set_size_inches((25, 15), forward=False)
386*402f91bcSMilica Matic    if opts.plot_path[0] == "-":
387*402f91bcSMilica Matic        plt.savefig("llvm-mca-plot.png", dpi=500)
388*402f91bcSMilica Matic        print("The plot was saved within llvm-mca-plot.png")
389*402f91bcSMilica Matic    else:
390*402f91bcSMilica Matic        plt.savefig(
391*402f91bcSMilica Matic            os.path.normpath(os.path.join(opts.plot_path[0], "llvm-mca-plot.png")),
392*402f91bcSMilica Matic            dpi=500,
393*402f91bcSMilica Matic        )
394*402f91bcSMilica Matic        print(
395*402f91bcSMilica Matic            "The plot was saved within {}.".format(
396*402f91bcSMilica Matic                os.path.normpath(os.path.join(opts.plot_path[0], "llvm-mca-plot.png"))
397*402f91bcSMilica Matic            )
398*402f91bcSMilica Matic        )
399*402f91bcSMilica Matic
400*402f91bcSMilica Matic
401*402f91bcSMilica Matic# Calculates the average value (summary view) per region.
402*402f91bcSMilica Maticdef summary_average_code_region(array_of_code_regions, file_name):
403*402f91bcSMilica Matic    summary = Summary(file_name, 0, 0, 0, 0, 0, 0, 0, 0, None, None)
404*402f91bcSMilica Matic    for i in range(len(array_of_code_regions)):
405*402f91bcSMilica Matic        summary.block_rthroughput += array_of_code_regions[i].block_rthroughput
406*402f91bcSMilica Matic        summary.dispatch_width += array_of_code_regions[i].dispatch_width
407*402f91bcSMilica Matic        summary.ipc += array_of_code_regions[i].ipc
408*402f91bcSMilica Matic        summary.instructions += array_of_code_regions[i].instructions
409*402f91bcSMilica Matic        summary.iterations += array_of_code_regions[i].iterations
410*402f91bcSMilica Matic        summary.total_cycles += array_of_code_regions[i].total_cycles
411*402f91bcSMilica Matic        summary.total_uops += array_of_code_regions[i].total_uops
412*402f91bcSMilica Matic        summary.uops_per_cycle += array_of_code_regions[i].uops_per_cycle
413*402f91bcSMilica Matic    summary.block_rthroughput = round(
414*402f91bcSMilica Matic        summary.block_rthroughput / len(array_of_code_regions), 2
415*402f91bcSMilica Matic    )
416*402f91bcSMilica Matic    summary.dispatch_width = round(
417*402f91bcSMilica Matic        summary.dispatch_width / len(array_of_code_regions), 2
418*402f91bcSMilica Matic    )
419*402f91bcSMilica Matic    summary.ipc = round(summary.ipc / len(array_of_code_regions), 2)
420*402f91bcSMilica Matic    summary.instructions = round(summary.instructions / len(array_of_code_regions), 2)
421*402f91bcSMilica Matic    summary.iterations = round(summary.iterations / len(array_of_code_regions), 2)
422*402f91bcSMilica Matic    summary.total_cycles = round(summary.total_cycles / len(array_of_code_regions), 2)
423*402f91bcSMilica Matic    summary.total_uops = round(summary.total_uops / len(array_of_code_regions), 2)
424*402f91bcSMilica Matic    summary.uops_per_cycle = round(
425*402f91bcSMilica Matic        summary.uops_per_cycle / len(array_of_code_regions), 2
426*402f91bcSMilica Matic    )
427*402f91bcSMilica Matic    return summary
428*402f91bcSMilica Matic
429*402f91bcSMilica Matic
430*402f91bcSMilica Matic# Based on the obtained results (resource pressure per iter) of llvm-mca tool, draws plots for multiple input files.
431*402f91bcSMilica Maticdef draw_plot_resource_pressure(
432*402f91bcSMilica Matic    array_average_resource_pressure_per_file, opts, name_target_info_resources
433*402f91bcSMilica Matic):
434*402f91bcSMilica Matic    try:
435*402f91bcSMilica Matic        import matplotlib.pyplot as plt
436*402f91bcSMilica Matic    except ImportError:
437*402f91bcSMilica Matic        print("error: matplotlib.pyplot not found.")
438*402f91bcSMilica Matic        sys.exit(1)
439*402f91bcSMilica Matic    try:
440*402f91bcSMilica Matic        from matplotlib.cm import get_cmap
441*402f91bcSMilica Matic    except ImportError:
442*402f91bcSMilica Matic        print("error: get_cmap (matplotlib.cm) not found.")
443*402f91bcSMilica Matic        sys.exit(1)
444*402f91bcSMilica Matic
445*402f91bcSMilica Matic    fig, axs = plt.subplots()
446*402f91bcSMilica Matic    fig.suptitle(
447*402f91bcSMilica Matic        "Resource pressure per iterations",
448*402f91bcSMilica Matic        fontsize=20,
449*402f91bcSMilica Matic        fontweight="bold",
450*402f91bcSMilica Matic        color="black",
451*402f91bcSMilica Matic    )
452*402f91bcSMilica Matic
453*402f91bcSMilica Matic    maxValue = 0
454*402f91bcSMilica Matic    for j in range(len(opts.file_names)):
455*402f91bcSMilica Matic        if maxValue < max(array_average_resource_pressure_per_file[j]):
456*402f91bcSMilica Matic            maxValue = max(array_average_resource_pressure_per_file[j])
457*402f91bcSMilica Matic
458*402f91bcSMilica Matic    cmap = get_cmap("tab20")
459*402f91bcSMilica Matic    colors = cmap.colors
460*402f91bcSMilica Matic
461*402f91bcSMilica Matic    xticklabels = [None] * len(opts.file_names) * len(name_target_info_resources)
462*402f91bcSMilica Matic    index = 0
463*402f91bcSMilica Matic
464*402f91bcSMilica Matic    for j in range(len(name_target_info_resources)):
465*402f91bcSMilica Matic        for i in range(len(opts.file_names)):
466*402f91bcSMilica Matic            if i == 0:
467*402f91bcSMilica Matic                axs.bar(
468*402f91bcSMilica Matic                    j * len(opts.file_names) * 10 + i * 10,
469*402f91bcSMilica Matic                    array_average_resource_pressure_per_file[i][j],
470*402f91bcSMilica Matic                    width=1,
471*402f91bcSMilica Matic                    color=colors[j],
472*402f91bcSMilica Matic                    label=name_target_info_resources[j],
473*402f91bcSMilica Matic                )
474*402f91bcSMilica Matic            else:
475*402f91bcSMilica Matic                axs.bar(
476*402f91bcSMilica Matic                    j * len(opts.file_names) * 10 + i * 10,
477*402f91bcSMilica Matic                    array_average_resource_pressure_per_file[i][j],
478*402f91bcSMilica Matic                    width=1,
479*402f91bcSMilica Matic                    color=colors[j],
480*402f91bcSMilica Matic                )
481*402f91bcSMilica Matic            axs.text(
482*402f91bcSMilica Matic                j * len(opts.file_names) * 10 + i * 10,
483*402f91bcSMilica Matic                array_average_resource_pressure_per_file[i][j] + (maxValue / 40),
484*402f91bcSMilica Matic                s=str(array_average_resource_pressure_per_file[i][j]),
485*402f91bcSMilica Matic                color=colors[j],
486*402f91bcSMilica Matic                fontweight="bold",
487*402f91bcSMilica Matic                fontsize=3,
488*402f91bcSMilica Matic            )
489*402f91bcSMilica Matic            xticklabels[index] = opts.file_names[i]
490*402f91bcSMilica Matic            index = index + 1
491*402f91bcSMilica Matic
492*402f91bcSMilica Matic    axs.set_xticks(
493*402f91bcSMilica Matic        [
494*402f91bcSMilica Matic            j * len(opts.file_names) * 10 + i * 10
495*402f91bcSMilica Matic            for j in range(len(name_target_info_resources))
496*402f91bcSMilica Matic            for i in range(len(opts.file_names))
497*402f91bcSMilica Matic        ]
498*402f91bcSMilica Matic    )
499*402f91bcSMilica Matic    axs.set_xticklabels(xticklabels, rotation=65)
500*402f91bcSMilica Matic
501*402f91bcSMilica Matic    axs.set_axisbelow(True)
502*402f91bcSMilica Matic    axs.set_xlim([-0.5, len(opts.file_names) * len(name_target_info_resources) * 10])
503*402f91bcSMilica Matic    axs.set_ylim([0, maxValue + maxValue / 10])
504*402f91bcSMilica Matic
505*402f91bcSMilica Matic    fig.legend(prop={"size": 15})
506*402f91bcSMilica Matic    figg = plt.gcf()
507*402f91bcSMilica Matic    figg.set_size_inches((25, 15), forward=False)
508*402f91bcSMilica Matic    if opts.plot_path[0] == "-":
509*402f91bcSMilica Matic        plt.savefig("llvm-mca-plot-resource-pressure.png", dpi=500)
510*402f91bcSMilica Matic        print("The plot was saved within llvm-mca-plot-resource-pressure.png")
511*402f91bcSMilica Matic    else:
512*402f91bcSMilica Matic        plt.savefig(
513*402f91bcSMilica Matic            os.path.normpath(
514*402f91bcSMilica Matic                os.path.join(opts.plot_path[0], "llvm-mca-plot-resource-pressure.png")
515*402f91bcSMilica Matic            ),
516*402f91bcSMilica Matic            dpi=500,
517*402f91bcSMilica Matic        )
518*402f91bcSMilica Matic        print(
519*402f91bcSMilica Matic            "The plot was saved within {}.".format(
520*402f91bcSMilica Matic                os.path.normpath(
521*402f91bcSMilica Matic                    os.path.join(
522*402f91bcSMilica Matic                        opts.plot_path[0], "llvm-mca-plot-resource-pressure.png"
523*402f91bcSMilica Matic                    )
524*402f91bcSMilica Matic                )
525*402f91bcSMilica Matic            )
526*402f91bcSMilica Matic        )
527*402f91bcSMilica Matic
528*402f91bcSMilica Matic
529*402f91bcSMilica Matic# Calculates the average value (resource pressure per iter) per region.
530*402f91bcSMilica Maticdef average_code_region_resource_pressure(array_of_code_regions, file_name):
531*402f91bcSMilica Matic    resource_pressure_per_iter_one_file = [0] * len(
532*402f91bcSMilica Matic        array_of_code_regions[0].iteration_resource_pressure
533*402f91bcSMilica Matic    )
534*402f91bcSMilica Matic    for i in range(len(array_of_code_regions)):
535*402f91bcSMilica Matic        for j in range(len(array_of_code_regions[i].iteration_resource_pressure)):
536*402f91bcSMilica Matic            if array_of_code_regions[i].iteration_resource_pressure[j] != "-":
537*402f91bcSMilica Matic                resource_pressure_per_iter_one_file[j] += float(
538*402f91bcSMilica Matic                    array_of_code_regions[i].iteration_resource_pressure[j]
539*402f91bcSMilica Matic                )
540*402f91bcSMilica Matic    for i in range(len(resource_pressure_per_iter_one_file)):
541*402f91bcSMilica Matic        resource_pressure_per_iter_one_file[i] = round(
542*402f91bcSMilica Matic            resource_pressure_per_iter_one_file[i] / len(array_of_code_regions), 2
543*402f91bcSMilica Matic        )
544*402f91bcSMilica Matic    return resource_pressure_per_iter_one_file
545*402f91bcSMilica Matic
546*402f91bcSMilica Matic
5470e343479SDjordje Todorovicdef Main():
5480e343479SDjordje Todorovic    parser = argparse.ArgumentParser()
5490e343479SDjordje Todorovic    opts = parse_program_args(parser)
5500e343479SDjordje Todorovic
551*402f91bcSMilica Matic    if not verify_program_inputs(opts):
552*402f91bcSMilica Matic        parser.print_help()
553*402f91bcSMilica Matic        sys.exit(1)
554*402f91bcSMilica Matic
5550e343479SDjordje Todorovic    matrix_of_code_regions = [None] * len(opts.file_names)
5560e343479SDjordje Todorovic
5570e343479SDjordje Todorovic    for i in range(len(opts.file_names)):
5580e343479SDjordje Todorovic        matrix_of_code_regions[i] = run_llvm_mca_tool(opts, opts.file_names[i])
559*402f91bcSMilica Matic    if not opts.plot and not opts.plot_resource_pressure:
5600e343479SDjordje Todorovic        console_print_results(matrix_of_code_regions, opts)
561*402f91bcSMilica Matic    else:
562*402f91bcSMilica Matic        if opts.plot:
563*402f91bcSMilica Matic            array_average_summary_per_file = [None] * len(matrix_of_code_regions)
564*402f91bcSMilica Matic            for j in range(len(matrix_of_code_regions)):
565*402f91bcSMilica Matic                array_average_summary_per_file[j] = summary_average_code_region(
566*402f91bcSMilica Matic                    matrix_of_code_regions[j], opts.file_names[j]
567*402f91bcSMilica Matic                )
568*402f91bcSMilica Matic            draw_plot_files_summary(array_average_summary_per_file, opts)
569*402f91bcSMilica Matic        if opts.plot_resource_pressure:
570*402f91bcSMilica Matic            array_average_resource_pressure_per_file = [None] * len(
571*402f91bcSMilica Matic                matrix_of_code_regions
572*402f91bcSMilica Matic            )
573*402f91bcSMilica Matic            for j in range(len(matrix_of_code_regions)):
574*402f91bcSMilica Matic                array_average_resource_pressure_per_file[
575*402f91bcSMilica Matic                    j
576*402f91bcSMilica Matic                ] = average_code_region_resource_pressure(
577*402f91bcSMilica Matic                    matrix_of_code_regions[j], opts.file_names[j]
578*402f91bcSMilica Matic                )
579*402f91bcSMilica Matic            draw_plot_resource_pressure(
580*402f91bcSMilica Matic                array_average_resource_pressure_per_file,
581*402f91bcSMilica Matic                opts,
582*402f91bcSMilica Matic                matrix_of_code_regions[0][0].name_target_info_resources,
583*402f91bcSMilica Matic            )
5840e343479SDjordje Todorovic
5850e343479SDjordje Todorovic
5860e343479SDjordje Todorovicif __name__ == "__main__":
5870e343479SDjordje Todorovic    Main()
5880e343479SDjordje Todorovic    sys.exit(0)
589