Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SPIR-V] Change a way SPIR-V Backend API works with user facing options #124745

Merged
merged 2 commits into from
Jan 28, 2025

Conversation

VyacheslavLevytskyy
Copy link
Contributor

@VyacheslavLevytskyy VyacheslavLevytskyy commented Jan 28, 2025

This PR fixes #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.

@llvmbot
Copy link
Member

llvmbot commented Jan 28, 2025

@llvm/pr-subscribers-backend-spir-v

Author: Vyacheslav Levytskyy (VyacheslavLevytskyy)

Changes

This PR fixes #124703:

  • added a new API call SPIRVTranslate that is to replace entirely existing 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 is 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.

Patch is 22.59 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/124745.diff

7 Files Affected:

  • (modified) llvm/lib/Target/SPIRV/SPIRVAPI.cpp (+36-47)
  • (modified) llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp (+5)
  • (modified) llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp (+4-2)
  • (modified) llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp (+17-9)
  • (modified) llvm/lib/Target/SPIRV/SPIRVSubtarget.h (+4)
  • (modified) llvm/unittests/Target/SPIRV/CMakeLists.txt (+1)
  • (modified) llvm/unittests/Target/SPIRV/SPIRVAPITest.cpp (+140-52)
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..fc31bbd06387c3 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(
+    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..eb289b7aa38f3e 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.h
+++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.h
@@ -61,6 +61,7 @@ class SPIRVSubtarget : public SPIRVGenSubtargetInfo {
   // based on the environment settings.
   void initAvailableExtensions();
   void initAvailableExtInstSets();
+  void accountForAMDShaderTrinaryMinmax();
 
 public:
   // This constructor initializes the data members to match that
@@ -69,6 +70,9 @@ class SPIRVSubtarget : public SPIRVGenSubtargetInfo {
                  const std::string &FS, const SPIRVTargetMachine &TM);
   SPIRVSubtarget &initSubtargetDependencies(StringRef CPU, StringRef FS);
 
+  void
+  initAvailableExtensions(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) ...
[truncated]

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks reasonable to me.


// Set available extensions after SPIRVSubtarget is created.
void SPIRVSubtarget::initAvailableExtensions(
std::set<SPIRV::Extension::Extension> AllowedExtIds) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accept by const reference? Don't think the copy is needed here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, thank you. Changed.

@VyacheslavLevytskyy
Copy link
Contributor Author

@nikic Are we good to merge or you'd like to proceed with the review?

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@VyacheslavLevytskyy VyacheslavLevytskyy merged commit df122fc into llvm:main Jan 28, 2025
9 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jan 28, 2025

LLVM Buildbot has detected a new failure on builder openmp-offload-libc-amdgpu-runtime running on omp-vega20-1 while building llvm at step 7 "Add check check-offload".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/73/builds/12591

Here is the relevant piece of the build log for the reference
Step 7 (Add check check-offload) failure: test (failure)
******************** TEST 'libomptarget :: amdgcn-amd-amdhsa :: api/omp_host_call.c' FAILED ********************
Exit Code: 2

Command Output (stdout):
--
# RUN: at line 1
/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/clang -fopenmp    -I /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test -I /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src  -nogpulib -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib  -fopenmp-targets=amdgcn-amd-amdhsa /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/api/omp_host_call.c -o /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/api/Output/omp_host_call.c.tmp -Xoffload-linker -lc -Xoffload-linker -lm /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib/libomptarget.devicertl.a && /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/api/Output/omp_host_call.c.tmp | /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/FileCheck /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/api/omp_host_call.c
# executed command: /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/clang -fopenmp -I /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test -I /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -nogpulib -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib -fopenmp-targets=amdgcn-amd-amdhsa /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/api/omp_host_call.c -o /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/api/Output/omp_host_call.c.tmp -Xoffload-linker -lc -Xoffload-linker -lm /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib/libomptarget.devicertl.a
# executed command: /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/api/Output/omp_host_call.c.tmp
# note: command had no output on stdout or stderr
# error: command failed with exit status: -11
# executed command: /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/FileCheck /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/api/omp_host_call.c
# .---command stderr------------
# | FileCheck error: '<stdin>' is empty.
# | FileCheck command line:  /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/FileCheck /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/api/omp_host_call.c
# `-----------------------------
# error: command failed with exit status: 2

--

********************


@llvm-ci
Copy link
Collaborator

llvm-ci commented Jan 28, 2025

LLVM Buildbot has detected a new failure on builder flang-aarch64-dylib running on linaro-flang-aarch64-dylib while building llvm at step 5 "build-unified-tree".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/50/builds/9518

Here is the relevant piece of the build log for the reference
Step 5 (build-unified-tree) failure: build (failure)
...
209.815 [1143/1/5682] Building CXX object tools/mlir/lib/Target/LLVMIR/Dialect/GPU/CMakeFiles/obj.MLIRGPUToLLVMIRTranslation.dir/GPUToLLVMIRTranslation.cpp.o
210.002 [1142/1/5683] Building CXX object tools/mlir/lib/Target/LLVMIR/Dialect/AMX/CMakeFiles/obj.MLIRAMXToLLVMIRTranslation.dir/AMXToLLVMIRTranslation.cpp.o
210.199 [1141/1/5684] Building CXX object tools/mlir/lib/Target/LLVMIR/Dialect/Builtin/CMakeFiles/obj.MLIRBuiltinToLLVMIRTranslation.dir/BuiltinToLLVMIRTranslation.cpp.o
210.399 [1140/1/5685] Building CXX object tools/mlir/lib/Target/LLVMIR/Dialect/NVVM/CMakeFiles/obj.MLIRLLVMIRToNVVMTranslation.dir/LLVMIRToNVVMTranslation.cpp.o
210.559 [1139/1/5686] Building CXX object tools/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/CMakeFiles/obj.MLIRLLVMIRToLLVMTranslation.dir/LLVMIRToLLVMTranslation.cpp.o
210.787 [1138/1/5687] Building CXX object tools/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/CMakeFiles/obj.MLIRLLVMToLLVMIRTranslation.dir/LLVMToLLVMIRTranslation.cpp.o
210.913 [1137/1/5688] Building CXX object tools/mlir/lib/Target/LLVMIR/Dialect/OpenACC/CMakeFiles/obj.MLIROpenACCToLLVMIRTranslation.dir/OpenACCToLLVMIRTranslation.cpp.o
211.070 [1136/1/5689] Building CXX object tools/mlir/lib/Target/LLVMIR/Dialect/ROCDL/CMakeFiles/obj.MLIRROCDLToLLVMIRTranslation.dir/ROCDLToLLVMIRTranslation.cpp.o
211.218 [1135/1/5690] Building CXX object tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestPrintNesting.cpp.o
222.122 [1134/1/5691] Building CXX object tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestSideEffects.cpp.o
FAILED: tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestSideEffects.cpp.o 
/usr/local/bin/c++ -DGTEST_HAS_RTTI=0 -DMLIR_INCLUDE_TESTS -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/mlir/test/lib/IR -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/mlir/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/llvm/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/../Dialect/Test -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/mlir/test/lib/IR/../Dialect/Test -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Wundef -Werror=mismatched-tags -O3 -DNDEBUG -std=c++17  -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -MD -MT tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestSideEffects.cpp.o -MF tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestSideEffects.cpp.o.d -o tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestSideEffects.cpp.o -c /home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/TestSideEffects.cpp
In file included from /home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/TestSideEffects.cpp:9:
/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/../Dialect/Test/TestOps.h:148:10: fatal error: 'TestOps.h.inc' file not found
  148 | #include "TestOps.h.inc"
      |          ^~~~~~~~~~~~~~~
1 error generated.
ninja: build stopped: subcommand failed.

@svenvh
Copy link
Member

svenvh commented Jan 29, 2025

@VyacheslavLevytskyy are you planning to update the API usage in the SPIRV-LLVM-Translator too? I believe this commit broke its spirvbackend-usage.ll test:

Fails to save LLVM as SPIR-V: Invalid optimization level!

@VyacheslavLevytskyy
Copy link
Contributor Author

@VyacheslavLevytskyy are you planning to update the API usage in the SPIRV-LLVM-Translator too? I believe this commit broke its spirvbackend-usage.ll test:

Fails to save LLVM as SPIR-V: Invalid optimization level!

Sure, thank you. Please see KhronosGroup/SPIRV-LLVM-Translator#2978

VyacheslavLevytskyy added a commit to KhronosGroup/SPIRV-LLVM-Translator that referenced this pull request Jan 29, 2025
…ove unneeded options in the call to the SPIR-V Backend API call (#2978)

This PR is to fix usage of the SPIR-V Backend API by updating the list of supported by the SPIR-V Backend extensions and removing no longer needed options in the call to the SPIR-V Backend API call. More details about the context of the change are available in llvm/llvm-project#124745 where The SPIR-V Backend API was refactored wrt. a way it's working with user facing options.
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jan 30, 2025

LLVM Buildbot has detected a new failure on builder lld-x86_64-win running on as-worker-93 while building llvm at step 7 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/146/builds/2191

Here is the relevant piece of the build log for the reference
Step 7 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'LLVM-Unit :: Support/./SupportTests.exe/38/87' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe-LLVM-Unit-11960-38-87.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=87 GTEST_SHARD_INDEX=38 C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe
--

Script:
--
C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe --gtest_filter=ProgramEnvTest.CreateProcessLongPath
--
C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp(160): error: Expected equality of these values:
  0
  RC
    Which is: -2

C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp(163): error: fs::remove(Twine(LongPath)): did not return errc::success.
error number: 13
error message: permission denied



C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp:160
Expected equality of these values:
  0
  RC
    Which is: -2

C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp:163
fs::remove(Twine(LongPath)): did not return errc::success.
error number: 13
error message: permission denied




********************


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[SPIR-V] Review SPIR-V Backend work with user options
6 participants