1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s
4 %struct.obj = type { i64 }
6 define dso_local void @_Z7releaseP3obj(ptr nocapture %o) nounwind uwtable ssp {
7 ; CHECK-LABEL: _Z7releaseP3obj:
8 ; CHECK: # %bb.0: # %entry
9 ; CHECK-NEXT: decq (%rdi)
10 ; CHECK-NEXT: je .LBB0_2
11 ; CHECK-NEXT: # %bb.1: # %return
13 ; CHECK-NEXT: .LBB0_2: # %if.end
14 ; CHECK-NEXT: jmp free # TAILCALL
16 %0 = load i64, ptr %o, align 8
18 store i64 %dec, ptr %o, align 8
19 %tobool = icmp eq i64 %dec, 0
20 br i1 %tobool, label %if.end, label %return
22 if.end: ; preds = %entry
23 tail call void @free(ptr %o)
26 return: ; preds = %entry, %if.end
30 @c = common dso_local global i64 0, align 8
31 @a = common dso_local global i32 0, align 4
32 @.str = private unnamed_addr constant [5 x i8] c"%ld\0A\00", align 1
33 @b = common dso_local global i32 0, align 4
35 define dso_local i32 @test() nounwind uwtable ssp {
37 ; CHECK: # %bb.0: # %entry
38 ; CHECK-NEXT: pushq %rax
39 ; CHECK-NEXT: .cfi_def_cfa_offset 16
40 ; CHECK-NEXT: movq c(%rip), %rsi
41 ; CHECK-NEXT: xorl %eax, %eax
42 ; CHECK-NEXT: decq %rsi
43 ; CHECK-NEXT: movq %rsi, c(%rip)
44 ; CHECK-NEXT: setne %al
45 ; CHECK-NEXT: movl %eax, a(%rip)
46 ; CHECK-NEXT: movl $.L.str, %edi
47 ; CHECK-NEXT: xorl %eax, %eax
48 ; CHECK-NEXT: callq printf@PLT
49 ; CHECK-NEXT: xorl %eax, %eax
50 ; CHECK-NEXT: popq %rcx
51 ; CHECK-NEXT: .cfi_def_cfa_offset 8
54 %0 = load i64, ptr @c, align 8
55 %dec.i = add nsw i64 %0, -1
56 store i64 %dec.i, ptr @c, align 8
57 %tobool.i = icmp ne i64 %dec.i, 0
58 %lor.ext.i = zext i1 %tobool.i to i32
59 store i32 %lor.ext.i, ptr @a, align 4
60 %call = tail call i32 (ptr, ...) @printf(ptr @.str, i64 %dec.i) nounwind
64 define dso_local i32 @test2() nounwind uwtable ssp {
66 ; CHECK: # %bb.0: # %entry
67 ; CHECK-NEXT: pushq %rax
68 ; CHECK-NEXT: .cfi_def_cfa_offset 16
69 ; CHECK-NEXT: movq c(%rip), %rsi
70 ; CHECK-NEXT: xorl %eax, %eax
71 ; CHECK-NEXT: addq $-1, %rsi
72 ; CHECK-NEXT: setb %al
73 ; CHECK-NEXT: movq %rsi, c(%rip)
74 ; CHECK-NEXT: movl %eax, a(%rip)
75 ; CHECK-NEXT: movl $.L.str, %edi
76 ; CHECK-NEXT: xorl %eax, %eax
77 ; CHECK-NEXT: callq printf@PLT
78 ; CHECK-NEXT: xorl %eax, %eax
79 ; CHECK-NEXT: popq %rcx
80 ; CHECK-NEXT: .cfi_def_cfa_offset 8
83 %0 = load i64, ptr @c, align 8
84 %dec.i = add nsw i64 %0, -1
85 store i64 %dec.i, ptr @c, align 8
86 %tobool.i = icmp ne i64 %0, 0
87 %lor.ext.i = zext i1 %tobool.i to i32
88 store i32 %lor.ext.i, ptr @a, align 4
89 %call = tail call i32 (ptr, ...) @printf(ptr @.str, i64 %dec.i) nounwind
93 declare i32 @printf(ptr nocapture, ...) nounwind
95 declare dso_local void @free(ptr nocapture) nounwind
97 %struct.obj2 = type { i64, i32, i16, i8 }
99 declare dso_local void @other(ptr ) nounwind;
101 define dso_local void @example_dec(ptr %o) nounwind uwtable ssp {
103 ; CHECK-LABEL: example_dec:
104 ; CHECK: # %bb.0: # %entry
105 ; CHECK-NEXT: decq (%rdi)
106 ; CHECK-NEXT: jne .LBB3_4
107 ; CHECK-NEXT: # %bb.1: # %if.end
108 ; CHECK-NEXT: decl 8(%rdi)
109 ; CHECK-NEXT: jne .LBB3_4
110 ; CHECK-NEXT: # %bb.2: # %if.end1
111 ; CHECK-NEXT: decw 12(%rdi)
112 ; CHECK-NEXT: jne .LBB3_4
113 ; CHECK-NEXT: # %bb.3: # %if.end2
114 ; CHECK-NEXT: decb 14(%rdi)
115 ; CHECK-NEXT: je .LBB3_5
116 ; CHECK-NEXT: .LBB3_4: # %return
118 ; CHECK-NEXT: .LBB3_5: # %if.end4
119 ; CHECK-NEXT: jmp other # TAILCALL
121 %0 = load i64, ptr %o, align 8
122 %dec = add i64 %0, -1
123 store i64 %dec, ptr %o, align 8
124 %tobool = icmp eq i64 %dec, 0
125 br i1 %tobool, label %if.end, label %return
129 %s32 = getelementptr inbounds %struct.obj2, ptr %o, i64 0, i32 1
130 %1 = load i32, ptr %s32, align 4
131 %dec1 = add i32 %1, -1
132 store i32 %dec1, ptr %s32, align 4
133 %tobool2 = icmp eq i32 %dec1, 0
134 br i1 %tobool2, label %if.end1, label %return
138 %s16 = getelementptr inbounds %struct.obj2, ptr %o, i64 0, i32 2
139 %2 = load i16, ptr %s16, align 2
140 %dec2 = add i16 %2, -1
141 store i16 %dec2, ptr %s16, align 2
142 %tobool3 = icmp eq i16 %dec2, 0
143 br i1 %tobool3, label %if.end2, label %return
147 %s8 = getelementptr inbounds %struct.obj2, ptr %o, i64 0, i32 3
148 %3 = load i8, ptr %s8
149 %dec3 = add i8 %3, -1
150 store i8 %dec3, ptr %s8
151 %tobool4 = icmp eq i8 %dec3, 0
152 br i1 %tobool4, label %if.end4, label %return
155 tail call void @other(ptr %o) nounwind
158 return: ; preds = %if.end4, %if.end, %entry
162 define dso_local void @example_inc(ptr %o) nounwind uwtable ssp {
164 ; CHECK-LABEL: example_inc:
165 ; CHECK: # %bb.0: # %entry
166 ; CHECK-NEXT: incq (%rdi)
167 ; CHECK-NEXT: jne .LBB4_4
168 ; CHECK-NEXT: # %bb.1: # %if.end
169 ; CHECK-NEXT: incl 8(%rdi)
170 ; CHECK-NEXT: jne .LBB4_4
171 ; CHECK-NEXT: # %bb.2: # %if.end1
172 ; CHECK-NEXT: incw 12(%rdi)
173 ; CHECK-NEXT: jne .LBB4_4
174 ; CHECK-NEXT: # %bb.3: # %if.end2
175 ; CHECK-NEXT: incb 14(%rdi)
176 ; CHECK-NEXT: jne .LBB4_4
177 ; CHECK-NEXT: # %bb.5: # %if.end4
178 ; CHECK-NEXT: jmp other # TAILCALL
179 ; CHECK-NEXT: .LBB4_4: # %return
182 %0 = load i64, ptr %o, align 8
184 store i64 %inc, ptr %o, align 8
185 %tobool = icmp eq i64 %inc, 0
186 br i1 %tobool, label %if.end, label %return
190 %s32 = getelementptr inbounds %struct.obj2, ptr %o, i64 0, i32 1
191 %1 = load i32, ptr %s32, align 4
192 %inc1 = add i32 %1, 1
193 store i32 %inc1, ptr %s32, align 4
194 %tobool2 = icmp eq i32 %inc1, 0
195 br i1 %tobool2, label %if.end1, label %return
199 %s16 = getelementptr inbounds %struct.obj2, ptr %o, i64 0, i32 2
200 %2 = load i16, ptr %s16, align 2
201 %inc2 = add i16 %2, 1
202 store i16 %inc2, ptr %s16, align 2
203 %tobool3 = icmp eq i16 %inc2, 0
204 br i1 %tobool3, label %if.end2, label %return
208 %s8 = getelementptr inbounds %struct.obj2, ptr %o, i64 0, i32 3
209 %3 = load i8, ptr %s8
211 store i8 %inc3, ptr %s8
212 %tobool4 = icmp eq i8 %inc3, 0
213 br i1 %tobool4, label %if.end4, label %return
216 tail call void @other(ptr %o) nounwind
223 ; Deal with TokenFactor chain
225 @foo = external dso_local global ptr, align 8
227 define dso_local void @test3() nounwind ssp {
228 ; CHECK-LABEL: test3:
229 ; CHECK: # %bb.0: # %entry
230 ; CHECK-NEXT: movq foo(%rip), %rax
231 ; CHECK-NEXT: decq 16(%rax)
232 ; CHECK-NEXT: je .LBB5_2
233 ; CHECK-NEXT: # %bb.1: # %if.end
235 ; CHECK-NEXT: .LBB5_2: # %if.then
236 ; CHECK-NEXT: jmp baz # TAILCALL
238 %0 = load ptr, ptr @foo, align 8
239 %arrayidx = getelementptr inbounds i64, ptr %0, i64 2
240 %1 = load i64, ptr %arrayidx, align 8
241 %dec = add i64 %1, -1
242 store i64 %dec, ptr %arrayidx, align 8
243 %cmp = icmp eq i64 %dec, 0
244 br i1 %cmp, label %if.then, label %if.end
247 tail call void @baz() nounwind
254 declare dso_local void @baz()
256 ; Avoid creating a cycle in the DAG which would trigger an assert in the
260 @x = external dso_local global i32, align 4
261 @y = external dso_local global i32, align 4
262 @z = external dso_local global i32, align 4
264 define dso_local void @test4() nounwind uwtable ssp {
265 ; CHECK-LABEL: test4:
266 ; CHECK: # %bb.0: # %entry
267 ; CHECK-NEXT: xorl %eax, %eax
268 ; CHECK-NEXT: decl y(%rip)
269 ; CHECK-NEXT: je .LBB6_2
270 ; CHECK-NEXT: # %bb.1: # %entry
271 ; CHECK-NEXT: movl x(%rip), %eax
272 ; CHECK-NEXT: .LBB6_2: # %entry
273 ; CHECK-NEXT: movl %eax, z(%rip)
276 %0 = load i32, ptr @x, align 4
277 %1 = load i32, ptr @y, align 4
278 %dec = add nsw i32 %1, -1
279 store i32 %dec, ptr @y, align 4
280 %tobool.i = icmp ne i32 %dec, 0
281 %cond.i = select i1 %tobool.i, i32 %0, i32 0
282 store i32 %cond.i, ptr @z, align 4