diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -321,7 +321,8 @@ print("Cannot find a triple. Assume 'x86'", file=sys.stderr) return 'x86' -def build_function_body_dictionary_for_triple(args, raw_tool_output, triple, prefixes, func_dict): +def build_function_body_dictionary_for_triple(args, raw_tool_output, triple, + prefixes, func_dict, func_order): target_handlers = { 'i686': (scrub_asm_x86, ASM_FUNCTION_X86_RE), 'x86': (scrub_asm_x86, ASM_FUNCTION_X86_RE), @@ -364,7 +365,7 @@ scrubber, function_re = handler common.build_function_body_dictionary( function_re, scrubber, [args], raw_tool_output, prefixes, - func_dict, args.verbose, False) + func_dict, func_order, args.verbose, False) ##### Generator of assembly CHECK lines 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 @@ -169,7 +169,7 @@ 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, func_order, verbose, record_args): for m in function_re.finditer(raw_tool_output): if not m: continue @@ -209,6 +209,7 @@ continue func_dict[prefix][func] = function_body(scrubbed_body, scrubbed_extra, args_and_sig) + func_order[prefix].append(func) ##### Generator of LLVM IR CHECK lines diff --git a/llvm/utils/update_cc_test_checks.py b/llvm/utils/update_cc_test_checks.py --- a/llvm/utils/update_cc_test_checks.py +++ b/llvm/utils/update_cc_test_checks.py @@ -129,6 +129,8 @@ help='Use more regex for x86 matching to reduce diffs between various subtargets') parser.add_argument('--function-signature', action='store_true', help='Keep function signature information around for the check line') + parser.add_argument('--include-generated-funcs', action='store_true', + help='Output checks for functions not in source') parser.add_argument('tests', nargs='+') args = common.parse_commandline_args(parser) args.clang_args = shlex.split(args.clang_args or '') @@ -168,7 +170,8 @@ return args -def get_function_body(args, filename, clang_args, extra_commands, prefixes, triple_in_cmd, func_dict): +def get_function_body(args, filename, clang_args, extra_commands, prefixes, + triple_in_cmd, func_dict, func_order): # TODO Clean up duplication of asm/common build_function_body_dictionary # Invoke external tool and extract function bodies. raw_tool_output = common.invoke_tool(args.clang, clang_args, filename) @@ -188,7 +191,8 @@ if '-emit-llvm' in clang_args: common.build_function_body_dictionary( common.OPT_FUNCTION_RE, common.scrub_body, [], - raw_tool_output, prefixes, func_dict, args.verbose, args.function_signature) + raw_tool_output, prefixes, func_dict, func_order, args.verbose, + args.function_signature) else: print('The clang command line should include -emit-llvm as asm tests ' 'are discouraged in Clang testsuite.', file=sys.stderr) @@ -267,21 +271,25 @@ # Execute clang, generate LLVM IR, and extract functions. func_dict = {} + func_order = {} for p in run_list: prefixes = p[0] for prefix in prefixes: func_dict.update({prefix: dict()}) + func_order.update({prefix: []}) for prefixes, clang_args, extra_commands, triple_in_cmd in run_list: common.debug('Extracted clang cmd: clang {}'.format(clang_args)) common.debug('Extracted FileCheck prefixes: {}'.format(prefixes)) - get_function_body(args, filename, clang_args, extra_commands, prefixes, triple_in_cmd, func_dict) + get_function_body(args, filename, clang_args, extra_commands, prefixes, + triple_in_cmd, func_dict, func_order) # Invoke clang -Xclang -ast-dump=json to get mapping from start lines to # mangled names. Forward all clang args for now. for k, v in get_line2spell_and_mangled(args, clang_args).items(): line2spell_and_mangled_list[k].append(v) + checked = set() output_lines = [autogenerated_note] for idx, line in enumerate(input_lines): # Discard any previous script advertising. @@ -305,7 +313,40 @@ False, args.function_signature) output_lines.append(line.rstrip('\n')) - + if args.include_generated_funcs: + # Generate the appropriate checks for each function. We need to emit + # these in the same order as in the output file so that CHECK-LABEL works + # properly. func_order provides that. + added = set() + for prefix, funcs in func_order.items(): + for func in funcs: + if func not in checked: + # This is a generated function, as no source line mapped to it. + if added: + output_lines.append('//') + added.add(func) + + # The add_*_checks routines expect a run list whose items are tuples + # that have a list of prefixes as their first element and tool + # command args string as their second element. They output checks + # for each prefix in the list of prefixes. By doing so, it + # implicitly assumes that for each function every run line will + # generate something for that function. That is not the case for + # generated functions as some run lines might not generate them + # (e.g. -fopenmp vs. -fno-openmp). + # + # Therefore,pass just the prefix we're interested in. This has the + # effect of generating all of the checks for functions of a single + # prefix before moving on to the next prefix. So checks are ordered + # by prefix instead of by function as for "normal" functions. + if '-emit-llvm' in clang_args: + common.add_ir_checks(output_lines, '//', [([prefix], clang_args)], + func_dict, func, False) + else: + asm.add_asm_checks(output_lines, '//', [([prefix], clang_args)], + func_dict, func) + + # Update the test file. common.debug('Writing %d lines to %s...' % (len(output_lines), filename)) with open(filename, 'wb') as f: f.writelines(['{}\n'.format(l).encode('utf-8') for l in output_lines]) diff --git a/llvm/utils/update_llc_test_checks.py b/llvm/utils/update_llc_test_checks.py --- a/llvm/utils/update_llc_test_checks.py +++ b/llvm/utils/update_llc_test_checks.py @@ -123,10 +123,12 @@ autogenerated_note = (comment_sym + ADVERT + 'utils/' + script_name) func_dict = {} + func_order = {} for p in run_list: prefixes = p[0] for prefix in prefixes: func_dict.update({prefix: dict()}) + func_order.update({prefix: []}) for prefixes, llc_args, triple_in_cmd, march_in_cmd in run_list: common.debug('Extracted LLC cmd:', llc_tool, llc_args) common.debug('Extracted FileCheck prefixes:', str(prefixes)) @@ -138,7 +140,7 @@ triple = asm.get_triple_from_march(march_in_cmd) asm.build_function_body_dictionary_for_triple(args, raw_tool_output, - triple, prefixes, func_dict) + triple, prefixes, func_dict, func_order) 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 @@ -137,9 +137,11 @@ prefix_list.append((check_prefixes, tool_cmd_args)) func_dict = {} + func_order = {} for prefixes, _ in prefix_list: for prefix in prefixes: func_dict.update({prefix: dict()}) + func_order.update({prefix: []}) for prefixes, opt_args in prefix_list: common.debug('Extracted opt cmd: ' + opt_basename + ' ' + opt_args) common.debug('Extracted FileCheck prefixes: ' + str(prefixes)) @@ -147,7 +149,7 @@ raw_tool_output = common.invoke_tool(args.opt_binary, opt_args, test) common.build_function_body_dictionary( common.OPT_FUNCTION_RE, common.scrub_body, [], - raw_tool_output, prefixes, func_dict, args.verbose, + raw_tool_output, prefixes, func_dict, func_order, args.verbose, args.function_signature) is_in_function = False