[llvm] [DirectX] Fix the writing of ConstantExpr GEPs to DXIL bitcode (PR #154446)
Deric C. via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 25 10:56:05 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/7] 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/7] 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/7] 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/7] 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/7] 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/7] 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;
>From aedbaa5bed59ccd686eb22fc9c5b579a1057674c Mon Sep 17 00:00:00 2001
From: Deric Cheung <dericcheung at microsoft.com>
Date: Mon, 25 Aug 2025 17:55:16 +0000
Subject: [PATCH 7/7] Add an i8 ConstantExpr GEP in dxil-dis test to exercise
removeDeadConstantUsers
---
llvm/test/tools/dxil-dis/constantexpr-gep.ll | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/llvm/test/tools/dxil-dis/constantexpr-gep.ll b/llvm/test/tools/dxil-dis/constantexpr-gep.ll
index 56d46d071df7a..59251474f1a4b 100644
--- a/llvm/test/tools/dxil-dis/constantexpr-gep.ll
+++ b/llvm/test/tools/dxil-dis/constantexpr-gep.ll
@@ -23,4 +23,13 @@ define i32 @fn2() #0 {
ret i32 %ld
}
+define i32 @fn3() #0 {
+; CHECK-LABEL: define i32 @fn3()
+; CHECK-NEXT: [[LOAD:%.*]] = load i32, i32 addrspace(3)* getelementptr inbounds ([10 x i32], [10 x i32] addrspace(3)* [[GLOBAL]], i32 0, i32 3), align 4
+; CHECK-NEXT: ret i32 [[LOAD]]
+;
+ %ld = load i32, ptr addrspace(3) getelementptr (i8, ptr addrspace(3) @g, i32 12), align 4
+ ret i32 %ld
+}
+
attributes #0 = { "hlsl.export" }
More information about the llvm-commits
mailing list