greened updated this revision to Diff 275831. greened added a comment. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Fixed various bugs, added tests. This now has two modes because generated function output can't be ordered with respect to source file functions. When clang generates functions it can sometimes output original source functions in a different (non-source) order so checks can't be placed next to their definitions in the source file. I don't particularly like this mode dichotomy but unifying it would necessitate updating a whole lot of clang tests. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D83004/new/ https://reviews.llvm.org/D83004 Files: clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.generated.expected clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.no-generated.expected clang/test/utils/update_cc_test_checks/generated-funcs.test llvm/utils/UpdateTestChecks/asm.py llvm/utils/UpdateTestChecks/common.py llvm/utils/update_cc_test_checks.py llvm/utils/update_llc_test_checks.py llvm/utils/update_test_checks.py
Index: llvm/utils/update_test_checks.py =================================================================== --- llvm/utils/update_test_checks.py +++ 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 Index: llvm/utils/update_llc_test_checks.py =================================================================== --- llvm/utils/update_llc_test_checks.py +++ 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 Index: llvm/utils/update_cc_test_checks.py =================================================================== --- llvm/utils/update_cc_test_checks.py +++ 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,15 +271,18 @@ # 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. @@ -283,29 +290,76 @@ line2spell_and_mangled_list[k].append(v) output_lines = [autogenerated_note] - for idx, line in enumerate(input_lines): - # Discard any previous script advertising. - if line.startswith(ADVERT): - continue - if idx in line2spell_and_mangled_list: - added = set() - for spell, mangled in line2spell_and_mangled_list[idx]: - # One line may contain multiple function declarations. - # Skip if the mangled name has been added before. - # The line number may come from an included file, - # we simply require the spelling name to appear on the line - # to exclude functions from other files. - if mangled in added or spell not in line: - continue - if args.functions is None or any(re.search(regex, spell) for regex in args.functions): - if added: - output_lines.append('//') - added.add(mangled) - common.add_ir_checks(output_lines, '//', run_list, func_dict, mangled, - 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 order according to the generated output so that CHECK-LABEL + # works properly. func_order provides that. + + # It turns out that when clang generates functions (for example, with + # -fopenmp), it can sometimes cause functions to be re-ordered in the + # output, even functions that exist in the source file. Therefore we + # can't insert check lines before each source function and instead have to + # put them at the end. So the first thing to do is dump out the source + # lines. + for idx, line in enumerate(input_lines): + # Discard any previous script advertising. + if line.startswith(ADVERT): + continue + output_lines.append(line.rstrip('\n')) + + # Now generate all the checks. + added = set() + for prefix, funcs in func_order.items(): + for func in funcs: + 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. no -fopenmp). + # + # 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, + args.function_signature) + else: + asm.add_asm_checks(output_lines, '//', [([prefix], clang_args)], + func_dict, func) + else: + # Normal mode. Put checks before each source function. + for idx, line in enumerate(input_lines): + # Discard any previous script advertising. + if line.startswith(ADVERT): + continue + if idx in line2spell_and_mangled_list: + added = set() + for spell, mangled in line2spell_and_mangled_list[idx]: + # One line may contain multiple function declarations. + # Skip if the mangled name has been added before. + # The line number may come from an included file, + # we simply require the spelling name to appear on the line + # to exclude functions from other files. + if mangled in added or spell not in line: + continue + if args.functions is None or any(re.search(regex, spell) for regex in args.functions): + if added: + output_lines.append('//') + added.add(mangled) + common.add_ir_checks(output_lines, '//', run_list, func_dict, + mangled, False, args.function_signature) + output_lines.append(line.rstrip('\n')) + + # 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]) Index: llvm/utils/UpdateTestChecks/common.py =================================================================== --- llvm/utils/UpdateTestChecks/common.py +++ 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 Index: llvm/utils/UpdateTestChecks/asm.py =================================================================== --- llvm/utils/UpdateTestChecks/asm.py +++ 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 Index: clang/test/utils/update_cc_test_checks/generated-funcs.test =================================================================== --- /dev/null +++ clang/test/utils/update_cc_test_checks/generated-funcs.test @@ -0,0 +1,11 @@ +## Test that CHECK lines are generated for clang-generated functions + +# RUN: cp %S/Inputs/generated-funcs.c %t-generated.c && %update_cc_test_checks --include-generated-funcs %t-generated.c +# RUN: diff -u %S/Inputs/generated-funcs.c.generated.expected %t-generated.c +# RUN: cp %S/Inputs/generated-funcs.c %t-no-generated.c && %update_cc_test_checks %t-no-generated.c +# RUN: diff -u %S/Inputs/generated-funcs.c.no-generated.expected %t-no-generated.c +## Check that re-running update_cc_test_checks doesn't change the output +# RUN: %update_cc_test_checks --include-generated-funcs %t-generated.c +# RUN: diff -u %S/Inputs/generated-funcs.c.generated.expected %t-generated.c +# RUN: %update_cc_test_checks %t-no-generated.c +# RUN: diff -u %S/Inputs/generated-funcs.c.no-generated.expected %t-no-generated.c Index: clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.no-generated.expected =================================================================== --- /dev/null +++ clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.no-generated.expected @@ -0,0 +1,100 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// Check that the CHECK lines are generated for clang-generated functions +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fopenmp %s -emit-llvm -o - | FileCheck --check-prefix=OMP %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -emit-llvm -o - | FileCheck --check-prefix=NOOMP %s + +const int size = 1024*1024*32; + +double A[size]; + +void foo(void); + +// OMP-LABEL: @main( +// OMP-NEXT: entry: +// OMP-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// OMP-NEXT: [[I:%.*]] = alloca i32, align 4 +// OMP-NEXT: store i32 0, i32* [[RETVAL]], align 4 +// OMP-NEXT: store i32 0, i32* [[I]], align 4 +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @1, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..1 to void (i32*, i32*, ...)*)) +// OMP-NEXT: call void @foo() +// OMP-NEXT: ret i32 0 +// +// NOOMP-LABEL: @main( +// NOOMP-NEXT: entry: +// NOOMP-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// NOOMP-NEXT: [[I:%.*]] = alloca i32, align 4 +// NOOMP-NEXT: store i32 0, i32* [[RETVAL]], align 4 +// NOOMP-NEXT: store i32 0, i32* [[I]], align 4 +// NOOMP-NEXT: store i32 0, i32* [[I]], align 4 +// NOOMP-NEXT: br label [[FOR_COND:%.*]] +// NOOMP: for.cond: +// NOOMP-NEXT: [[TMP0:%.*]] = load i32, i32* [[I]], align 4 +// NOOMP-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 33554432 +// NOOMP-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +// NOOMP: for.body: +// NOOMP-NEXT: [[TMP1:%.*]] = load i32, i32* [[I]], align 4 +// NOOMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP1]] to i64 +// NOOMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], [33554432 x double]* @A, i64 0, i64 [[IDXPROM]] +// NOOMP-NEXT: store double 0.000000e+00, double* [[ARRAYIDX]], align 8 +// NOOMP-NEXT: br label [[FOR_INC:%.*]] +// NOOMP: for.inc: +// NOOMP-NEXT: [[TMP2:%.*]] = load i32, i32* [[I]], align 4 +// NOOMP-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1 +// NOOMP-NEXT: store i32 [[INC]], i32* [[I]], align 4 +// NOOMP-NEXT: br label [[FOR_COND]] +// NOOMP: for.end: +// NOOMP-NEXT: call void @foo() +// NOOMP-NEXT: ret i32 0 +// +int main() { + int i = 0; + +#pragma omp parallel for + for (i = 0; i < size; ++i) { + A[i] = 0.0; + } + + foo(); + + return 0; +} + +// OMP-LABEL: @foo( +// OMP-NEXT: entry: +// OMP-NEXT: [[I:%.*]] = alloca i32, align 4 +// OMP-NEXT: store i32 0, i32* [[I]], align 4 +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @1, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined. to void (i32*, i32*, ...)*)) +// OMP-NEXT: ret void +// +// NOOMP-LABEL: @foo( +// NOOMP-NEXT: entry: +// NOOMP-NEXT: [[I:%.*]] = alloca i32, align 4 +// NOOMP-NEXT: store i32 0, i32* [[I]], align 4 +// NOOMP-NEXT: store i32 0, i32* [[I]], align 4 +// NOOMP-NEXT: br label [[FOR_COND:%.*]] +// NOOMP: for.cond: +// NOOMP-NEXT: [[TMP0:%.*]] = load i32, i32* [[I]], align 4 +// NOOMP-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 33554432 +// NOOMP-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +// NOOMP: for.body: +// NOOMP-NEXT: [[TMP1:%.*]] = load i32, i32* [[I]], align 4 +// NOOMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP1]] to i64 +// NOOMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], [33554432 x double]* @A, i64 0, i64 [[IDXPROM]] +// NOOMP-NEXT: store double 1.000000e+00, double* [[ARRAYIDX]], align 8 +// NOOMP-NEXT: br label [[FOR_INC:%.*]] +// NOOMP: for.inc: +// NOOMP-NEXT: [[TMP2:%.*]] = load i32, i32* [[I]], align 4 +// NOOMP-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1 +// NOOMP-NEXT: store i32 [[INC]], i32* [[I]], align 4 +// NOOMP-NEXT: br label [[FOR_COND]] +// NOOMP: for.end: +// NOOMP-NEXT: ret void +// +void foo(void) { + int i = 0; + +#pragma omp parallel for + for (i = 0; i < size; ++i) { + A[i] = 1.0; + } +} Index: clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.generated.expected =================================================================== --- /dev/null +++ clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.generated.expected @@ -0,0 +1,229 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// Check that the CHECK lines are generated for clang-generated functions +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fopenmp %s -emit-llvm -o - | FileCheck --check-prefix=OMP %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -emit-llvm -o - | FileCheck --check-prefix=NOOMP %s + +const int size = 1024*1024*32; + +double A[size]; + +void foo(void); + +int main() { + int i = 0; + +#pragma omp parallel for + for (i = 0; i < size; ++i) { + A[i] = 0.0; + } + + foo(); + + return 0; +} + +void foo(void) { + int i = 0; + +#pragma omp parallel for + for (i = 0; i < size; ++i) { + A[i] = 1.0; + } +} +// NOOMP-LABEL: @main( +// NOOMP-NEXT: entry: +// NOOMP-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// NOOMP-NEXT: [[I:%.*]] = alloca i32, align 4 +// NOOMP-NEXT: store i32 0, i32* [[RETVAL]], align 4 +// NOOMP-NEXT: store i32 0, i32* [[I]], align 4 +// NOOMP-NEXT: store i32 0, i32* [[I]], align 4 +// NOOMP-NEXT: br label [[FOR_COND:%.*]] +// NOOMP: for.cond: +// NOOMP-NEXT: [[TMP0:%.*]] = load i32, i32* [[I]], align 4 +// NOOMP-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 33554432 +// NOOMP-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +// NOOMP: for.body: +// NOOMP-NEXT: [[TMP1:%.*]] = load i32, i32* [[I]], align 4 +// NOOMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP1]] to i64 +// NOOMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], [33554432 x double]* @A, i64 0, i64 [[IDXPROM]] +// NOOMP-NEXT: store double 0.000000e+00, double* [[ARRAYIDX]], align 8 +// NOOMP-NEXT: br label [[FOR_INC:%.*]] +// NOOMP: for.inc: +// NOOMP-NEXT: [[TMP2:%.*]] = load i32, i32* [[I]], align 4 +// NOOMP-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1 +// NOOMP-NEXT: store i32 [[INC]], i32* [[I]], align 4 +// NOOMP-NEXT: br label [[FOR_COND]] +// NOOMP: for.end: +// NOOMP-NEXT: call void @foo() +// NOOMP-NEXT: ret i32 0 +// +// +// NOOMP-LABEL: @foo( +// NOOMP-NEXT: entry: +// NOOMP-NEXT: [[I:%.*]] = alloca i32, align 4 +// NOOMP-NEXT: store i32 0, i32* [[I]], align 4 +// NOOMP-NEXT: store i32 0, i32* [[I]], align 4 +// NOOMP-NEXT: br label [[FOR_COND:%.*]] +// NOOMP: for.cond: +// NOOMP-NEXT: [[TMP0:%.*]] = load i32, i32* [[I]], align 4 +// NOOMP-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 33554432 +// NOOMP-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +// NOOMP: for.body: +// NOOMP-NEXT: [[TMP1:%.*]] = load i32, i32* [[I]], align 4 +// NOOMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP1]] to i64 +// NOOMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], [33554432 x double]* @A, i64 0, i64 [[IDXPROM]] +// NOOMP-NEXT: store double 1.000000e+00, double* [[ARRAYIDX]], align 8 +// NOOMP-NEXT: br label [[FOR_INC:%.*]] +// NOOMP: for.inc: +// NOOMP-NEXT: [[TMP2:%.*]] = load i32, i32* [[I]], align 4 +// NOOMP-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1 +// NOOMP-NEXT: store i32 [[INC]], i32* [[I]], align 4 +// NOOMP-NEXT: br label [[FOR_COND]] +// NOOMP: for.end: +// NOOMP-NEXT: ret void +// +// +// OMP-LABEL: @foo( +// OMP-NEXT: entry: +// OMP-NEXT: [[I:%.*]] = alloca i32, align 4 +// OMP-NEXT: store i32 0, i32* [[I]], align 4 +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @1, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined. to void (i32*, i32*, ...)*)) +// OMP-NEXT: ret void +// +// +// OMP-LABEL: @.omp_outlined.( +// OMP-NEXT: entry: +// OMP-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca i32*, align 8 +// OMP-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca i32*, align 8 +// OMP-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 +// OMP-NEXT: [[TMP:%.*]] = alloca i32, align 4 +// OMP-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 +// OMP-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 +// OMP-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4 +// OMP-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4 +// OMP-NEXT: [[I:%.*]] = alloca i32, align 4 +// OMP-NEXT: store i32* [[DOTGLOBAL_TID_:%.*]], i32** [[DOTGLOBAL_TID__ADDR]], align 8 +// OMP-NEXT: store i32* [[DOTBOUND_TID_:%.*]], i32** [[DOTBOUND_TID__ADDR]], align 8 +// OMP-NEXT: store i32 0, i32* [[DOTOMP_LB]], align 4 +// OMP-NEXT: store i32 33554431, i32* [[DOTOMP_UB]], align 4 +// OMP-NEXT: store i32 1, i32* [[DOTOMP_STRIDE]], align 4 +// OMP-NEXT: store i32 0, i32* [[DOTOMP_IS_LAST]], align 4 +// OMP-NEXT: [[TMP0:%.*]] = load i32*, i32** [[DOTGLOBAL_TID__ADDR]], align 8 +// OMP-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 +// OMP-NEXT: call void @__kmpc_for_static_init_4(%struct.ident_t* @0, i32 [[TMP1]], i32 34, i32* [[DOTOMP_IS_LAST]], i32* [[DOTOMP_LB]], i32* [[DOTOMP_UB]], i32* [[DOTOMP_STRIDE]], i32 1, i32 1) +// OMP-NEXT: [[TMP2:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4 +// OMP-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP2]], 33554431 +// OMP-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +// OMP: cond.true: +// OMP-NEXT: br label [[COND_END:%.*]] +// OMP: cond.false: +// OMP-NEXT: [[TMP3:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4 +// OMP-NEXT: br label [[COND_END]] +// OMP: cond.end: +// OMP-NEXT: [[COND:%.*]] = phi i32 [ 33554431, [[COND_TRUE]] ], [ [[TMP3]], [[COND_FALSE]] ] +// OMP-NEXT: store i32 [[COND]], i32* [[DOTOMP_UB]], align 4 +// OMP-NEXT: [[TMP4:%.*]] = load i32, i32* [[DOTOMP_LB]], align 4 +// OMP-NEXT: store i32 [[TMP4]], i32* [[DOTOMP_IV]], align 4 +// OMP-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] +// OMP: omp.inner.for.cond: +// OMP-NEXT: [[TMP5:%.*]] = load i32, i32* [[DOTOMP_IV]], align 4 +// OMP-NEXT: [[TMP6:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4 +// OMP-NEXT: [[CMP1:%.*]] = icmp sle i32 [[TMP5]], [[TMP6]] +// OMP-NEXT: br i1 [[CMP1]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_END:%.*]] +// OMP: omp.inner.for.body: +// OMP-NEXT: [[TMP7:%.*]] = load i32, i32* [[DOTOMP_IV]], align 4 +// OMP-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP7]], 1 +// OMP-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] +// OMP-NEXT: store i32 [[ADD]], i32* [[I]], align 4 +// OMP-NEXT: [[TMP8:%.*]] = load i32, i32* [[I]], align 4 +// OMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP8]] to i64 +// OMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], [33554432 x double]* @A, i64 0, i64 [[IDXPROM]] +// OMP-NEXT: store double 1.000000e+00, double* [[ARRAYIDX]], align 8 +// OMP-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] +// OMP: omp.body.continue: +// OMP-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] +// OMP: omp.inner.for.inc: +// OMP-NEXT: [[TMP9:%.*]] = load i32, i32* [[DOTOMP_IV]], align 4 +// OMP-NEXT: [[ADD2:%.*]] = add nsw i32 [[TMP9]], 1 +// OMP-NEXT: store i32 [[ADD2]], i32* [[DOTOMP_IV]], align 4 +// OMP-NEXT: br label [[OMP_INNER_FOR_COND]] +// OMP: omp.inner.for.end: +// OMP-NEXT: br label [[OMP_LOOP_EXIT:%.*]] +// OMP: omp.loop.exit: +// OMP-NEXT: call void @__kmpc_for_static_fini(%struct.ident_t* @0, i32 [[TMP1]]) +// OMP-NEXT: ret void +// +// +// OMP-LABEL: @main( +// OMP-NEXT: entry: +// OMP-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// OMP-NEXT: [[I:%.*]] = alloca i32, align 4 +// OMP-NEXT: store i32 0, i32* [[RETVAL]], align 4 +// OMP-NEXT: store i32 0, i32* [[I]], align 4 +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @1, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..1 to void (i32*, i32*, ...)*)) +// OMP-NEXT: call void @foo() +// OMP-NEXT: ret i32 0 +// +// +// OMP-LABEL: @.omp_outlined..1( +// OMP-NEXT: entry: +// OMP-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca i32*, align 8 +// OMP-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca i32*, align 8 +// OMP-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 +// OMP-NEXT: [[TMP:%.*]] = alloca i32, align 4 +// OMP-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 +// OMP-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 +// OMP-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4 +// OMP-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4 +// OMP-NEXT: [[I:%.*]] = alloca i32, align 4 +// OMP-NEXT: store i32* [[DOTGLOBAL_TID_:%.*]], i32** [[DOTGLOBAL_TID__ADDR]], align 8 +// OMP-NEXT: store i32* [[DOTBOUND_TID_:%.*]], i32** [[DOTBOUND_TID__ADDR]], align 8 +// OMP-NEXT: store i32 0, i32* [[DOTOMP_LB]], align 4 +// OMP-NEXT: store i32 33554431, i32* [[DOTOMP_UB]], align 4 +// OMP-NEXT: store i32 1, i32* [[DOTOMP_STRIDE]], align 4 +// OMP-NEXT: store i32 0, i32* [[DOTOMP_IS_LAST]], align 4 +// OMP-NEXT: [[TMP0:%.*]] = load i32*, i32** [[DOTGLOBAL_TID__ADDR]], align 8 +// OMP-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 +// OMP-NEXT: call void @__kmpc_for_static_init_4(%struct.ident_t* @0, i32 [[TMP1]], i32 34, i32* [[DOTOMP_IS_LAST]], i32* [[DOTOMP_LB]], i32* [[DOTOMP_UB]], i32* [[DOTOMP_STRIDE]], i32 1, i32 1) +// OMP-NEXT: [[TMP2:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4 +// OMP-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP2]], 33554431 +// OMP-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +// OMP: cond.true: +// OMP-NEXT: br label [[COND_END:%.*]] +// OMP: cond.false: +// OMP-NEXT: [[TMP3:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4 +// OMP-NEXT: br label [[COND_END]] +// OMP: cond.end: +// OMP-NEXT: [[COND:%.*]] = phi i32 [ 33554431, [[COND_TRUE]] ], [ [[TMP3]], [[COND_FALSE]] ] +// OMP-NEXT: store i32 [[COND]], i32* [[DOTOMP_UB]], align 4 +// OMP-NEXT: [[TMP4:%.*]] = load i32, i32* [[DOTOMP_LB]], align 4 +// OMP-NEXT: store i32 [[TMP4]], i32* [[DOTOMP_IV]], align 4 +// OMP-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] +// OMP: omp.inner.for.cond: +// OMP-NEXT: [[TMP5:%.*]] = load i32, i32* [[DOTOMP_IV]], align 4 +// OMP-NEXT: [[TMP6:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4 +// OMP-NEXT: [[CMP1:%.*]] = icmp sle i32 [[TMP5]], [[TMP6]] +// OMP-NEXT: br i1 [[CMP1]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_END:%.*]] +// OMP: omp.inner.for.body: +// OMP-NEXT: [[TMP7:%.*]] = load i32, i32* [[DOTOMP_IV]], align 4 +// OMP-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP7]], 1 +// OMP-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] +// OMP-NEXT: store i32 [[ADD]], i32* [[I]], align 4 +// OMP-NEXT: [[TMP8:%.*]] = load i32, i32* [[I]], align 4 +// OMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP8]] to i64 +// OMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], [33554432 x double]* @A, i64 0, i64 [[IDXPROM]] +// OMP-NEXT: store double 0.000000e+00, double* [[ARRAYIDX]], align 8 +// OMP-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] +// OMP: omp.body.continue: +// OMP-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] +// OMP: omp.inner.for.inc: +// OMP-NEXT: [[TMP9:%.*]] = load i32, i32* [[DOTOMP_IV]], align 4 +// OMP-NEXT: [[ADD2:%.*]] = add nsw i32 [[TMP9]], 1 +// OMP-NEXT: store i32 [[ADD2]], i32* [[DOTOMP_IV]], align 4 +// OMP-NEXT: br label [[OMP_INNER_FOR_COND]] +// OMP: omp.inner.for.end: +// OMP-NEXT: br label [[OMP_LOOP_EXIT:%.*]] +// OMP: omp.loop.exit: +// OMP-NEXT: call void @__kmpc_for_static_fini(%struct.ident_t* @0, i32 [[TMP1]]) +// OMP-NEXT: ret void +// Index: clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c =================================================================== --- /dev/null +++ clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c @@ -0,0 +1,31 @@ +// Check that the CHECK lines are generated for clang-generated functions +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fopenmp %s -emit-llvm -o - | FileCheck --check-prefix=OMP %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -emit-llvm -o - | FileCheck --check-prefix=NOOMP %s + +const int size = 1024*1024*32; + +double A[size]; + +void foo(void); + +int main() { + int i = 0; + +#pragma omp parallel for + for (i = 0; i < size; ++i) { + A[i] = 0.0; + } + + foo(); + + return 0; +} + +void foo(void) { + int i = 0; + +#pragma omp parallel for + for (i = 0; i < size; ++i) { + A[i] = 1.0; + } +}
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits