[llvm] [DirectX] Cast the pointer for atomics whose value type differs (PR #226563)
Joshua Batista via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 2 12:00:00 PDT 2026
https://github.com/bob80905 updated https://github.com/llvm/llvm-project/pull/226563
>From fca6e981802ba138d820d16709d6acc99142142e Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 25 Sep 2026 11:27:59 -0700
Subject: [PATCH 1/3] first attempt
---
llvm/lib/Target/DirectX/DXILPrepare.cpp | 19 +++++++++++++++++++
.../DirectXIRPasses/PointerTypeAnalysis.cpp | 4 ++++
llvm/test/tools/dxil-dis/atomicrmw.ll | 19 +++++++++++++++++--
3 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp
index 23bc42e549dee..c73c4658478ac 100644
--- a/llvm/lib/Target/DirectX/DXILPrepare.cpp
+++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp
@@ -190,6 +190,25 @@ class DXILPrepareModule : public ModulePass {
GEP->setOperand(0, NoOpBitcast);
continue;
}
+ // An atomic on a float allocation exchanges the bit pattern as an
+ // integer, so the pointer element type does not match the value
+ // type. Typed pointers need a cast to keep the two in agreement.
+ if (auto *RMW = dyn_cast<AtomicRMWInst>(&I)) {
+ if (Value *NoOpBitcast = maybeGenerateBitcast(
+ Builder, PointerTypes, I, RMW->getPointerOperand(),
+ RMW->getValOperand()->getType()))
+ RMW->setOperand(AtomicRMWInst::getPointerOperandIndex(),
+ NoOpBitcast);
+ continue;
+ }
+ if (auto *CmpXchg = dyn_cast<AtomicCmpXchgInst>(&I)) {
+ if (Value *NoOpBitcast = maybeGenerateBitcast(
+ Builder, PointerTypes, I, CmpXchg->getPointerOperand(),
+ CmpXchg->getNewValOperand()->getType()))
+ CmpXchg->setOperand(AtomicCmpXchgInst::getPointerOperandIndex(),
+ NoOpBitcast);
+ continue;
+ }
}
}
}
diff --git a/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp b/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp
index c58af1560a6b7..5da22aaea3b82 100644
--- a/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp
+++ b/llvm/lib/Target/DirectX/DirectXIRPasses/PointerTypeAnalysis.cpp
@@ -63,6 +63,10 @@ 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<AtomicRMWInst>(User)) {
+ NewPointeeTy = Inst->getValOperand()->getType();
+ } else if (const auto *Inst = dyn_cast<AtomicCmpXchgInst>(User)) {
+ NewPointeeTy = Inst->getNewValOperand()->getType();
} else if (const auto *GEP = dyn_cast<GEPOperator>(User)) {
NewPointeeTy = GEP->getSourceElementType();
}
diff --git a/llvm/test/tools/dxil-dis/atomicrmw.ll b/llvm/test/tools/dxil-dis/atomicrmw.ll
index d8edc4c68aa6c..9c49d9943d617 100644
--- a/llvm/test/tools/dxil-dis/atomicrmw.ll
+++ b/llvm/test/tools/dxil-dis/atomicrmw.ll
@@ -1,17 +1,32 @@
; RUN: llc --filetype=obj %s --stop-after=dxil-write-bitcode -o %t.bc
; RUN: dxil-dis %t.bc -o - | FileCheck %s
-; Verify that the DXIL reader supports the atomicrmw record.
+; Verify that the DXIL reader supports the atomicrmw and the cmpxchg records.
+; A float allocation needs a pointer cast, because the atomic value is an
+; integer and a DXIL pointer carries the element type.
target triple = "dxil-pc-shadermodel6.0-compute"
@gsm = internal addrspace(3) global i32 zeroinitializer, align 4
+ at gsm_float = internal addrspace(3) global float zeroinitializer, align 4
+ at gsm_float_arr = internal addrspace(3) global [4 x float] zeroinitializer, align 4
; CHECK-LABEL: define void @main()
-; CHECK: atomicrmw add i32 addrspace(3)* @gsm, i32 1 monotonic
+; An integer allocation already agrees with the value, so it gets no cast.
+; CHECK-NEXT: atomicrmw add i32 addrspace(3)* @gsm, i32 1 monotonic
+; CHECK-NEXT: [[P0:%.*]] = bitcast float addrspace(3)* @gsm_float to i32 addrspace(3)*
+; CHECK-NEXT: atomicrmw xchg i32 addrspace(3)* [[P0]], i32 2 monotonic
+; CHECK-NEXT: [[P1:%.*]] = bitcast float addrspace(3)* getelementptr {{.*}}@gsm_float_arr{{.*}} to i32 addrspace(3)*
+; CHECK-NEXT: atomicrmw xchg i32 addrspace(3)* [[P1]], i32 3 monotonic
+; CHECK-NEXT: [[P2:%.*]] = bitcast float addrspace(3)* @gsm_float to i32 addrspace(3)*
+; CHECK-NEXT: cmpxchg i32 addrspace(3)* [[P2]], i32 4, i32 5 monotonic monotonic
define void @main() #0 {
%old = atomicrmw add ptr addrspace(3) @gsm, i32 1 monotonic
+ %f = atomicrmw xchg ptr addrspace(3) @gsm_float, i32 2 monotonic
+ %gep = getelementptr [4 x float], ptr addrspace(3) @gsm_float_arr, i32 0, i32 1
+ %g = atomicrmw xchg ptr addrspace(3) %gep, i32 3 monotonic
+ %c = cmpxchg ptr addrspace(3) @gsm_float, i32 4, i32 5 monotonic monotonic
ret void
}
>From 223b51b6496b5252301fe74e61947d6f342407b6 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Wed, 30 Sep 2026 16:50:20 -0700
Subject: [PATCH 2/3] address Finn
---
llvm/test/tools/dxil-dis/atomicrmw.ll | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/llvm/test/tools/dxil-dis/atomicrmw.ll b/llvm/test/tools/dxil-dis/atomicrmw.ll
index 9c49d9943d617..783356b25299f 100644
--- a/llvm/test/tools/dxil-dis/atomicrmw.ll
+++ b/llvm/test/tools/dxil-dis/atomicrmw.ll
@@ -8,23 +8,27 @@
target triple = "dxil-pc-shadermodel6.0-compute"
@gsm = internal addrspace(3) global i32 zeroinitializer, align 4
+ at gsm_arr = internal addrspace(3) global [4 x i32] zeroinitializer, align 4
@gsm_float = internal addrspace(3) global float zeroinitializer, align 4
- at gsm_float_arr = internal addrspace(3) global [4 x float] zeroinitializer, align 4
+ at gsm_farr = internal addrspace(3) global [4 x float] zeroinitializer, align 4
; CHECK-LABEL: define void @main()
; An integer allocation already agrees with the value, so it gets no cast.
; CHECK-NEXT: atomicrmw add i32 addrspace(3)* @gsm, i32 1 monotonic
+; CHECK-NEXT: atomicrmw add i32 addrspace(3)* getelementptr {{.*}}@gsm_arr{{.*}}, i32 6 monotonic
; CHECK-NEXT: [[P0:%.*]] = bitcast float addrspace(3)* @gsm_float to i32 addrspace(3)*
; CHECK-NEXT: atomicrmw xchg i32 addrspace(3)* [[P0]], i32 2 monotonic
-; CHECK-NEXT: [[P1:%.*]] = bitcast float addrspace(3)* getelementptr {{.*}}@gsm_float_arr{{.*}} to i32 addrspace(3)*
+; CHECK-NEXT: [[P1:%.*]] = bitcast float addrspace(3)* getelementptr {{.*}}@gsm_farr{{.*}} to i32 addrspace(3)*
; CHECK-NEXT: atomicrmw xchg i32 addrspace(3)* [[P1]], i32 3 monotonic
; CHECK-NEXT: [[P2:%.*]] = bitcast float addrspace(3)* @gsm_float to i32 addrspace(3)*
; CHECK-NEXT: cmpxchg i32 addrspace(3)* [[P2]], i32 4, i32 5 monotonic monotonic
define void @main() #0 {
%old = atomicrmw add ptr addrspace(3) @gsm, i32 1 monotonic
+ %int_gep = getelementptr [4 x i32], ptr addrspace(3) @gsm_arr, i32 0, i32 1
+ %arr = atomicrmw add ptr addrspace(3) %int_gep, i32 6 monotonic
%f = atomicrmw xchg ptr addrspace(3) @gsm_float, i32 2 monotonic
- %gep = getelementptr [4 x float], ptr addrspace(3) @gsm_float_arr, i32 0, i32 1
+ %gep = getelementptr [4 x float], ptr addrspace(3) @gsm_farr, i32 0, i32 1
%g = atomicrmw xchg ptr addrspace(3) %gep, i32 3 monotonic
%c = cmpxchg ptr addrspace(3) @gsm_float, i32 4, i32 5 monotonic monotonic
ret void
>From 45e6ddaea0276d17cad67a8dda80e1e302e847dc Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 2 Oct 2026 11:59:39 -0700
Subject: [PATCH 3/3] fix macos test failure
Co-authored-by: Copilot <223556219+Copilot at users.noreply.github.com>
Copilot-Session: f3b26c5c-98e3-4091-8c86-a002c4ba46dc
---
llvm/test/tools/dxil-dis/atomicrmw.ll | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/llvm/test/tools/dxil-dis/atomicrmw.ll b/llvm/test/tools/dxil-dis/atomicrmw.ll
index 783356b25299f..06b816dcb0e3a 100644
--- a/llvm/test/tools/dxil-dis/atomicrmw.ll
+++ b/llvm/test/tools/dxil-dis/atomicrmw.ll
@@ -15,20 +15,28 @@ target triple = "dxil-pc-shadermodel6.0-compute"
; CHECK-LABEL: define void @main()
; An integer allocation already agrees with the value, so it gets no cast.
; CHECK-NEXT: atomicrmw add i32 addrspace(3)* @gsm, i32 1 monotonic
-; CHECK-NEXT: atomicrmw add i32 addrspace(3)* getelementptr {{.*}}@gsm_arr{{.*}}, i32 6 monotonic
+; CHECK-NEXT: [[INDEX:%.*]] = load i32, i32 addrspace(3)* @gsm, align 4
+; CHECK-NEXT: [[INT_MUL:%.*]] = mul i32 [[INDEX]], 1
+; CHECK-NEXT: [[INT_INDEX:%.*]] = add i32 0, [[INT_MUL]]
+; CHECK-NEXT: [[INT_GEP:%.*]] = getelementptr [4 x i32], [4 x i32] addrspace(3)* @gsm_arr, i32 0, i32 [[INT_INDEX]]
+; CHECK-NEXT: atomicrmw add i32 addrspace(3)* [[INT_GEP]], i32 6 monotonic
; CHECK-NEXT: [[P0:%.*]] = bitcast float addrspace(3)* @gsm_float to i32 addrspace(3)*
; CHECK-NEXT: atomicrmw xchg i32 addrspace(3)* [[P0]], i32 2 monotonic
-; CHECK-NEXT: [[P1:%.*]] = bitcast float addrspace(3)* getelementptr {{.*}}@gsm_farr{{.*}} to i32 addrspace(3)*
+; CHECK-NEXT: [[FLOAT_MUL:%.*]] = mul i32 [[INDEX]], 1
+; CHECK-NEXT: [[FLOAT_INDEX:%.*]] = add i32 0, [[FLOAT_MUL]]
+; CHECK-NEXT: [[FLOAT_GEP:%.*]] = getelementptr [4 x float], [4 x float] addrspace(3)* @gsm_farr, i32 0, i32 [[FLOAT_INDEX]]
+; CHECK-NEXT: [[P1:%.*]] = bitcast float addrspace(3)* [[FLOAT_GEP]] to i32 addrspace(3)*
; CHECK-NEXT: atomicrmw xchg i32 addrspace(3)* [[P1]], i32 3 monotonic
; CHECK-NEXT: [[P2:%.*]] = bitcast float addrspace(3)* @gsm_float to i32 addrspace(3)*
; CHECK-NEXT: cmpxchg i32 addrspace(3)* [[P2]], i32 4, i32 5 monotonic monotonic
define void @main() #0 {
%old = atomicrmw add ptr addrspace(3) @gsm, i32 1 monotonic
- %int_gep = getelementptr [4 x i32], ptr addrspace(3) @gsm_arr, i32 0, i32 1
+ %index = load i32, ptr addrspace(3) @gsm, align 4
+ %int_gep = getelementptr [4 x i32], ptr addrspace(3) @gsm_arr, i32 0, i32 %index
%arr = atomicrmw add ptr addrspace(3) %int_gep, i32 6 monotonic
%f = atomicrmw xchg ptr addrspace(3) @gsm_float, i32 2 monotonic
- %gep = getelementptr [4 x float], ptr addrspace(3) @gsm_farr, i32 0, i32 1
+ %gep = getelementptr [4 x float], ptr addrspace(3) @gsm_farr, i32 0, i32 %index
%g = atomicrmw xchg ptr addrspace(3) %gep, i32 3 monotonic
%c = cmpxchg ptr addrspace(3) @gsm_float, i32 4, i32 5 monotonic monotonic
ret void
More information about the llvm-commits
mailing list