From 70496cee2f209e01f938954636b290ce1b8c1caa Mon Sep 17 00:00:00 2001 From: Paulo Matos Date: Wed, 13 Sep 2023 15:40:56 +0200 Subject: [PATCH 1/6] [UpdateTestChecks] Add support for SPIRV in update_llc_test_checks.py We have to change the location of the comment for function start in SPIRV. We add a new command line flag --skip-check-label, because there's no function label on SPIRV. Previously https://reviews.llvm.org/D157858 --- llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp | 1 + .../SPIRV/extensions/SPV_INTEL_optnone.ll | 8 +++++ llvm/utils/UpdateTestChecks/asm.py | 30 +++++++++++++++++++ llvm/utils/UpdateTestChecks/common.py | 12 ++++++-- 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp index 27da0f21f1571..bc0cd64b0b4d1 100644 --- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp @@ -118,6 +118,7 @@ void SPIRVAsmPrinter::emitFunctionHeader() { OutStreamer->getCommentOS() << "-- Begin function " << GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n'; + OutStreamer->addBlankLine(); } auto Section = getObjFileLowering().SectionForGlobal(&F, TM); diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll index 99d22a4a2ee63..370c2e9e9d051 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --skip-check-label --version 3 ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_optnone %s -o - | FileCheck %s --check-prefix=CHECK-EXTENSION ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-NO-EXTENSION @@ -12,6 +13,13 @@ ; Function Attrs: nounwind optnone noinline define spir_func void @_Z3foov() #0 { +; CHECK-EXTENSION: %5 = OpLabel +; CHECK-EXTENSION-NEXT: OpReturn +; CHECK-EXTENSION-NEXT: OpFunctionEnd +; +; CHECK-NO-EXTENSION: %5 = OpLabel +; CHECK-NO-EXTENSION-NEXT: OpReturn +; CHECK-NO-EXTENSION-NEXT: OpFunctionEnd entry: ret void } diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py index 3357906513217..ea823d766469a 100644 --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -15,6 +15,11 @@ class string: # RegEx: this is where the magic happens. ##### Assembly parser +# +# The set of per-arch regular expressions define several groups. +# The required groups are "func" (function name) and "body" (body of the function). +# Although some backends require some additional groups like: "directives" +# and "func_name_separator" ASM_FUNCTION_X86_RE = re.compile( r'^_?(?P[^:]+):[ \t]*#+[ \t]*(@"?(?P=func)"?| -- Begin function (?P=func))\n(?:\s*\.?Lfunc_begin[^:\n]*:\n)?' @@ -197,6 +202,18 @@ class string: flags=(re.M | re.S), ) +# We parse the function name from the comments issued by the backend: +# ; -- Begin function +# and then the final comment +# ; -- End function +# If these change in the future, we need to change the regex. +ASM_FUNCTION_SPIRV_RE = re.compile( + r'[ \t]+; \-\- Begin function (?P[^\n]+)\n' + r"(?P.*?)\n" + r"[ \t]+; \-\- End function", + flags=(re.M | re.S), +) + ASM_FUNCTION_VE_RE = re.compile( r"^_?(?P[^:]+):[ \t]*#+[ \t]*@(?P=func)\n" r"(?:\s*\.?L(?P=func)\$local:\n)?" # optional .L$local: due to -fno-semantic-interposition @@ -433,6 +450,17 @@ def scrub_asm_sparc(asm, args): return asm +def scrub_asm_spirv(asm, args): + # Scrub runs of whitespace out of the assembly, but leave the leading + # whitespace in place. + asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm) + # Expand the tabs used for indentation. + asm = string.expandtabs(asm, 2) + # Strip trailing whitespace. + asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm) + return asm + + def scrub_asm_systemz(asm, args): # Scrub runs of whitespace out of the assembly, but leave the leading # whitespace in place. @@ -547,6 +575,8 @@ def get_run_handler(triple): "riscv64": (scrub_asm_riscv, ASM_FUNCTION_RISCV_RE), "lanai": (scrub_asm_lanai, ASM_FUNCTION_LANAI_RE), "sparc": (scrub_asm_sparc, ASM_FUNCTION_SPARC_RE), + "spirv32": (scrub_asm_spirv, ASM_FUNCTION_SPIRV_RE), + "spirv64": (scrub_asm_spirv, ASM_FUNCTION_SPIRV_RE), "s390x": (scrub_asm_systemz, ASM_FUNCTION_SYSTEMZ_RE), "wasm32": (scrub_asm_wasm, ASM_FUNCTION_WASM_RE), "wasm64": (scrub_asm_wasm, ASM_FUNCTION_WASM_RE), diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py index 22c05322d9c7d..4f7b3bb6fb85e 100644 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -196,6 +196,13 @@ def __call__(self, parser, namespace, values, option_string=None): default=[], help="List of regular expressions such that, for matching global value declarations, literal integer values should be encoded in hex in the associated FileCheck directives", ) + parser.add_argument( + "--skip-check-label", + action="store_true", + dest="skip_check_label", + default=False, + help="Skip CHECK-LABEL line generation per function", + ) # FIXME: in 3.9, we can use argparse.BooleanOptionalAction. At that point, # we need to rename the flag to just -generate-body-for-unused-prefixes. parser.add_argument( @@ -212,10 +219,11 @@ def __call__(self, parser, namespace, values, option_string=None): ) args = parser.parse_args() # TODO: This should not be handled differently from the other options - global _verbose, _global_value_regex, _global_hex_value_regex + global _verbose, _global_value_regex, _global_hex_value_regex, _skip_check_label _verbose = args.verbose _global_value_regex = args.global_value_regex _global_hex_value_regex = args.global_hex_value_regex + _skip_check_label = args.skip_check_label return args @@ -1306,7 +1314,7 @@ def add_checks( output_lines.append( "%s %s-SAME: %s" % (comment_marker, checkprefix, args_and_sig) ) - else: + elif not _skip_check_label: output_lines.append( check_label_format % ( From b3f9b951524787cfc56f9107f328e1a56c9ece67 Mon Sep 17 00:00:00 2001 From: Paulo Matos Date: Fri, 15 Sep 2023 14:27:09 +0200 Subject: [PATCH 2/6] Update test generated from script --- llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll index 370c2e9e9d051..996a3e0c306c2 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll @@ -13,11 +13,13 @@ ; Function Attrs: nounwind optnone noinline define spir_func void @_Z3foov() #0 { -; CHECK-EXTENSION: %5 = OpLabel +; CHECK-EXTENSION: %4 = OpFunction %2 DontInline %3 +; CHECK-EXTENSION-NEXT: %5 = OpLabel ; CHECK-EXTENSION-NEXT: OpReturn ; CHECK-EXTENSION-NEXT: OpFunctionEnd ; -; CHECK-NO-EXTENSION: %5 = OpLabel +; CHECK-NO-EXTENSION: %4 = OpFunction %2 DontInline %3 +; CHECK-NO-EXTENSION-NEXT: %5 = OpLabel ; CHECK-NO-EXTENSION-NEXT: OpReturn ; CHECK-NO-EXTENSION-NEXT: OpFunctionEnd entry: From d8548c4a124e9ceb115abec683a140ec0e107405 Mon Sep 17 00:00:00 2001 From: Paulo Matos Date: Fri, 15 Sep 2023 14:30:09 +0200 Subject: [PATCH 3/6] Fixup python formatting --- llvm/utils/UpdateTestChecks/asm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py index ea823d766469a..d64cde31f9104 100644 --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -208,7 +208,7 @@ class string: # ; -- End function # If these change in the future, we need to change the regex. ASM_FUNCTION_SPIRV_RE = re.compile( - r'[ \t]+; \-\- Begin function (?P[^\n]+)\n' + r"[ \t]+; \-\- Begin function (?P[^\n]+)\n" r"(?P.*?)\n" r"[ \t]+; \-\- End function", flags=(re.M | re.S), From 746bef5412dc7b44e54f5ac4246d0d3ba5b7501d Mon Sep 17 00:00:00 2001 From: Paulo Matos Date: Tue, 19 Sep 2023 17:17:04 +0200 Subject: [PATCH 4/6] Remove --skip-check-label Simplify regexp based on suggestions and update testcase (now broken). --- llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp | 1 - .../CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll | 8 +++++--- llvm/utils/UpdateTestChecks/asm.py | 12 ++++-------- llvm/utils/UpdateTestChecks/common.py | 12 ++---------- 4 files changed, 11 insertions(+), 22 deletions(-) diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp index bc0cd64b0b4d1..27da0f21f1571 100644 --- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp @@ -118,7 +118,6 @@ void SPIRVAsmPrinter::emitFunctionHeader() { OutStreamer->getCommentOS() << "-- Begin function " << GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n'; - OutStreamer->addBlankLine(); } auto Section = getObjFileLowering().SectionForGlobal(&F, TM); diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll index 996a3e0c306c2..321415a3df8d4 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --skip-check-label --version 3 +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_optnone %s -o - | FileCheck %s --check-prefix=CHECK-EXTENSION ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-NO-EXTENSION @@ -13,12 +13,14 @@ ; Function Attrs: nounwind optnone noinline define spir_func void @_Z3foov() #0 { -; CHECK-EXTENSION: %4 = OpFunction %2 DontInline %3 +; CHECK-EXTENSION-LABEL: _Z3foov: +; CHECK-EXTENSION: %4 = OpFunction %2 DontInline %3 ; CHECK-EXTENSION-NEXT: %5 = OpLabel ; CHECK-EXTENSION-NEXT: OpReturn ; CHECK-EXTENSION-NEXT: OpFunctionEnd ; -; CHECK-NO-EXTENSION: %4 = OpFunction %2 DontInline %3 +; CHECK-NO-EXTENSION-LABEL: _Z3foov: +; CHECK-NO-EXTENSION: %4 = OpFunction %2 DontInline %3 ; CHECK-NO-EXTENSION-NEXT: %5 = OpLabel ; CHECK-NO-EXTENSION-NEXT: OpReturn ; CHECK-NO-EXTENSION-NEXT: OpFunctionEnd diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py index d64cde31f9104..554576b5ffbac 100644 --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -202,15 +202,11 @@ class string: flags=(re.M | re.S), ) -# We parse the function name from the comments issued by the backend: -# ; -- Begin function -# and then the final comment -# ; -- End function -# If these change in the future, we need to change the regex. +# We parse the function name from OpName, and grab the variable name 'var' +# for this function. Then we match that when the variable is assigned with +# OpFunction and match its body. ASM_FUNCTION_SPIRV_RE = re.compile( - r"[ \t]+; \-\- Begin function (?P[^\n]+)\n" - r"(?P.*?)\n" - r"[ \t]+; \-\- End function", + r'OpName (?P%[0-9]+) "(?P[^"]+)".*(?P(?P=var) = OpFunction.+?OpFunctionEnd)', flags=(re.M | re.S), ) diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py index 4f7b3bb6fb85e..22c05322d9c7d 100644 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -196,13 +196,6 @@ def __call__(self, parser, namespace, values, option_string=None): default=[], help="List of regular expressions such that, for matching global value declarations, literal integer values should be encoded in hex in the associated FileCheck directives", ) - parser.add_argument( - "--skip-check-label", - action="store_true", - dest="skip_check_label", - default=False, - help="Skip CHECK-LABEL line generation per function", - ) # FIXME: in 3.9, we can use argparse.BooleanOptionalAction. At that point, # we need to rename the flag to just -generate-body-for-unused-prefixes. parser.add_argument( @@ -219,11 +212,10 @@ def __call__(self, parser, namespace, values, option_string=None): ) args = parser.parse_args() # TODO: This should not be handled differently from the other options - global _verbose, _global_value_regex, _global_hex_value_regex, _skip_check_label + global _verbose, _global_value_regex, _global_hex_value_regex _verbose = args.verbose _global_value_regex = args.global_value_regex _global_hex_value_regex = args.global_hex_value_regex - _skip_check_label = args.skip_check_label return args @@ -1314,7 +1306,7 @@ def add_checks( output_lines.append( "%s %s-SAME: %s" % (comment_marker, checkprefix, args_and_sig) ) - elif not _skip_check_label: + else: output_lines.append( check_label_format % ( From 8291c4054e96e31e6ff33a411ff630ea8249a01e Mon Sep 17 00:00:00 2001 From: Paulo Matos Date: Wed, 20 Sep 2023 13:01:40 +0200 Subject: [PATCH 5/6] Add common prefix and update test --- .../SPIRV/extensions/SPV_INTEL_optnone.ll | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll index 321415a3df8d4..f74a07cb16497 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_optnone %s -o - | FileCheck %s --check-prefix=CHECK-EXTENSION -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-NO-EXTENSION +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_optnone %s -o - | FileCheck %s --check-prefix=CHECK,CHECK-EXTENSION +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK,CHECK-NO-EXTENSION ; CHECK-EXTENSION: OpCapability OptNoneINTEL ; CHECK-EXTENSION: OpExtension "SPV_INTEL_optnone" @@ -13,19 +13,16 @@ ; Function Attrs: nounwind optnone noinline define spir_func void @_Z3foov() #0 { -; CHECK-EXTENSION-LABEL: _Z3foov: -; CHECK-EXTENSION: %4 = OpFunction %2 DontInline %3 -; CHECK-EXTENSION-NEXT: %5 = OpLabel -; CHECK-EXTENSION-NEXT: OpReturn -; CHECK-EXTENSION-NEXT: OpFunctionEnd -; -; CHECK-NO-EXTENSION-LABEL: _Z3foov: -; CHECK-NO-EXTENSION: %4 = OpFunction %2 DontInline %3 -; CHECK-NO-EXTENSION-NEXT: %5 = OpLabel -; CHECK-NO-EXTENSION-NEXT: OpReturn -; CHECK-NO-EXTENSION-NEXT: OpFunctionEnd +; CHECK-LABEL: _Z3foov: +; CHECK: %4 = OpFunction %2 DontInline %3 +; CHECK-NEXT: %5 = OpLabel +; CHECK-NEXT: OpReturn +; CHECK-NEXT: OpFunctionEnd entry: ret void } attributes #0 = { nounwind optnone noinline } +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; CHECK-EXTENSION: {{.*}} +; CHECK-NO-EXTENSION: {{.*}} From 02787fa0d191eb409b4da42808304c55add861f4 Mon Sep 17 00:00:00 2001 From: Paulo Matos Date: Wed, 20 Sep 2023 13:12:07 +0200 Subject: [PATCH 6/6] Empty match for func_name_separator and update test --- .../CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll | 11 ++++------- llvm/utils/UpdateTestChecks/asm.py | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll index f74a07cb16497..afbcaec9c5c52 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll @@ -1,19 +1,15 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_optnone %s -o - | FileCheck %s --check-prefix=CHECK,CHECK-EXTENSION -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK,CHECK-NO-EXTENSION +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_optnone %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-EXTENSION +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NO-EXTENSION ; CHECK-EXTENSION: OpCapability OptNoneINTEL ; CHECK-EXTENSION: OpExtension "SPV_INTEL_optnone" ; CHECK-NO-EXTENSION-NOT: OpCapability OptNoneINTEL ; CHECK-NO-EXTENSION-NOT: OpExtension "SPV_INTEL_optnone" -;; Per SPIR-V spec: -;; FunctionControlDontInlineMask = 0x2 (2) -; CHECK-EXTENSION: %[[#]] = OpFunction %[[#]] DontInline - ; Function Attrs: nounwind optnone noinline define spir_func void @_Z3foov() #0 { -; CHECK-LABEL: _Z3foov: +; CHECK-LABEL: _Z3foov ; CHECK: %4 = OpFunction %2 DontInline %3 ; CHECK-NEXT: %5 = OpLabel ; CHECK-NEXT: OpReturn @@ -23,6 +19,7 @@ entry: } attributes #0 = { nounwind optnone noinline } + ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: ; CHECK-EXTENSION: {{.*}} ; CHECK-NO-EXTENSION: {{.*}} diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py index 554576b5ffbac..7c3c60032e213 100644 --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -206,7 +206,7 @@ class string: # for this function. Then we match that when the variable is assigned with # OpFunction and match its body. ASM_FUNCTION_SPIRV_RE = re.compile( - r'OpName (?P%[0-9]+) "(?P[^"]+)".*(?P(?P=var) = OpFunction.+?OpFunctionEnd)', + r'OpName (?P%[0-9]+) "(?P[^"]+)(?P)".*(?P(?P=var) = OpFunction.+?OpFunctionEnd)', flags=(re.M | re.S), )