diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp --- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp @@ -115,6 +115,7 @@ OutStreamer->getCommentOS() << "-- Begin function " << GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n'; + OutStreamer->addBlankLine(); } auto Section = getObjFileLowering().SectionForGlobal(&F, TM); diff --git a/llvm/test/CodeGen/SPIRV/expect.ll b/llvm/test/CodeGen/SPIRV/expect.ll deleted file mode 100644 --- a/llvm/test/CodeGen/SPIRV/expect.ll +++ /dev/null @@ -1,20 +0,0 @@ -; RUN: llc -mtriple=spirv32-unknown-unknown < %s | FileCheck %s -; RUN: llc -mtriple=spirv64-unknown-unknown < %s | FileCheck %s - -; CHECK: OpCapability ExpectAssumeKHR -; CHECK-NEXT: OpExtension "SPV_KHR_expect_assume" - -declare i32 @llvm.expect.i32(i32, i32) -declare i32 @getOne() - -; CHECK-DAG: %2 = OpTypeInt 32 0 -; CHECK-DAG: %6 = OpFunctionParameter %2 -; CHECK-DAG: %9 = OpIMul %2 %6 %8 -; CHECK-DAG: %10 = OpExpectKHR %2 %9 %6 - -define i32 @test(i32 %x) { - %one = call i32 @getOne() - %val = mul i32 %x, %one - %v = call i32 @llvm.expect.i32(i32 %val, i32 %x) - ret i32 %v -} diff --git a/llvm/test/CodeGen/SPIRV/optnone.ll b/llvm/test/CodeGen/SPIRV/optnone.ll --- a/llvm/test/CodeGen/SPIRV/optnone.ll +++ b/llvm/test/CodeGen/SPIRV/optnone.ll @@ -1,15 +1,15 @@ -;; Check that optnone is correctly ignored when extension is not enabled -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --skip-check-label --version 2 +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s -; CHECK-SPIRV: OpCapability OptNoneINTEL -; CHECK-SPIRV: OpExtension "SPV_INTEL_optnone" - -;; Per SPIR-V spec: -;; FunctionControlDontInlineMask = 0x2 (2) -; CHECK-SPIRV: %[[#]] = OpFunction %[[#]] DontInline +; CHECK: OpCapability OptNoneINTEL +; CHECK-NEXT: OpExtension "SPV_INTEL_optnone" ; Function Attrs: nounwind optnone noinline define spir_func void @_Z3foov() #0 { +; CHECK: %4 = OpFunction %2 DontInline %3 +; CHECK-NEXT: %5 = OpLabel +; CHECK-NEXT: OpReturn +; CHECK-NEXT: OpFunctionEnd entry: ret void } diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -15,6 +15,11 @@ # 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 @@ 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 @@ 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 @@ "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 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -194,6 +194,13 @@ 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="Activate 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( @@ -209,10 +216,11 @@ "--version", type=int, default=1, help="The version of output format" ) args = parser.parse_args() - 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 @@ -1284,7 +1292,7 @@ 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 % (