[llvm] [DirectX] Remove intrinsic definitions with no use (PR #133459)

via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 28 08:51:23 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-directx

Author: Farzon Lotfi (farzonl)

<details>
<summary>Changes</summary>

I was planning to use GlobalDCE, but that does more than whats needed to fix the backend. GlobalDCE also doesn't honor `hlsl.export` and making it be able to is more work than expanding the DXIL legalizer.

This change reduces "Unsupported intrinsic for DXIL lowering" errors when compiling DML shaders from 12218 to 415. and improves our compilation success rate from less than 1% to 44%.

---
Full diff: https://github.com/llvm/llvm-project/pull/133459.diff


5 Files Affected:

- (modified) llvm/lib/Target/DirectX/DXILLegalizePass.cpp (+39-14) 
- (modified) llvm/lib/Target/DirectX/DXILLegalizePass.h (+1-1) 
- (modified) llvm/lib/Target/DirectX/DirectX.h (+1-1) 
- (modified) llvm/lib/Target/DirectX/DirectXPassRegistry.def (+1-1) 
- (added) llvm/test/CodeGen/DirectX/remove-dead-intriniscs.ll (+22) 


``````````diff
diff --git a/llvm/lib/Target/DirectX/DXILLegalizePass.cpp b/llvm/lib/Target/DirectX/DXILLegalizePass.cpp
index 395311e430fbb..8eb0a0458d478 100644
--- a/llvm/lib/Target/DirectX/DXILLegalizePass.cpp
+++ b/llvm/lib/Target/DirectX/DXILLegalizePass.cpp
@@ -12,6 +12,7 @@
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/InstIterator.h"
 #include "llvm/IR/Instruction.h"
+#include "llvm/IR/Module.h"
 #include "llvm/Pass.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include <functional>
@@ -20,6 +21,12 @@
 
 using namespace llvm;
 
+static void removeDeadIntrinsics(Function &F,
+                                 SmallVectorImpl<Function *> &ToRemove) {
+  if (F.isIntrinsic() && F.use_empty())
+    ToRemove.push_back(&F);
+}
+
 static void fixI8TruncUseChain(Instruction &I,
                                SmallVectorImpl<Instruction *> &ToRemove,
                                DenseMap<Value *, Value *> &ReplacedValues) {
@@ -146,11 +153,26 @@ class DXILLegalizationPipeline {
 public:
   DXILLegalizationPipeline() { initializeLegalizationPipeline(); }
 
-  bool runLegalizationPipeline(Function &F) {
+  bool runLegalizationPipeline(Module &M) {
+    bool Changes = false;
+    SmallVector<Function *> ToRemove;
+    for (auto &F : make_early_inc_range(M.functions())) {
+      Changes |= runFunctionLegalizationPipeline(F);
+      for (auto &LegalizationFn : ModuleLegalizationPipeline)
+        LegalizationFn(F, ToRemove);
+    }
+
+    for (Function *F : ToRemove)
+      F->eraseFromParent();
+
+    return Changes && !ToRemove.empty();
+  }
+
+  bool runFunctionLegalizationPipeline(Function &F) {
     SmallVector<Instruction *> ToRemove;
     DenseMap<Value *, Value *> ReplacedValues;
     for (auto &I : instructions(F)) {
-      for (auto &LegalizationFn : LegalizationPipeline)
+      for (auto &LegalizationFn : FunctionLegalizationPipeline)
         LegalizationFn(I, ToRemove, ReplacedValues);
     }
 
@@ -164,37 +186,40 @@ class DXILLegalizationPipeline {
   SmallVector<
       std::function<void(Instruction &, SmallVectorImpl<Instruction *> &,
                          DenseMap<Value *, Value *> &)>>
-      LegalizationPipeline;
+      FunctionLegalizationPipeline;
+  SmallVector<std::function<void(Function &, SmallVectorImpl<Function *> &)>>
+      ModuleLegalizationPipeline;
 
   void initializeLegalizationPipeline() {
-    LegalizationPipeline.push_back(fixI8TruncUseChain);
-    LegalizationPipeline.push_back(downcastI64toI32InsertExtractElements);
+    FunctionLegalizationPipeline.push_back(fixI8TruncUseChain);
+    FunctionLegalizationPipeline.push_back(
+        downcastI64toI32InsertExtractElements);
+    ModuleLegalizationPipeline.push_back(removeDeadIntrinsics);
   }
 };
 
-class DXILLegalizeLegacy : public FunctionPass {
+class DXILLegalizeLegacy : public ModulePass {
 
 public:
-  bool runOnFunction(Function &F) override;
-  DXILLegalizeLegacy() : FunctionPass(ID) {}
+  bool runOnModule(Module &M) override;
+  DXILLegalizeLegacy() : ModulePass(ID) {}
 
   static char ID; // Pass identification.
 };
 } // namespace
 
-PreservedAnalyses DXILLegalizePass::run(Function &F,
-                                        FunctionAnalysisManager &FAM) {
+PreservedAnalyses DXILLegalizePass::run(Module &M, ModuleAnalysisManager &MAM) {
   DXILLegalizationPipeline DXLegalize;
-  bool MadeChanges = DXLegalize.runLegalizationPipeline(F);
+  bool MadeChanges = DXLegalize.runLegalizationPipeline(M);
   if (!MadeChanges)
     return PreservedAnalyses::all();
   PreservedAnalyses PA;
   return PA;
 }
 
-bool DXILLegalizeLegacy::runOnFunction(Function &F) {
+bool DXILLegalizeLegacy::runOnModule(Module &M) {
   DXILLegalizationPipeline DXLegalize;
-  return DXLegalize.runLegalizationPipeline(F);
+  return DXLegalize.runLegalizationPipeline(M);
 }
 
 char DXILLegalizeLegacy::ID = 0;
@@ -204,6 +229,6 @@ INITIALIZE_PASS_BEGIN(DXILLegalizeLegacy, DEBUG_TYPE, "DXIL Legalizer", false,
 INITIALIZE_PASS_END(DXILLegalizeLegacy, DEBUG_TYPE, "DXIL Legalizer", false,
                     false)
 
-FunctionPass *llvm::createDXILLegalizeLegacyPass() {
+ModulePass *llvm::createDXILLegalizeLegacyPass() {
   return new DXILLegalizeLegacy();
 }
diff --git a/llvm/lib/Target/DirectX/DXILLegalizePass.h b/llvm/lib/Target/DirectX/DXILLegalizePass.h
index 9d6d1cd19081d..dfa8124be7108 100644
--- a/llvm/lib/Target/DirectX/DXILLegalizePass.h
+++ b/llvm/lib/Target/DirectX/DXILLegalizePass.h
@@ -15,7 +15,7 @@ namespace llvm {
 
 class DXILLegalizePass : public PassInfoMixin<DXILLegalizePass> {
 public:
-  PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
 };
 } // namespace llvm
 
diff --git a/llvm/lib/Target/DirectX/DirectX.h b/llvm/lib/Target/DirectX/DirectX.h
index 96a8a08c875f8..98985db39fc61 100644
--- a/llvm/lib/Target/DirectX/DirectX.h
+++ b/llvm/lib/Target/DirectX/DirectX.h
@@ -52,7 +52,7 @@ void initializeDXILLegalizeLegacyPass(PassRegistry &);
 
 /// Pass to Legalize DXIL by remove i8 truncations and i64 insert/extract
 /// elements
-FunctionPass *createDXILLegalizeLegacyPass();
+ModulePass *createDXILLegalizeLegacyPass();
 
 /// Initializer for DXILOpLowering
 void initializeDXILOpLoweringLegacyPass(PassRegistry &);
diff --git a/llvm/lib/Target/DirectX/DirectXPassRegistry.def b/llvm/lib/Target/DirectX/DirectXPassRegistry.def
index 87d91ead1896f..473f142589d1f 100644
--- a/llvm/lib/Target/DirectX/DirectXPassRegistry.def
+++ b/llvm/lib/Target/DirectX/DirectXPassRegistry.def
@@ -26,6 +26,7 @@ MODULE_ANALYSIS("dxil-root-signature-analysis", dxil::RootSignatureAnalysis())
 MODULE_PASS("dxil-data-scalarization", DXILDataScalarization())
 MODULE_PASS("dxil-flatten-arrays", DXILFlattenArrays())
 MODULE_PASS("dxil-intrinsic-expansion", DXILIntrinsicExpansion())
+MODULE_PASS("dxil-legalize", DXILLegalizePass())
 MODULE_PASS("dxil-op-lower", DXILOpLowering())
 MODULE_PASS("dxil-pretty-printer", DXILPrettyPrinterPass(dbgs()))
 MODULE_PASS("dxil-translate-metadata", DXILTranslateMetadata())
@@ -38,5 +39,4 @@ MODULE_PASS("print<dxil-root-signature>", dxil::RootSignatureAnalysisPrinter(dbg
 #define FUNCTION_PASS(NAME, CREATE_PASS)
 #endif
 FUNCTION_PASS("dxil-resource-access", DXILResourceAccess())
-FUNCTION_PASS("dxil-legalize", DXILLegalizePass())
 #undef FUNCTION_PASS
diff --git a/llvm/test/CodeGen/DirectX/remove-dead-intriniscs.ll b/llvm/test/CodeGen/DirectX/remove-dead-intriniscs.ll
new file mode 100644
index 0000000000000..e3b1f0b69d0b7
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/remove-dead-intriniscs.ll
@@ -0,0 +1,22 @@
+
+; RUN: llc %s -mtriple=dxil-pc-shadermodel6.3-library --filetype=asm -o - | FileCheck %s
+
+declare void @llvm.lifetime.start.p0(i64, ptr) #1
+declare void @llvm.lifetime.end.p0(i64, ptr) #1
+declare i32 @llvm.dx.udot.v4i32(<4 x i32>, <4 x i32>) #2
+declare void @llvm.memset.p0.i32(ptr, i8, i32, i1) #3
+
+; CHECK-NOT: declare void @llvm.lifetime.start.p0(i64, ptr)
+; CHECK-NOT: declare void @llvm.lifetime.end.p0(i64, ptr)
+; CHECK-NOT: declare i32 @llvm.dx.udot.v4i32(<4 x i32>, <4 x i32>)
+; CHECK-NOT: declare void @llvm.memset.p0.i32(ptr, i8, i32, i1)
+
+; CHECK-LABEL: empty_fn
+define void @empty_fn () local_unnamed_addr #0 {
+    ret void
+ } 
+
+attributes #0 = { convergent norecurse nounwind "hlsl.export"}
+attributes #1 = { nounwind memory(argmem: readwrite) }
+attributes #2 = { nounwind memory(none) }
+attributes #3 = { nounwind memory(argmem: write) }

``````````

</details>


https://github.com/llvm/llvm-project/pull/133459


More information about the llvm-commits mailing list