[llvm] Adjust bit cast instruction filter for DXIL Prepare pass (PR #142678)

Joshua Batista via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 3 15:05:40 PDT 2025


https://github.com/bob80905 created https://github.com/llvm/llvm-project/pull/142678

This PR addresses a specific edge case when deciding whether or not to produce a bitcast instruction.
Specifically, when the given instruction is a global array, the element type of the array wasn't correctly compared to the return type. In this specific case, if the types are equal, a bitcast shouldn't be created, but it was.
This PR checks to see if the element type of the array is the same as the return type, and if it is, it doesn't create a bitcast instruction. 

Fixes https://github.com/llvm/llvm-project/issues/139013

>From 0aff10620880dd7f58bd453ef5836fbf963f35dd Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Tue, 3 Jun 2025 15:03:02 -0700
Subject: [PATCH] first attempt

---
 llvm/lib/Target/DirectX/DXILPrepare.cpp       | 37 +++++++++++++++++-
 .../DirectX/noop_bitcast_global_array_type.ll | 39 +++++++++++++++++++
 2 files changed, 74 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/DirectX/noop_bitcast_global_array_type.ll

diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp
index e0068787f5e5a..54e4499830ff0 100644
--- a/llvm/lib/Target/DirectX/DXILPrepare.cpp
+++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp
@@ -148,9 +148,42 @@ class DXILPrepareModule : public ModulePass {
                                      Type *Ty) {
     // Omit bitcasts if the incoming value matches the instruction type.
     auto It = PointerTypes.find(Operand);
-    if (It != PointerTypes.end())
-      if (cast<TypedPointerType>(It->second)->getElementType() == Ty)
+    if (It != PointerTypes.end()) {
+      auto OpTy = cast<TypedPointerType>(It->second)->getElementType();
+      if (OpTy == Ty)
         return nullptr;
+    }
+
+    // Also omit the bitcast for matching global array types
+    if (auto *GlobalVar = llvm::dyn_cast<llvm::GlobalVariable>(Operand)) {
+      llvm::Type *ValTy = GlobalVar->getValueType();
+
+      if (auto *ArrTy = llvm::dyn_cast<llvm::ArrayType>(ValTy)) {
+        llvm::Type *ElTy = ArrTy->getElementType();
+        if (ElTy == Ty)
+          return nullptr;
+      }
+    }
+
+    // finally, drill down GEP instructions until we get the array
+    // that is being accessed, and compare element types
+    if (auto *GEPInstr = llvm::dyn_cast<llvm::ConstantExpr>(Operand)) {
+      while (GEPInstr->getOpcode() == llvm::Instruction::GetElementPtr) {
+        llvm::Value *OpArg = GEPInstr->getOperand(0);
+
+        if (auto *GlobalVar = llvm::dyn_cast<llvm::GlobalVariable>(OpArg)) {
+          llvm::Constant *initializer = GlobalVar->getInitializer();
+
+          llvm::Type *ValTy = GlobalVar->getValueType();
+          if (auto *ArrTy = llvm::dyn_cast<llvm::ArrayType>(ValTy)) {
+            llvm::Type *ElTy = ArrTy->getElementType();
+            if (ElTy == Ty)
+              return nullptr;
+          }
+        }
+      }
+    }
+
     // Insert bitcasts where we are removing the instruction.
     Builder.SetInsertPoint(&Inst);
     // This code only gets hit in opaque-pointer mode, so the type of the
diff --git a/llvm/test/CodeGen/DirectX/noop_bitcast_global_array_type.ll b/llvm/test/CodeGen/DirectX/noop_bitcast_global_array_type.ll
new file mode 100644
index 0000000000000..4cca76efcf461
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/noop_bitcast_global_array_type.ll
@@ -0,0 +1,39 @@
+; RUN: opt -S --dxil-prepare %s | FileCheck %s
+
+; Test that global arrays do not get a bitcast instruction
+; after the dxil-prepare pass.
+
+target triple = "dxilv1.2-unknown-shadermodel6.2-compute"
+
+ at inputTile.1dim = local_unnamed_addr addrspace(3) global [3 x float] zeroinitializer, align 2
+
+define float @testload() local_unnamed_addr {
+  ; NOTE: this would be "bitcast ptr addrspace(3)..." before the change that introduced this test,
+  ; after the dxil-prepare pass is run
+  ; CHECK: load float, ptr addrspace(3) @inputTile.1dim, align 2
+  %v = load float, ptr addrspace(3) @inputTile.1dim, align 2  
+  
+  ret float %v
+}
+
+define void @teststore() local_unnamed_addr {  
+  ; CHECK: store float 2.000000e+00, ptr addrspace(3) @inputTile.1dim, align 2
+  store float 2.000000e+00, ptr addrspace(3) @inputTile.1dim, align 2  
+  
+  ret void
+}
+
+define float @testGEPConst() local_unnamed_addr {  
+  ; CHECK: load float, ptr addrspace(3) getelementptr (float, ptr addrspace(3) @inputTile.1dim, i32 1), align 4
+  %v = load float, ptr addrspace(3) getelementptr (float, ptr addrspace(3) @inputTile.1dim, i32 1), align 4
+  
+  ret float %v
+}
+
+define float @testGEPNonConst(i32 %i) local_unnamed_addr {  
+  ; CHECK: getelementptr float, ptr addrspace(3) @inputTile.1dim, i32 %i
+  %gep = getelementptr float, ptr addrspace(3) @inputTile.1dim, i32 %i
+  %v = load float, ptr addrspace(3) %gep
+  
+  ret float %v
+}



More information about the llvm-commits mailing list