Browse Source

Allow removal of trivially dead convergent marker (#3643)

merge #3640 into release-1.6.2104

Failing to remove this because it is marked as having side effects so it
can prevent unwanted code movement resulted in trivially dead code being
retained unnecessarily because the marker isn't removed until after dead
code elimination. By allowing its removal when the operation that needed
it has been removed so it has no users, this dead code can be
eliminated.

(cherry picked from commit cf135fa88b79cb336129c3cd15845d31f2e2ddad)
Greg Roth 4 năm trước cách đây
mục cha
commit
985b29b467

+ 3 - 0
include/dxc/DXIL/DxilUtil.h

@@ -152,6 +152,9 @@ namespace dxilutil {
 
   void ReplaceRawBufferLoad64Bit(llvm::Function *F, llvm::Type *EltTy, hlsl::OP *hlslOP);
   void ReplaceRawBufferStore64Bit(llvm::Function *F, llvm::Type *ETy, hlsl::OP *hlslOP);
+
+  bool IsConvergentMarker(llvm::Value *V);
+  llvm::Value *GetConvergentSource(llvm::Value *V);
 }
 
 }

+ 0 - 19
include/dxc/HLSL/DxilConvergent.h

@@ -1,19 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// DxilConvergent.h                                                          //
-// Copyright (C) Microsoft Corporation. All rights reserved.                 //
-// This file is distributed under the University of Illinois Open Source     //
-// License. See LICENSE.TXT for details.                                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-#pragma once
-
-namespace llvm {
-  class Value;
-  class Function;
-}
-
-namespace hlsl {
-  bool IsConvergentMarker(llvm::Value *V);
-  llvm::Value *GetConvergentSource(llvm::Value *V);
-}

+ 21 - 0
lib/DXIL/DxilUtil.cpp

@@ -14,6 +14,7 @@
 #include "dxc/DXIL/DxilUtil.h"
 #include "dxc/DXIL/DxilModule.h"
 #include "dxc/DXIL/DxilOperations.h"
+#include "dxc/HLSL/DxilConvergentName.h"
 #include "dxc/Support/Global.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/Twine.h"
@@ -1171,6 +1172,26 @@ void ReplaceRawBufferStore64Bit(llvm::Function *F, llvm::Type *ETy, hlsl::OP *hl
   }
 }
 
+bool IsConvergentMarker(const char *Name) {
+  StringRef RName = Name;
+  return RName.startswith(kConvergentFunctionPrefix);
+}
+
+bool IsConvergentMarker(const Function *F) {
+  return F && F->getName().startswith(kConvergentFunctionPrefix);
+}
+
+bool IsConvergentMarker(Value *V) {
+  CallInst *CI = dyn_cast<CallInst>(V);
+  if (!CI)
+    return false;
+  return IsConvergentMarker(CI->getCalledFunction());
+}
+
+Value *GetConvergentSource(Value *V) {
+  return cast<CallInst>(V)->getOperand(0);
+}
+
 }
 }
 

+ 0 - 11
lib/HLSL/DxilConvergent.cpp

@@ -22,24 +22,13 @@
 #include "dxc/HLSL/DxilGenerationPass.h"
 #include "dxc/HLSL/HLOperations.h"
 #include "dxc/HLSL/HLModule.h"
-#include "dxc/HLSL/DxilConvergent.h"
 #include "dxc/HlslIntrinsicOp.h"
 #include "dxc/HLSL/DxilConvergentName.h"
 
 using namespace llvm;
 using namespace hlsl;
 
-bool hlsl::IsConvergentMarker(Value *V) {
-  CallInst *CI = dyn_cast<CallInst>(V);
-  if (!CI)
-    return false;
-  Function *F = CI->getCalledFunction();
-  return F->getName().startswith(kConvergentFunctionPrefix);
-}
 
-Value *hlsl::GetConvergentSource(Value *V) {
-  return cast<CallInst>(V)->getOperand(0);
-}
 
 ///////////////////////////////////////////////////////////////////////////////
 // DxilConvergent.

+ 2 - 3
lib/HLSL/HLOperationLower.cpp

@@ -25,7 +25,6 @@
 #include "dxc/HLSL/HLOperationLowerExtension.h"
 #include "dxc/HLSL/HLOperations.h"
 #include "dxc/HlslIntrinsicOp.h"
-#include "dxc/HLSL/DxilConvergent.h"
 #include "dxc/DXIL/DxilResourceProperties.h"
 
 #include "llvm/IR/GetElementPtrTypeIterator.h"
@@ -844,8 +843,8 @@ Value *FindScalarSource(Value *src, unsigned vecIdx = 0) {
         vecIdx = (unsigned)cast<ConstantInt>(EE->getIndexOperand())
           ->getUniqueInteger().getLimitedValue();
         src = EE->getVectorOperand();
-      } else if (hlsl::IsConvergentMarker(src)) {
-        src = hlsl::GetConvergentSource(src);
+      } else if (hlsl::dxilutil::IsConvergentMarker(src)) {
+        src = hlsl::dxilutil::GetConvergentSource(src);
       } else {
         break;  // Found it.
       }

+ 5 - 0
lib/Transforms/Utils/Local.cpp

@@ -46,6 +46,7 @@
 #include "llvm/Support/raw_ostream.h"
 
 #include "dxc/DXIL/DxilMetadataHelper.h" // HLSL Change - combine dxil metadata.
+#include "dxc/DXIL/DxilUtil.h" // HLSL Change - special handling of convergent marker
 using namespace llvm;
 
 #define DEBUG_TYPE "local"
@@ -331,6 +332,10 @@ bool llvm::isInstructionTriviallyDead(Instruction *I,
     if (Constant *C = dyn_cast<Constant>(CI->getArgOperand(0)))
       return C->isNullValue() || isa<UndefValue>(C);
 
+  // HLSL change - don't force unused convergenet markers to stay
+  if (CallInst *CI = dyn_cast<CallInst>(I))
+    if (hlsl::dxilutil::IsConvergentMarker(CI)) return true;
+
   return false;
 }
 

+ 20 - 0
tools/clang/test/HLSLFileCheck/passes/llvm/dce/remove_convergent_marker.hlsl

@@ -0,0 +1,20 @@
+// RUN: %dxc /T ps_6_0  %s | FileCheck %s
+
+// Tests that a convergent marker added by a derivative call
+// is removed in time to let the rest of the dead code be removed
+
+
+// Since everything is ignored, there should be no conditionals
+// and just a single return void
+
+// CHECK: void @main
+// CHECK-NOT: br
+// CHECK: storeOutput
+// CHECK: ret void
+
+float main(float d : DEPTH0) : SV_Target {
+    if (d > 0)
+      d = max(d, 3.0);
+    ddx(d+1);
+    return 0.0;
+}