diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -142,7 +142,7 @@ UTC_ADVERT = 'NOTE: Assertions have been autogenerated by ' OPT_FUNCTION_RE = re.compile( - r'^\s*define\s+(?:internal\s+)?[^@]*@(?P[\w.-]+?)\s*' + r'^(\s*;\s*Function\sAttrs:\s(?P[\w\s]+?))?\s*define\s+(?:internal\s+)?[^@]*@(?P[\w.-]+?)\s*' r'(?P\((\)|(.*?[\w.-]+?)\))[^{]*)\{\n(?P.*?)^\}$', flags=(re.M | re.S)) @@ -218,11 +218,12 @@ # Build up a dictionary of all the function bodies. class function_body(object): - def __init__(self, string, extra, args_and_sig): + def __init__(self, string, extra, args_and_sig, attrs): self.scrub = string self.extrascrub = extra self.args_and_sig = args_and_sig - def is_same_except_arg_names(self, extrascrub, args_and_sig): + self.attrs = attrs + def is_same_except_arg_names(self, extrascrub, args_and_sig, attrs): arg_names = set() def drop_arg_names(match): arg_names.add(match.group(2)) @@ -231,6 +232,8 @@ if match.group(2) in arg_names: return match.group(1) + match.group(3) return match.group(1) + match.group(2) + match.group(3) + if self.attrs != attrs: + return False ans0 = IR_VALUE_RE.sub(drop_arg_names, self.args_and_sig) ans1 = IR_VALUE_RE.sub(drop_arg_names, args_and_sig) if ans0 != ans1: @@ -244,12 +247,13 @@ def __str__(self): return self.scrub -def build_function_body_dictionary(function_re, scrubber, scrubber_args, raw_tool_output, prefixes, func_dict, verbose, record_args): +def build_function_body_dictionary(function_re, scrubber, scrubber_args, raw_tool_output, prefixes, func_dict, verbose, record_args, check_attributes): for m in function_re.finditer(raw_tool_output): if not m: continue func = m.group('func') body = m.group('body') + attrs = m.group('attrs') if check_attributes else '' # Determine if we print arguments, the opening brace, or nothing after the function name if record_args and 'args_and_sig' in m.groupdict(): args_and_sig = scrub_body(m.group('args_and_sig').strip()) @@ -271,19 +275,20 @@ for l in scrubbed_body.splitlines(): print(' ' + l, file=sys.stderr) for prefix in prefixes: - if func in func_dict[prefix] and (str(func_dict[prefix][func]) != scrubbed_body or (func_dict[prefix][func] and func_dict[prefix][func].args_and_sig != args_and_sig)): - if func_dict[prefix][func] and func_dict[prefix][func].is_same_except_arg_names(scrubbed_extra, args_and_sig): - func_dict[prefix][func].scrub = scrubbed_extra - func_dict[prefix][func].args_and_sig = args_and_sig - continue - else: - if prefix == prefixes[-1]: - warn('Found conflicting asm under the same prefix: %r!' % (prefix,)) - else: - func_dict[prefix][func] = None + if func in func_dict[prefix]: + if str(func_dict[prefix][func]) != scrubbed_body or (func_dict[prefix][func] and (func_dict[prefix][func].args_and_sig != args_and_sig or func_dict[prefix][func].attrs != attrs)): + if func_dict[prefix][func] and func_dict[prefix][func].is_same_except_arg_names(scrubbed_extra, args_and_sig, attrs): + func_dict[prefix][func].scrub = scrubbed_extra + func_dict[prefix][func].args_and_sig = args_and_sig continue + else: + if prefix == prefixes[-1]: + warn('Found conflicting asm under the same prefix: %r!' % (prefix,)) + else: + func_dict[prefix][func] = None + continue - func_dict[prefix][func] = function_body(scrubbed_body, scrubbed_extra, args_and_sig) + func_dict[prefix][func] = function_body(scrubbed_body, scrubbed_extra, args_and_sig, attrs) ##### Generator of LLVM IR CHECK lines @@ -347,7 +352,7 @@ return lines -def add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, check_label_format, is_asm, is_analyze): +def add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, check_label_format, is_asm, is_analyze, check_attributes): # prefix_exclusions are prefixes we cannot use to print the function because it doesn't exist in run lines that use these prefixes as well. prefix_exclusions = set() printed_prefixes = [] @@ -383,6 +388,10 @@ vars_seen = set() printed_prefixes.append(checkprefix) + attrs = str(func_dict[checkprefix][func_name].attrs) + attrs = '' if attrs == 'None' else attrs + if attrs and check_attributes: + output_lines.append('%s %s: Function Attrs: %s' % (comment_marker, checkprefix, attrs)) args_and_sig = str(func_dict[checkprefix][func_name].args_and_sig) args_and_sig = genericize_check_lines([args_and_sig], is_analyze, vars_seen)[0] if '[[' in args_and_sig: @@ -441,16 +450,16 @@ break def add_ir_checks(output_lines, comment_marker, prefix_list, func_dict, - func_name, preserve_names, function_sig): + func_name, preserve_names, function_sig, check_attributes): # Label format is based on IR string. function_def_regex = 'define {{[^@]+}}' if function_sig else '' check_label_format = '{} %s-LABEL: {}@%s%s'.format(comment_marker, function_def_regex) add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, - check_label_format, False, preserve_names) + check_label_format, False, preserve_names, check_attributes) def add_analyze_checks(output_lines, comment_marker, prefix_list, func_dict, func_name): check_label_format = '{} %s-LABEL: \'%s%s\''.format(comment_marker) - add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, check_label_format, False, True) + add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, check_label_format, False, True, False) def check_prefix(prefix): diff --git a/llvm/utils/update_analyze_test_checks.py b/llvm/utils/update_analyze_test_checks.py --- a/llvm/utils/update_analyze_test_checks.py +++ b/llvm/utils/update_analyze_test_checks.py @@ -122,7 +122,7 @@ for raw_tool_output in re.split(r'Printing analysis ', raw_tool_outputs): common.build_function_body_dictionary( common.ANALYZE_FUNCTION_RE, common.scrub_body, [], - raw_tool_output, prefixes, func_dict, args.verbose, False) + raw_tool_output, prefixes, func_dict, args.verbose, False, False) is_in_function = False is_in_function_start = False diff --git a/llvm/utils/update_test_checks.py b/llvm/utils/update_test_checks.py --- a/llvm/utils/update_test_checks.py +++ b/llvm/utils/update_test_checks.py @@ -52,6 +52,8 @@ help='Keep function signature information around for the check line') parser.add_argument('--scrub-attributes', action='store_true', help='Remove attribute annotations (#0) from the end of check line') + parser.add_argument('--check-attributes', action='store_true', + help='Check "Function Attributes" for functions') parser.add_argument('tests', nargs='+') initial_args = common.parse_commandline_args(parser) @@ -111,7 +113,7 @@ common.build_function_body_dictionary( common.OPT_FUNCTION_RE, common.scrub_body, [], raw_tool_output, prefixes, func_dict, ti.args.verbose, - ti.args.function_signature) + ti.args.function_signature, ti.args.check_attributes) is_in_function = False is_in_function_start = False @@ -132,7 +134,7 @@ # Print out the various check lines here. common.add_ir_checks(output_lines, ';', prefix_list, func_dict, - func_name, args.preserve_names, args.function_signature) + func_name, args.preserve_names, args.function_signature, args.check_attributes) is_in_function_start = False if is_in_function: