Skip to content

Commit c30c461

Browse files
committed
[RISCV][test] Add tests for atomic compare exchange + branch on result
Due to the late expansion of the compare exchange sequences, there's scope for improving codegen by folding the branches into the cmpxchg loop (avoiding a branch-to-branch).
1 parent 7a2a640 commit c30c461

File tree

1 file changed

+252
-0
lines changed

1 file changed

+252
-0
lines changed
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -mtriple=riscv32 -mattr=+a -verify-machineinstrs < %s \
3+
; RUN: | FileCheck -check-prefixes=CHECK,RV32IA %s
4+
; RUN: llc -mtriple=riscv64 -mattr=+a -verify-machineinstrs < %s \
5+
; RUN: | FileCheck -check-prefixes=CHECK,RV64IA %s
6+
7+
; Test cmpxchg followed by a branch on the cmpxchg success value to see if the
8+
; branch is folded into the cmpxchg expansion.
9+
10+
define void @cmpxchg_and_branch1(i32* %ptr, i32 signext %cmp, i32 signext %val) nounwind {
11+
; CHECK-LABEL: cmpxchg_and_branch1:
12+
; CHECK: # %bb.0: # %entry
13+
; CHECK-NEXT: .LBB0_1: # %do_cmpxchg
14+
; CHECK-NEXT: # =>This Loop Header: Depth=1
15+
; CHECK-NEXT: # Child Loop BB0_3 Depth 2
16+
; CHECK-NEXT: .LBB0_3: # %do_cmpxchg
17+
; CHECK-NEXT: # Parent Loop BB0_1 Depth=1
18+
; CHECK-NEXT: # => This Inner Loop Header: Depth=2
19+
; CHECK-NEXT: lr.w.aqrl a3, (a0)
20+
; CHECK-NEXT: bne a3, a1, .LBB0_5
21+
; CHECK-NEXT: # %bb.4: # %do_cmpxchg
22+
; CHECK-NEXT: # in Loop: Header=BB0_3 Depth=2
23+
; CHECK-NEXT: sc.w.aqrl a4, a2, (a0)
24+
; CHECK-NEXT: bnez a4, .LBB0_3
25+
; CHECK-NEXT: .LBB0_5: # %do_cmpxchg
26+
; CHECK-NEXT: # in Loop: Header=BB0_1 Depth=1
27+
; CHECK-NEXT: bne a3, a1, .LBB0_1
28+
; CHECK-NEXT: # %bb.2: # %exit
29+
; CHECK-NEXT: ret
30+
entry:
31+
br label %do_cmpxchg
32+
do_cmpxchg:
33+
%0 = cmpxchg i32* %ptr, i32 %cmp, i32 %val seq_cst seq_cst
34+
%1 = extractvalue { i32, i1 } %0, 1
35+
br i1 %1, label %exit, label %do_cmpxchg
36+
exit:
37+
ret void
38+
}
39+
40+
define void @cmpxchg_and_branch2(i32* %ptr, i32 signext %cmp, i32 signext %val) nounwind {
41+
; CHECK-LABEL: cmpxchg_and_branch2:
42+
; CHECK: # %bb.0: # %entry
43+
; CHECK-NEXT: .LBB1_1: # %do_cmpxchg
44+
; CHECK-NEXT: # =>This Loop Header: Depth=1
45+
; CHECK-NEXT: # Child Loop BB1_3 Depth 2
46+
; CHECK-NEXT: .LBB1_3: # %do_cmpxchg
47+
; CHECK-NEXT: # Parent Loop BB1_1 Depth=1
48+
; CHECK-NEXT: # => This Inner Loop Header: Depth=2
49+
; CHECK-NEXT: lr.w.aqrl a3, (a0)
50+
; CHECK-NEXT: bne a3, a1, .LBB1_5
51+
; CHECK-NEXT: # %bb.4: # %do_cmpxchg
52+
; CHECK-NEXT: # in Loop: Header=BB1_3 Depth=2
53+
; CHECK-NEXT: sc.w.aqrl a4, a2, (a0)
54+
; CHECK-NEXT: bnez a4, .LBB1_3
55+
; CHECK-NEXT: .LBB1_5: # %do_cmpxchg
56+
; CHECK-NEXT: # in Loop: Header=BB1_1 Depth=1
57+
; CHECK-NEXT: beq a3, a1, .LBB1_1
58+
; CHECK-NEXT: # %bb.2: # %exit
59+
; CHECK-NEXT: ret
60+
entry:
61+
br label %do_cmpxchg
62+
do_cmpxchg:
63+
%0 = cmpxchg i32* %ptr, i32 %cmp, i32 %val seq_cst seq_cst
64+
%1 = extractvalue { i32, i1 } %0, 1
65+
br i1 %1, label %do_cmpxchg, label %exit
66+
exit:
67+
ret void
68+
}
69+
70+
define void @cmpxchg_masked_and_branch1(i8* %ptr, i8 signext %cmp, i8 signext %val) nounwind {
71+
; RV32IA-LABEL: cmpxchg_masked_and_branch1:
72+
; RV32IA: # %bb.0: # %entry
73+
; RV32IA-NEXT: andi a3, a0, -4
74+
; RV32IA-NEXT: slli a4, a0, 3
75+
; RV32IA-NEXT: li a0, 255
76+
; RV32IA-NEXT: sll a0, a0, a4
77+
; RV32IA-NEXT: andi a1, a1, 255
78+
; RV32IA-NEXT: sll a1, a1, a4
79+
; RV32IA-NEXT: andi a2, a2, 255
80+
; RV32IA-NEXT: sll a2, a2, a4
81+
; RV32IA-NEXT: .LBB2_1: # %do_cmpxchg
82+
; RV32IA-NEXT: # =>This Loop Header: Depth=1
83+
; RV32IA-NEXT: # Child Loop BB2_3 Depth 2
84+
; RV32IA-NEXT: .LBB2_3: # %do_cmpxchg
85+
; RV32IA-NEXT: # Parent Loop BB2_1 Depth=1
86+
; RV32IA-NEXT: # => This Inner Loop Header: Depth=2
87+
; RV32IA-NEXT: lr.w.aqrl a4, (a3)
88+
; RV32IA-NEXT: and a5, a4, a0
89+
; RV32IA-NEXT: bne a5, a1, .LBB2_5
90+
; RV32IA-NEXT: # %bb.4: # %do_cmpxchg
91+
; RV32IA-NEXT: # in Loop: Header=BB2_3 Depth=2
92+
; RV32IA-NEXT: xor a5, a4, a2
93+
; RV32IA-NEXT: and a5, a5, a0
94+
; RV32IA-NEXT: xor a5, a4, a5
95+
; RV32IA-NEXT: sc.w.aqrl a5, a5, (a3)
96+
; RV32IA-NEXT: bnez a5, .LBB2_3
97+
; RV32IA-NEXT: .LBB2_5: # %do_cmpxchg
98+
; RV32IA-NEXT: # in Loop: Header=BB2_1 Depth=1
99+
; RV32IA-NEXT: and a4, a4, a0
100+
; RV32IA-NEXT: bne a1, a4, .LBB2_1
101+
; RV32IA-NEXT: # %bb.2: # %exit
102+
; RV32IA-NEXT: ret
103+
;
104+
; RV64IA-LABEL: cmpxchg_masked_and_branch1:
105+
; RV64IA: # %bb.0: # %entry
106+
; RV64IA-NEXT: andi a3, a0, -4
107+
; RV64IA-NEXT: slliw a4, a0, 3
108+
; RV64IA-NEXT: li a0, 255
109+
; RV64IA-NEXT: sllw a0, a0, a4
110+
; RV64IA-NEXT: andi a1, a1, 255
111+
; RV64IA-NEXT: sllw a1, a1, a4
112+
; RV64IA-NEXT: andi a2, a2, 255
113+
; RV64IA-NEXT: sllw a2, a2, a4
114+
; RV64IA-NEXT: .LBB2_1: # %do_cmpxchg
115+
; RV64IA-NEXT: # =>This Loop Header: Depth=1
116+
; RV64IA-NEXT: # Child Loop BB2_3 Depth 2
117+
; RV64IA-NEXT: .LBB2_3: # %do_cmpxchg
118+
; RV64IA-NEXT: # Parent Loop BB2_1 Depth=1
119+
; RV64IA-NEXT: # => This Inner Loop Header: Depth=2
120+
; RV64IA-NEXT: lr.w.aqrl a4, (a3)
121+
; RV64IA-NEXT: and a5, a4, a0
122+
; RV64IA-NEXT: bne a5, a1, .LBB2_5
123+
; RV64IA-NEXT: # %bb.4: # %do_cmpxchg
124+
; RV64IA-NEXT: # in Loop: Header=BB2_3 Depth=2
125+
; RV64IA-NEXT: xor a5, a4, a2
126+
; RV64IA-NEXT: and a5, a5, a0
127+
; RV64IA-NEXT: xor a5, a4, a5
128+
; RV64IA-NEXT: sc.w.aqrl a5, a5, (a3)
129+
; RV64IA-NEXT: bnez a5, .LBB2_3
130+
; RV64IA-NEXT: .LBB2_5: # %do_cmpxchg
131+
; RV64IA-NEXT: # in Loop: Header=BB2_1 Depth=1
132+
; RV64IA-NEXT: and a4, a4, a0
133+
; RV64IA-NEXT: sext.w a4, a4
134+
; RV64IA-NEXT: bne a1, a4, .LBB2_1
135+
; RV64IA-NEXT: # %bb.2: # %exit
136+
; RV64IA-NEXT: ret
137+
entry:
138+
br label %do_cmpxchg
139+
do_cmpxchg:
140+
%0 = cmpxchg i8* %ptr, i8 %cmp, i8 %val seq_cst seq_cst
141+
%1 = extractvalue { i8, i1 } %0, 1
142+
br i1 %1, label %exit, label %do_cmpxchg
143+
exit:
144+
ret void
145+
}
146+
147+
define void @cmpxchg_masked_and_branch2(i8* %ptr, i8 signext %cmp, i8 signext %val) nounwind {
148+
; RV32IA-LABEL: cmpxchg_masked_and_branch2:
149+
; RV32IA: # %bb.0: # %entry
150+
; RV32IA-NEXT: andi a3, a0, -4
151+
; RV32IA-NEXT: slli a4, a0, 3
152+
; RV32IA-NEXT: li a0, 255
153+
; RV32IA-NEXT: sll a0, a0, a4
154+
; RV32IA-NEXT: andi a1, a1, 255
155+
; RV32IA-NEXT: sll a1, a1, a4
156+
; RV32IA-NEXT: andi a2, a2, 255
157+
; RV32IA-NEXT: sll a2, a2, a4
158+
; RV32IA-NEXT: .LBB3_1: # %do_cmpxchg
159+
; RV32IA-NEXT: # =>This Loop Header: Depth=1
160+
; RV32IA-NEXT: # Child Loop BB3_3 Depth 2
161+
; RV32IA-NEXT: .LBB3_3: # %do_cmpxchg
162+
; RV32IA-NEXT: # Parent Loop BB3_1 Depth=1
163+
; RV32IA-NEXT: # => This Inner Loop Header: Depth=2
164+
; RV32IA-NEXT: lr.w.aqrl a4, (a3)
165+
; RV32IA-NEXT: and a5, a4, a0
166+
; RV32IA-NEXT: bne a5, a1, .LBB3_5
167+
; RV32IA-NEXT: # %bb.4: # %do_cmpxchg
168+
; RV32IA-NEXT: # in Loop: Header=BB3_3 Depth=2
169+
; RV32IA-NEXT: xor a5, a4, a2
170+
; RV32IA-NEXT: and a5, a5, a0
171+
; RV32IA-NEXT: xor a5, a4, a5
172+
; RV32IA-NEXT: sc.w.aqrl a5, a5, (a3)
173+
; RV32IA-NEXT: bnez a5, .LBB3_3
174+
; RV32IA-NEXT: .LBB3_5: # %do_cmpxchg
175+
; RV32IA-NEXT: # in Loop: Header=BB3_1 Depth=1
176+
; RV32IA-NEXT: and a4, a4, a0
177+
; RV32IA-NEXT: beq a1, a4, .LBB3_1
178+
; RV32IA-NEXT: # %bb.2: # %exit
179+
; RV32IA-NEXT: ret
180+
;
181+
; RV64IA-LABEL: cmpxchg_masked_and_branch2:
182+
; RV64IA: # %bb.0: # %entry
183+
; RV64IA-NEXT: andi a3, a0, -4
184+
; RV64IA-NEXT: slliw a4, a0, 3
185+
; RV64IA-NEXT: li a0, 255
186+
; RV64IA-NEXT: sllw a0, a0, a4
187+
; RV64IA-NEXT: andi a1, a1, 255
188+
; RV64IA-NEXT: sllw a1, a1, a4
189+
; RV64IA-NEXT: andi a2, a2, 255
190+
; RV64IA-NEXT: sllw a2, a2, a4
191+
; RV64IA-NEXT: .LBB3_1: # %do_cmpxchg
192+
; RV64IA-NEXT: # =>This Loop Header: Depth=1
193+
; RV64IA-NEXT: # Child Loop BB3_3 Depth 2
194+
; RV64IA-NEXT: .LBB3_3: # %do_cmpxchg
195+
; RV64IA-NEXT: # Parent Loop BB3_1 Depth=1
196+
; RV64IA-NEXT: # => This Inner Loop Header: Depth=2
197+
; RV64IA-NEXT: lr.w.aqrl a4, (a3)
198+
; RV64IA-NEXT: and a5, a4, a0
199+
; RV64IA-NEXT: bne a5, a1, .LBB3_5
200+
; RV64IA-NEXT: # %bb.4: # %do_cmpxchg
201+
; RV64IA-NEXT: # in Loop: Header=BB3_3 Depth=2
202+
; RV64IA-NEXT: xor a5, a4, a2
203+
; RV64IA-NEXT: and a5, a5, a0
204+
; RV64IA-NEXT: xor a5, a4, a5
205+
; RV64IA-NEXT: sc.w.aqrl a5, a5, (a3)
206+
; RV64IA-NEXT: bnez a5, .LBB3_3
207+
; RV64IA-NEXT: .LBB3_5: # %do_cmpxchg
208+
; RV64IA-NEXT: # in Loop: Header=BB3_1 Depth=1
209+
; RV64IA-NEXT: and a4, a4, a0
210+
; RV64IA-NEXT: sext.w a4, a4
211+
; RV64IA-NEXT: beq a1, a4, .LBB3_1
212+
; RV64IA-NEXT: # %bb.2: # %exit
213+
; RV64IA-NEXT: ret
214+
entry:
215+
br label %do_cmpxchg
216+
do_cmpxchg:
217+
%0 = cmpxchg i8* %ptr, i8 %cmp, i8 %val seq_cst seq_cst
218+
%1 = extractvalue { i8, i1 } %0, 1
219+
br i1 %1, label %do_cmpxchg, label %exit
220+
exit:
221+
ret void
222+
}
223+
224+
define void @cmpxchg_and_irrelevant_branch(i32* %ptr, i32 signext %cmp, i32 signext %val, i1 zeroext %bool) nounwind {
225+
; CHECK-LABEL: cmpxchg_and_irrelevant_branch:
226+
; CHECK: # %bb.0: # %entry
227+
; CHECK-NEXT: .LBB4_1: # %do_cmpxchg
228+
; CHECK-NEXT: # =>This Loop Header: Depth=1
229+
; CHECK-NEXT: # Child Loop BB4_3 Depth 2
230+
; CHECK-NEXT: .LBB4_3: # %do_cmpxchg
231+
; CHECK-NEXT: # Parent Loop BB4_1 Depth=1
232+
; CHECK-NEXT: # => This Inner Loop Header: Depth=2
233+
; CHECK-NEXT: lr.w.aqrl a4, (a0)
234+
; CHECK-NEXT: bne a4, a1, .LBB4_5
235+
; CHECK-NEXT: # %bb.4: # %do_cmpxchg
236+
; CHECK-NEXT: # in Loop: Header=BB4_3 Depth=2
237+
; CHECK-NEXT: sc.w.aqrl a5, a2, (a0)
238+
; CHECK-NEXT: bnez a5, .LBB4_3
239+
; CHECK-NEXT: .LBB4_5: # %do_cmpxchg
240+
; CHECK-NEXT: # in Loop: Header=BB4_1 Depth=1
241+
; CHECK-NEXT: beqz a3, .LBB4_1
242+
; CHECK-NEXT: # %bb.2: # %exit
243+
; CHECK-NEXT: ret
244+
entry:
245+
br label %do_cmpxchg
246+
do_cmpxchg:
247+
%0 = cmpxchg i32* %ptr, i32 %cmp, i32 %val seq_cst seq_cst
248+
%1 = extractvalue { i32, i1 } %0, 1
249+
br i1 %bool, label %exit, label %do_cmpxchg
250+
exit:
251+
ret void
252+
}

0 commit comments

Comments
 (0)