Browse Source

[spirv] Add CL option to disable SPIR-V legalization (#814)

/fcgl is reused in SPIR-V CodeGen for disabling SPIR-V legalization.
Lei Zhang 7 years ago
parent
commit
0b309e9faf

+ 1 - 0
include/dxc/Support/HLSLOptions.h

@@ -158,6 +158,7 @@ public:
   // SPIRV Change Starts
   // SPIRV Change Starts
 #ifdef ENABLE_SPIRV_CODEGEN
 #ifdef ENABLE_SPIRV_CODEGEN
   bool GenSPIRV; // OPT_spirv
   bool GenSPIRV; // OPT_spirv
+  bool DisableSpirvLegalization; // OPT_fcgl
   llvm::StringRef VkStageIoOrder; // OPT_fvk_stage_io_order
   llvm::StringRef VkStageIoOrder; // OPT_fvk_stage_io_order
   llvm::SmallVector<uint32_t, 4> VkBShift; // OPT_fvk_b_shift
   llvm::SmallVector<uint32_t, 4> VkBShift; // OPT_fvk_b_shift
   llvm::SmallVector<uint32_t, 4> VkTShift; // OPT_fvk_t_shift
   llvm::SmallVector<uint32_t, 4> VkTShift; // OPT_fvk_t_shift

+ 1 - 0
lib/DxcSupport/HLSLOptions.cpp

@@ -481,6 +481,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
   // SPIRV Change Starts
   // SPIRV Change Starts
 #ifdef ENABLE_SPIRV_CODEGEN
 #ifdef ENABLE_SPIRV_CODEGEN
   const bool genSpirv = opts.GenSPIRV = Args.hasFlag(OPT_spirv, OPT_INVALID, false);
   const bool genSpirv = opts.GenSPIRV = Args.hasFlag(OPT_spirv, OPT_INVALID, false);
+  opts.DisableSpirvLegalization = Args.hasFlag(OPT_fcgl, OPT_INVALID, false);
 
 
   // Collects the arguments for -fvk-{b|s|t|u}-shift.
   // Collects the arguments for -fvk-{b|s|t|u}-shift.
   const auto handleVkShiftArgs = [genSpirv, &Args, &errors](
   const auto handleVkShiftArgs = [genSpirv, &Args, &errors](

+ 1 - 0
tools/clang/include/clang/SPIRV/EmitSPIRVOptions.h

@@ -15,6 +15,7 @@
 namespace clang {
 namespace clang {
 /// Structs for controlling behaviors of SPIR-V codegen.
 /// Structs for controlling behaviors of SPIR-V codegen.
 struct EmitSPIRVOptions {
 struct EmitSPIRVOptions {
+  bool disableLegalization;
   llvm::StringRef stageIoOrder;
   llvm::StringRef stageIoOrder;
   llvm::SmallVector<uint32_t, 4> bShift;
   llvm::SmallVector<uint32_t, 4> bShift;
   llvm::SmallVector<uint32_t, 4> tShift;
   llvm::SmallVector<uint32_t, 4> tShift;

+ 25 - 5
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -174,7 +174,7 @@ const Expr *isStructuredBufferLoad(const Expr *expr, const Expr **index) {
   return nullptr;
   return nullptr;
 }
 }
 
 
-bool spirvToolsOptimize(std::vector<uint32_t> *module, std::string *messages) {
+bool spirvToolsLegalize(std::vector<uint32_t> *module, std::string *messages) {
   spvtools::Optimizer optimizer(SPV_ENV_VULKAN_1_0);
   spvtools::Optimizer optimizer(SPV_ENV_VULKAN_1_0);
 
 
   optimizer.SetMessageConsumer(
   optimizer.SetMessageConsumer(
@@ -205,6 +205,19 @@ bool spirvToolsOptimize(std::vector<uint32_t> *module, std::string *messages) {
   return optimizer.Run(module->data(), module->size(), module);
   return optimizer.Run(module->data(), module->size(), module);
 }
 }
 
 
+bool spirvToolsOptimize(std::vector<uint32_t> *module, std::string *messages) {
+  spvtools::Optimizer optimizer(SPV_ENV_VULKAN_1_0);
+
+  optimizer.SetMessageConsumer(
+      [messages](spv_message_level_t /*level*/, const char * /*source*/,
+                 const spv_position_t & /*position*/,
+                 const char *message) { *messages += message; });
+
+  optimizer.RegisterPerformancePasses();
+
+  return optimizer.Run(module->data(), module->size(), module);
+}
+
 /// Translates atomic HLSL opcodes into the equivalent SPIR-V opcode.
 /// Translates atomic HLSL opcodes into the equivalent SPIR-V opcode.
 spv::Op translateAtomicHlslOpcodeToSpirvOpcode(hlsl::IntrinsicOp opcode) {
 spv::Op translateAtomicHlslOpcodeToSpirvOpcode(hlsl::IntrinsicOp opcode) {
   using namespace hlsl;
   using namespace hlsl;
@@ -349,14 +362,21 @@ void SPIRVEmitter::HandleTranslationUnit(ASTContext &context) {
   // Output the constructed module.
   // Output the constructed module.
   std::vector<uint32_t> m = theBuilder.takeModule();
   std::vector<uint32_t> m = theBuilder.takeModule();
 
 
+  // Run legalization passes
+  if (!spirvOptions.disableLegalization && needsLegalization) {
+    std::string messages;
+    if (!spirvToolsLegalize(&m, &messages)) {
+      emitFatalError("failed to legalize SPIR-V: %0", {}) << messages;
+      return;
+    }
+  }
+
   const auto optLevel = theCompilerInstance.getCodeGenOpts().OptimizationLevel;
   const auto optLevel = theCompilerInstance.getCodeGenOpts().OptimizationLevel;
-  if (needsLegalization || optLevel > 0) {
-    if (needsLegalization && optLevel == 0)
-      emitWarning("-O0 ignored since SPIR-V legalization required", {});
 
 
+  if (optLevel > 0) {
     std::string messages;
     std::string messages;
     if (!spirvToolsOptimize(&m, &messages)) {
     if (!spirvToolsOptimize(&m, &messages)) {
-      emitFatalError("failed to legalize/optimize SPIR-V: %0", {}) << messages;
+      emitFatalError("failed to optimize SPIR-V: %0", {}) << messages;
       return;
       return;
     }
     }
   }
   }

+ 1 - 0
tools/clang/tools/dxcompiler/dxcompilerobj.cpp

@@ -464,6 +464,7 @@ public:
 #ifdef ENABLE_SPIRV_CODEGEN
 #ifdef ENABLE_SPIRV_CODEGEN
       else if (opts.GenSPIRV) {
       else if (opts.GenSPIRV) {
           clang::EmitSPIRVOptions spirvOpts;
           clang::EmitSPIRVOptions spirvOpts;
+          spirvOpts.disableLegalization = opts.DisableSpirvLegalization;
           spirvOpts.stageIoOrder = opts.VkStageIoOrder;
           spirvOpts.stageIoOrder = opts.VkStageIoOrder;
           spirvOpts.bShift = opts.VkBShift;
           spirvOpts.bShift = opts.VkBShift;
           spirvOpts.tShift = opts.VkTShift;
           spirvOpts.tShift = opts.VkTShift;

+ 2 - 1
tools/clang/unittests/SPIRV/FileTestUtils.cpp

@@ -137,7 +137,8 @@ bool runCompilerWithSpirvGeneration(const llvm::StringRef inputFilePath,
     flags.push_back(L"-T");
     flags.push_back(L"-T");
     flags.push_back(profile.c_str());
     flags.push_back(profile.c_str());
     flags.push_back(L"-spirv");
     flags.push_back(L"-spirv");
-    flags.push_back(L"-O0"); // Disable optimization for testing
+    flags.push_back(L"-fcgl"); // Disable legalization for testing
+    flags.push_back(L"-O0");   // Disable optimization for testing
     for (const auto &arg : rest)
     for (const auto &arg : rest)
       flags.push_back(arg.c_str());
       flags.push_back(arg.c_str());