[llvm] [DirectX] Cast the pointer for atomics whose value type differs (PR #226563)
Joshua Batista via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 30 16:50:37 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/2] 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/2] 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
More information about the llvm-commits
mailing list