[llvm] df122fc - [SPIR-V] Change a way SPIR-V Backend API works with user facing options (#124745)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 28 08:33:16 PST 2025
Author: Vyacheslav Levytskyy
Date: 2025-01-28T17:33:11+01:00
New Revision: df122fc734ce002632f3bfe8a5fc5010349dba16
URL: https://github.com/llvm/llvm-project/commit/df122fc734ce002632f3bfe8a5fc5010349dba16
DIFF: https://github.com/llvm/llvm-project/commit/df122fc734ce002632f3bfe8a5fc5010349dba16.diff
LOG: [SPIR-V] Change a way SPIR-V Backend API works with user facing options (#124745)
This PR fixes https://github.com/llvm/llvm-project/issues/124703:
* added a new API call `SPIRVTranslate` that is to replace entirely old
`SPIRVTranslateModule` after existing clients switch into the new
function;
* the new `SPIRVTranslate` doesn't require option parsing, replacing the
`Opts` argument with explicit `CodeGenOptLevel` and `Triple` arguments;
* the old `SPIRVTranslateModule` call is a wrapper for `SPIRVTranslate`,
it doesn't require option parsing either and doesn't hold any logic
inside except for converting string options into `CodeGenOptLevel` and
`Triple` arguments;
* usage of the extensions list is reworked to avoid writes to the global
cl::opt variable `lib/Target/SPIRV/SPIRVSubtarget.cpp::Extensions` --
instead a new class member in SPIRVSubtarget.cpp is implemented that
allows to replace supported extensions after SPIRVSubtarget.cpp is
created;
* both API calls don't require option parsing and don't write to global
cl::opt variables.
Other related/required changes:
* SPIRV::Capability::Shader is marked as an capability of lesser
priority for OpenCL environment (to remediate absence of the
"avoid-spirv-capabilities" command line option in API calls);
* unit tests are updated and extended to cover testing of a newer API
call;
* old API call is marked with TODO to remove it after existing clients
switch into the new function.
Added:
Modified:
llvm/lib/Target/SPIRV/SPIRVAPI.cpp
llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp
llvm/lib/Target/SPIRV/SPIRVSubtarget.h
llvm/unittests/Target/SPIRV/CMakeLists.txt
llvm/unittests/Target/SPIRV/SPIRVAPITest.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/SPIRV/SPIRVAPI.cpp b/llvm/lib/Target/SPIRV/SPIRVAPI.cpp
index 95c9b0e5200608..a19384d4e279ca 100644
--- a/llvm/lib/Target/SPIRV/SPIRVAPI.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVAPI.cpp
@@ -8,6 +8,7 @@
#include "SPIRVCommandLine.h"
#include "SPIRVSubtarget.h"
+#include "SPIRVTargetMachine.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -40,25 +41,6 @@ using namespace llvm;
namespace {
-// Mimic limited number of command line flags from llc to provide a better
-// user experience when passing options into the translate API call.
-static cl::opt<char> SpirvOptLevel("spirv-O", cl::Hidden, cl::Prefix,
- cl::init('0'));
-static cl::opt<std::string> SpirvTargetTriple("spirv-mtriple", cl::Hidden,
- cl::init(""));
-
-// Utility to accept options in a command line style.
-void parseSPIRVCommandLineOptions(const std::vector<std::string> &Options,
- raw_ostream *Errs) {
- static constexpr const char *Origin = "SPIRVTranslateModule";
- if (!Options.empty()) {
- std::vector<const char *> Argv(1, Origin);
- for (const auto &Arg : Options)
- Argv.push_back(Arg.c_str());
- cl::ParseCommandLineOptions(Argv.size(), Argv.data(), Origin, Errs);
- }
-}
-
std::once_flag InitOnceFlag;
void InitializeSPIRVTarget() {
std::call_once(InitOnceFlag, []() {
@@ -75,35 +57,15 @@ namespace llvm {
// The goal of this function is to facilitate integration of SPIRV Backend into
// tools and libraries by means of exposing an API call that translate LLVM
// module to SPIR-V and write results into a string as binary SPIR-V output,
-// providing diagnostics on fail and means of configuring translation in a style
-// of command line options.
+// providing diagnostics on fail and means of configuring translation.
extern "C" LLVM_EXTERNAL_VISIBILITY bool
-SPIRVTranslateModule(Module *M, std::string &SpirvObj, std::string &ErrMsg,
- const std::vector<std::string> &AllowExtNames,
- const std::vector<std::string> &Opts) {
+SPIRVTranslate(Module *M, std::string &SpirvObj, std::string &ErrMsg,
+ const std::vector<std::string> &AllowExtNames,
+ llvm::CodeGenOptLevel OLevel, Triple TargetTriple) {
// Fallbacks for option values.
static const std::string DefaultTriple = "spirv64-unknown-unknown";
static const std::string DefaultMArch = "";
- // Parse Opts as if it'd be command line arguments.
- std::string Errors;
- raw_string_ostream ErrorStream(Errors);
- parseSPIRVCommandLineOptions(Opts, &ErrorStream);
- if (!Errors.empty()) {
- ErrMsg = Errors;
- return false;
- }
-
- llvm::CodeGenOptLevel OLevel;
- if (auto Level = CodeGenOpt::parseLevel(SpirvOptLevel)) {
- OLevel = *Level;
- } else {
- ErrMsg = "Invalid optimization level!";
- return false;
- }
-
- // Overrides/ammends `-spirv-ext` command line switch (if present) by the
- // explicit list of allowed SPIR-V extensions.
std::set<SPIRV::Extension::Extension> AllowedExtIds;
StringRef UnknownExt =
SPIRVExtensionsParser::checkExtensions(AllowExtNames, AllowedExtIds);
@@ -111,14 +73,10 @@ SPIRVTranslateModule(Module *M, std::string &SpirvObj, std::string &ErrMsg,
ErrMsg = "Unknown SPIR-V extension: " + UnknownExt.str();
return false;
}
- SPIRVSubtarget::addExtensionsToClOpt(AllowedExtIds);
// SPIR-V-specific target initialization.
InitializeSPIRVTarget();
- Triple TargetTriple(SpirvTargetTriple.empty()
- ? M->getTargetTriple()
- : Triple::normalize(SpirvTargetTriple));
if (TargetTriple.getTriple().empty()) {
TargetTriple.setTriple(DefaultTriple);
M->setTargetTriple(DefaultTriple);
@@ -142,6 +100,11 @@ SPIRVTranslateModule(Module *M, std::string &SpirvObj, std::string &ErrMsg,
return false;
}
+ // Set available extensions.
+ SPIRVTargetMachine *STM = static_cast<SPIRVTargetMachine *>(Target.get());
+ const_cast<SPIRVSubtarget *>(STM->getSubtargetImpl())
+ ->initAvailableExtensions(AllowedExtIds);
+
if (M->getCodeModel())
Target->setCodeModel(*M->getCodeModel());
@@ -177,4 +140,30 @@ SPIRVTranslateModule(Module *M, std::string &SpirvObj, std::string &ErrMsg,
return true;
}
+// TODO: Remove this wrapper after existing clients switch into a newer
+// implementation of SPIRVTranslate().
+extern "C" LLVM_EXTERNAL_VISIBILITY bool
+SPIRVTranslateModule(Module *M, std::string &SpirvObj, std::string &ErrMsg,
+ const std::vector<std::string> &AllowExtNames,
+ const std::vector<std::string> &Opts) {
+ // optional: Opts[0] is a string representation of Triple,
+ // take Module triple otherwise
+ Triple TargetTriple(Opts.empty() || Opts[0].empty()
+ ? M->getTargetTriple()
+ : Triple::normalize(Opts[0]));
+ // optional: Opts[1] is a string representation of CodeGenOptLevel,
+ // no optimization otherwise
+ llvm::CodeGenOptLevel OLevel = CodeGenOptLevel::None;
+ if (Opts.size() > 1 && !Opts[1].empty()) {
+ if (auto Level = CodeGenOpt::parseLevel(Opts[1][0])) {
+ OLevel = *Level;
+ } else {
+ ErrMsg = "Invalid optimization level!";
+ return false;
+ }
+ }
+ return SPIRVTranslate(M, SpirvObj, ErrMsg, AllowExtNames, OLevel,
+ TargetTriple);
+}
+
} // namespace llvm
diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
index 45b39c51164795..13683fd9a266d0 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
@@ -133,6 +133,11 @@ llvm::StringRef SPIRVExtensionsParser::checkExtensions(
const std::vector<std::string> &ExtNames,
std::set<SPIRV::Extension::Extension> &AllowedExtensions) {
for (const auto &Ext : ExtNames) {
+ if (Ext == "all") {
+ for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap)
+ AllowedExtensions.insert(ExtensionEnum);
+ break;
+ }
auto It = SPIRVExtensionMap.find(Ext);
if (It == SPIRVExtensionMap.end())
return Ext;
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index bc00d5032544fd..d3afaf42e05b73 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -73,8 +73,10 @@ static SPIRV::Requirements
getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category,
unsigned i, const SPIRVSubtarget &ST,
SPIRV::RequirementHandler &Reqs) {
- static AvoidCapabilitiesSet
- AvoidCaps; // contains capabilities to avoid if there is another option
+ // A set of capabilities to avoid if there is another option.
+ AvoidCapabilitiesSet AvoidCaps;
+ if (ST.isOpenCLEnv())
+ AvoidCaps.S.insert(SPIRV::Capability::Shader);
VersionTuple ReqMinVer = getSymbolicOperandMinVersion(Category, i);
VersionTuple ReqMaxVer = getSymbolicOperandMaxVersion(Category, i);
diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp
index a476b51c3120af..3587570931541e 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp
@@ -84,7 +84,7 @@ SPIRVSubtarget::SPIRVSubtarget(const Triple &TT, const std::string &CPU,
OpenCLVersion = VersionTuple(2, 2);
// The order of initialization is important.
- initAvailableExtensions();
+ initAvailableExtensions(Extensions);
initAvailableExtInstSets();
GR = std::make_unique<SPIRVGlobalRegistry>(PointerSize);
@@ -135,9 +135,12 @@ bool SPIRVSubtarget::canDirectlyComparePointers() const {
return !SPVTranslatorCompat && isAtLeastVer(SPIRVVersion, VersionTuple(1, 4));
}
-void SPIRVSubtarget::initAvailableExtensions() {
- AvailableExtensions.clear();
- AvailableExtensions.insert(Extensions.begin(), Extensions.end());
+void SPIRVSubtarget::accountForAMDShaderTrinaryMinmax() {
+ if (canUseExtension(
+ SPIRV::Extension::SPV_AMD_shader_trinary_minmax_extension)) {
+ AvailableExtInstSets.insert(
+ SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax);
+ }
}
// TODO: use command line args for this rather than just defaults.
@@ -150,9 +153,14 @@ void SPIRVSubtarget::initAvailableExtInstSets() {
AvailableExtInstSets.insert(SPIRV::InstructionSet::OpenCL_std);
// Handle extended instruction sets from extensions.
- if (canUseExtension(
- SPIRV::Extension::SPV_AMD_shader_trinary_minmax_extension)) {
- AvailableExtInstSets.insert(
- SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax);
- }
+ accountForAMDShaderTrinaryMinmax();
+}
+
+// Set available extensions after SPIRVSubtarget is created.
+void SPIRVSubtarget::initAvailableExtensions(
+ const std::set<SPIRV::Extension::Extension> &AllowedExtIds) {
+ AvailableExtensions.clear();
+ AvailableExtensions.insert(AllowedExtIds.begin(), AllowedExtIds.end());
+
+ accountForAMDShaderTrinaryMinmax();
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.h b/llvm/lib/Target/SPIRV/SPIRVSubtarget.h
index e587739a7636fb..e4484f6508b6b9 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.h
+++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.h
@@ -59,8 +59,8 @@ class SPIRVSubtarget : public SPIRVGenSubtargetInfo {
// TODO: Initialise the available extensions, extended instruction sets
// based on the environment settings.
- void initAvailableExtensions();
void initAvailableExtInstSets();
+ void accountForAMDShaderTrinaryMinmax();
public:
// This constructor initializes the data members to match that
@@ -69,6 +69,9 @@ class SPIRVSubtarget : public SPIRVGenSubtargetInfo {
const std::string &FS, const SPIRVTargetMachine &TM);
SPIRVSubtarget &initSubtargetDependencies(StringRef CPU, StringRef FS);
+ void initAvailableExtensions(
+ const std::set<SPIRV::Extension::Extension> &AllowedExtIds);
+
// Parses features string setting specified subtarget options.
// The definition of this function is auto generated by tblgen.
void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
diff --git a/llvm/unittests/Target/SPIRV/CMakeLists.txt b/llvm/unittests/Target/SPIRV/CMakeLists.txt
index af7d9395605d04..d7f0290089c4cf 100644
--- a/llvm/unittests/Target/SPIRV/CMakeLists.txt
+++ b/llvm/unittests/Target/SPIRV/CMakeLists.txt
@@ -11,6 +11,7 @@ set(LLVM_LINK_COMPONENTS
SPIRVCodeGen
SPIRVAnalysis
Support
+ TargetParser
)
add_llvm_target_unittest(SPIRVTests
diff --git a/llvm/unittests/Target/SPIRV/SPIRVAPITest.cpp b/llvm/unittests/Target/SPIRV/SPIRVAPITest.cpp
index f0b4a2f55c1519..5eae9277c4438b 100644
--- a/llvm/unittests/Target/SPIRV/SPIRVAPITest.cpp
+++ b/llvm/unittests/Target/SPIRV/SPIRVAPITest.cpp
@@ -16,6 +16,7 @@
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
+#include "llvm/TargetParser/Triple.h"
#include "gtest/gtest.h"
#include <gmock/gmock.h>
#include <string>
@@ -25,6 +26,11 @@ using ::testing::StartsWith;
namespace llvm {
+extern "C" LLVM_EXTERNAL_VISIBILITY bool
+SPIRVTranslate(Module *M, std::string &SpirvObj, std::string &ErrMsg,
+ const std::vector<std::string> &AllowExtNames,
+ llvm::CodeGenOptLevel OLevel, Triple TargetTriple);
+
extern "C" bool
SPIRVTranslateModule(Module *M, std::string &SpirvObj, std::string &ErrMsg,
const std::vector<std::string> &AllowExtNames,
@@ -34,7 +40,27 @@ class SPIRVAPITest : public testing::Test {
protected:
bool toSpirv(StringRef Assembly, std::string &Result, std::string &ErrMsg,
const std::vector<std::string> &AllowExtNames,
- const std::vector<std::string> &Opts) {
+ llvm::CodeGenOptLevel OLevel, Triple TargetTriple) {
+ SMDiagnostic ParseError;
+ LLVMContext Context;
+ std::unique_ptr<Module> M =
+ parseAssemblyString(Assembly, ParseError, Context);
+ if (!M) {
+ ParseError.print("IR parsing failed: ", errs());
+ report_fatal_error("Can't parse input assembly.");
+ }
+ bool Status = SPIRVTranslate(M.get(), Result, ErrMsg, AllowExtNames, OLevel,
+ TargetTriple);
+ if (!Status)
+ errs() << ErrMsg;
+ return Status;
+ }
+ // TODO: Remove toSpirvLegacy() and related tests after existing clients
+ // switch into a newer implementation of SPIRVTranslate().
+ bool toSpirvLegacy(StringRef Assembly, std::string &Result,
+ std::string &ErrMsg,
+ const std::vector<std::string> &AllowExtNames,
+ const std::vector<std::string> &Opts) {
SMDiagnostic ParseError;
LLVMContext Context;
std::unique_ptr<Module> M =
@@ -77,48 +103,21 @@ class SPIRVAPITest : public testing::Test {
TEST_F(SPIRVAPITest, checkTranslateOk) {
StringRef Assemblies[] = {"", OkAssembly};
- // Those command line arguments that overlap with registered by llc/codegen
- // are to be started with the ' ' symbol.
- std::vector<std::string> SetOfOpts[] = {
- {}, {"--spirv-mtriple=spirv32-unknown-unknown"}};
- for (const auto &Opts : SetOfOpts) {
- for (StringRef &Assembly : Assemblies) {
- std::string Result, Error;
- bool Status = toSpirv(Assembly, Result, Error, {}, Opts);
- EXPECT_TRUE(Status && Error.empty() && !Result.empty());
- EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);
- }
+ for (StringRef &Assembly : Assemblies) {
+ std::string Result, Error;
+ bool Status = toSpirv(Assembly, Result, Error, {}, CodeGenOptLevel::Default,
+ Triple("spirv32-unknown-unknown"));
+ EXPECT_TRUE(Status && Error.empty() && !Result.empty());
+ EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);
}
}
-TEST_F(SPIRVAPITest, checkTranslateError) {
- std::string Result, Error;
- bool Status = toSpirv(OkAssembly, Result, Error, {},
- {"-mtriple=spirv32-unknown-unknown"});
- EXPECT_FALSE(Status);
- EXPECT_TRUE(Result.empty());
- EXPECT_THAT(Error,
- StartsWith("SPIRVTranslateModule: Unknown command line argument "
- "'-mtriple=spirv32-unknown-unknown'"));
- Status = toSpirv(OkAssembly, Result, Error, {}, {"--spirv-O 5"});
- EXPECT_FALSE(Status);
- EXPECT_TRUE(Result.empty());
- EXPECT_EQ(Error, "Invalid optimization level!");
-}
-
-TEST_F(SPIRVAPITest, checkTranslateSupportExtensionByOpts) {
- std::string Result, Error;
- std::vector<std::string> Opts{
- "--spirv-ext=+SPV_KHR_uniform_group_instructions"};
- bool Status = toSpirv(ExtensionAssembly, Result, Error, {}, Opts);
- EXPECT_TRUE(Status && Error.empty() && !Result.empty());
- EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);
-}
-
TEST_F(SPIRVAPITest, checkTranslateSupportExtensionByArg) {
std::string Result, Error;
std::vector<std::string> ExtNames{"SPV_KHR_uniform_group_instructions"};
- bool Status = toSpirv(ExtensionAssembly, Result, Error, ExtNames, {});
+ bool Status =
+ toSpirv(ExtensionAssembly, Result, Error, ExtNames,
+ CodeGenOptLevel::Aggressive, Triple("spirv64-unknown-unknown"));
EXPECT_TRUE(Status && Error.empty() && !Result.empty());
EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);
}
@@ -128,15 +127,19 @@ TEST_F(SPIRVAPITest, checkTranslateSupportExtensionByArgList) {
std::vector<std::string> ExtNames{"SPV_KHR_subgroup_rotate",
"SPV_KHR_uniform_group_instructions",
"SPV_KHR_subgroup_rotate"};
- bool Status = toSpirv(ExtensionAssembly, Result, Error, ExtNames, {});
+ bool Status =
+ toSpirv(ExtensionAssembly, Result, Error, ExtNames,
+ CodeGenOptLevel::Aggressive, Triple("spirv64-unknown-unknown"));
EXPECT_TRUE(Status && Error.empty() && !Result.empty());
EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);
}
TEST_F(SPIRVAPITest, checkTranslateAllExtensions) {
std::string Result, Error;
- std::vector<std::string> Opts{"--spirv-ext=all"};
- bool Status = toSpirv(ExtensionAssembly, Result, Error, {}, Opts);
+ std::vector<std::string> ExtNames{"all"};
+ bool Status =
+ toSpirv(ExtensionAssembly, Result, Error, ExtNames,
+ CodeGenOptLevel::Aggressive, Triple("spirv64-unknown-unknown"));
EXPECT_TRUE(Status && Error.empty() && !Result.empty());
EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);
}
@@ -144,7 +147,9 @@ TEST_F(SPIRVAPITest, checkTranslateAllExtensions) {
TEST_F(SPIRVAPITest, checkTranslateUnknownExtensionByArg) {
std::string Result, Error;
std::vector<std::string> ExtNames{"SPV_XYZ_my_unknown_extension"};
- bool Status = toSpirv(ExtensionAssembly, Result, Error, ExtNames, {});
+ bool Status =
+ toSpirv(ExtensionAssembly, Result, Error, ExtNames,
+ CodeGenOptLevel::Aggressive, Triple("spirv64-unknown-unknown"));
EXPECT_FALSE(Status);
EXPECT_TRUE(Result.empty());
EXPECT_EQ(Error, "Unknown SPIR-V extension: SPV_XYZ_my_unknown_extension");
@@ -153,35 +158,118 @@ TEST_F(SPIRVAPITest, checkTranslateUnknownExtensionByArg) {
#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
TEST_F(SPIRVAPITest, checkTranslateExtensionError) {
std::string Result, Error;
- std::vector<std::string> Opts;
EXPECT_DEATH_IF_SUPPORTED(
- { toSpirv(ExtensionAssembly, Result, Error, {}, Opts); },
+ {
+ toSpirv(ExtensionAssembly, Result, Error, {},
+ CodeGenOptLevel::Aggressive, Triple("spirv64-unknown-unknown"));
+ },
"LLVM ERROR: __spirv_GroupBitwiseAndKHR: the builtin requires the "
"following SPIR-V extension: SPV_KHR_uniform_group_instructions");
}
-TEST_F(SPIRVAPITest, checkTranslateUnknownExtensionByOpts) {
+TEST_F(SPIRVAPITest, checkTranslateWrongExtensionByArg) {
std::string Result, Error;
- std::vector<std::string> Opts{"--spirv-ext=+SPV_XYZ_my_unknown_extension"};
+ std::vector<std::string> ExtNames{"SPV_KHR_subgroup_rotate"};
EXPECT_DEATH_IF_SUPPORTED(
- { toSpirv(ExtensionAssembly, Result, Error, {}, Opts); },
- "SPIRVTranslateModule: for the --spirv-ext option: Unknown SPIR-V");
+ {
+ toSpirv(ExtensionAssembly, Result, Error, ExtNames,
+ CodeGenOptLevel::Aggressive, Triple("spirv64-unknown-unknown"));
+ },
+ "LLVM ERROR: __spirv_GroupBitwiseAndKHR: the builtin requires the "
+ "following SPIR-V extension: SPV_KHR_uniform_group_instructions");
}
+#endif
-TEST_F(SPIRVAPITest, checkTranslateWrongExtensionByOpts) {
+// Legacy API calls. TODO: Remove after transition into a newer API.
+TEST_F(SPIRVAPITest, checkTranslateStringOptsOk) {
+ StringRef Assemblies[] = {"", OkAssembly};
+ std::vector<std::string> SetOfOpts[] = {{}, {"spirv32-unknown-unknown"}};
+ for (const auto &Opts : SetOfOpts) {
+ for (StringRef &Assembly : Assemblies) {
+ std::string Result, Error;
+ bool Status = toSpirvLegacy(Assembly, Result, Error, {}, Opts);
+ EXPECT_TRUE(Status && Error.empty() && !Result.empty());
+ EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);
+ }
+ }
+}
+
+TEST_F(SPIRVAPITest, checkTranslateStringOptsError) {
+ std::string Result, Error;
+ bool Status = toSpirvLegacy(OkAssembly, Result, Error, {},
+ {"spirv64v1.6-unknown-unknown", "5"});
+ EXPECT_FALSE(Status);
+ EXPECT_TRUE(Result.empty());
+ EXPECT_EQ(Error, "Invalid optimization level!");
+}
+
+TEST_F(SPIRVAPITest, checkTranslateStringOptsErrorOk) {
+ {
+ std::string Result, Error;
+ bool Status = toSpirvLegacy(OkAssembly, Result, Error, {},
+ {"spirv64v1.6-unknown-unknown", "5"});
+ EXPECT_FALSE(Status);
+ EXPECT_TRUE(Result.empty());
+ EXPECT_EQ(Error, "Invalid optimization level!");
+ }
+ {
+ std::string Result, Error;
+ bool Status = toSpirvLegacy(OkAssembly, Result, Error, {},
+ {"spirv64v1.6-unknown-unknown", "3"});
+ EXPECT_TRUE(Status && Error.empty() && !Result.empty());
+ EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);
+ }
+}
+
+TEST_F(SPIRVAPITest, checkTranslateStringOptsSupportExtensionByArg) {
+ std::string Result, Error;
+ std::vector<std::string> ExtNames{"SPV_KHR_uniform_group_instructions"};
+ bool Status = toSpirvLegacy(ExtensionAssembly, Result, Error, ExtNames, {});
+ EXPECT_TRUE(Status && Error.empty() && !Result.empty());
+ EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);
+}
+
+TEST_F(SPIRVAPITest, checkTranslateStringOptsSupportExtensionByArgList) {
+ std::string Result, Error;
+ std::vector<std::string> ExtNames{"SPV_KHR_subgroup_rotate",
+ "SPV_KHR_uniform_group_instructions",
+ "SPV_KHR_subgroup_rotate"};
+ bool Status = toSpirvLegacy(ExtensionAssembly, Result, Error, ExtNames, {});
+ EXPECT_TRUE(Status && Error.empty() && !Result.empty());
+ EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);
+}
+
+TEST_F(SPIRVAPITest, checkTranslateStringOptsAllExtensions) {
+ std::string Result, Error;
+ std::vector<std::string> ExtNames{"all"};
+ bool Status = toSpirvLegacy(ExtensionAssembly, Result, Error, ExtNames, {});
+ EXPECT_TRUE(Status && Error.empty() && !Result.empty());
+ EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);
+}
+
+TEST_F(SPIRVAPITest, checkTranslateStringOptsUnknownExtensionByArg) {
+ std::string Result, Error;
+ std::vector<std::string> ExtNames{"SPV_XYZ_my_unknown_extension"};
+ bool Status = toSpirvLegacy(ExtensionAssembly, Result, Error, ExtNames, {});
+ EXPECT_FALSE(Status);
+ EXPECT_TRUE(Result.empty());
+ EXPECT_EQ(Error, "Unknown SPIR-V extension: SPV_XYZ_my_unknown_extension");
+}
+
+#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
+TEST_F(SPIRVAPITest, checkTranslateStringOptsExtensionError) {
std::string Result, Error;
- std::vector<std::string> Opts{"--spirv-ext=+SPV_KHR_subgroup_rotate"};
EXPECT_DEATH_IF_SUPPORTED(
- { toSpirv(ExtensionAssembly, Result, Error, {}, Opts); },
+ { toSpirvLegacy(ExtensionAssembly, Result, Error, {}, {}); },
"LLVM ERROR: __spirv_GroupBitwiseAndKHR: the builtin requires the "
"following SPIR-V extension: SPV_KHR_uniform_group_instructions");
}
-TEST_F(SPIRVAPITest, checkTranslateWrongExtensionByArg) {
+TEST_F(SPIRVAPITest, checkTranslateStringOptsWrongExtensionByArg) {
std::string Result, Error;
std::vector<std::string> ExtNames{"SPV_KHR_subgroup_rotate"};
EXPECT_DEATH_IF_SUPPORTED(
- { toSpirv(ExtensionAssembly, Result, Error, ExtNames, {}); },
+ { toSpirvLegacy(ExtensionAssembly, Result, Error, ExtNames, {}); },
"LLVM ERROR: __spirv_GroupBitwiseAndKHR: the builtin requires the "
"following SPIR-V extension: SPV_KHR_uniform_group_instructions");
}
More information about the llvm-commits
mailing list