Skip to content

Commit c9e48a9

Browse files
committed
[Attributor] Add support for atomic operations in AAAddressSpace
1 parent 357bd61 commit c9e48a9

File tree

3 files changed

+176
-3
lines changed

3 files changed

+176
-3
lines changed

llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,10 +1084,15 @@ static bool runImpl(Module &M, AnalysisGetter &AG, TargetMachine &TM,
10841084
if (auto *LI = dyn_cast<LoadInst>(&I)) {
10851085
A.getOrCreateAAFor<AAAddressSpace>(
10861086
IRPosition::value(*LI->getPointerOperand()));
1087-
}
1088-
if (auto *SI = dyn_cast<StoreInst>(&I)) {
1087+
} else if (auto *SI = dyn_cast<StoreInst>(&I)) {
10891088
A.getOrCreateAAFor<AAAddressSpace>(
10901089
IRPosition::value(*SI->getPointerOperand()));
1090+
} else if (auto *AI = dyn_cast<AtomicRMWInst>(&I)) {
1091+
A.getOrCreateAAFor<AAAddressSpace>(
1092+
IRPosition::value(*AI->getPointerOperand()));
1093+
} else if (auto *CmpX = dyn_cast<AtomicCmpXchgInst>(&I)) {
1094+
A.getOrCreateAAFor<AAAddressSpace>(
1095+
IRPosition::value(*CmpX->getPointerOperand()));
10911096
}
10921097
}
10931098
}

