Browse Source

Remove all discard instructions (#400)

* Add remove-discards pass

* explicit lfs

* Change pass name, remove copy-pasted member enum, reduced include set

* CR feedback: better way to delete instructions, stale comment, end iterator could go stale, CHECK-NOT is a good idea.
Jeff Noyle 8 years ago
parent
commit
fa94808e09

+ 2 - 0
include/dxc/HLSL/DxilGenerationPass.h

@@ -53,6 +53,7 @@ ModulePass *createDxilLegalizeEvalOperationsPass();
 FunctionPass *createDxilLegalizeSampleOffsetPass();
 FunctionPass *createSimplifyInstPass();
 ModulePass *createDxilOutputColorBecomesConstantPass();
+ModulePass *createDxilRemoveDiscardsPass();
 
 void initializeDxilCondenseResourcesPass(llvm::PassRegistry&);
 void initializeDxilEliminateOutputDynamicIndexingPass(llvm::PassRegistry&);
@@ -70,6 +71,7 @@ void initializeDxilLegalizeEvalOperationsPass(llvm::PassRegistry&);
 void initializeDxilLegalizeSampleOffsetPassPass(llvm::PassRegistry&);
 void initializeSimplifyInstPass(llvm::PassRegistry&);
 void initializeDxilOutputColorBecomesConstantPass(llvm::PassRegistry&);
+void initializeDxilRemoveDiscardsPass(llvm::PassRegistry&);
 
 bool AreDxilResourcesDense(llvm::Module *M, hlsl::DxilResourceBase **ppNonDense);
 

+ 1 - 0
lib/HLSL/CMakeLists.txt

@@ -19,6 +19,7 @@ add_llvm_library(LLVMHLSL
   DxilModule.cpp
   DxilOperations.cpp
   DxilOutputColorBecomesConstant.cpp
+  DxilRemoveDiscards.cpp
   DxilPreserveAllOutputs.cpp
   DxilResource.cpp
   DxilResourceBase.cpp

+ 1 - 0
lib/HLSL/DxcOptimizer.cpp

@@ -95,6 +95,7 @@ HRESULT SetupRegistryPassForHLSL() {
     initializeDxilOutputColorBecomesConstantPass(Registry);
     initializeDxilPrecisePropagatePassPass(Registry);
     initializeDxilPreserveAllOutputsPass(Registry);
+    initializeDxilRemoveDiscardsPass(Registry);
     initializeDynamicIndexingVectorToArrayPass(Registry);
     initializeEarlyCSELegacyPassPass(Registry);
     initializeEliminateAvailableExternallyPass(Registry);

+ 60 - 0
lib/HLSL/DxilRemoveDiscards.cpp

@@ -0,0 +1,60 @@
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// DxilRemoveDiscards.cpp                                                    //
+// Copyright (C) Microsoft Corporation. All rights reserved.                 //
+// This file is distributed under the University of Illinois Open Source     //
+// License. See LICENSE.TXT for details.                                     //
+//                                                                           //
+// Provides a pass to remove all instances of the discard instruction        //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+#include "dxc/HLSL/DxilGenerationPass.h"
+#include "dxc/HLSL/DxilOperations.h"
+#include "dxc/HLSL/DxilModule.h"
+
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/PassManager.h"
+
+using namespace llvm;
+using namespace hlsl;
+
+class DxilRemoveDiscards : public ModulePass {
+
+public:
+  static char ID; // Pass identification, replacement for typeid
+  explicit DxilRemoveDiscards() : ModulePass(ID) {}
+  const char *getPassName() const override { return "DXIL Remove all discard instructions"; }
+  bool runOnModule(Module &M) override;
+};
+
+bool DxilRemoveDiscards::runOnModule(Module &M)
+{
+  // This pass removes all instances of the discard instruction within the shader.
+  DxilModule &DM = M.GetOrCreateDxilModule();
+
+  LLVMContext & Ctx = M.getContext();
+  OP *HlslOP = DM.GetOP();
+  Function * DiscardFunction = HlslOP->GetOpFunc(DXIL::OpCode::Discard, Type::getVoidTy(Ctx));
+  auto DiscardFunctionUses = DiscardFunction->uses();
+
+  bool Modified = false;
+
+  for (auto FI = DiscardFunctionUses.begin(); FI != DiscardFunctionUses.end(); ) {
+    auto & FunctionUse = *FI++;
+    auto FunctionUser = FunctionUse.getUser();
+    auto instruction = cast<Instruction>(FunctionUser);
+    instruction->eraseFromParent();
+    Modified = true;
+  }
+
+  return Modified;
+}
+
+char DxilRemoveDiscards::ID = 0;
+
+ModulePass *llvm::createDxilRemoveDiscardsPass() {
+  return new DxilRemoveDiscards();
+}
+
+INITIALIZE_PASS(DxilRemoveDiscards, "hlsl-dxil-remove-discards", "HLSL DXIL Remove all discard instructions", false, false)

+ 29 - 0
tools/clang/test/HLSL/pix/removeDiscards.hlsl

@@ -0,0 +1,29 @@
+// RUN: %dxc -Emain -Tps_6_0 %s | %opt -S -hlsl-dxil-remove-discards | %FileCheck %s
+
+// Check that the discard within the if/then was removed:
+//     CHECK: if.then:                                          ; preds = %entry
+// CHECK-NOT:   call void @dx.op.discard(i32 82, i1 true)
+//     CHECK:   br label %if.end
+//     CHECK: if.end:
+
+struct RTOut
+{
+  int i : SV_Target;
+  float4 c : SV_Target1;
+};
+
+[RootSignature("")]
+RTOut main(float r : r, float g : g, float b : b, float a : a)  {
+  r *= 2.f;
+  g *= 4.f;
+  b *= 8.f;
+  a *= 16.f;
+  if (r > 3.f)
+  {
+    discard;
+  }
+  RTOut rtOut;
+  rtOut.i = 8;
+  rtOut.c = float4(r,g,b,a);
+  return rtOut;
+}

+ 5 - 0
tools/clang/unittests/HLSL/CompilerTest.cpp

@@ -361,6 +361,7 @@ public:
   TEST_METHOD(CompileHlsl2017ThenOK)
   TEST_METHOD(CompileHlsl2018ThenFail)
 
+  TEST_METHOD(PixRemoveDiscards)
   TEST_METHOD(PixConstantColor)
   TEST_METHOD(PixConstantColorInt)
   TEST_METHOD(PixConstantColorMRT)
@@ -2225,6 +2226,10 @@ TEST_F(CompilerTest, CompileHlsl2018ThenFail) {
   CheckOperationResultMsgs(pResult, &pErrorMsg, 1, false, false);
 }
 
+TEST_F(CompilerTest, PixRemoveDiscards) {
+  CodeGenTestCheck(L"pix\\removeDiscards.hlsl");
+}
+
 TEST_F(CompilerTest, PixConstantColor) {
   CodeGenTestCheck(L"pix\\constantcolor.hlsl");
 }

+ 1 - 0
utils/hct/hctdb.py

@@ -1269,6 +1269,7 @@ class db_dxil(object):
             {'n':'constant-green','t':'float','c':1},
             {'n':'constant-blue','t':'float','c':1},
             {'n':'constant-alpha','t':'float','c':1}])
+        add_pass('hlsl-dxil-remove-discards', 'DxilRemoveDiscards', 'HLSL DXIL Remove all discard instructions', [])
         add_pass('hlsl-dxilemit', 'DxilEmitMetadata', 'HLSL DXIL Metadata Emit', [])
         add_pass('hlsl-dxilload', 'DxilLoadMetadata', 'HLSL DXIL Metadata Load', [])
         add_pass('hlsl-dxil-expand-trig', 'DxilExpandTrigIntrinsics', 'DXIL expand trig intrinsics', [])