From c80789d1feb752f0e05576e5a9cf3a3169aa9f9a Mon Sep 17 00:00:00 2001 From: Farzon Lotfi Date: Fri, 28 Mar 2025 11:42:26 -0400 Subject: [PATCH 1/2] [DirectX] Remove intrinsic definitions with no use 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%. --- llvm/lib/Target/DirectX/DXILLegalizePass.cpp | 53 ++++++++++++++----- llvm/lib/Target/DirectX/DXILLegalizePass.h | 2 +- llvm/lib/Target/DirectX/DirectX.h | 2 +- .../Target/DirectX/DirectXPassRegistry.def | 2 +- .../CodeGen/DirectX/remove-dead-intriniscs.ll | 22 ++++++++ 5 files changed, 64 insertions(+), 17 deletions(-) create mode 100644 llvm/test/CodeGen/DirectX/remove-dead-intriniscs.ll 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 @@ -20,6 +21,12 @@ using namespace llvm; +static void removeDeadIntrinsics(Function &F, + SmallVectorImpl &ToRemove) { + if (F.isIntrinsic() && F.use_empty()) + ToRemove.push_back(&F); +} + static void fixI8TruncUseChain(Instruction &I, SmallVectorImpl &ToRemove, DenseMap &ReplacedValues) { @@ -146,11 +153,26 @@ class DXILLegalizationPipeline { public: DXILLegalizationPipeline() { initializeLegalizationPipeline(); } - bool runLegalizationPipeline(Function &F) { + bool runLegalizationPipeline(Module &M) { + bool Changes = false; + SmallVector 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 ToRemove; DenseMap 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 &, DenseMap &)>> - LegalizationPipeline; + FunctionLegalizationPipeline; + SmallVector &)>> + 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 { 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::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) } From 82cac25e1b30a8bd13da9aea1d2587cb2b0b8c01 Mon Sep 17 00:00:00 2001 From: Farzon Lotfi Date: Fri, 28 Mar 2025 16:19:14 -0400 Subject: [PATCH 2/2] revert changes to LegalizerPass, instead do cleanup in DXILFinalizeLinkage.cpp where intrinsics are getting orphaned --- .../Target/DirectX/DXILFinalizeLinkage.cpp | 12 ++++- llvm/lib/Target/DirectX/DXILLegalizePass.cpp | 53 +++++-------------- llvm/lib/Target/DirectX/DXILLegalizePass.h | 2 +- llvm/lib/Target/DirectX/DirectX.h | 2 +- .../Target/DirectX/DirectXPassRegistry.def | 2 +- 5 files changed, 27 insertions(+), 44 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp b/llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp index 91ac758150fb4..7651617adc43b 100644 --- a/llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp +++ b/llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp @@ -18,7 +18,7 @@ using namespace llvm; static bool finalizeLinkage(Module &M) { - SmallPtrSet Funcs; + SmallVector Funcs; // Collect non-entry and non-exported functions to set to internal linkage. for (Function &EF : M.functions()) { @@ -26,7 +26,7 @@ static bool finalizeLinkage(Module &M) { continue; if (EF.hasFnAttribute("hlsl.shader") || EF.hasFnAttribute("hlsl.export")) continue; - Funcs.insert(&EF); + Funcs.push_back(&EF); } for (Function *F : Funcs) { @@ -36,6 +36,14 @@ static bool finalizeLinkage(Module &M) { M.getFunctionList().erase(F); } + // Do a pass over intrinsics that are no longer used and remove them. + Funcs.clear(); + for (Function &F : M.functions()) + if (F.isIntrinsic() && F.use_empty()) + Funcs.push_back(&F); + for (Function *F : Funcs) + F->eraseFromParent(); + return false; } diff --git a/llvm/lib/Target/DirectX/DXILLegalizePass.cpp b/llvm/lib/Target/DirectX/DXILLegalizePass.cpp index 8eb0a0458d478..395311e430fbb 100644 --- a/llvm/lib/Target/DirectX/DXILLegalizePass.cpp +++ b/llvm/lib/Target/DirectX/DXILLegalizePass.cpp @@ -12,7 +12,6 @@ #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 @@ -21,12 +20,6 @@ using namespace llvm; -static void removeDeadIntrinsics(Function &F, - SmallVectorImpl &ToRemove) { - if (F.isIntrinsic() && F.use_empty()) - ToRemove.push_back(&F); -} - static void fixI8TruncUseChain(Instruction &I, SmallVectorImpl &ToRemove, DenseMap &ReplacedValues) { @@ -153,26 +146,11 @@ class DXILLegalizationPipeline { public: DXILLegalizationPipeline() { initializeLegalizationPipeline(); } - bool runLegalizationPipeline(Module &M) { - bool Changes = false; - SmallVector 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) { + bool runLegalizationPipeline(Function &F) { SmallVector ToRemove; DenseMap ReplacedValues; for (auto &I : instructions(F)) { - for (auto &LegalizationFn : FunctionLegalizationPipeline) + for (auto &LegalizationFn : LegalizationPipeline) LegalizationFn(I, ToRemove, ReplacedValues); } @@ -186,40 +164,37 @@ class DXILLegalizationPipeline { SmallVector< std::function &, DenseMap &)>> - FunctionLegalizationPipeline; - SmallVector &)>> - ModuleLegalizationPipeline; + LegalizationPipeline; void initializeLegalizationPipeline() { - FunctionLegalizationPipeline.push_back(fixI8TruncUseChain); - FunctionLegalizationPipeline.push_back( - downcastI64toI32InsertExtractElements); - ModuleLegalizationPipeline.push_back(removeDeadIntrinsics); + LegalizationPipeline.push_back(fixI8TruncUseChain); + LegalizationPipeline.push_back(downcastI64toI32InsertExtractElements); } }; -class DXILLegalizeLegacy : public ModulePass { +class DXILLegalizeLegacy : public FunctionPass { public: - bool runOnModule(Module &M) override; - DXILLegalizeLegacy() : ModulePass(ID) {} + bool runOnFunction(Function &F) override; + DXILLegalizeLegacy() : FunctionPass(ID) {} static char ID; // Pass identification. }; } // namespace -PreservedAnalyses DXILLegalizePass::run(Module &M, ModuleAnalysisManager &MAM) { +PreservedAnalyses DXILLegalizePass::run(Function &F, + FunctionAnalysisManager &FAM) { DXILLegalizationPipeline DXLegalize; - bool MadeChanges = DXLegalize.runLegalizationPipeline(M); + bool MadeChanges = DXLegalize.runLegalizationPipeline(F); if (!MadeChanges) return PreservedAnalyses::all(); PreservedAnalyses PA; return PA; } -bool DXILLegalizeLegacy::runOnModule(Module &M) { +bool DXILLegalizeLegacy::runOnFunction(Function &F) { DXILLegalizationPipeline DXLegalize; - return DXLegalize.runLegalizationPipeline(M); + return DXLegalize.runLegalizationPipeline(F); } char DXILLegalizeLegacy::ID = 0; @@ -229,6 +204,6 @@ INITIALIZE_PASS_BEGIN(DXILLegalizeLegacy, DEBUG_TYPE, "DXIL Legalizer", false, INITIALIZE_PASS_END(DXILLegalizeLegacy, DEBUG_TYPE, "DXIL Legalizer", false, false) -ModulePass *llvm::createDXILLegalizeLegacyPass() { +FunctionPass *llvm::createDXILLegalizeLegacyPass() { return new DXILLegalizeLegacy(); } diff --git a/llvm/lib/Target/DirectX/DXILLegalizePass.h b/llvm/lib/Target/DirectX/DXILLegalizePass.h index dfa8124be7108..9d6d1cd19081d 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 { public: - PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); + PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM); }; } // namespace llvm diff --git a/llvm/lib/Target/DirectX/DirectX.h b/llvm/lib/Target/DirectX/DirectX.h index 98985db39fc61..96a8a08c875f8 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 -ModulePass *createDXILLegalizeLegacyPass(); +FunctionPass *createDXILLegalizeLegacyPass(); /// Initializer for DXILOpLowering void initializeDXILOpLoweringLegacyPass(PassRegistry &); diff --git a/llvm/lib/Target/DirectX/DirectXPassRegistry.def b/llvm/lib/Target/DirectX/DirectXPassRegistry.def index 473f142589d1f..87d91ead1896f 100644 --- a/llvm/lib/Target/DirectX/DirectXPassRegistry.def +++ b/llvm/lib/Target/DirectX/DirectXPassRegistry.def @@ -26,7 +26,6 @@ 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()) @@ -39,4 +38,5 @@ MODULE_PASS("print", dxil::RootSignatureAnalysisPrinter(dbg #define FUNCTION_PASS(NAME, CREATE_PASS) #endif FUNCTION_PASS("dxil-resource-access", DXILResourceAccess()) +FUNCTION_PASS("dxil-legalize", DXILLegalizePass()) #undef FUNCTION_PASS