diff --git a/README_Alive2Script.md b/README_Alive2Script.md new file mode 100644 index 0000000000000000000000000000000000000000..3082ab1e3bd2ac835872696db59904e3d6f23daf --- /dev/null +++ b/README_Alive2Script.md @@ -0,0 +1,14 @@ +# READ ME + +### This merge includes two files +#### alive2script.py and instList.txt + +a. Run the script using the command python alive2script.py test.ll, where test.ll is the test file. + +b. This script can automatically identify and distinguish the tools and options to be tested. Please write the tool and options after ; RUN:. + +c. Some custom options are already listed in instList.txt. To test specific options, add them to this file. Each option should occupy one line. When an option may have values like =true or =false, you only need to add the part before the = sign to the file. For example, -force-customized-pipeline= should be written as -force-customized-pipeline= in the file. + +d. This script can recognize multiple RUN markers in a single file. + +e.Optional debug mode, add the '-debug' option after the input file to output detailed information about the script execution. (for example : python alive2script.py xxx.ll -debug) \ No newline at end of file diff --git a/alive2script.py b/alive2script.py new file mode 100644 index 0000000000000000000000000000000000000000..962d070385377d9b458598f78b477f562acd3732 --- /dev/null +++ b/alive2script.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 +import re +import os +import sys +import subprocess +from itertools import permutations + +# function to read options from the instList.txt file +def read_bisheng_options(file_path): + with open(file_path, 'r') as file: + options = [line.strip() for line in file.readlines()] + return options + +def extract_opt_options(file_path, bisheng_options): + with open(file_path, 'r') as file: + content = file.read() + tool_info_list = [] + # Define a pattern to match a single RUN line + run_pattern = r'; RUN:(.*?)(?=\n; RUN:|$)' + run_matches = re.finditer(run_pattern, content, re.DOTALL) + for run_match in run_matches: + run_content = run_match.group(1).strip() + # Find the index of the first '|' character + first_pipe_index = run_content.find('|') + + if first_pipe_index != -1: + # Split run_content at the first '|' character + run_content = run_content[:first_pipe_index] + + # Extract the tool name from the RUN line + tool_name_match = re.search(r'(\w+)', run_content) + if tool_name_match: + tool_name = tool_name_match.group(1) + else: + continue # Skip if tool name is not found + + # Extract options from the RUN line + tool_option_match = re.search(r'\b' + re.escape(tool_name) + r'\b\s+(.*)', run_content) + if tool_option_match: + tool_options = tool_option_match.group(1).strip().split() + else: + tool_options = [] + + # Replace %s in each option with the input file path + current_file_path = os.path.abspath(file_path) + tool_options_with_path = [opt.replace('%s', current_file_path) for opt in tool_options] + + # Match options in the IR file with options in bisheng_options + need_test_option = [opt for opt in tool_options_with_path if any(bisheng_opt in opt for bisheng_opt in bisheng_options)] + + # Store options other than those in need_test_option + other_options = [opt for opt in tool_options_with_path if opt not in need_test_option] + + tool_info_list.append((tool_name, other_options, need_test_option)) + + return tool_info_list + + +def run_tool(input_file, tool_options, tool_name): + tool_command = f"{tool_name} {' '.join(tool_options)} -o {input_file}.bc" + if "-debug" in sys.argv: + print(f"----------------------Debug Info: Testing: '{tool_command}'") + try: + subprocess.run(tool_command, shell=True, check=True) + return f"{input_file}.bc" + except subprocess.CalledProcessError: + print(f"Failed to run the {tool_name} tool") + return None + +def run_alive_tv(input_file, bc_file): + alive_tv_command = f"alive-tv {input_file} {bc_file}" + try: + result = subprocess.run(alive_tv_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + if "Transformation seems to be correct!" in result.stdout and "ERROR" not in result.stdout: + return True + else: + return False + except subprocess.CalledProcessError: + print("Failed to run the alive-tv tool") + return False + +def test_optionX_combinations(input_file, need_test_option, other_options, tool_name): + + unique_optionX_combinations = set() + for r in range(1, len(need_test_option) + 1): + for combination in permutations(need_test_option, r): + sorted_combination = tuple(sorted(combination)) + if sorted_combination not in unique_optionX_combinations: + unique_optionX_combinations.add(sorted_combination) + + all_tool_options = list(combination) + other_options + bc_file = run_tool(input_file, all_tool_options,tool_name) + if bc_file: + if run_alive_tv(input_file, bc_file): + print(f"Successful option combination for '{tool_name}': {combination}") + else: + print(f"Error: Failed option combination for '{tool_name}': {combination}") + else: + print(f"{tool_name} couldn't run this Option combination : {combination}") + + + if bc_file: + os.remove(bc_file) + +if len(sys.argv) < 2: + print("Please provide the path to an LLVM IR file as a command-line argument") +else: + llvm_ir_path = sys.argv[1] + bisheng_option_file = "instList.txt" + bisheng_options = read_bisheng_options(bisheng_option_file) + + tool_info_list = extract_opt_options(llvm_ir_path, bisheng_options) + + for tool_info in tool_info_list: + tool_name, other_options, need_test_option = tool_info + + if "-debug" in sys.argv: + print(f"Debug Info for '{tool_name}':") + print(f" need_test_option: {need_test_option}") + print(f" other_options: {other_options}") + + if need_test_option: + test_optionX_combinations(llvm_ir_path, need_test_option, other_options, tool_name) \ No newline at end of file diff --git a/instList.txt b/instList.txt new file mode 100644 index 0000000000000000000000000000000000000000..619127eee26a9fa1db448f72a35244c0185eb330 --- /dev/null +++ b/instList.txt @@ -0,0 +1,57 @@ +-force-customized-pipeline= +-sad-pattern-recognition= +-instcombine-ctz-array= +-aarch64-loopcond-opt= +-aarch64-hadd-generation= +-enable-loop-split= +-enable-mem-chk-simplification= +-aarch64-ldp-stp-noq= +-enable-func-arg-analysis= +-enable-modest-vectorization-unrolling-factors= +-instcombine-shrink-vector-element= +-instcombine-reorder-sum-of-reduce-add= +-replace-fortran-mem-alloc= +-enable-pg-math-call-simplification= +-instcombine-gep-common= +-enable-sroa-after-unroll= +-disable-recursive-bonus= +-disable-recip-sqrt-opt= +-disable-loop-aware-reassociation= +-enable-gzipcrc32= +-enable-aes= +-enable-plle= +-plle-hotpathcost-threshold= +-plle-bf-lowerbound= +-enable-merge-reversed-icmps= +-Hx,70,0x20000000 +-update-iv-scev +-gep-common +-gep-common= +-gep-cluster-min= +-gep-loop-mindepth= +-array-restructuring +-enable-array-restructuring= +-skip-array-restructuring-codegen= +-struct-peel +-enable-struct-peel= +-struct-peel-skip-transform= +-struct-peel-this= +-fopenmp-reduction-duplicate +-fopenmp-firstprivatize-locals +-sort-ivusers-before-lsr +-foverflow-shift-alt-behavior +-Mx,218,0x1 +-warn-large-symbols= +-instcombine-simplify-mul64= +-replace-sqrt-compare-by-square= +-enable-combine-sqrt-exp= +-loop-load-widen-patterns= +-enable-aggressive-inline= +-shift rounding +-aggressive-instcombine-simplify-sqr64= +-enable-value-spec= +-vspec-min-select-users= +-vspec-search-users-depth= +-relaxed-ordering-level= +-enable-highlevel-branch-prediction= +-enable-branch-metadata -mllvm -enable-boscc= \ No newline at end of file