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 free # TAILCALL
11 ; CHECK-NEXT: # %bb.1: # %return
14 %0 = load i64, ptr %o, align 8
16 store i64 %dec, ptr %o, align 8
17 %tobool = icmp eq i64 %dec, 0
18 br i1 %tobool, label %if.end, label %return
20 if.end: ; preds = %entry
21 tail call void @free(ptr %o)
24 return: ; preds = %entry, %if.end
28 @c = common dso_local global i64 0, align 8
29 @a = common dso_local global i32 0, align 4
30 @.str = private unnamed_addr constant [5 x i8] c"%ld\0A\00", align 1
31 @b = common dso_local global i32 0, align 4
33 define dso_local i32 @test() nounwind uwtable ssp {
35 ; CHECK: # %bb.0: # %entry
36 ; CHECK-NEXT: pushq %rax
37 ; CHECK-NEXT: .cfi_def_cfa_offset 16
38 ; CHECK-NEXT: movq c(%rip), %rsi
39 ; CHECK-NEXT: xorl %eax, %eax
40 ; CHECK-NEXT: decq %rsi
41 ; CHECK-NEXT: movq %rsi, c(%rip)
42 ; CHECK-NEXT: setne %al
43 ; CHECK-NEXT: movl %eax, a(%rip)
44 ; CHECK-NEXT: movl $.L.str, %edi
45 ; CHECK-NEXT: xorl %eax, %eax
46 ; CHECK-NEXT: callq printf@PLT
47 ; CHECK-NEXT: xorl %eax, %eax
48 ; CHECK-NEXT: popq %rcx
49 ; CHECK-NEXT: .cfi_def_cfa_offset 8
52 %0 = load i64, ptr @c, align 8
53 %dec.i = add nsw i64 %0, -1
54 store i64 %dec.i, ptr @c, align 8
55 %tobool.i = icmp ne i64 %dec.i, 0
56 %lor.ext.i = zext i1 %tobool.i to i32
57 store i32 %lor.ext.i, ptr @a, align 4
58 %call = tail call i32 (ptr, ...) @printf(ptr @.str, i64 %dec.i) nounwind
62 define dso_local i32 @test2() nounwind uwtable ssp {
64 ; CHECK: # %bb.0: # %entry
65 ; CHECK-NEXT: pushq %rax
66 ; CHECK-NEXT: .cfi_def_cfa_offset 16
67 ; CHECK-NEXT: movq c(%rip), %rsi
68 ; CHECK-NEXT: xorl %eax, %eax
69 ; CHECK-NEXT: addq $-1, %rsi
70 ; CHECK-NEXT: setb %al
71 ; CHECK-NEXT: movq %rsi, c(%rip)
72 ; CHECK-NEXT: movl %eax, a(%rip)
73 ; CHECK-NEXT: movl $.L.str, %edi
74 ; CHECK-NEXT: xorl %eax, %eax
75 ; CHECK-NEXT: callq printf@PLT
76 ; CHECK-NEXT: xorl %eax, %eax
77 ; CHECK-NEXT: popq %rcx
78 ; CHECK-NEXT: .cfi_def_cfa_offset 8
81 %0 = load i64, ptr @c, align 8
82 %dec.i = add nsw i64 %0, -1
83 store i64 %dec.i, ptr @c, align 8
84 %tobool.i = icmp ne i64 %0, 0
85 %lor.ext.i = zext i1 %tobool.i to i32
86 store i32 %lor.ext.i, ptr @a, align 4
87 %call = tail call i32 (ptr, ...) @printf(ptr @.str, i64 %dec.i) nounwind
91 declare i32 @printf(ptr nocapture, ...) nounwind
93 declare dso_local void @free(ptr nocapture) nounwind
95 %struct.obj2 = type { i64, i32, i16, i8 }
97 declare dso_local void @other(ptr ) nounwind;
99 define dso_local void @example_dec(ptr %o) nounwind uwtable ssp {
101 ; CHECK-LABEL: example_dec:
102 ; CHECK: # %bb.0: # %entry
103 ; CHECK-NEXT: decq (%rdi)
104 ; CHECK-NEXT: jne .LBB3_4
105 ; CHECK-NEXT: # %bb.1: # %if.end
106 ; CHECK-NEXT: decl 8(%rdi)
107 ; CHECK-NEXT: jne .LBB3_4
108 ; CHECK-NEXT: # %bb.2: # %if.end1
109 ; CHECK-NEXT: decw 12(%rdi)
110 ; CHECK-NEXT: jne .LBB3_4
111 ; CHECK-NEXT: # %bb.3: # %if.end2
112 ; CHECK-NEXT: decb 14(%rdi)
113 ; CHECK-NEXT: je other # TAILCALL
114 ; CHECK-NEXT: .LBB3_4: # %return
117 %0 = load i64, ptr %o, align 8
118 %dec = add i64 %0, -1
119 store i64 %dec, ptr %o, align 8
120 %tobool = icmp eq i64 %dec, 0
121 br i1 %tobool, label %if.end, label %return
125 %s32 = getelementptr inbounds %struct.obj2, ptr %o, i64 0, i32 1
126 %1 = load i32, ptr %s32, align 4
127 %dec1 = add i32 %1, -1
128 store i32 %dec1, ptr %s32, align 4
129 %tobool2 = icmp eq i32 %dec1, 0
130 br i1 %tobool2, label %if.end1, label %return
134 %s16 = getelementptr inbounds %struct.obj2, ptr %o, i64 0, i32 2
135 %2 = load i16, ptr %s16, align 2
136 %dec2 = add i16 %2, -1
137 store i16 %dec2, ptr %s16, align 2
138 %tobool3 = icmp eq i16 %dec2, 0
139 br i1 %tobool3, label %if.end2, label %return
143 %s8 = getelementptr inbounds %struct.obj2, ptr %o, i64 0, i32 3
144 %3 = load i8, ptr %s8
145 %dec3 = add i8 %3, -1
146 store i8 %dec3, ptr %s8
147 %tobool4 = icmp eq i8 %dec3, 0
148 br i1 %tobool4, label %if.end4, label %return
151 tail call void @other(ptr %o) nounwind
154 return: ; preds = %if.end4, %if.end, %entry
158 define dso_local void @example_inc(ptr %o) nounwind uwtable ssp {
160 ; CHECK-LABEL: example_inc:
161 ; CHECK: # %bb.0: # %entry
162 ; CHECK-NEXT: incq (%rdi)
163 ; CHECK-NEXT: jne .LBB4_4
164 ; CHECK-NEXT: # %bb.1: # %if.end
165 ; CHECK-NEXT: incl 8(%rdi)
166 ; CHECK-NEXT: jne .LBB4_4
167 ; CHECK-NEXT: # %bb.2: # %if.end1
168 ; CHECK-NEXT: incw 12(%rdi)
169 ; CHECK-NEXT: jne .LBB4_4
170 ; CHECK-NEXT: # %bb.3: # %if.end2
171 ; CHECK-NEXT: incb 14(%rdi)
172 ; CHECK-NEXT: je other # TAILCALL
173 ; CHECK-NEXT: .LBB4_4: # %return
176 %0 = load i64, ptr %o, align 8
178 store i64 %inc, ptr %o, align 8
179 %tobool = icmp eq i64 %inc, 0
180 br i1 %tobool, label %if.end, label %return
184 %s32 = getelementptr inbounds %struct.obj2, ptr %o, i64 0, i32 1
185 %1 = load i32, ptr %s32, align 4
186 %inc1 = add i32 %1, 1
187 store i32 %inc1, ptr %s32, align 4
188 %tobool2 = icmp eq i32 %inc1, 0
189 br i1 %tobool2, label %if.end1, label %return
193 %s16 = getelementptr inbounds %struct.obj2, ptr %o, i64 0, i32 2
194 %2 = load i16, ptr %s16, align 2
195 %inc2 = add i16 %2, 1
196 store i16 %inc2, ptr %s16, align 2
197 %tobool3 = icmp eq i16 %inc2, 0
198 br i1 %tobool3, label %if.end2, label %return
202 %s8 = getelementptr inbounds %struct.obj2, ptr %o, i64 0, i32 3
203 %3 = load i8, ptr %s8
205 store i8 %inc3, ptr %s8
206 %tobool4 = icmp eq i8 %inc3, 0
207 br i1 %tobool4, label %if.end4, label %return
210 tail call void @other(ptr %o) nounwind
217 ; Deal with TokenFactor chain
219 @foo = external dso_local global ptr, align 8
221 define dso_local void @test3() nounwind ssp {
222 ; CHECK-LABEL: test3:
223 ; CHECK: # %bb.0: # %entry
224 ; CHECK-NEXT: movq foo(%rip), %rax
225 ; CHECK-NEXT: decq 16(%rax)
226 ; CHECK-NEXT: je baz # TAILCALL
227 ; CHECK-NEXT: # %bb.1: # %if.end
230 %0 = load ptr, ptr @foo, align 8
231 %arrayidx = getelementptr inbounds i64, ptr %0, i64 2
232 %1 = load i64, ptr %arrayidx, align 8
233 %dec = add i64 %1, -1
234 store i64 %dec, ptr %arrayidx, align 8
235 %cmp = icmp eq i64 %dec, 0
236 br i1 %cmp, label %if.then, label %if.end
239 tail call void @baz() nounwind
246 declare dso_local void @baz()
248 ; Avoid creating a cycle in the DAG which would trigger an assert in the
252 @x = external dso_local global i32, align 4
253 @y = external dso_local global i32, align 4
254 @z = external dso_local global i32, align 4
256 define dso_local void @test4() nounwind uwtable ssp {
257 ; CHECK-LABEL: test4:
258 ; CHECK: # %bb.0: # %entry
259 ; CHECK-NEXT: xorl %eax, %eax
260 ; CHECK-NEXT: decl y(%rip)
261 ; CHECK-NEXT: je .LBB6_2
262 ; CHECK-NEXT: # %bb.1: # %entry
263 ; CHECK-NEXT: movl x(%rip), %eax
264 ; CHECK-NEXT: .LBB6_2: # %entry
265 ; CHECK-NEXT: movl %eax, z(%rip)
268 %0 = load i32, ptr @x, align 4
269 %1 = load i32, ptr @y, align 4
270 %dec = add nsw i32 %1, -1
271 store i32 %dec, ptr @y, align 4
272 %tobool.i = icmp ne i32 %dec, 0
273 %cond.i = select i1 %tobool.i, i32 %0, i32 0
274 store i32 %cond.i, ptr @z, align 4