[llvm] [DirectX] Fix the writing of ConstantExpr GEPs to DXIL bitcode (PR #154446)

Deric C. via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 21 15:49:44 PDT 2025


https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/154446

>From 8567ba96bea7f864d4e6968538a56723ab8061e3 Mon Sep 17 00:00:00 2001
From: Deric Cheung <dericcheung at microsoft.com>
Date: Tue, 19 Aug 2025 23:57:29 +0000
Subject: [PATCH 1/6] Use old bitc for ConstantExpr GEPs when writing DXIL

---
 llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
index 1d79c3018439e..bc1a3a7995bda 100644
--- a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
+++ b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
@@ -2113,7 +2113,7 @@ void DXILBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,
         }
         break;
       case Instruction::GetElementPtr: {
-        Code = bitc::CST_CODE_CE_GEP;
+        Code = bitc::CST_CODE_CE_GEP_OLD;
         const auto *GO = cast<GEPOperator>(C);
         if (GO->isInBounds())
           Code = bitc::CST_CODE_CE_INBOUNDS_GEP;

>From 0ec0c08fad897595166c776dc49b4f669d0b10a9 Mon Sep 17 00:00:00 2001
From: Deric Cheung <dericcheung at microsoft.com>
Date: Tue, 19 Aug 2025 16:48:06 +0000
Subject: [PATCH 2/6] Include ConstantExpr GEPs in PointerTypeAnalysis

---
 .../DirectXIRPasses/PointerTypeAnalysis.cpp   | 22 ++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp b/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp
index f99bb4f4eaee1..a93f177a279ca 100644
--- a/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp
+++ b/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp
@@ -15,25 +15,34 @@
 #include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/Operator.h"
 
 using namespace llvm;
 using namespace llvm::dxil;
 
 namespace {
 
+Type *classifyFunctionType(const Function &F, PointerTypeMap &Map);
+
 // Classifies the type of the value passed in by walking the value's users to
 // find a typed instruction to materialize a type from.
 Type *classifyPointerType(const Value *V, PointerTypeMap &Map) {
   assert(V->getType()->isPointerTy() &&
          "classifyPointerType called with non-pointer");
+
+  // A CallInst will trigger this case, and we want to classify its Function
+  // operand as a Function rather than a generic Value.
+  if (const Function *F = dyn_cast<Function>(V))
+    return classifyFunctionType(*F, Map);
+
   auto It = Map.find(V);
   if (It != Map.end())
     return It->second;
 
   Type *PointeeTy = nullptr;
-  if (auto *Inst = dyn_cast<GetElementPtrInst>(V)) {
-    if (!Inst->getResultElementType()->isPointerTy())
-      PointeeTy = Inst->getResultElementType();
+  if (auto *GEP = dyn_cast<GEPOperator>(V)) {
+    if (!GEP->getResultElementType()->isPointerTy())
+      PointeeTy = GEP->getResultElementType();
   } else if (auto *Inst = dyn_cast<AllocaInst>(V)) {
     PointeeTy = Inst->getAllocatedType();
   } else if (auto *GV = dyn_cast<GlobalVariable>(V)) {
@@ -49,8 +58,8 @@ Type *classifyPointerType(const Value *V, PointerTypeMap &Map) {
       // When store value is ptr type, cannot get more type info.
       if (NewPointeeTy->isPointerTy())
         continue;
-    } else if (const auto *Inst = dyn_cast<GetElementPtrInst>(User)) {
-      NewPointeeTy = Inst->getSourceElementType();
+    } else if (const auto *GEP = dyn_cast<GEPOperator>(User)) {
+      NewPointeeTy = GEP->getSourceElementType();
     }
     if (NewPointeeTy) {
       // HLSL doesn't support pointers, so it is unlikely to get more than one
@@ -204,6 +213,9 @@ PointerTypeMap PointerTypeAnalysis::run(const Module &M) {
       for (const auto &I : B) {
         if (I.getType()->isPointerTy())
           classifyPointerType(&I, Map);
+        for (const auto &O : I.operands())
+          if (O.get()->getType()->isPointerTy())
+            classifyPointerType(O.get(), Map);
       }
     }
   }

>From 184601fd800aecfa05e3efa37edfef2ff00f3795 Mon Sep 17 00:00:00 2001
From: Deric Cheung <dericcheung at microsoft.com>
Date: Tue, 19 Aug 2025 16:48:57 +0000
Subject: [PATCH 3/6] Remove ConstantExprs after potentially replacing all its
 uses

---
 llvm/lib/Target/DirectX/DXILDataScalarization.cpp           | 6 +++++-
 llvm/lib/Target/DirectX/DXILFlattenArrays.cpp               | 6 ++++++
 llvm/lib/Target/DirectX/DXILLegalizePass.cpp                | 4 ++++
 .../Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp  | 5 +++++
 4 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/DirectX/DXILDataScalarization.cpp b/llvm/lib/Target/DirectX/DXILDataScalarization.cpp
index feecfc0880e25..5eb6382e2177a 100644
--- a/llvm/lib/Target/DirectX/DXILDataScalarization.cpp
+++ b/llvm/lib/Target/DirectX/DXILDataScalarization.cpp
@@ -153,6 +153,8 @@ bool DataScalarizerVisitor::visitLoadInst(LoadInst &LI) {
     NewLoad->setAlignment(LI.getAlign());
     LI.replaceAllUsesWith(NewLoad);
     LI.eraseFromParent();
+    if (CE->use_empty())
+      CE->destroyConstant();
     visitGetElementPtrInst(*OldGEP);
     return true;
   }
@@ -173,6 +175,8 @@ bool DataScalarizerVisitor::visitStoreInst(StoreInst &SI) {
     NewStore->setAlignment(SI.getAlign());
     SI.replaceAllUsesWith(NewStore);
     SI.eraseFromParent();
+    if (CE->use_empty())
+      CE->destroyConstant();
     visitGetElementPtrInst(*OldGEP);
     return true;
   }
@@ -343,7 +347,7 @@ bool DataScalarizerVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) {
 
   GOp->replaceAllUsesWith(NewGEP);
 
-  if (auto *CE = dyn_cast<ConstantExpr>(GOp))
+  if (auto *CE = dyn_cast<ConstantExpr>(GOp); CE && CE->use_empty())
     CE->destroyConstant();
   else if (auto *OldGEPI = dyn_cast<GetElementPtrInst>(GOp))
     OldGEPI->eraseFromParent();
diff --git a/llvm/lib/Target/DirectX/DXILFlattenArrays.cpp b/llvm/lib/Target/DirectX/DXILFlattenArrays.cpp
index 7e1436e05a34a..9ab236a9c367d 100644
--- a/llvm/lib/Target/DirectX/DXILFlattenArrays.cpp
+++ b/llvm/lib/Target/DirectX/DXILFlattenArrays.cpp
@@ -166,6 +166,8 @@ bool DXILFlattenArraysVisitor::visitLoadInst(LoadInst &LI) {
       NewLoad->setAlignment(LI.getAlign());
       LI.replaceAllUsesWith(NewLoad);
       LI.eraseFromParent();
+      if (CE->use_empty())
+        CE->destroyConstant();
       visitGetElementPtrInst(*OldGEP);
       return true;
     }
@@ -188,6 +190,8 @@ bool DXILFlattenArraysVisitor::visitStoreInst(StoreInst &SI) {
       NewStore->setAlignment(SI.getAlign());
       SI.replaceAllUsesWith(NewStore);
       SI.eraseFromParent();
+      if (CE->use_empty())
+        CE->destroyConstant();
       visitGetElementPtrInst(*OldGEP);
       return true;
     }
@@ -243,6 +247,8 @@ bool DXILFlattenArraysVisitor::visitGetElementPtrInst(GetElementPtrInst &GEP) {
 
     GEP.replaceAllUsesWith(NewGEPI);
     GEP.eraseFromParent();
+    if (PtrOpGEPCE->use_empty())
+      PtrOpGEPCE->destroyConstant();
     visitGetElementPtrInst(*OldGEPI);
     visitGetElementPtrInst(*NewGEPI);
     return true;
diff --git a/llvm/lib/Target/DirectX/DXILLegalizePass.cpp b/llvm/lib/Target/DirectX/DXILLegalizePass.cpp
index 3427968d199f6..515f64a4d726d 100644
--- a/llvm/lib/Target/DirectX/DXILLegalizePass.cpp
+++ b/llvm/lib/Target/DirectX/DXILLegalizePass.cpp
@@ -143,6 +143,10 @@ static bool fixI8UseChain(Instruction &I,
     LoadInst *NewLoad = Builder.CreateLoad(ElementType, NewGEP);
     ReplacedValues[Load] = NewLoad;
     Load->replaceAllUsesWith(NewLoad);
+    Load->setOperand(Load->getPointerOperandIndex(),
+                     PoisonValue::get(CE->getType()));
+    if (CE->use_empty())
+      CE->destroyConstant();
     ToRemove.push_back(Load);
     return true;
   }
diff --git a/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp b/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp
index a93f177a279ca..b996075e31ad2 100644
--- a/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp
+++ b/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp
@@ -50,6 +50,11 @@ Type *classifyPointerType(const Value *V, PointerTypeMap &Map) {
   }
 
   for (const auto *User : V->users()) {
+    // This assert is here because there have been ConstantExpr GEPs with no
+    // users causing the pointer type analysis to misclassify the PointeeTy.
+    [[maybe_unused]] const Constant *C = dyn_cast<Constant>(User);
+    assert((!C || !C->use_empty()) && "A Constant should not have no uses");
+
     Type *NewPointeeTy = nullptr;
     if (const auto *Inst = dyn_cast<LoadInst>(User)) {
       NewPointeeTy = Inst->getType();

>From 040fac6420170a4df2f06a553d3abe506c9124ae Mon Sep 17 00:00:00 2001
From: Deric Cheung <dericcheung at microsoft.com>
Date: Tue, 19 Aug 2025 23:47:24 +0000
Subject: [PATCH 4/6] Add ConstantExpr GEP tests for PointerTypeAnalysis and
 dxil-dis

---
 llvm/test/tools/dxil-dis/constantexpr-gep.ll  | 26 +++++++++++++++++
 .../DirectX/PointerTypeAnalysisTests.cpp      | 28 +++++++++++++++++++
 2 files changed, 54 insertions(+)
 create mode 100644 llvm/test/tools/dxil-dis/constantexpr-gep.ll

diff --git a/llvm/test/tools/dxil-dis/constantexpr-gep.ll b/llvm/test/tools/dxil-dis/constantexpr-gep.ll
new file mode 100644
index 0000000000000..56d46d071df7a
--- /dev/null
+++ b/llvm/test/tools/dxil-dis/constantexpr-gep.ll
@@ -0,0 +1,26 @@
+; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s
+target triple = "dxil-unknown-shadermodel6.7-library"
+
+; CHECK: [[GLOBAL:@.*]] = unnamed_addr addrspace(3) global [10 x i32] zeroinitializer, align 4
+ at g = local_unnamed_addr addrspace(3) global [10 x i32] zeroinitializer, align 4
+
+define i32 @fn() #0 {
+; CHECK-LABEL:  define i32 @fn()
+; CHECK-NEXT:   [[LOAD:%.*]] = load i32, i32 addrspace(3)* getelementptr inbounds ([10 x i32], [10 x i32] addrspace(3)* [[GLOBAL]], i32 0, i32 1), align 4
+; CHECK-NEXT:   ret i32 [[LOAD]]
+;
+  %gep = getelementptr [10 x i32], ptr addrspace(3) @g, i32 0, i32 1
+  %ld = load i32, ptr addrspace(3) %gep, align 4
+  ret i32 %ld
+}
+
+define i32 @fn2() #0 {
+; CHECK-LABEL:  define i32 @fn2()
+; CHECK-NEXT:   [[LOAD:%.*]] = load i32, i32 addrspace(3)* getelementptr inbounds ([10 x i32], [10 x i32] addrspace(3)* [[GLOBAL]], i32 0, i32 2), align 4
+; CHECK-NEXT:   ret i32 [[LOAD]]
+;
+  %ld = load i32, ptr addrspace(3) getelementptr ([10 x i32], ptr addrspace(3) @g, i32 0, i32 2), align 4
+  ret i32 %ld
+}
+
+attributes #0 = { "hlsl.export" }
diff --git a/llvm/unittests/Target/DirectX/PointerTypeAnalysisTests.cpp b/llvm/unittests/Target/DirectX/PointerTypeAnalysisTests.cpp
index 9d41e94bb0bae..6ae139e076281 100644
--- a/llvm/unittests/Target/DirectX/PointerTypeAnalysisTests.cpp
+++ b/llvm/unittests/Target/DirectX/PointerTypeAnalysisTests.cpp
@@ -8,6 +8,7 @@
 
 #include "DirectXIRPasses/PointerTypeAnalysis.h"
 #include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
@@ -123,6 +124,33 @@ TEST(PointerTypeAnalysis, DiscoverGEP) {
   EXPECT_THAT(Map, Contains(Pair(IsA<GetElementPtrInst>(), I64Ptr)));
 }
 
+TEST(PointerTypeAnalysis, DiscoverConstantExprGEP) {
+  StringRef Assembly = R"(
+    @g = internal global [10 x i32] zeroinitializer
+    define i32 @test() {
+      %i = load i32, ptr getelementptr ([10 x i32], ptr @g, i64 0, i64 1)
+      ret i32 %i
+    }
+  )";
+
+  LLVMContext Context;
+  SMDiagnostic Error;
+  auto M = parseAssemblyString(Assembly, Error, Context);
+  ASSERT_TRUE(M) << "Bad assembly?";
+
+  PointerTypeMap Map = PointerTypeAnalysis::run(*M);
+  ASSERT_EQ(Map.size(), 3u);
+  Type *I32Ty = Type::getInt32Ty(Context);
+  Type *I32Ptr = TypedPointerType::get(I32Ty, 0);
+  Type *I32ArrPtr = TypedPointerType::get(ArrayType::get(I32Ty, 10), 0);
+  Type *FnTy = FunctionType::get(I32Ty, {}, false);
+
+  EXPECT_THAT(Map, Contains(Pair(IsA<GlobalVariable>(), I32ArrPtr)));
+  EXPECT_THAT(Map,
+              Contains(Pair(IsA<Function>(), TypedPointerType::get(FnTy, 0))));
+  EXPECT_THAT(Map, Contains(Pair(IsA<ConstantExpr>(), I32Ptr)));
+}
+
 TEST(PointerTypeAnalysis, TraceIndirect) {
   StringRef Assembly = R"(
     define i64 @test(ptr %p) {

>From 1e655345ba08c8174b2b928bfb48a647c9cdd6f8 Mon Sep 17 00:00:00 2001
From: Deric Cheung <dericcheung at microsoft.com>
Date: Thu, 21 Aug 2025 22:46:42 +0000
Subject: [PATCH 5/6] Revert "Remove ConstantExprs after potentially replacing
 all its uses"

This reverts commit 184601fd800aecfa05e3efa37edfef2ff00f3795.
---
 llvm/lib/Target/DirectX/DXILDataScalarization.cpp           | 6 +-----
 llvm/lib/Target/DirectX/DXILFlattenArrays.cpp               | 6 ------
 llvm/lib/Target/DirectX/DXILLegalizePass.cpp                | 4 ----
 .../Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp  | 5 -----
 4 files changed, 1 insertion(+), 20 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILDataScalarization.cpp b/llvm/lib/Target/DirectX/DXILDataScalarization.cpp
index 5eb6382e2177a..feecfc0880e25 100644
--- a/llvm/lib/Target/DirectX/DXILDataScalarization.cpp
+++ b/llvm/lib/Target/DirectX/DXILDataScalarization.cpp
@@ -153,8 +153,6 @@ bool DataScalarizerVisitor::visitLoadInst(LoadInst &LI) {
     NewLoad->setAlignment(LI.getAlign());
     LI.replaceAllUsesWith(NewLoad);
     LI.eraseFromParent();
-    if (CE->use_empty())
-      CE->destroyConstant();
     visitGetElementPtrInst(*OldGEP);
     return true;
   }
@@ -175,8 +173,6 @@ bool DataScalarizerVisitor::visitStoreInst(StoreInst &SI) {
     NewStore->setAlignment(SI.getAlign());
     SI.replaceAllUsesWith(NewStore);
     SI.eraseFromParent();
-    if (CE->use_empty())
-      CE->destroyConstant();
     visitGetElementPtrInst(*OldGEP);
     return true;
   }
@@ -347,7 +343,7 @@ bool DataScalarizerVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) {
 
   GOp->replaceAllUsesWith(NewGEP);
 
-  if (auto *CE = dyn_cast<ConstantExpr>(GOp); CE && CE->use_empty())
+  if (auto *CE = dyn_cast<ConstantExpr>(GOp))
     CE->destroyConstant();
   else if (auto *OldGEPI = dyn_cast<GetElementPtrInst>(GOp))
     OldGEPI->eraseFromParent();
diff --git a/llvm/lib/Target/DirectX/DXILFlattenArrays.cpp b/llvm/lib/Target/DirectX/DXILFlattenArrays.cpp
index 9ab236a9c367d..7e1436e05a34a 100644
--- a/llvm/lib/Target/DirectX/DXILFlattenArrays.cpp
+++ b/llvm/lib/Target/DirectX/DXILFlattenArrays.cpp
@@ -166,8 +166,6 @@ bool DXILFlattenArraysVisitor::visitLoadInst(LoadInst &LI) {
       NewLoad->setAlignment(LI.getAlign());
       LI.replaceAllUsesWith(NewLoad);
       LI.eraseFromParent();
-      if (CE->use_empty())
-        CE->destroyConstant();
       visitGetElementPtrInst(*OldGEP);
       return true;
     }
@@ -190,8 +188,6 @@ bool DXILFlattenArraysVisitor::visitStoreInst(StoreInst &SI) {
       NewStore->setAlignment(SI.getAlign());
       SI.replaceAllUsesWith(NewStore);
       SI.eraseFromParent();
-      if (CE->use_empty())
-        CE->destroyConstant();
       visitGetElementPtrInst(*OldGEP);
       return true;
     }
@@ -247,8 +243,6 @@ bool DXILFlattenArraysVisitor::visitGetElementPtrInst(GetElementPtrInst &GEP) {
 
     GEP.replaceAllUsesWith(NewGEPI);
     GEP.eraseFromParent();
-    if (PtrOpGEPCE->use_empty())
-      PtrOpGEPCE->destroyConstant();
     visitGetElementPtrInst(*OldGEPI);
     visitGetElementPtrInst(*NewGEPI);
     return true;
diff --git a/llvm/lib/Target/DirectX/DXILLegalizePass.cpp b/llvm/lib/Target/DirectX/DXILLegalizePass.cpp
index 515f64a4d726d..3427968d199f6 100644
--- a/llvm/lib/Target/DirectX/DXILLegalizePass.cpp
+++ b/llvm/lib/Target/DirectX/DXILLegalizePass.cpp
@@ -143,10 +143,6 @@ static bool fixI8UseChain(Instruction &I,
     LoadInst *NewLoad = Builder.CreateLoad(ElementType, NewGEP);
     ReplacedValues[Load] = NewLoad;
     Load->replaceAllUsesWith(NewLoad);
-    Load->setOperand(Load->getPointerOperandIndex(),
-                     PoisonValue::get(CE->getType()));
-    if (CE->use_empty())
-      CE->destroyConstant();
     ToRemove.push_back(Load);
     return true;
   }
diff --git a/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp b/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp
index b996075e31ad2..a93f177a279ca 100644
--- a/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp
+++ b/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp
@@ -50,11 +50,6 @@ Type *classifyPointerType(const Value *V, PointerTypeMap &Map) {
   }
 
   for (const auto *User : V->users()) {
-    // This assert is here because there have been ConstantExpr GEPs with no
-    // users causing the pointer type analysis to misclassify the PointeeTy.
-    [[maybe_unused]] const Constant *C = dyn_cast<Constant>(User);
-    assert((!C || !C->use_empty()) && "A Constant should not have no uses");
-
     Type *NewPointeeTy = nullptr;
     if (const auto *Inst = dyn_cast<LoadInst>(User)) {
       NewPointeeTy = Inst->getType();

>From 4d32109ffac21e49425505fe6f42d7cc5f957f50 Mon Sep 17 00:00:00 2001
From: Deric Cheung <dericcheung at microsoft.com>
Date: Thu, 21 Aug 2025 22:49:25 +0000
Subject: [PATCH 6/6] Call removeDeadConstantUsers on GlobalVariables before
 checking uses

---
 llvm/lib/Target/DirectX/DXILDataScalarization.cpp            | 4 +---
 llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp              | 4 +++-
 .../Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp   | 5 +++++
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILDataScalarization.cpp b/llvm/lib/Target/DirectX/DXILDataScalarization.cpp
index feecfc0880e25..d507d71b99fc9 100644
--- a/llvm/lib/Target/DirectX/DXILDataScalarization.cpp
+++ b/llvm/lib/Target/DirectX/DXILDataScalarization.cpp
@@ -343,9 +343,7 @@ bool DataScalarizerVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) {
 
   GOp->replaceAllUsesWith(NewGEP);
 
-  if (auto *CE = dyn_cast<ConstantExpr>(GOp))
-    CE->destroyConstant();
-  else if (auto *OldGEPI = dyn_cast<GetElementPtrInst>(GOp))
+  if (auto *OldGEPI = dyn_cast<GetElementPtrInst>(GOp))
     OldGEPI->eraseFromParent();
 
   return true;
diff --git a/llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp b/llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp
index 13e3408815bba..aa16e795dc768 100644
--- a/llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp
+++ b/llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp
@@ -22,11 +22,13 @@ static bool finalizeLinkage(Module &M) {
 
   // Convert private globals and external globals with no usage to internal
   // linkage.
-  for (GlobalVariable &GV : M.globals())
+  for (GlobalVariable &GV : M.globals()) {
+    GV.removeDeadConstantUsers();
     if (GV.hasPrivateLinkage() || (GV.hasExternalLinkage() && GV.use_empty())) {
       GV.setLinkage(GlobalValue::InternalLinkage);
       MadeChange = true;
     }
+  }
 
   SmallVector<Function *> Funcs;
 
diff --git a/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp b/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp
index a93f177a279ca..c2e139edc6bd1 100644
--- a/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp
+++ b/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp
@@ -35,6 +35,11 @@ Type *classifyPointerType(const Value *V, PointerTypeMap &Map) {
   if (const Function *F = dyn_cast<Function>(V))
     return classifyFunctionType(*F, Map);
 
+  // There can potentially be dead constants hanging off of the globals we do
+  // not want to deal with. So we remove them here.
+  if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
+    GV->removeDeadConstantUsers();
+
   auto It = Map.find(V);
   if (It != Map.end())
     return It->second;



More information about the llvm-commits mailing list