llvm/lib/Transforms/IPO/AttributorAttributes.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12583,10 +12583,14 @@ struct AAAddressSpaceImpl : public AAAddressSpace {
1258312583
return true;
1258412584
if (isa<LoadInst>(Inst))
1258512585
MakeChange(Inst, const_cast<Use &>(U));
12586-
if (isa<StoreInst>(Inst)) {
12586+
else if (isa<StoreInst>(Inst)) {
1258712587
// We only make changes if the use is the pointer operand.
1258812588
if (U.getOperandNo() == 1)
1258912589
MakeChange(Inst, const_cast<Use &>(U));
12590+
} else if (isa<AtomicRMWInst>(Inst) || isa<AtomicCmpXchgInst>(Inst)) {
12591+
// We only make changes if the use is the pointer operand.
12592+
if (U.getOperandNo() == 0)
12593+
MakeChange(Inst, const_cast<Use &>(U));
1259012594
}
1259112595
return true;
1259212596
};
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -mtriple=amdgcn-amd-amdhsa -passes=amdgpu-attributor -S %s -o - | FileCheck %s
3+
4+
@g1 = protected addrspace(1) externally_initialized global i32 0, align 4
5+
@g2 = protected addrspace(1) externally_initialized global i32 0, align 4
6+
7+
define internal void @can_infer_cmpxchg(ptr %word) {
8+
; CHECK-LABEL: define internal void @can_infer_cmpxchg(
9+
; CHECK-SAME: ptr [[WORD:%.*]]) #[[ATTR0:[0-9]+]] {
10+
; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
11+
; CHECK-NEXT: [[CMPXCHG_0:%.*]] = cmpxchg ptr addrspace(1) [[TMP1]], i32 0, i32 4 monotonic monotonic, align 4
12+
; CHECK-NEXT: [[TMP2:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
13+
; CHECK-NEXT: [[CMPXCHG_1:%.*]] = cmpxchg ptr addrspace(1) [[TMP2]], i32 0, i32 5 acq_rel monotonic, align 4
14+
; CHECK-NEXT: [[TMP3:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
15+
; CHECK-NEXT: [[CMPXCHG_2:%.*]] = cmpxchg ptr addrspace(1) [[TMP3]], i32 0, i32 6 acquire monotonic, align 4
16+
; CHECK-NEXT: [[TMP4:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
17+
; CHECK-NEXT: [[CMPXCHG_3:%.*]] = cmpxchg ptr addrspace(1) [[TMP4]], i32 0, i32 7 release monotonic, align 4
18+
; CHECK-NEXT: [[TMP5:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
19+
; CHECK-NEXT: [[CMPXCHG_4:%.*]] = cmpxchg ptr addrspace(1) [[TMP5]], i32 0, i32 8 seq_cst monotonic, align 4
20+
; CHECK-NEXT: [[TMP6:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
21+
; CHECK-NEXT: [[CMPXCHG_5:%.*]] = cmpxchg weak ptr addrspace(1) [[TMP6]], i32 0, i32 9 seq_cst monotonic, align 4
22+
; CHECK-NEXT: [[TMP7:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
23+
; CHECK-NEXT: [[CMPXCHG_6:%.*]] = cmpxchg volatile ptr addrspace(1) [[TMP7]], i32 0, i32 10 seq_cst monotonic, align 4
24+
; CHECK-NEXT: [[TMP8:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
25+
; CHECK-NEXT: [[CMPXCHG_7:%.*]] = cmpxchg weak volatile ptr addrspace(1) [[TMP8]], i32 0, i32 11 syncscope("singlethread") seq_cst monotonic, align 4
26+
; CHECK-NEXT: ret void
27+
;
28+
%cmpxchg.0 = cmpxchg ptr %word, i32 0, i32 4 monotonic monotonic, align 4
29+
%cmpxchg.1 = cmpxchg ptr %word, i32 0, i32 5 acq_rel monotonic, align 4
30+
%cmpxchg.2 = cmpxchg ptr %word, i32 0, i32 6 acquire monotonic, align 4
31+
%cmpxchg.3 = cmpxchg ptr %word, i32 0, i32 7 release monotonic, align 4
32+
%cmpxchg.4 = cmpxchg ptr %word, i32 0, i32 8 seq_cst monotonic, align 4
33+
%cmpxchg.5 = cmpxchg weak ptr %word, i32 0, i32 9 seq_cst monotonic, align 4
34+
%cmpxchg.6 = cmpxchg volatile ptr %word, i32 0, i32 10 seq_cst monotonic, align 4
35+
%cmpxchg.7 = cmpxchg weak volatile ptr %word, i32 0, i32 11 syncscope("singlethread") seq_cst monotonic, align 4
36+
ret void
37+
}
38+
39+
define internal void @can_not_infer_cmpxchg(ptr %word) {
40+
; CHECK-LABEL: define internal void @can_not_infer_cmpxchg(
41+
; CHECK-SAME: ptr [[WORD:%.*]]) #[[ATTR0]] {
42+
; CHECK-NEXT: [[CMPXCHG_0:%.*]] = cmpxchg ptr [[WORD]], i32 0, i32 4 monotonic monotonic, align 4
43+
; CHECK-NEXT: [[CMPXCHG_1:%.*]] = cmpxchg ptr [[WORD]], i32 0, i32 5 acq_rel monotonic, align 4
44+
; CHECK-NEXT: [[CMPXCHG_2:%.*]] = cmpxchg ptr [[WORD]], i32 0, i32 6 acquire monotonic, align 4
45+
; CHECK-NEXT: [[CMPXCHG_3:%.*]] = cmpxchg ptr [[WORD]], i32 0, i32 7 release monotonic, align 4
46+
; CHECK-NEXT: [[CMPXCHG_4:%.*]] = cmpxchg ptr [[WORD]], i32 0, i32 8 seq_cst monotonic, align 4
47+
; CHECK-NEXT: [[CMPXCHG_5:%.*]] = cmpxchg weak ptr [[WORD]], i32 0, i32 9 seq_cst monotonic, align 4
48+
; CHECK-NEXT: [[CMPXCHG_6:%.*]] = cmpxchg volatile ptr [[WORD]], i32 0, i32 10 seq_cst monotonic, align 4
49+
; CHECK-NEXT: [[CMPXCHG_7:%.*]] = cmpxchg weak volatile ptr [[WORD]], i32 0, i32 11 syncscope("singlethread") seq_cst monotonic, align 4
50+
; CHECK-NEXT: ret void
51+
;
52+
%cmpxchg.0 = cmpxchg ptr %word, i32 0, i32 4 monotonic monotonic, align 4
53+
%cmpxchg.1 = cmpxchg ptr %word, i32 0, i32 5 acq_rel monotonic, align 4
54+
%cmpxchg.2 = cmpxchg ptr %word, i32 0, i32 6 acquire monotonic, align 4
55+
%cmpxchg.3 = cmpxchg ptr %word, i32 0, i32 7 release monotonic, align 4
56+
%cmpxchg.4 = cmpxchg ptr %word, i32 0, i32 8 seq_cst monotonic, align 4
57+
%cmpxchg.5 = cmpxchg weak ptr %word, i32 0, i32 9 seq_cst monotonic, align 4
58+
%cmpxchg.6 = cmpxchg volatile ptr %word, i32 0, i32 10 seq_cst monotonic, align 4
59+
%cmpxchg.7 = cmpxchg weak volatile ptr %word, i32 0, i32 11 syncscope("singlethread") seq_cst monotonic, align 4
60+
ret void
61+
}
62+
63+
define internal void @can_infer_atomicrmw(ptr %word) {
64+
; CHECK-LABEL: define internal void @can_infer_atomicrmw(
65+
; CHECK-SAME: ptr [[WORD:%.*]]) #[[ATTR0]] {
66+
; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
67+
; CHECK-NEXT: [[ATOMICRMW_XCHG:%.*]] = atomicrmw xchg ptr addrspace(1) [[TMP1]], i32 12 monotonic, align 4
68+
; CHECK-NEXT: [[TMP2:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
69+
; CHECK-NEXT: [[ATOMICRMW_ADD:%.*]] = atomicrmw add ptr addrspace(1) [[TMP2]], i32 13 monotonic, align 4
70+
; CHECK-NEXT: [[TMP3:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
71+
; CHECK-NEXT: [[ATOMICRMW_SUB:%.*]] = atomicrmw sub ptr addrspace(1) [[TMP3]], i32 14 monotonic, align 4
72+
; CHECK-NEXT: [[TMP4:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
73+
; CHECK-NEXT: [[ATOMICRMW_AND:%.*]] = atomicrmw and ptr addrspace(1) [[TMP4]], i32 15 monotonic, align 4
74+
; CHECK-NEXT: [[TMP5:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
75+
; CHECK-NEXT: [[ATOMICRMW_NAND:%.*]] = atomicrmw nand ptr addrspace(1) [[TMP5]], i32 16 monotonic, align 4
76+
; CHECK-NEXT: [[TMP6:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
77+
; CHECK-NEXT: [[ATOMICRMW_OR:%.*]] = atomicrmw or ptr addrspace(1) [[TMP6]], i32 17 monotonic, align 4
78+
; CHECK-NEXT: [[TMP7:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
79+
; CHECK-NEXT: [[ATOMICRMW_XOR:%.*]] = atomicrmw xor ptr addrspace(1) [[TMP7]], i32 18 monotonic, align 4
80+
; CHECK-NEXT: [[TMP8:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
81+
; CHECK-NEXT: [[ATOMICRMW_MAX:%.*]] = atomicrmw max ptr addrspace(1) [[TMP8]], i32 19 monotonic, align 4
82+
; CHECK-NEXT: [[TMP9:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
83+
; CHECK-NEXT: [[ATOMICRMW_MIN:%.*]] = atomicrmw volatile min ptr addrspace(1) [[TMP9]], i32 20 monotonic, align 4
84+
; CHECK-NEXT: [[TMP10:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
85+
; CHECK-NEXT: [[ATOMICRMW_UMAX:%.*]] = atomicrmw umax ptr addrspace(1) [[TMP10]], i32 21 syncscope("singlethread") monotonic, align 4
86+
; CHECK-NEXT: [[TMP11:%.*]] = addrspacecast ptr [[WORD]] to ptr addrspace(1)
87+
; CHECK-NEXT: [[ATOMICRMW_UMIN:%.*]] = atomicrmw volatile umin ptr addrspace(1) [[TMP11]], i32 22 syncscope("singlethread") monotonic, align 4
88+
; CHECK-NEXT: ret void
89+
;
90+
%atomicrmw.xchg = atomicrmw xchg ptr %word, i32 12 monotonic, align 4
91+
%atomicrmw.add = atomicrmw add ptr %word, i32 13 monotonic, align 4
92+
%atomicrmw.sub = atomicrmw sub ptr %word, i32 14 monotonic, align 4
93+
%atomicrmw.and = atomicrmw and ptr %word, i32 15 monotonic, align 4
94+
%atomicrmw.nand = atomicrmw nand ptr %word, i32 16 monotonic, align 4
95+
%atomicrmw.or = atomicrmw or ptr %word, i32 17 monotonic, align 4
96+
%atomicrmw.xor = atomicrmw xor ptr %word, i32 18 monotonic, align 4
97+
%atomicrmw.max = atomicrmw max ptr %word, i32 19 monotonic, align 4
98+
%atomicrmw.min = atomicrmw volatile min ptr %word, i32 20 monotonic, align 4
99+
%atomicrmw.umax = atomicrmw umax ptr %word, i32 21 syncscope("singlethread") monotonic, align 4
100+
%atomicrmw.umin = atomicrmw volatile umin ptr %word, i32 22 syncscope("singlethread") monotonic, align 4
101+
ret void
102+
}
103+
104+
define internal void @can_not_infer_atomicrmw(ptr %word) {
105+
; CHECK-LABEL: define internal void @can_not_infer_atomicrmw(
106+
; CHECK-SAME: ptr [[WORD:%.*]]) #[[ATTR0]] {
107+
; CHECK-NEXT: [[ATOMICRMW_XCHG:%.*]] = atomicrmw xchg ptr [[WORD]], i32 12 monotonic, align 4
108+
; CHECK-NEXT: [[ATOMICRMW_ADD:%.*]] = atomicrmw add ptr [[WORD]], i32 13 monotonic, align 4
109+
; CHECK-NEXT: [[ATOMICRMW_SUB:%.*]] = atomicrmw sub ptr [[WORD]], i32 14 monotonic, align 4
110+
; CHECK-NEXT: [[ATOMICRMW_AND:%.*]] = atomicrmw and ptr [[WORD]], i32 15 monotonic, align 4
111+
; CHECK-NEXT: [[ATOMICRMW_NAND:%.*]] = atomicrmw nand ptr [[WORD]], i32 16 monotonic, align 4
112+
; CHECK-NEXT: [[ATOMICRMW_OR:%.*]] = atomicrmw or ptr [[WORD]], i32 17 monotonic, align 4
113+
; CHECK-NEXT: [[ATOMICRMW_XOR:%.*]] = atomicrmw xor ptr [[WORD]], i32 18 monotonic, align 4
114+
; CHECK-NEXT: [[ATOMICRMW_MAX:%.*]] = atomicrmw max ptr [[WORD]], i32 19 monotonic, align 4
115+
; CHECK-NEXT: [[ATOMICRMW_MIN:%.*]] = atomicrmw volatile min ptr [[WORD]], i32 20 monotonic, align 4
116+
; CHECK-NEXT: [[ATOMICRMW_UMAX:%.*]] = atomicrmw umax ptr [[WORD]], i32 21 syncscope("singlethread") monotonic, align 4
117+
; CHECK-NEXT: [[ATOMICRMW_UMIN:%.*]] = atomicrmw volatile umin ptr [[WORD]], i32 22 syncscope("singlethread") monotonic, align 4
118+
; CHECK-NEXT: ret void
119+
;
120+
%atomicrmw.xchg = atomicrmw xchg ptr %word, i32 12 monotonic, align 4
121+
%atomicrmw.add = atomicrmw add ptr %word, i32 13 monotonic, align 4
122+
%atomicrmw.sub = atomicrmw sub ptr %word, i32 14 monotonic, align 4
123+
%atomicrmw.and = atomicrmw and ptr %word, i32 15 monotonic, align 4
124+
%atomicrmw.nand = atomicrmw nand ptr %word, i32 16 monotonic, align 4
125+
%atomicrmw.or = atomicrmw or ptr %word, i32 17 monotonic, align 4
126+
%atomicrmw.xor = atomicrmw xor ptr %word, i32 18 monotonic, align 4
127+
%atomicrmw.max = atomicrmw max ptr %word, i32 19 monotonic, align 4
128+
%atomicrmw.min = atomicrmw volatile min ptr %word, i32 20 monotonic, align 4
129+
%atomicrmw.umax = atomicrmw umax ptr %word, i32 21 syncscope("singlethread") monotonic, align 4
130+
%atomicrmw.umin = atomicrmw volatile umin ptr %word, i32 22 syncscope("singlethread") monotonic, align 4
131+
ret void
132+
}
133+
134+
define void @foo(ptr addrspace(3) %val) {
135+
; CHECK-LABEL: define void @foo(
136+
; CHECK-SAME: ptr addrspace(3) [[VAL:%.*]]) #[[ATTR1:[0-9]+]] {
137+
; CHECK-NEXT: [[VAL_CAST:%.*]] = addrspacecast ptr addrspace(3) [[VAL]] to ptr
138+
; CHECK-NEXT: call void @can_infer_cmpxchg(ptr addrspacecast (ptr addrspace(1) @g1 to ptr))
139+
; CHECK-NEXT: call void @can_infer_cmpxchg(ptr addrspacecast (ptr addrspace(1) @g2 to ptr))
140+
; CHECK-NEXT: call void @can_not_infer_cmpxchg(ptr addrspacecast (ptr addrspace(1) @g1 to ptr))
141+
; CHECK-NEXT: call void @can_not_infer_cmpxchg(ptr addrspacecast (ptr addrspace(1) @g2 to ptr))
142+
; CHECK-NEXT: call void @can_not_infer_cmpxchg(ptr [[VAL_CAST]])
143+
; CHECK-NEXT: call void @can_infer_atomicrmw(ptr addrspacecast (ptr addrspace(1) @g1 to ptr))
144+
; CHECK-NEXT: call void @can_infer_atomicrmw(ptr addrspacecast (ptr addrspace(1) @g2 to ptr))
145+
; CHECK-NEXT: call void @can_not_infer_atomicrmw(ptr addrspacecast (ptr addrspace(1) @g1 to ptr))
146+
; CHECK-NEXT: call void @can_not_infer_atomicrmw(ptr addrspacecast (ptr addrspace(1) @g2 to ptr))
147+
; CHECK-NEXT: call void @can_not_infer_atomicrmw(ptr [[VAL_CAST]])
148+
; CHECK-NEXT: ret void
149+
;
150+
%g1.cast = addrspacecast ptr addrspace(1) @g1 to ptr
151+
%g2.cast = addrspacecast ptr addrspace(1) @g2 to ptr
152+
%val.cast = addrspacecast ptr addrspace(3) %val to ptr
153+
call void @can_infer_cmpxchg(ptr %g1.cast)
154+
call void @can_infer_cmpxchg(ptr %g2.cast)
155+
call void @can_not_infer_cmpxchg(ptr %g1.cast)
156+
call void @can_not_infer_cmpxchg(ptr %g2.cast)
157+
call void @can_not_infer_cmpxchg(ptr %val.cast)
158+
call void @can_infer_atomicrmw(ptr %g1.cast)
159+
call void @can_infer_atomicrmw(ptr %g2.cast)
160+
call void @can_not_infer_atomicrmw(ptr %g1.cast)
161+
call void @can_not_infer_atomicrmw(ptr %g2.cast)
162+
call void @can_not_infer_atomicrmw(ptr %val.cast)
163+
ret void
164+
}

0 commit comments

Comments
 (0)