jdoerfert created this revision. jdoerfert added reviewers: greened, arichardson, ggeorgakoudis. Herald added a subscriber: bollu. jdoerfert requested review of this revision. Herald added subscribers: cfe-commits, sstefan1. Herald added projects: clang, LLVM.
With D83004 <https://reviews.llvm.org/D83004> we allowed to check for generated functions. However, since those might be generated in various places we did simply check for all functions in the end. Furthermore, this prevented us from reusing check prefixes across run lines. For every run line we checked for all functions regardless if the functions were equal across prefixes. To reduce the number of check lines we now allow to reuse them across run lines. That is, we can have prefixes that span multiple run lines even when we check for generated functions. This will only reduce the run lines if we can find a total order of the generated functions though. The check lines for generated functions are placed in-between check lines of existing functions or at the end, as necessary. The IR update script needs adjusts similar to the CC one. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D102558 Files: clang/test/utils/update_cc_test_checks/Inputs/generated-funcs-regex.c.expected clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.generated.expected clang/test/utils/update_cc_test_checks/Inputs/lots-of-generated-funcs.c clang/test/utils/update_cc_test_checks/Inputs/lots-of-generated-funcs.c.lots-of-generated.expected clang/test/utils/update_cc_test_checks/Inputs/lots-of-generated-funcs.c.no-lots-of-generated.expected clang/test/utils/update_cc_test_checks/lots-of-generated-funcs.test llvm/utils/UpdateTestChecks/common.py llvm/utils/update_cc_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 @@ -138,6 +138,9 @@ '--include-generated-funcs', True) + # TODO: use common.get_total_function_order to avoid adding new functions at the end but + # instead place them in order between existing ones. See the CC script. + if 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 Index: llvm/utils/update_cc_test_checks.py =================================================================== --- llvm/utils/update_cc_test_checks.py +++ llvm/utils/update_cc_test_checks.py @@ -305,8 +305,9 @@ lambda args: ti.args.include_generated_funcs, '--include-generated-funcs', True) + total_function_order = common.get_total_function_order(filecheck_run_list, builder.func_order()) - if include_generated_funcs: + if include_generated_funcs and not total_function_order: # 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. @@ -337,6 +338,59 @@ check_generator(my_output_lines, prefixes, func)) else: + trailing_functions = [] + # If we might have generated functions we need to place them in the right position now, + # trailing ones are kept separate though. + if include_generated_funcs: + total_order_idx = 0 + for line in line2spell_and_mangled_list.keys(): + to_be_added = [] + for spell, mangled in line2spell_and_mangled_list[line]: + if mangled not in total_function_order: + continue + # Figure out where this existing function is in the total order. All functions we + # skipped are inserted before this one. + index = total_function_order.index(mangled) + while total_order_idx < index: + to_be_added.append(total_function_order[total_order_idx]) + total_order_idx += 1 + # Account for the function itself (spell, mangled) + total_order_idx += 1 + # Reverse the order to match total order again before we insert the functions + # in the current line. + to_be_added.reverse() + for tba in to_be_added: + line2spell_and_mangled_list[line].insert(0, ('', tba)) + + # All functions we have not handled yet are added to the end. + while total_order_idx < len(total_function_order): + func = total_function_order[total_order_idx] + trailing_functions.append(func) + total_order_idx += 1 + + def handle_functions_on_line(output_lines, line, args, spell, mangled, added, include_line): + # 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 and spell not in line): + return + if args.functions is None or any(re.search(regex, spell) for regex in args.functions): + last_line = output_lines[-1].strip() + while last_line == '//': + # Remove the comment line since we will generate a new comment + # line as part of common.add_ir_checks() + output_lines.pop() + last_line = output_lines[-1].strip() + if added: + output_lines.append('//') + added.add(mangled) + common.add_ir_checks(output_lines, '//', filecheck_run_list, func_dict, mangled, + False, args.function_signature, global_vars_seen_dict) + if line.rstrip('\n') == '//': + include_line = False + # Normal mode. Put checks before each source function. for line_info in ti.iterlines(output_lines): idx = line_info.line_number @@ -349,31 +403,17 @@ 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): - last_line = output_lines[-1].strip() - while last_line == '//': - # Remove the comment line since we will generate a new comment - # line as part of common.add_ir_checks() - output_lines.pop() - last_line = output_lines[-1].strip() - if added: - output_lines.append('//') - added.add(mangled) - common.add_ir_checks(output_lines, '//', filecheck_run_list, func_dict, mangled, - False, args.function_signature, global_vars_seen_dict) - if line.rstrip('\n') == '//': - include_line = False + handle_functions_on_line(output_lines, line, args, spell, mangled, added, include_line) if include_line: output_lines.append(line.rstrip('\n')) + # After we inserted check lines in the original program we append all check lines for functions + # that were generated after the existing ones. + added = set() + for func in trailing_functions: + handle_functions_on_line(output_lines, func, args, func, func, added, include_line) + common.debug('Writing %d lines to %s...' % (len(output_lines), ti.path)) with open(ti.path, '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 @@ -290,6 +290,24 @@ def __str__(self): return self.scrub +# Try to put all functions into a total order, this might not work if two run +# lines generated the functions in a different order. +def get_total_function_order(prefix_list, func_order): + total_order = [] + for prefix_item in prefix_list: + prefixes = prefix_item[0] + for prefix in prefixes: + for func in func_order[prefix]: + total_idx = 0 + if func in total_order: + idx = total_order.index(func) + if idx < total_idx: + return None + total_idx = idx + 1 + else: + total_order.append(func) + return total_order + class FunctionTestBuilder: def __init__(self, run_list, flags, scrubber_args): self._verbose = flags.verbose @@ -349,28 +367,8 @@ print('Processing function: ' + func, file=sys.stderr) for l in scrubbed_body.splitlines(): print(' ' + l, file=sys.stderr) - for prefix in prefixes: - if func in self._func_dict[prefix]: - if (self._func_dict[prefix][func] is None or - str(self._func_dict[prefix][func]) != scrubbed_body or - self._func_dict[prefix][func].args_and_sig != args_and_sig or - self._func_dict[prefix][func].attrs != attrs): - if (self._func_dict[prefix][func] is not None and - self._func_dict[prefix][func].is_same_except_arg_names( - scrubbed_extra, - args_and_sig, - attrs)): - self._func_dict[prefix][func].scrub = scrubbed_extra - self._func_dict[prefix][func].args_and_sig = args_and_sig - continue - else: - # This means a previous RUN line produced a body for this function - # that is different from the one produced by this current RUN line, - # so the body can't be common accross RUN lines. We use None to - # indicate that. - self._func_dict[prefix][func] = None - continue + for prefix in prefixes: # Replace function names matching the regex. for regex in self._replace_value_regex: # Pattern that matches capture groups in the regex in leftmost order. @@ -395,6 +393,27 @@ # capture groups set. scrubbed_body = re.sub(func_repl, '{{' + func_repl + '}}', scrubbed_body) + if func in self._func_dict[prefix]: + if (self._func_dict[prefix][func] is None or + str(self._func_dict[prefix][func]) != scrubbed_body or + self._func_dict[prefix][func].args_and_sig != args_and_sig or + self._func_dict[prefix][func].attrs != attrs): + if (self._func_dict[prefix][func] is not None and + self._func_dict[prefix][func].is_same_except_arg_names( + scrubbed_extra, + args_and_sig, + attrs)): + self._func_dict[prefix][func].scrub = scrubbed_extra + self._func_dict[prefix][func].args_and_sig = args_and_sig + continue + else: + # This means a previous RUN line produced a body for this function + # that is different from the one produced by this current RUN line, + # so the body can't be common across RUN lines. We use None to + # indicate that. + self._func_dict[prefix][func] = None + continue + self._func_dict[prefix][func] = function_body( scrubbed_body, scrubbed_extra, args_and_sig, attrs) self._func_order[prefix].append(func) Index: clang/test/utils/update_cc_test_checks/lots-of-generated-funcs.test =================================================================== --- /dev/null +++ clang/test/utils/update_cc_test_checks/lots-of-generated-funcs.test @@ -0,0 +1,12 @@ +## Test that CHECK lines are generated for clang-generated functions + +# RUN: cp %S/Inputs/lots-of-generated-funcs.c %t-lots-of-generated.c && %update_cc_test_checks --include-generated-funcs %t-lots-of-generated.c +# RUN: diff -u %S/Inputs/lots-of-generated-funcs.c.lots-of-generated.expected %t-lots-of-generated.c +# RUN: cp %S/Inputs/lots-of-generated-funcs.c %t-no-lots-of-generated.c && %update_cc_test_checks %t-no-lots-of-generated.c +# RUN: diff -u %S/Inputs/lots-of-generated-funcs.c.no-lots-of-generated.expected %t-no-lots-of-generated.c + +## Check that re-running update_cc_test_checks doesn't change the output +# RUN: %update_cc_test_checks --include-generated-funcs %t-lots-of-generated.c +# RUN: diff -u %S/Inputs/lots-of-generated-funcs.c.lots-of-generated.expected %t-lots-of-generated.c +# RUN: %update_cc_test_checks %t-no-lots-of-generated.c +# RUN: diff -u %S/Inputs/lots-of-generated-funcs.c.no-lots-of-generated.expected %t-no-lots-of-generated.c Index: clang/test/utils/update_cc_test_checks/Inputs/lots-of-generated-funcs.c.no-lots-of-generated.expected =================================================================== --- /dev/null +++ clang/test/utils/update_cc_test_checks/Inputs/lots-of-generated-funcs.c.no-lots-of-generated.expected @@ -0,0 +1,73 @@ +// 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 + +// OMP-LABEL: @t0( +// OMP-NEXT: entry: +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1:[0-9]+]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined. to void (i32*, i32*, ...)*)) +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..1 to void (i32*, i32*, ...)*)) +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..2 to void (i32*, i32*, ...)*)) +// OMP-NEXT: ret void +// +// NOOMP-LABEL: @t0( +// NOOMP-NEXT: entry: +// NOOMP-NEXT: ret void +// +void t0() { + #pragma omp parallel + { + } + #pragma omp parallel + { + } + #pragma omp parallel + { + } +} + +// OMP-LABEL: @t1( +// OMP-NEXT: entry: +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..3 to void (i32*, i32*, ...)*)) +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..4 to void (i32*, i32*, ...)*)) +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..5 to void (i32*, i32*, ...)*)) +// OMP-NEXT: ret void +// +// NOOMP-LABEL: @t1( +// NOOMP-NEXT: entry: +// NOOMP-NEXT: ret void +// +void t1() { + #pragma omp parallel + { + } + #pragma omp parallel + { + } + #pragma omp parallel + { + } +} + +// OMP-LABEL: @t2( +// OMP-NEXT: entry: +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..6 to void (i32*, i32*, ...)*)) +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..7 to void (i32*, i32*, ...)*)) +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..8 to void (i32*, i32*, ...)*)) +// OMP-NEXT: ret void +// +// NOOMP-LABEL: @t2( +// NOOMP-NEXT: entry: +// NOOMP-NEXT: ret void +// +void t2() { + #pragma omp parallel + { + } + #pragma omp parallel + { + } + #pragma omp parallel + { + } +} Index: clang/test/utils/update_cc_test_checks/Inputs/lots-of-generated-funcs.c.lots-of-generated.expected =================================================================== --- /dev/null +++ clang/test/utils/update_cc_test_checks/Inputs/lots-of-generated-funcs.c.lots-of-generated.expected @@ -0,0 +1,121 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs +// 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 + +// OMP-LABEL: @t0( +// OMP-NEXT: entry: +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1:[0-9]+]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined. to void (i32*, i32*, ...)*)) +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..1 to void (i32*, i32*, ...)*)) +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..2 to void (i32*, i32*, ...)*)) +// OMP-NEXT: ret void +// +// NOOMP-LABEL: @t0( +// NOOMP-NEXT: entry: +// NOOMP-NEXT: ret void +// +void t0() { + #pragma omp parallel + { + } + #pragma omp parallel + { + } + #pragma omp parallel + { + } +} + +// 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: store i32* [[DOTGLOBAL_TID_:%.*]], i32** [[DOTGLOBAL_TID__ADDR]], align 8 +// OMP-NEXT: store i32* [[DOTBOUND_TID_:%.*]], i32** [[DOTBOUND_TID__ADDR]], align 8 +// OMP-NEXT: ret void +// +// OMP-LABEL: @.omp_outlined..2( +// OMP-NEXT: entry: +// OMP-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca i32*, align 8 +// OMP-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca i32*, align 8 +// 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: ret void +// +// OMP-LABEL: @t1( +// OMP-NEXT: entry: +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..3 to void (i32*, i32*, ...)*)) +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..4 to void (i32*, i32*, ...)*)) +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..5 to void (i32*, i32*, ...)*)) +// OMP-NEXT: ret void +// +// NOOMP-LABEL: @t1( +// NOOMP-NEXT: entry: +// NOOMP-NEXT: ret void +// +void t1() { + #pragma omp parallel + { + } + #pragma omp parallel + { + } + #pragma omp parallel + { + } +} + +// OMP-LABEL: @.omp_outlined..4( +// OMP-NEXT: entry: +// OMP-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca i32*, align 8 +// OMP-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca i32*, align 8 +// 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: ret void +// +// OMP-LABEL: @.omp_outlined..5( +// OMP-NEXT: entry: +// OMP-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca i32*, align 8 +// OMP-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca i32*, align 8 +// 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: ret void +// +// OMP-LABEL: @t2( +// OMP-NEXT: entry: +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..6 to void (i32*, i32*, ...)*)) +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..7 to void (i32*, i32*, ...)*)) +// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..8 to void (i32*, i32*, ...)*)) +// OMP-NEXT: ret void +// +// NOOMP-LABEL: @t2( +// NOOMP-NEXT: entry: +// NOOMP-NEXT: ret void +// +void t2() { + #pragma omp parallel + { + } + #pragma omp parallel + { + } + #pragma omp parallel + { + } +} +// OMP-LABEL: @.omp_outlined..7( +// OMP-NEXT: entry: +// OMP-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca i32*, align 8 +// OMP-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca i32*, align 8 +// 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: ret void +// +// OMP-LABEL: @.omp_outlined..8( +// OMP-NEXT: entry: +// OMP-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca i32*, align 8 +// OMP-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca i32*, align 8 +// 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: ret void +// Index: clang/test/utils/update_cc_test_checks/Inputs/lots-of-generated-funcs.c =================================================================== --- /dev/null +++ clang/test/utils/update_cc_test_checks/Inputs/lots-of-generated-funcs.c @@ -0,0 +1,39 @@ +// 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 + +void t0() { + #pragma omp parallel + { + } + #pragma omp parallel + { + } + #pragma omp parallel + { + } +} + +void t1() { + #pragma omp parallel + { + } + #pragma omp parallel + { + } + #pragma omp parallel + { + } +} + +void t2() { + #pragma omp parallel + { + } + #pragma omp parallel + { + } + #pragma omp parallel + { + } +} Index: clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.generated.expected =================================================================== --- clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.generated.expected +++ clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.generated.expected @@ -9,27 +9,6 @@ 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; - } -} // OMP-LABEL: @main( // OMP-NEXT: entry: // OMP-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 @@ -40,141 +19,6 @@ // OMP-NEXT: call void @foo() // OMP-NEXT: ret i32 0 // -// -// 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* @[[GLOB1:[0-9]+]], 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* @[[GLOB1]], i32 [[TMP1]]) -// OMP-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* @[[GLOB2]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..1 to void (i32*, i32*, ...)*)) -// OMP-NEXT: ret void -// -// -// 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* @[[GLOB1]], 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* @[[GLOB1]], i32 [[TMP1]]) -// OMP-NEXT: ret void -// -// // NOOMP-LABEL: @main( // NOOMP-NEXT: entry: // NOOMP-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 @@ -202,6 +46,25 @@ // 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* @[[GLOB2]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..1 to void (i32*, i32*, ...)*)) +// OMP-NEXT: ret void // // NOOMP-LABEL: @foo( // NOOMP-NEXT: entry: @@ -227,3 +90,11 @@ // 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-regex.c.expected =================================================================== --- clang/test/utils/update_cc_test_checks/Inputs/generated-funcs-regex.c.expected +++ clang/test/utils/update_cc_test_checks/Inputs/generated-funcs-regex.c.expected @@ -4,14 +4,6 @@ void __test_offloading_42_abcdef_bar_l123(); void use(int); -void foo(int a) -{ - #pragma omp target - use(a); - - __test_offloading_42_abcdef_bar_l123(); - int somevar_abc123_; -} // CHECK-LABEL: @foo( // CHECK-NEXT: entry: // CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 @@ -26,7 +18,14 @@ // CHECK-NEXT: call void (...) @{{__test_offloading_[a-z0-9]+_[a-z0-9]+_bar_l[0-9]+}}() // CHECK-NEXT: ret void // -// +void foo(int a) +{ + #pragma omp target + use(a); + + __test_offloading_42_abcdef_bar_l123(); + int somevar_abc123_; +} // CHECK-LABEL: @{{__omp_offloading_[a-z0-9]+_[a-z0-9]+_foo_l[0-9]+}}( // CHECK-NEXT: entry: // CHECK-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits