17bfcb912SWen-Heng (Jack) Chung#!/usr/bin/env python3 2a9d4015dSRiver Riddle"""A script to generate FileCheck statements for mlir unit tests. 3a9d4015dSRiver Riddle 4a9d4015dSRiver RiddleThis script is a utility to add FileCheck patterns to an mlir file. 5a9d4015dSRiver Riddle 6a9d4015dSRiver RiddleNOTE: The input .mlir is expected to be the output from the parser, not a 7a9d4015dSRiver Riddlestripped down variant. 8a9d4015dSRiver Riddle 9a9d4015dSRiver RiddleExample usage: 10a9d4015dSRiver Riddle$ generate-test-checks.py foo.mlir 11a9d4015dSRiver Riddle$ mlir-opt foo.mlir -transformation | generate-test-checks.py 12b877f33dSTim Shen$ mlir-opt foo.mlir -transformation | generate-test-checks.py --source foo.mlir 13b877f33dSTim Shen$ mlir-opt foo.mlir -transformation | generate-test-checks.py --source foo.mlir -i 14b877f33dSTim Shen$ mlir-opt foo.mlir -transformation | generate-test-checks.py --source foo.mlir -i --source_delim_regex='gpu.func @' 15a9d4015dSRiver Riddle 16b877f33dSTim ShenThe script will heuristically generate CHECK/CHECK-LABEL commands for each line 17a9d4015dSRiver Riddlewithin the file. By default this script will also try to insert string 18b877f33dSTim Shensubstitution blocks for all SSA value names. If --source file is specified, the 19b877f33dSTim Shenscript will attempt to insert the generated CHECKs to the source file by looking 20b877f33dSTim Shenfor line positions matched by --source_delim_regex. 21b877f33dSTim Shen 22b877f33dSTim ShenThe script is designed to make adding checks to a test case fast, it is *not* 23b877f33dSTim Shendesigned to be authoritative about what constitutes a good test! 24a9d4015dSRiver Riddle""" 25a9d4015dSRiver Riddle 2656222a06SMehdi Amini# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 2756222a06SMehdi Amini# See https://llvm.org/LICENSE.txt for license information. 2856222a06SMehdi Amini# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 29a9d4015dSRiver Riddle 30a9d4015dSRiver Riddleimport argparse 31a9d4015dSRiver Riddleimport os # Used to advertise this file's name ("autogenerated_note"). 32a9d4015dSRiver Riddleimport re 33a9d4015dSRiver Riddleimport sys 34a9d4015dSRiver Riddle 35f9008e63STobias HietaADVERT_BEGIN = "// NOTE: Assertions have been autogenerated by " 364e7c0a37SMehdi AminiADVERT_END = """ 374e7c0a37SMehdi Amini// The script is designed to make adding checks to 384e7c0a37SMehdi Amini// a test case fast, it is *not* designed to be authoritative 394e7c0a37SMehdi Amini// about what constitutes a good test! The CHECK should be 404e7c0a37SMehdi Amini// minimized and named to reflect the test intent. 414e7c0a37SMehdi Amini""" 424e7c0a37SMehdi Amini 43a9d4015dSRiver Riddle 44a9d4015dSRiver Riddle# Regex command to match an SSA identifier. 45f9008e63STobias HietaSSA_RE_STR = "[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*" 46a9d4015dSRiver RiddleSSA_RE = re.compile(SSA_RE_STR) 47a9d4015dSRiver Riddle 48dea01f5eSRafael Ubal Tena# Regex matching the left-hand side of an assignment 49dea01f5eSRafael Ubal TenaSSA_RESULTS_STR = r'\s*(%' + SSA_RE_STR + r')(\s*,\s*(%' + SSA_RE_STR + r'))*\s*=' 50dea01f5eSRafael Ubal TenaSSA_RESULTS_RE = re.compile(SSA_RESULTS_STR) 51dea01f5eSRafael Ubal Tena 52dea01f5eSRafael Ubal Tena# Regex matching attributes 53dea01f5eSRafael Ubal TenaATTR_RE_STR = r'(#[a-zA-Z._-][a-zA-Z0-9._-]*)' 54dea01f5eSRafael Ubal TenaATTR_RE = re.compile(ATTR_RE_STR) 55dea01f5eSRafael Ubal Tena 56dea01f5eSRafael Ubal Tena# Regex matching the left-hand side of an attribute definition 57dea01f5eSRafael Ubal TenaATTR_DEF_RE_STR = r'\s*' + ATTR_RE_STR + r'\s*=' 58dea01f5eSRafael Ubal TenaATTR_DEF_RE = re.compile(ATTR_DEF_RE_STR) 59dea01f5eSRafael Ubal Tena 60a9d4015dSRiver Riddle 61a9d4015dSRiver Riddle# Class used to generate and manage string substitution blocks for SSA value 62a9d4015dSRiver Riddle# names. 63dea01f5eSRafael Ubal Tenaclass VariableNamer: 64dea01f5eSRafael Ubal Tena def __init__(self, variable_names): 65a9d4015dSRiver Riddle self.scopes = [] 66a9d4015dSRiver Riddle self.name_counter = 0 67a9d4015dSRiver Riddle 68dea01f5eSRafael Ubal Tena # Number of variable names to still generate in parent scope 69dea01f5eSRafael Ubal Tena self.generate_in_parent_scope_left = 0 70dea01f5eSRafael Ubal Tena 71dea01f5eSRafael Ubal Tena # Parse variable names 72dea01f5eSRafael Ubal Tena self.variable_names = [name.upper() for name in variable_names.split(',')] 73dea01f5eSRafael Ubal Tena self.used_variable_names = set() 74dea01f5eSRafael Ubal Tena 75dea01f5eSRafael Ubal Tena # Generate the following 'n' variable names in the parent scope. 76dea01f5eSRafael Ubal Tena def generate_in_parent_scope(self, n): 77dea01f5eSRafael Ubal Tena self.generate_in_parent_scope_left = n 78dea01f5eSRafael Ubal Tena 79f28c5acaSKazuaki Ishizaki # Generate a substitution name for the given ssa value name. 80dea01f5eSRafael Ubal Tena def generate_name(self, source_variable_name): 81dea01f5eSRafael Ubal Tena 82dea01f5eSRafael Ubal Tena # Compute variable name 83dea01f5eSRafael Ubal Tena variable_name = self.variable_names.pop(0) if len(self.variable_names) > 0 else '' 84dea01f5eSRafael Ubal Tena if variable_name == '': 85dea01f5eSRafael Ubal Tena variable_name = "VAL_" + str(self.name_counter) 86a9d4015dSRiver Riddle self.name_counter += 1 87dea01f5eSRafael Ubal Tena 88dea01f5eSRafael Ubal Tena # Scope where variable name is saved 89dea01f5eSRafael Ubal Tena scope = len(self.scopes) - 1 90dea01f5eSRafael Ubal Tena if self.generate_in_parent_scope_left > 0: 91dea01f5eSRafael Ubal Tena self.generate_in_parent_scope_left -= 1 92dea01f5eSRafael Ubal Tena scope = len(self.scopes) - 2 93dea01f5eSRafael Ubal Tena assert(scope >= 0) 94dea01f5eSRafael Ubal Tena 95dea01f5eSRafael Ubal Tena # Save variable 96dea01f5eSRafael Ubal Tena if variable_name in self.used_variable_names: 97dea01f5eSRafael Ubal Tena raise RuntimeError(variable_name + ': duplicate variable name') 98dea01f5eSRafael Ubal Tena self.scopes[scope][source_variable_name] = variable_name 99dea01f5eSRafael Ubal Tena self.used_variable_names.add(variable_name) 100dea01f5eSRafael Ubal Tena 101dea01f5eSRafael Ubal Tena return variable_name 102a9d4015dSRiver Riddle 103a9d4015dSRiver Riddle # Push a new variable name scope. 104a9d4015dSRiver Riddle def push_name_scope(self): 105a9d4015dSRiver Riddle self.scopes.append({}) 106a9d4015dSRiver Riddle 107a9d4015dSRiver Riddle # Pop the last variable name scope. 108a9d4015dSRiver Riddle def pop_name_scope(self): 109a9d4015dSRiver Riddle self.scopes.pop() 110a9d4015dSRiver Riddle 111b877f33dSTim Shen # Return the level of nesting (number of pushed scopes). 11225b38067STim Shen def num_scopes(self): 11325b38067STim Shen return len(self.scopes) 11425b38067STim Shen 115*dbf798faSBenjamin Maxwell # Reset the counter and used variable names. 116*dbf798faSBenjamin Maxwell def clear_names(self): 11725b38067STim Shen self.name_counter = 0 118*dbf798faSBenjamin Maxwell self.used_variable_names = set() 11925b38067STim Shen 120dea01f5eSRafael Ubal Tenaclass AttributeNamer: 121dea01f5eSRafael Ubal Tena 122dea01f5eSRafael Ubal Tena def __init__(self, attribute_names): 123dea01f5eSRafael Ubal Tena self.name_counter = 0 124dea01f5eSRafael Ubal Tena self.attribute_names = [name.upper() for name in attribute_names.split(',')] 125dea01f5eSRafael Ubal Tena self.map = {} 126dea01f5eSRafael Ubal Tena self.used_attribute_names = set() 127dea01f5eSRafael Ubal Tena 128dea01f5eSRafael Ubal Tena # Generate a substitution name for the given attribute name. 129dea01f5eSRafael Ubal Tena def generate_name(self, source_attribute_name): 130dea01f5eSRafael Ubal Tena 131dea01f5eSRafael Ubal Tena # Compute FileCheck name 132dea01f5eSRafael Ubal Tena attribute_name = self.attribute_names.pop(0) if len(self.attribute_names) > 0 else '' 133dea01f5eSRafael Ubal Tena if attribute_name == '': 134dea01f5eSRafael Ubal Tena attribute_name = "ATTR_" + str(self.name_counter) 135dea01f5eSRafael Ubal Tena self.name_counter += 1 136dea01f5eSRafael Ubal Tena 137dea01f5eSRafael Ubal Tena # Prepend global symbol 138dea01f5eSRafael Ubal Tena attribute_name = '$' + attribute_name 139dea01f5eSRafael Ubal Tena 140dea01f5eSRafael Ubal Tena # Save attribute 141dea01f5eSRafael Ubal Tena if attribute_name in self.used_attribute_names: 142dea01f5eSRafael Ubal Tena raise RuntimeError(attribute_name + ': duplicate attribute name') 143dea01f5eSRafael Ubal Tena self.map[source_attribute_name] = attribute_name 144dea01f5eSRafael Ubal Tena self.used_attribute_names.add(attribute_name) 145dea01f5eSRafael Ubal Tena return attribute_name 146dea01f5eSRafael Ubal Tena 147dea01f5eSRafael Ubal Tena # Get the saved substitution name for the given attribute name. If no name 148dea01f5eSRafael Ubal Tena # has been generated for the given attribute yet, the source attribute name 149dea01f5eSRafael Ubal Tena # itself is returned. 150dea01f5eSRafael Ubal Tena def get_name(self, source_attribute_name): 151dea01f5eSRafael Ubal Tena return self.map[source_attribute_name] if source_attribute_name in self.map else '?' 152dea01f5eSRafael Ubal Tena 153dea01f5eSRafael Ubal Tena# Return the number of SSA results in a line of type 154dea01f5eSRafael Ubal Tena# %0, %1, ... = ... 155dea01f5eSRafael Ubal Tena# The function returns 0 if there are no results. 156dea01f5eSRafael Ubal Tenadef get_num_ssa_results(input_line): 157dea01f5eSRafael Ubal Tena m = SSA_RESULTS_RE.match(input_line) 158dea01f5eSRafael Ubal Tena return m.group().count('%') if m else 0 159dea01f5eSRafael Ubal Tena 160a9d4015dSRiver Riddle 161a9d4015dSRiver Riddle# Process a line of input that has been split at each SSA identifier '%'. 162a9d4015dSRiver Riddledef process_line(line_chunks, variable_namer): 163f9008e63STobias Hieta output_line = "" 164a9d4015dSRiver Riddle 165a9d4015dSRiver Riddle # Process the rest that contained an SSA value name. 166a9d4015dSRiver Riddle for chunk in line_chunks: 167a9d4015dSRiver Riddle m = SSA_RE.match(chunk) 168dea01f5eSRafael Ubal Tena ssa_name = m.group(0) if m is not None else '' 169a9d4015dSRiver Riddle 170a9d4015dSRiver Riddle # Check if an existing variable exists for this name. 171a9d4015dSRiver Riddle variable = None 172a9d4015dSRiver Riddle for scope in variable_namer.scopes: 173a9d4015dSRiver Riddle variable = scope.get(ssa_name) 174a9d4015dSRiver Riddle if variable is not None: 175a9d4015dSRiver Riddle break 176a9d4015dSRiver Riddle 177a9d4015dSRiver Riddle # If one exists, then output the existing name. 178a9d4015dSRiver Riddle if variable is not None: 179f9008e63STobias Hieta output_line += "%[[" + variable + "]]" 180a9d4015dSRiver Riddle else: 181a9d4015dSRiver Riddle # Otherwise, generate a new variable. 182a9d4015dSRiver Riddle variable = variable_namer.generate_name(ssa_name) 183f9008e63STobias Hieta output_line += "%[[" + variable + ":.*]]" 184a9d4015dSRiver Riddle 185a9d4015dSRiver Riddle # Append the non named group. 186a9d4015dSRiver Riddle output_line += chunk[len(ssa_name) :] 187a9d4015dSRiver Riddle 188f9008e63STobias Hieta return output_line.rstrip() + "\n" 189a9d4015dSRiver Riddle 190a9d4015dSRiver Riddle 191b877f33dSTim Shen# Process the source file lines. The source file doesn't have to be .mlir. 19225b38067STim Shendef process_source_lines(source_lines, note, args): 19325b38067STim Shen source_split_re = re.compile(args.source_delim_regex) 19425b38067STim Shen 19525b38067STim Shen source_segments = [[]] 19625b38067STim Shen for line in source_lines: 197b877f33dSTim Shen # Remove previous note. 19825b38067STim Shen if line == note: 19925b38067STim Shen continue 200b877f33dSTim Shen # Remove previous CHECK lines. 20125b38067STim Shen if line.find(args.check_prefix) != -1: 20225b38067STim Shen continue 203b877f33dSTim Shen # Segment the file based on --source_delim_regex. 20425b38067STim Shen if source_split_re.search(line): 20525b38067STim Shen source_segments.append([]) 20625b38067STim Shen 207f9008e63STobias Hieta source_segments[-1].append(line + "\n") 20825b38067STim Shen return source_segments 20925b38067STim Shen 210dea01f5eSRafael Ubal Tenadef process_attribute_definition(line, attribute_namer, output): 211dea01f5eSRafael Ubal Tena m = ATTR_DEF_RE.match(line) 212dea01f5eSRafael Ubal Tena if m: 213dea01f5eSRafael Ubal Tena attribute_name = attribute_namer.generate_name(m.group(1)) 214dea01f5eSRafael Ubal Tena line = '// CHECK: #[[' + attribute_name + ':.+]] =' + line[len(m.group(0)):] + '\n' 215dea01f5eSRafael Ubal Tena output.write(line) 216dea01f5eSRafael Ubal Tena 217dea01f5eSRafael Ubal Tenadef process_attribute_references(line, attribute_namer): 218dea01f5eSRafael Ubal Tena 219dea01f5eSRafael Ubal Tena output_line = '' 220dea01f5eSRafael Ubal Tena components = ATTR_RE.split(line) 221dea01f5eSRafael Ubal Tena for component in components: 222dea01f5eSRafael Ubal Tena m = ATTR_RE.match(component) 223dea01f5eSRafael Ubal Tena if m: 224dea01f5eSRafael Ubal Tena output_line += '#[[' + attribute_namer.get_name(m.group(1)) + ']]' 225dea01f5eSRafael Ubal Tena output_line += component[len(m.group()):] 226dea01f5eSRafael Ubal Tena else: 227dea01f5eSRafael Ubal Tena output_line += component 228dea01f5eSRafael Ubal Tena return output_line 22925b38067STim Shen 2303e2ac62bSRiver Riddle# Pre-process a line of input to remove any character sequences that will be 2313e2ac62bSRiver Riddle# problematic with FileCheck. 2323e2ac62bSRiver Riddledef preprocess_line(line): 2333e2ac62bSRiver Riddle # Replace any double brackets, '[[' with escaped replacements. '[[' 2343e2ac62bSRiver Riddle # corresponds to variable names in FileCheck. 235f9008e63STobias Hieta output_line = line.replace("[[", "{{\\[\\[}}") 2363e2ac62bSRiver Riddle 2373e2ac62bSRiver Riddle # Replace any single brackets that are followed by an SSA identifier, the 2383e2ac62bSRiver Riddle # identifier will be replace by a variable; Creating the same situation as 2393e2ac62bSRiver Riddle # above. 240f9008e63STobias Hieta output_line = output_line.replace("[%", "{{\\[}}%") 2413e2ac62bSRiver Riddle 2423e2ac62bSRiver Riddle return output_line 2433e2ac62bSRiver Riddle 2443e2ac62bSRiver Riddle 245a9d4015dSRiver Riddledef main(): 246a9d4015dSRiver Riddle parser = argparse.ArgumentParser( 247f9008e63STobias Hieta description=__doc__, formatter_class=argparse.RawTextHelpFormatter 248f9008e63STobias Hieta ) 249a9d4015dSRiver Riddle parser.add_argument( 250f9008e63STobias Hieta "--check-prefix", default="CHECK", help="Prefix to use from check file." 251f9008e63STobias Hieta ) 252a9d4015dSRiver Riddle parser.add_argument( 253f9008e63STobias Hieta "-o", "--output", nargs="?", type=argparse.FileType("w"), default=None 254f9008e63STobias Hieta ) 255a9d4015dSRiver Riddle parser.add_argument( 256f9008e63STobias Hieta "input", nargs="?", type=argparse.FileType("r"), default=sys.stdin 257f9008e63STobias Hieta ) 25825b38067STim Shen parser.add_argument( 259f9008e63STobias Hieta "--source", 260f9008e63STobias Hieta type=str, 261f9008e63STobias Hieta help="Print each CHECK chunk before each delimeter line in the source" 262f9008e63STobias Hieta "file, respectively. The delimeter lines are identified by " 263f9008e63STobias Hieta "--source_delim_regex.", 264f9008e63STobias Hieta ) 265f9008e63STobias Hieta parser.add_argument("--source_delim_regex", type=str, default="func @") 26625b38067STim Shen parser.add_argument( 267f9008e63STobias Hieta "--starts_from_scope", 268f9008e63STobias Hieta type=int, 269f9008e63STobias Hieta default=1, 270f9008e63STobias Hieta help="Omit the top specified level of content. For example, by default " 271f9008e63STobias Hieta 'it omits "module {"', 272f9008e63STobias Hieta ) 273f9008e63STobias Hieta parser.add_argument("-i", "--inplace", action="store_true", default=False) 274dea01f5eSRafael Ubal Tena parser.add_argument( 275dea01f5eSRafael Ubal Tena "--variable_names", 276dea01f5eSRafael Ubal Tena type=str, 277dea01f5eSRafael Ubal Tena default='', 278dea01f5eSRafael Ubal Tena help="Names to be used in FileCheck regular expression to represent SSA " 279dea01f5eSRafael Ubal Tena "variables in the order they are encountered. Separate names with commas, " 280dea01f5eSRafael Ubal Tena "and leave empty entries for default names (e.g.: 'DIM,,SUM,RESULT')") 281dea01f5eSRafael Ubal Tena parser.add_argument( 282dea01f5eSRafael Ubal Tena "--attribute_names", 283dea01f5eSRafael Ubal Tena type=str, 284dea01f5eSRafael Ubal Tena default='', 285dea01f5eSRafael Ubal Tena help="Names to be used in FileCheck regular expression to represent " 286dea01f5eSRafael Ubal Tena "attributes in the order they are defined. Separate names with commas," 287dea01f5eSRafael Ubal Tena "commas, and leave empty entries for default names (e.g.: 'MAP0,,,MAP1')") 28825b38067STim Shen 289a9d4015dSRiver Riddle args = parser.parse_args() 290a9d4015dSRiver Riddle 291a9d4015dSRiver Riddle # Open the given input file. 292a9d4015dSRiver Riddle input_lines = [l.rstrip() for l in args.input] 293a9d4015dSRiver Riddle args.input.close() 294a9d4015dSRiver Riddle 295a9d4015dSRiver Riddle # Generate a note used for the generated check file. 296a9d4015dSRiver Riddle script_name = os.path.basename(__file__) 297f9008e63STobias Hieta autogenerated_note = ADVERT_BEGIN + "utils/" + script_name + "\n" + ADVERT_END 298a9d4015dSRiver Riddle 29925b38067STim Shen source_segments = None 30025b38067STim Shen if args.source: 30125b38067STim Shen source_segments = process_source_lines( 302f9008e63STobias Hieta [l.rstrip() for l in open(args.source, "r")], autogenerated_note, args 30325b38067STim Shen ) 30425b38067STim Shen 30525b38067STim Shen if args.inplace: 30625b38067STim Shen assert args.output is None 307f9008e63STobias Hieta output = open(args.source, "w") 30825b38067STim Shen elif args.output is None: 30925b38067STim Shen output = sys.stdout 31025b38067STim Shen else: 31125b38067STim Shen output = args.output 31225b38067STim Shen 31325b38067STim Shen output_segments = [[]] 314dea01f5eSRafael Ubal Tena 315dea01f5eSRafael Ubal Tena # Namers 316dea01f5eSRafael Ubal Tena variable_namer = VariableNamer(args.variable_names) 317dea01f5eSRafael Ubal Tena attribute_namer = AttributeNamer(args.attribute_names) 318dea01f5eSRafael Ubal Tena 319dea01f5eSRafael Ubal Tena # Process lines 320a9d4015dSRiver Riddle for input_line in input_lines: 321a9d4015dSRiver Riddle if not input_line: 322a9d4015dSRiver Riddle continue 323dea01f5eSRafael Ubal Tena 324dea01f5eSRafael Ubal Tena # Check if this is an attribute definition and process it 325dea01f5eSRafael Ubal Tena process_attribute_definition(input_line, attribute_namer, output) 326a9d4015dSRiver Riddle 327a9d4015dSRiver Riddle # Lines with blocks begin with a ^. These lines have a trailing comment 328a9d4015dSRiver Riddle # that needs to be stripped. 329dea01f5eSRafael Ubal Tena lstripped_input_line = input_line.lstrip() 330f9008e63STobias Hieta is_block = lstripped_input_line[0] == "^" 331a9d4015dSRiver Riddle if is_block: 332f9008e63STobias Hieta input_line = input_line.rsplit("//", 1)[0].rstrip() 333a9d4015dSRiver Riddle 33425b38067STim Shen cur_level = variable_namer.num_scopes() 335a9d4015dSRiver Riddle 336a9d4015dSRiver Riddle # If the line starts with a '}', pop the last name scope. 337f9008e63STobias Hieta if lstripped_input_line[0] == "}": 338a9d4015dSRiver Riddle variable_namer.pop_name_scope() 33925b38067STim Shen cur_level = variable_namer.num_scopes() 340a9d4015dSRiver Riddle 341a9d4015dSRiver Riddle # If the line ends with a '{', push a new name scope. 342f9008e63STobias Hieta if input_line[-1] == "{": 343a9d4015dSRiver Riddle variable_namer.push_name_scope() 34425b38067STim Shen if cur_level == args.starts_from_scope: 34525b38067STim Shen output_segments.append([]) 34625b38067STim Shen 347dea01f5eSRafael Ubal Tena # Result SSA values must still be pushed to parent scope 348dea01f5eSRafael Ubal Tena num_ssa_results = get_num_ssa_results(input_line) 349dea01f5eSRafael Ubal Tena variable_namer.generate_in_parent_scope(num_ssa_results) 350dea01f5eSRafael Ubal Tena 35125b38067STim Shen # Omit lines at the near top level e.g. "module {". 35225b38067STim Shen if cur_level < args.starts_from_scope: 35325b38067STim Shen continue 35425b38067STim Shen 35525b38067STim Shen if len(output_segments[-1]) == 0: 356*dbf798faSBenjamin Maxwell variable_namer.clear_names() 357a9d4015dSRiver Riddle 3583e2ac62bSRiver Riddle # Preprocess the input to remove any sequences that may be problematic with 3593e2ac62bSRiver Riddle # FileCheck. 3603e2ac62bSRiver Riddle input_line = preprocess_line(input_line) 3613e2ac62bSRiver Riddle 362dea01f5eSRafael Ubal Tena # Process uses of attributes in this line 363dea01f5eSRafael Ubal Tena input_line = process_attribute_references(input_line, attribute_namer) 364dea01f5eSRafael Ubal Tena 365a9d4015dSRiver Riddle # Split the line at the each SSA value name. 366f9008e63STobias Hieta ssa_split = input_line.split("%") 367a9d4015dSRiver Riddle 368a9d4015dSRiver Riddle # If this is a top-level operation use 'CHECK-LABEL', otherwise 'CHECK:'. 36925b38067STim Shen if len(output_segments[-1]) != 0 or not ssa_split[0]: 370f9008e63STobias Hieta output_line = "// " + args.check_prefix + ": " 371a9d4015dSRiver Riddle # Pad to align with the 'LABEL' statements. 372f9008e63STobias Hieta output_line += " " * len("-LABEL") 373a9d4015dSRiver Riddle 374a9d4015dSRiver Riddle # Output the first line chunk that does not contain an SSA name. 375a9d4015dSRiver Riddle output_line += ssa_split[0] 376a9d4015dSRiver Riddle 377a9d4015dSRiver Riddle # Process the rest of the input line. 378a9d4015dSRiver Riddle output_line += process_line(ssa_split[1:], variable_namer) 379a9d4015dSRiver Riddle 380a9d4015dSRiver Riddle else: 381a9d4015dSRiver Riddle # Output the first line chunk that does not contain an SSA name for the 382a9d4015dSRiver Riddle # label. 383f9008e63STobias Hieta output_line = "// " + args.check_prefix + "-LABEL: " + ssa_split[0] + "\n" 384a9d4015dSRiver Riddle 38525b38067STim Shen # Process the rest of the input line on separate check lines. 38625b38067STim Shen for argument in ssa_split[1:]: 387f9008e63STobias Hieta output_line += "// " + args.check_prefix + "-SAME: " 388a9d4015dSRiver Riddle 389a9d4015dSRiver Riddle # Pad to align with the original position in the line. 390f9008e63STobias Hieta output_line += " " * len(ssa_split[0]) 391a9d4015dSRiver Riddle 392a9d4015dSRiver Riddle # Process the rest of the line. 39325b38067STim Shen output_line += process_line([argument], variable_namer) 394a9d4015dSRiver Riddle 395a9d4015dSRiver Riddle # Append the output line. 39625b38067STim Shen output_segments[-1].append(output_line) 39725b38067STim Shen 398f9008e63STobias Hieta output.write(autogenerated_note + "\n") 399a9d4015dSRiver Riddle 400a9d4015dSRiver Riddle # Write the output. 40125b38067STim Shen if source_segments: 40225b38067STim Shen assert len(output_segments) == len(source_segments) 40325b38067STim Shen for check_segment, source_segment in zip(output_segments, source_segments): 40425b38067STim Shen for line in check_segment: 40525b38067STim Shen output.write(line) 40625b38067STim Shen for line in source_segment: 40725b38067STim Shen output.write(line) 40825b38067STim Shen else: 40925b38067STim Shen for segment in output_segments: 410f9008e63STobias Hieta output.write("\n") 41125b38067STim Shen for output_line in segment: 41225b38067STim Shen output.write(output_line) 413f9008e63STobias Hieta output.write("\n") 41425b38067STim Shen output.close() 415a9d4015dSRiver Riddle 416a9d4015dSRiver Riddle 417f9008e63STobias Hietaif __name__ == "__main__": 418a9d4015dSRiver Riddle main() 419