diff --git a/sycl/test-e2e/NonUniformGroups/chunk.cpp b/sycl/test-e2e/NonUniformGroups/chunk.cpp index 7b2e875913a1a..76c351d83f65a 100644 --- a/sycl/test-e2e/NonUniformGroups/chunk.cpp +++ b/sycl/test-e2e/NonUniformGroups/chunk.cpp @@ -2,8 +2,8 @@ // RUN: %{run} %t.out // // Test CPU AOT as well when possible. -// RUN: %if any-device-is-cpu && opencl-aot %{ %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -o %t.x86.out %s %} -// RUN: %if cpu && opencl-aot %{ %{run} %t.x86.out %} +// RUN-IF: any-device-is-cpu && opencl-aot, %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -o %t.x86.out %s +// RUN-IF: cpu, %{run} %t.x86.out // // REQUIRES: cpu || gpu // REQUIRES: sg-32 diff --git a/sycl/test-e2e/NonUniformGroups/chunk_algorithms.cpp b/sycl/test-e2e/NonUniformGroups/chunk_algorithms.cpp index 3285ed8691f4f..1701620e0082b 100644 --- a/sycl/test-e2e/NonUniformGroups/chunk_algorithms.cpp +++ b/sycl/test-e2e/NonUniformGroups/chunk_algorithms.cpp @@ -2,8 +2,8 @@ // RUN: %{run} %t.out // // Test CPU AOT as well when possible. -// RUN: %if any-device-is-cpu && opencl-aot %{ %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -fsycl-device-code-split=per_kernel -o %t.x86.out %s %} -// RUN: %if cpu && opencl-aot %{ %{run} %t.x86.out %} +// RUN-IF: any-device-is-cpu && opencl-aot, %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -fsycl-device-code-split=per_kernel -o %t.x86.out %s +// RUN-IF: cpu, %{run} %t.x86.out // // REQUIRES: cpu || gpu // REQUIRES: sg-32 diff --git a/sycl/test-e2e/NonUniformGroups/fragment.cpp b/sycl/test-e2e/NonUniformGroups/fragment.cpp index 62a0bb2a5b1dc..3ac709401406a 100644 --- a/sycl/test-e2e/NonUniformGroups/fragment.cpp +++ b/sycl/test-e2e/NonUniformGroups/fragment.cpp @@ -2,8 +2,8 @@ // RUN: %{run} %t.out // // Test CPU AOT as well when possible. -// RUN: %if any-device-is-cpu && opencl-aot %{ %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -o %t.x86.out %s %} -// RUN: %if cpu && opencl-aot %{ %{run} %t.x86.out %} +// RUN-IF: any-device-is-cpu && opencl-aot, %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -o %t.x86.out %s +// RUN-IF: cpu, %{run} %t.x86.out // // REQUIRES: cpu || gpu // REQUIRES: aspect-ext_oneapi_fragment diff --git a/sycl/test-e2e/NonUniformGroups/fragment_algorithms.cpp b/sycl/test-e2e/NonUniformGroups/fragment_algorithms.cpp index 563bb98ce7b1e..9624dd0089eef 100644 --- a/sycl/test-e2e/NonUniformGroups/fragment_algorithms.cpp +++ b/sycl/test-e2e/NonUniformGroups/fragment_algorithms.cpp @@ -2,8 +2,8 @@ // RUN: %{run} %t.out // // Test CPU AOT as well when possible. -// RUN: %if any-device-is-cpu && opencl-aot %{ %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -o %t.x86.out %s %} -// RUN: %if cpu && opencl-aot %{ %{run} %t.x86.out %} +// RUN-IF: any-device-is-cpu && opencl-aot, %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -o %t.x86.out %s +// RUN-IF: cpu, %{run} %t.x86.out // // REQUIRES: cpu || gpu // REQUIRES: sg-32 diff --git a/sycl/test-e2e/NonUniformGroups/opportunistic.cpp b/sycl/test-e2e/NonUniformGroups/opportunistic.cpp index 9db60ed7f6a8b..96794243b82b2 100644 --- a/sycl/test-e2e/NonUniformGroups/opportunistic.cpp +++ b/sycl/test-e2e/NonUniformGroups/opportunistic.cpp @@ -2,8 +2,8 @@ // RUN: %{run} %t.out // // Test CPU AOT as well when possible. -// RUN: %if any-device-is-cpu && opencl-aot %{ %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -o %t.x86.out %s %} -// RUN: %if cpu && opencl-aot %{ %{run} %t.x86.out %} +// RUN-IF: any-device-is-cpu && opencl-aot, %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -o %t.x86.out %s +// RUN-IF: cpu, %{run} %t.x86.out // // REQUIRES: cpu || gpu // REQUIRES: aspect-ext_oneapi_fragment diff --git a/sycl/test-e2e/NonUniformGroups/opportunistic_algorithms.cpp b/sycl/test-e2e/NonUniformGroups/opportunistic_algorithms.cpp index 7ba4f68c9db93..941eced58f8f5 100644 --- a/sycl/test-e2e/NonUniformGroups/opportunistic_algorithms.cpp +++ b/sycl/test-e2e/NonUniformGroups/opportunistic_algorithms.cpp @@ -2,8 +2,8 @@ // RUN: %{run} %t.out // // Test CPU AOT as well when possible. -// RUN: %if any-device-is-cpu && opencl-aot %{ %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -o %t.x86.out %s %} -// RUN: %if cpu && opencl-aot %{ %{run} %t.x86.out %} +// RUN-IF: any-device-is-cpu && opencl-aot, %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -o %t.x86.out %s +// RUN-IF: cpu, %{run} %t.x86.out // // REQUIRES: cpu || gpu // REQUIRES: sg-32 diff --git a/sycl/test-e2e/NonUniformGroups/tangle.cpp b/sycl/test-e2e/NonUniformGroups/tangle.cpp index 2bface460eec7..700935d4e389a 100644 --- a/sycl/test-e2e/NonUniformGroups/tangle.cpp +++ b/sycl/test-e2e/NonUniformGroups/tangle.cpp @@ -2,8 +2,8 @@ // RUN: %{run} %t.out // // Test CPU AOT as well when possible. -// RUN: %if any-device-is-cpu && opencl-aot %{ %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -fno-sycl-early-optimizations -o %t.x86.out %s %} -// RUN: %if cpu && opencl-aot %{ %{run} %t.x86.out %} +// RUN-IF: any-device-is-cpu && opencl-aot, %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -fno-sycl-early-optimizations -o %t.x86.out %s +// RUN-IF: cpu, %{run} %t.x86.out // // REQUIRES: cpu || gpu // REQUIRES: aspect-ext_oneapi_tangle diff --git a/sycl/test-e2e/NonUniformGroups/tangle_algorithms.cpp b/sycl/test-e2e/NonUniformGroups/tangle_algorithms.cpp index e9b617893f72c..0a3f6841bcfdd 100644 --- a/sycl/test-e2e/NonUniformGroups/tangle_algorithms.cpp +++ b/sycl/test-e2e/NonUniformGroups/tangle_algorithms.cpp @@ -2,8 +2,8 @@ // RUN: %{run} %t.out // // Test CPU AOT as well when possible. -// RUN: %if any-device-is-cpu && opencl-aot %{ %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -fno-sycl-early-optimizations -o %t.x86.out %s %} -// RUN: %if cpu && opencl-aot %{ %{run} %t.x86.out %} +// RUN-IF: any-device-is-cpu && opencl-aot, %{run-aux} %clangxx -fsycl -fsycl-targets=spir64_x86_64 -fno-sycl-early-optimizations -o %t.x86.out %s +// RUN-IF: cpu, %{run} %t.x86.out // // REQUIRES: sg-32 // REQUIRES: aspect-ext_oneapi_tangle diff --git a/sycl/test-e2e/README.md b/sycl/test-e2e/README.md index 7199c9ce33585..4c764a3a1362d 100644 --- a/sycl/test-e2e/README.md +++ b/sycl/test-e2e/README.md @@ -11,6 +11,7 @@ * [llvm-lit parameters](#llvm-lit-parameters) * [Marking tests as expected to fail](#marking-tests-as-expected-to-fail) * [Marking tests as unsupported](#marking-tests-as-unsupported) + * [RUN-IF](#RUN-IF) * [SYCL core header file](#sycl-core-header-file) * [Compiling and executing tests on separate systems](#compiling-and-executing-tests-on-separate-systems) * [Run only mode](#run-only-mode) @@ -396,6 +397,21 @@ non-standard mechanism. Use `UNSUPPORTED: true` instead, we track `UNSUPPORTED` tests using the mechanism described above. Otherwise the test risks remaining untraceable. +#### RUN-IF + +As a convenience, we provide the `RUN-IF` lit keyword, which simplifies running +commands conditionally. The syntax is: + +```bash +RUN-IF: condition, command +``` + +A full example would be: + +```bash +RUN-IF: cpu, %{run} %t_cpu.out +``` + ### SYCL core header file While SYCL specification dictates that the only user-visible interface is diff --git a/sycl/test-e2e/format.py b/sycl/test-e2e/format.py index bf5f0d5c4c32b..76dae4014912b 100644 --- a/sycl/test-e2e/format.py +++ b/sycl/test-e2e/format.py @@ -51,6 +51,47 @@ def parse_min_intel_driver_req(line_number, line, output): return output +def parse_run_if(line_number, line, output): + """ + Parse RUN-IF directive in the format: + // RUN-IF: condition, command + where condition is a boolean expression and command is the command to execute. + Returns a CommandDirective with the condition embedded in the command as %if. + """ + if not output: + output = [] + + # Split on first comma to separate condition from command + parts = line.split(",", 1) + if len(parts) != 2: + raise ValueError( + f"Line {line_number}: RUN-IF directive must have format: condition, command" + ) + + condition = parts[0].strip() + command = parts[1].strip() + + if not condition or not command: + raise ValueError( + f"Line {line_number}: RUN-IF directive has empty condition or command" + ) + + # Strip outer %{ %} if present to avoid nested braces + if command.startswith("%{") and command.endswith("%}"): + command = command[2:-2].strip() + + # Convert RUN-IF to a RUN command with %if condition + # This leverages lit's built-in conditional support + conditional_command = f"%if {condition} %{{ {command} %}}" + + output.append( + lit.TestRunner.CommandDirective( + line_number, line_number, "RUN:", conditional_command + ) + ) + return output + + class SYCLEndToEndTest(lit.formats.ShTest): def parseTestScript(self, test): """This is based on lit.TestRunner.parseIntegratedTestScript but we @@ -66,9 +107,12 @@ def parseTestScript(self, test): "REQUIRES-INTEL-DRIVER:", ParserKind.CUSTOM, parse_min_intel_driver_req, - ) + ), + IntegratedTestKeywordParser( + "RUN-IF:", ParserKind.CUSTOM, parse_run_if + ), ], - require_script=True, + require_script=False, ) except ValueError as e: return lit.Test.Result(lit.Test.UNRESOLVED, str(e)) @@ -76,6 +120,16 @@ def parseTestScript(self, test): assert parsed["DEFINE:"] == script assert parsed["REDEFINE:"] == script + # Add RUN-IF commands to the script + if parsed["RUN-IF:"]: + script.extend(parsed["RUN-IF:"]) + + # Ensure we have at least one command (RUN or RUN-IF) + if not script: + return lit.Test.Result( + lit.Test.UNRESOLVED, "Test has no 'RUN:' or 'RUN-IF:' line" + ) + test.xfails += test.config.xfail_features test.xfails += parsed["XFAIL:"] or [] test.requires += test.config.required_features