diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll @@ -0,0 +1,37 @@ +; RUN: opt -passes=hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s --check-prefix=REUSE +; RUN: opt -passes=hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s --check-prefix=REUSE +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.14.0" + +@G = external dso_local global i32, align 4 + +define void @foo(i32) { + %2 = icmp eq i32 %0, 0 + tail call void @_Z10sideeffectv() + br i1 %2, label %sink, label %exit + +sink: + tail call void @_Z10sideeffectv() + call void @llvm.trap() + unreachable + +exit: + ret void +} + +define void @bar(i32) { + %2 = icmp eq i32 %0, 0 + tail call void @_Z10sideeffectv() + br i1 %2, label %sink, label %exit + +sink: + tail call void @_Z10sideeffectv() + call void @llvm.trap() + unreachable + +exit: + ret void +} + +declare void @llvm.trap() noreturn cold +declare void @_Z10sideeffectv() diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.expected new file mode 100644 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.expected @@ -0,0 +1,77 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs +; RUN: opt -passes=hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s --check-prefix=REUSE +; RUN: opt -passes=hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s --check-prefix=REUSE +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.14.0" + +@G = external dso_local global i32, align 4 + +define void @foo(i32) { + %2 = icmp eq i32 %0, 0 + tail call void @_Z10sideeffectv() + br i1 %2, label %sink, label %exit + +sink: + tail call void @_Z10sideeffectv() + call void @llvm.trap() + unreachable + +exit: + ret void +} + +define void @bar(i32) { + %2 = icmp eq i32 %0, 0 + tail call void @_Z10sideeffectv() + br i1 %2, label %sink, label %exit + +sink: + tail call void @_Z10sideeffectv() + call void @llvm.trap() + unreachable + +exit: + ret void +} + +declare void @llvm.trap() noreturn cold +declare void @_Z10sideeffectv() +; REUSE-LABEL: @foo( +; REUSE-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0:%.*]], 0 +; REUSE-NEXT: tail call void @_Z10sideeffectv() +; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] +; REUSE: codeRepl: +; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]] +; REUSE-NEXT: ret void +; REUSE: exit: +; REUSE-NEXT: ret void +; +; +; REUSE-LABEL: @bar( +; REUSE-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0:%.*]], 0 +; REUSE-NEXT: tail call void @_Z10sideeffectv() +; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] +; REUSE: codeRepl: +; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]] +; REUSE-NEXT: ret void +; REUSE: exit: +; REUSE-NEXT: ret void +; +; +; REUSE-LABEL: @foo.cold.1( +; REUSE-NEXT: newFuncRoot: +; REUSE-NEXT: br label [[SINK:%.*]] +; REUSE: sink: +; REUSE-NEXT: tail call void @_Z10sideeffectv() +; REUSE-NEXT: call void @llvm.trap() +; REUSE-NEXT: unreachable +; +; +; REUSE-LABEL: @bar.cold.1( +; REUSE-NEXT: newFuncRoot: +; REUSE-NEXT: br label [[SINK:%.*]] +; REUSE: sink: +; REUSE-NEXT: tail call void @_Z10sideeffectv() +; REUSE-NEXT: call void @llvm.trap() +; REUSE-NEXT: unreachable +; diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.globals.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.globals.expected new file mode 100644 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.globals.expected @@ -0,0 +1,85 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals --include-generated-funcs +; RUN: opt -passes=hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s --check-prefix=REUSE +; RUN: opt -passes=hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s --check-prefix=REUSE +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.14.0" + +@G = external dso_local global i32, align 4 + +define void @foo(i32) { + %2 = icmp eq i32 %0, 0 + tail call void @_Z10sideeffectv() + br i1 %2, label %sink, label %exit + +sink: + tail call void @_Z10sideeffectv() + call void @llvm.trap() + unreachable + +exit: + ret void +} + +define void @bar(i32) { + %2 = icmp eq i32 %0, 0 + tail call void @_Z10sideeffectv() + br i1 %2, label %sink, label %exit + +sink: + tail call void @_Z10sideeffectv() + call void @llvm.trap() + unreachable + +exit: + ret void +} + +declare void @llvm.trap() noreturn cold +declare void @_Z10sideeffectv() +;. +; REUSE: @[[G:[a-zA-Z0-9_$"\\.-]+]] = external dso_local global i32, align 4 +;. +; REUSE-LABEL: @foo( +; REUSE-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0:%.*]], 0 +; REUSE-NEXT: tail call void @_Z10sideeffectv() +; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] +; REUSE: codeRepl: +; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]] +; REUSE-NEXT: ret void +; REUSE: exit: +; REUSE-NEXT: ret void +; +; +; REUSE-LABEL: @bar( +; REUSE-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0:%.*]], 0 +; REUSE-NEXT: tail call void @_Z10sideeffectv() +; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] +; REUSE: codeRepl: +; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]] +; REUSE-NEXT: ret void +; REUSE: exit: +; REUSE-NEXT: ret void +; +; +; REUSE-LABEL: @foo.cold.1( +; REUSE-NEXT: newFuncRoot: +; REUSE-NEXT: br label [[SINK:%.*]] +; REUSE: sink: +; REUSE-NEXT: tail call void @_Z10sideeffectv() +; REUSE-NEXT: call void @llvm.trap() +; REUSE-NEXT: unreachable +; +; +; REUSE-LABEL: @bar.cold.1( +; REUSE-NEXT: newFuncRoot: +; REUSE-NEXT: br label [[SINK:%.*]] +; REUSE: sink: +; REUSE-NEXT: tail call void @_Z10sideeffectv() +; REUSE-NEXT: call void @llvm.trap() +; REUSE-NEXT: unreachable +; +;. +; REUSE: attributes #[[ATTR0:[0-9]+]] = { cold noreturn nounwind } +; REUSE: attributes #[[ATTR1:[0-9]+]] = { cold minsize noreturn } +; REUSE: attributes #[[ATTR2]] = { noinline } +;. diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.expected new file mode 100644 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.expected @@ -0,0 +1,58 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes=hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s --check-prefix=REUSE +; RUN: opt -passes=hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s --check-prefix=REUSE +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.14.0" + +@G = external dso_local global i32, align 4 + +define void @foo(i32) { +; REUSE-LABEL: @foo( +; REUSE-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0:%.*]], 0 +; REUSE-NEXT: tail call void @_Z10sideeffectv() +; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] +; REUSE: codeRepl: +; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]] +; REUSE-NEXT: ret void +; REUSE: exit: +; REUSE-NEXT: ret void +; + %2 = icmp eq i32 %0, 0 + tail call void @_Z10sideeffectv() + br i1 %2, label %sink, label %exit + +sink: + tail call void @_Z10sideeffectv() + call void @llvm.trap() + unreachable + +exit: + ret void +} + +define void @bar(i32) { +; REUSE-LABEL: @bar( +; REUSE-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0:%.*]], 0 +; REUSE-NEXT: tail call void @_Z10sideeffectv() +; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] +; REUSE: codeRepl: +; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]] +; REUSE-NEXT: ret void +; REUSE: exit: +; REUSE-NEXT: ret void +; + %2 = icmp eq i32 %0, 0 + tail call void @_Z10sideeffectv() + br i1 %2, label %sink, label %exit + +sink: + tail call void @_Z10sideeffectv() + call void @llvm.trap() + unreachable + +exit: + ret void +} + +declare void @llvm.trap() noreturn cold +declare void @_Z10sideeffectv() diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.globals.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.globals.expected new file mode 100644 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.globals.expected @@ -0,0 +1,66 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals +; RUN: opt -passes=hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s --check-prefix=REUSE +; RUN: opt -passes=hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s --check-prefix=REUSE +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.14.0" + +@G = external dso_local global i32, align 4 + +;. +; REUSE: @[[G:[a-zA-Z0-9_$"\\.-]+]] = external dso_local global i32, align 4 +;. +define void @foo(i32) { +; REUSE-LABEL: @foo( +; REUSE-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0:%.*]], 0 +; REUSE-NEXT: tail call void @_Z10sideeffectv() +; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] +; REUSE: codeRepl: +; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]] +; REUSE-NEXT: ret void +; REUSE: exit: +; REUSE-NEXT: ret void +; + %2 = icmp eq i32 %0, 0 + tail call void @_Z10sideeffectv() + br i1 %2, label %sink, label %exit + +sink: + tail call void @_Z10sideeffectv() + call void @llvm.trap() + unreachable + +exit: + ret void +} + +define void @bar(i32) { +; REUSE-LABEL: @bar( +; REUSE-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0:%.*]], 0 +; REUSE-NEXT: tail call void @_Z10sideeffectv() +; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] +; REUSE: codeRepl: +; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]] +; REUSE-NEXT: ret void +; REUSE: exit: +; REUSE-NEXT: ret void +; + %2 = icmp eq i32 %0, 0 + tail call void @_Z10sideeffectv() + br i1 %2, label %sink, label %exit + +sink: + tail call void @_Z10sideeffectv() + call void @llvm.trap() + unreachable + +exit: + ret void +} + +declare void @llvm.trap() noreturn cold +declare void @_Z10sideeffectv() +;. +; REUSE: attributes #[[ATTR0:[0-9]+]] = { cold noreturn nounwind } +; REUSE: attributes #[[ATTR1:[0-9]+]] = { cold minsize noreturn } +; REUSE: attributes #[[ATTR2]] = { noinline } +;. diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/generated_funcs_prefix_reuse.test b/llvm/test/tools/UpdateTestChecks/update_test_checks/generated_funcs_prefix_reuse.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/generated_funcs_prefix_reuse.test @@ -0,0 +1,21 @@ +## Check that generated functions are included. +# RUN: cp -f %S/Inputs/generated_funcs_prefix_reuse.ll %t.ll && %update_test_checks --include-generated-funcs %t.ll +# RUN: diff -u %t.ll %S/Inputs/generated_funcs_prefix_reuse.ll.generated.expected + +## Check that running the script again does not change the result: +# RUN: %update_test_checks --include-generated-funcs %t.ll +# RUN: diff -u %t.ll %S/Inputs/generated_funcs_prefix_reuse.ll.generated.expected +## Also try the --check-globals flag +# RUN: %update_test_checks %t.ll --check-globals +# RUN: diff -u %t.ll %S/Inputs/generated_funcs_prefix_reuse.ll.generated.globals.expected + +## Check that generated functions are not included. +# RUN: cp -f %S/Inputs/generated_funcs_prefix_reuse.ll %t.ll && %update_test_checks %t.ll +# RUN: diff -u %t.ll %S/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.expected + +## Check that running the script again does not change the result: +# RUN: %update_test_checks %t.ll +# RUN: diff -u %t.ll %S/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.expected +## Also try the --check-globals flag +# RUN: %update_test_checks %t.ll --check-globals +# RUN: diff -u %t.ll %S/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.globals.expected 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 @@ -1221,15 +1221,18 @@ def add_checks_at_end(output_lines, prefix_list, func_order, comment_string, check_generator): added = set() - generated_prefixes = [] + generated_prefixes = set() for prefix in prefix_list: prefixes = prefix[0] tool_args = prefix[1] for prefix in prefixes: for func in func_order[prefix]: + # The func order can contain the same functions multiple times. + # If we see one again we are done. + if (func, prefix) in added: + continue if added: output_lines.append(comment_string) - 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 @@ -1245,7 +1248,8 @@ # single prefix before moving on to the next prefix. So checks # are ordered by prefix instead of by function as in "normal" # mode. - generated_prefixes.extend(check_generator(output_lines, - [([prefix], tool_args)], - func)) + for generated_prefix in check_generator(output_lines, + [([prefix], tool_args)], func): + added.add((func, generated_prefix)) + generated_prefixes.add(generated_prefix) return generated_prefixes