Forráskód Böngészése

Add DxilLoopDeletion to remove unused loops. (#2927)

Xiang Li 5 éve
szülő
commit
3562970cd8

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

@@ -115,6 +115,8 @@ void initializeDxilValidateWaveSensitivityPass(llvm::PassRegistry&);
 FunctionPass *createCleanupDxBreakPass();
 void initializeCleanupDxBreakPass(llvm::PassRegistry&);
 
+FunctionPass *createDxilLoopDeletionPass();
+void initializeDxilLoopDeletionPass(llvm::PassRegistry &);
 
 ModulePass *createHLLegalizeParameter();
 void initializeHLLegalizeParameterPass(llvm::PassRegistry &);

+ 1 - 1
include/dxc/Support/HLSLOptions.td

@@ -320,7 +320,7 @@ def Oconfig : CommaJoined<["-"], "Oconfig=">, Group<spirv_Group>, Flags<[CoreOpt
 def target_profile : JoinedOrSeparate<["-", "/"], "T">, Flags<[CoreOption]>, Group<hlslcomp_Group>, MetaVarName<"<profile>">,
   /* <py::lines('VALRULE-TEXT')>hctdb_instrhelp.get_target_profiles()</py>*/
   // VALRULE-TEXT:BEGIN
-  HelpText<"Set target profile. \n\t<profile>: ps_6_0, ps_6_1, ps_6_2, ps_6_3, ps_6_4, ps_6_5, ps_6_6, \n\t\t as_6_5, as_6_6, \n\t\t vs_6_0, vs_6_1, vs_6_2, vs_6_3, vs_6_4, vs_6_5, vs_6_6, \n\t\t gs_6_0, gs_6_1, gs_6_2, gs_6_3, gs_6_4, gs_6_5, gs_6_6, \n\t\t ms_6_5, ms_6_6, \n\t\t lib_6_1, lib_6_2, lib_6_3, lib_6_4, lib_6_5, lib_6_6, \n\t\t cs_6_0, cs_6_1, cs_6_2, cs_6_3, cs_6_4, cs_6_5, cs_6_6, \n\t\t hs_6_0, hs_6_1, hs_6_2, hs_6_3, hs_6_4, hs_6_5, hs_6_6, \n\t\t ds_6_0, ds_6_1, ds_6_2, ds_6_3, ds_6_4, ds_6_5, ds_6_6, \n\t\t ">;
+  HelpText<"Set target profile. \n\t<profile>: ps_6_0, ps_6_1, ps_6_2, ps_6_3, ps_6_4, ps_6_5, ps_6_6, \n\t\t vs_6_0, vs_6_1, vs_6_2, vs_6_3, vs_6_4, vs_6_5, vs_6_6, \n\t\t gs_6_0, gs_6_1, gs_6_2, gs_6_3, gs_6_4, gs_6_5, gs_6_6, \n\t\t hs_6_0, hs_6_1, hs_6_2, hs_6_3, hs_6_4, hs_6_5, hs_6_6, \n\t\t ds_6_0, ds_6_1, ds_6_2, ds_6_3, ds_6_4, ds_6_5, ds_6_6, \n\t\t cs_6_0, cs_6_1, cs_6_2, cs_6_3, cs_6_4, cs_6_5, cs_6_6, \n\t\t lib_6_1, lib_6_2, lib_6_3, lib_6_4, lib_6_5, lib_6_6, \n\t\t ms_6_5, ms_6_6, \n\t\t as_6_5, as_6_6, \n\t\t ">;
   // VALRULE-TEXT:END
 def entrypoint :  JoinedOrSeparate<["-", "/"], "E">, Flags<[CoreOption, RewriteOption]>, Group<hlslcomp_Group>,
   HelpText<"Entry point name">;

+ 1 - 0
lib/HLSL/CMakeLists.txt

@@ -18,6 +18,7 @@ add_llvm_library(LLVMHLSL
   DxilLegalizeEvalOperations.cpp
   DxilLegalizeSampleOffsetPass.cpp
   DxilLinker.cpp
+  DxilLoopDeletion.cpp
   DxilPrecisePropagatePass.cpp
   DxilPreparePasses.cpp
   DxilPromoteResourcePasses.cpp

+ 1 - 0
lib/HLSL/DxcOptimizer.cpp

@@ -106,6 +106,7 @@ HRESULT SetupRegistryPassForHLSL() {
     initializeDxilLegalizeResourcesPass(Registry);
     initializeDxilLegalizeSampleOffsetPassPass(Registry);
     initializeDxilLoadMetadataPass(Registry);
+    initializeDxilLoopDeletionPass(Registry);
     initializeDxilLoopUnrollPass(Registry);
     initializeDxilLowerCreateHandleForLibPass(Registry);
     initializeDxilPrecisePropagatePassPass(Registry);

+ 64 - 0
lib/HLSL/DxilLoopDeletion.cpp

@@ -0,0 +1,64 @@
+//===- DxilLoopDeletion.cpp - Dead Loop Deletion Pass -----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file run LoopDeletion SimplifyCFG and DCE more than once to make sure
+// all unused loop can be removed. Use kMaxIteration to avoid dead loop.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/IR/Function.h"
+#include "dxc/HLSL/DxilGenerationPass.h"
+#include "llvm/IR/LegacyPassManager.h"
+
+using namespace llvm;
+
+namespace {
+  class DxilLoopDeletion : public FunctionPass {
+  public:
+    static char ID; // Pass ID, replacement for typeid
+    DxilLoopDeletion() : FunctionPass(ID) {
+    }
+
+    bool runOnFunction(Function &F) override;
+
+  };
+}
+
+char DxilLoopDeletion::ID = 0;
+INITIALIZE_PASS(DxilLoopDeletion, "dxil-loop-deletion",
+                "Delete dead loops", false, false)
+
+FunctionPass *llvm::createDxilLoopDeletionPass() { return new DxilLoopDeletion(); }
+
+bool DxilLoopDeletion::runOnFunction(Function &F) {
+  // Run loop simplify first to make sure loop invariant is moved so loop
+  // deletion will not update the function if not delete.
+  legacy::FunctionPassManager DeleteLoopPM(F.getParent());
+
+  DeleteLoopPM.add(createLoopDeletionPass());
+  bool bUpdated = false;
+
+  legacy::FunctionPassManager SimpilfyPM(F.getParent());
+  SimpilfyPM.add(createCFGSimplificationPass());
+  SimpilfyPM.add(createDeadCodeEliminationPass());
+
+  const unsigned kMaxIteration = 3;
+  unsigned i=0;
+  while (i<kMaxIteration) {
+    if (!DeleteLoopPM.run(F))
+      break;
+
+    SimpilfyPM.run(F);
+    i++;
+    bUpdated = true;
+  }
+
+  return bUpdated;
+}

+ 1 - 0
lib/Transforms/IPO/PassManagerBuilder.cpp

@@ -595,6 +595,7 @@ void PassManagerBuilder::populateModulePassManager(
 
   addExtensionsToPM(EP_Peephole, MPM);
   MPM.add(createCFGSimplificationPass());
+  MPM.add(createDxilLoopDeletionPass()); // HLSL Change - try to delete loop again.
   MPM.add(createInstructionCombiningPass());
 
   if (!DisableUnrollLoops) {

+ 5 - 3
lib/Transforms/Scalar/LoopDeletion.cpp

@@ -170,9 +170,11 @@ bool LoopDeletion::runOnLoop(Loop *L, LPPassManager &LPM) {
   // Don't remove loops for which we can't solve the trip count.
   // They could be infinite, in which case we'd be changing program behavior.
   ScalarEvolution &SE = getAnalysis<ScalarEvolution>();
-  const SCEV *S = SE.getMaxBackedgeTakenCount(L);
-  if (isa<SCEVCouldNotCompute>(S))
-    return Changed;
+  // HLSL Change begin - remove loops even cannot solve the trip count.
+  //const SCEV *S = SE.getMaxBackedgeTakenCount(L);
+  ////if (isa<SCEVCouldNotCompute>(S))
+  //  return Changed;
+  // HLSL Change end.
 
   // Now that we know the removal is safe, remove the loop by changing the
   // branch from the preheader to go to the single exit block.

+ 80 - 0
tools/clang/test/HLSLFileCheck/passes/dxil/dxil_loop_deletion/loop_deletion.hlsl

@@ -0,0 +1,80 @@
+// RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
+
+// Make the loop which not contribute to output is removed.
+// CHECK: @main()
+// CHECK-NOT:phi
+
+const uint c;
+static float g_static;
+Buffer<uint> buffer;
+
+struct struct_f3 {
+  float3 f3;
+};
+
+void do_nothing() {
+  struct_f3 rt;
+  rt.f3.xyz = 0;
+}
+
+float do_branch0(uint u) {
+  if (u)
+    return 0;
+  return 1;
+}
+
+float do_branch1(const uint u) {
+  float f = 0.F;
+  if (u)
+    f = max(f, g_static);
+  if (u)
+    f = max(f, g_static);
+  if (u)
+    f += g_static;
+  return f;
+}
+
+void do_complex(inout struct_f3 result, const uint u) {
+  if (do_branch1(asuint(buffer[0])) <= 0)
+    return;
+
+  float3 d = normalize(0 - asfloat(buffer[0]).xxx);
+  float e = dot(d, asfloat(buffer[0]).xxx);
+  if (e >= 0) {
+    float3 b = d;
+    if (((u & 1) ? 0 : asfloat(0)) <= 0)
+      b = d;
+    float f2 = 1;
+    if (e < asfloat(0)) {
+      f2 *= pow(max(0, rcp(asfloat(0))), 2);
+    }
+    do_branch0(asuint(buffer[0]));
+    result.f3 += 2 * f2;
+  }
+}
+
+float4 main(const float4 pos : SV_POSITION) : SV_TARGET {
+  uint u = pos.x;
+  struct_f3 result;
+  result.f3 = 0;
+  for (uint i = 0; i < c; ++i) {
+    if (1 & u) {
+      do_nothing();
+      result.f3 += 0.1;
+    }
+  }
+  g_static = result.f3.x;
+
+  for (uint i = 0; i < 1; ++i) {
+    if (1 & u) {
+      do_complex(result, c);
+    }
+  }
+  for (uint i = 0; i < 1; ++i) {
+    if (1 & u) {
+      do_complex(result, c);
+    }
+  }
+
+  return 0;
+}

+ 1 - 0
utils/hct/hctdb.py

@@ -2020,6 +2020,7 @@ class db_dxil(object):
                 {'n':'AllowPreserves', 't':'bool', 'c':1},
             ])
         add_pass('dxil-preserves-to-select', 'DxilPreserveToSelect', 'Dxil Preserves To Select', [])
+        add_pass('dxil-delete-loop', 'DxilLoopDeletion', 'Dxil Loop Deletion', [])
         add_pass('dxil-value-cache', 'DxilValueCache', 'Dxil Value Cache',[])
         add_pass('hlsl-cleanup-dxbreak', 'CleanupDxBreak', 'HLSL Remove unnecessary dx.break conditions', [])