1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s
4 ; CodeGenPrepare is expected to form overflow intrinsics to improve DAG/isel.
6 define i1 @usubo_ult_i64(i64 %x, i64 %y, i64* %p) nounwind {
7 ; CHECK-LABEL: usubo_ult_i64:
9 ; CHECK-NEXT: subq %rsi, %rdi
10 ; CHECK-NEXT: setb %al
11 ; CHECK-NEXT: movq %rdi, (%rdx)
15 %ov = icmp ult i64 %x, %y
19 ; Verify insertion point for single-BB. Toggle predicate.
21 define i1 @usubo_ugt_i32(i32 %x, i32 %y, i32* %p) nounwind {
22 ; CHECK-LABEL: usubo_ugt_i32:
24 ; CHECK-NEXT: subl %esi, %edi
25 ; CHECK-NEXT: setb %al
26 ; CHECK-NEXT: movl %edi, (%rdx)
28 %ov = icmp ugt i32 %y, %x
34 ; Constant operand should match.
36 define i1 @usubo_ugt_constant_op0_i8(i8 %x, i8* %p) nounwind {
37 ; CHECK-LABEL: usubo_ugt_constant_op0_i8:
39 ; CHECK-NEXT: movb $42, %cl
40 ; CHECK-NEXT: subb %dil, %cl
41 ; CHECK-NEXT: setb %al
42 ; CHECK-NEXT: movb %cl, (%rsi)
45 %ov = icmp ugt i8 %x, 42
50 ; Compare with constant operand 0 is canonicalized by commuting, but verify match for non-canonical form.
52 define i1 @usubo_ult_constant_op0_i16(i16 %x, i16* %p) nounwind {
53 ; CHECK-LABEL: usubo_ult_constant_op0_i16:
55 ; CHECK-NEXT: movw $43, %cx
56 ; CHECK-NEXT: subw %di, %cx
57 ; CHECK-NEXT: setb %al
58 ; CHECK-NEXT: movw %cx, (%rsi)
61 %ov = icmp ult i16 43, %x
66 ; Subtract with constant operand 1 is canonicalized to add.
68 define i1 @usubo_ult_constant_op1_i16(i16 %x, i16* %p) nounwind {
69 ; CHECK-LABEL: usubo_ult_constant_op1_i16:
71 ; CHECK-NEXT: subw $44, %di
72 ; CHECK-NEXT: setb %al
73 ; CHECK-NEXT: movw %di, (%rsi)
76 %ov = icmp ult i16 %x, 44
81 define i1 @usubo_ugt_constant_op1_i8(i8 %x, i8* %p) nounwind {
82 ; CHECK-LABEL: usubo_ugt_constant_op1_i8:
84 ; CHECK-NEXT: subb $45, %dil
85 ; CHECK-NEXT: setb %al
86 ; CHECK-NEXT: movb %dil, (%rsi)
88 %ov = icmp ugt i8 45, %x
94 ; Special-case: subtract 1 changes the compare predicate and constant.
96 define i1 @usubo_eq_constant1_op1_i32(i32 %x, i32* %p) nounwind {
97 ; CHECK-LABEL: usubo_eq_constant1_op1_i32:
99 ; CHECK-NEXT: subl $1, %edi
100 ; CHECK-NEXT: setb %al
101 ; CHECK-NEXT: movl %edi, (%rsi)
104 %ov = icmp eq i32 %x, 0
105 store i32 %s, i32* %p
109 ; Special-case: subtract from 0 (negate) changes the compare predicate.
111 define i1 @usubo_ne_constant0_op1_i32(i32 %x, i32* %p) {
112 ; CHECK-LABEL: usubo_ne_constant0_op1_i32:
114 ; CHECK-NEXT: negl %edi
115 ; CHECK-NEXT: setb %al
116 ; CHECK-NEXT: movl %edi, (%rsi)
119 %ov = icmp ne i32 %x, 0
120 store i32 %s, i32* %p
124 ; This used to verify insertion point for multi-BB, but now we just bail out.
126 declare void @call(i1)
128 define i1 @usubo_ult_sub_dominates_i64(i64 %x, i64 %y, i64* %p, i1 %cond) nounwind {
129 ; CHECK-LABEL: usubo_ult_sub_dominates_i64:
130 ; CHECK: # %bb.0: # %entry
131 ; CHECK-NEXT: testb $1, %cl
132 ; CHECK-NEXT: je .LBB8_2
133 ; CHECK-NEXT: # %bb.1: # %t
134 ; CHECK-NEXT: movq %rdi, %rax
135 ; CHECK-NEXT: subq %rsi, %rax
136 ; CHECK-NEXT: movq %rax, (%rdx)
137 ; CHECK-NEXT: testb $1, %cl
138 ; CHECK-NEXT: je .LBB8_2
139 ; CHECK-NEXT: # %bb.3: # %end
140 ; CHECK-NEXT: cmpq %rsi, %rdi
141 ; CHECK-NEXT: setb %al
143 ; CHECK-NEXT: .LBB8_2: # %f
144 ; CHECK-NEXT: movl %ecx, %eax
147 br i1 %cond, label %t, label %f
151 store i64 %s, i64* %p
152 br i1 %cond, label %end, label %f
158 %ov = icmp ult i64 %x, %y
162 define i1 @usubo_ult_cmp_dominates_i64(i64 %x, i64 %y, i64* %p, i1 %cond) nounwind {
163 ; CHECK-LABEL: usubo_ult_cmp_dominates_i64:
164 ; CHECK: # %bb.0: # %entry
165 ; CHECK-NEXT: pushq %rbp
166 ; CHECK-NEXT: pushq %r15
167 ; CHECK-NEXT: pushq %r14
168 ; CHECK-NEXT: pushq %rbx
169 ; CHECK-NEXT: pushq %rax
170 ; CHECK-NEXT: movl %ecx, %ebp
171 ; CHECK-NEXT: testb $1, %bpl
172 ; CHECK-NEXT: je .LBB9_2
173 ; CHECK-NEXT: # %bb.1: # %t
174 ; CHECK-NEXT: movq %rdx, %r14
175 ; CHECK-NEXT: movq %rsi, %r15
176 ; CHECK-NEXT: movq %rdi, %rbx
177 ; CHECK-NEXT: xorl %edi, %edi
178 ; CHECK-NEXT: cmpq %rsi, %rbx
179 ; CHECK-NEXT: setb %dil
180 ; CHECK-NEXT: callq call
181 ; CHECK-NEXT: subq %r15, %rbx
182 ; CHECK-NEXT: jae .LBB9_2
183 ; CHECK-NEXT: # %bb.4: # %end
184 ; CHECK-NEXT: setb %al
185 ; CHECK-NEXT: movq %rbx, (%r14)
186 ; CHECK-NEXT: jmp .LBB9_3
187 ; CHECK-NEXT: .LBB9_2: # %f
188 ; CHECK-NEXT: movl %ebp, %eax
189 ; CHECK-NEXT: .LBB9_3: # %f
190 ; CHECK-NEXT: addq $8, %rsp
191 ; CHECK-NEXT: popq %rbx
192 ; CHECK-NEXT: popq %r14
193 ; CHECK-NEXT: popq %r15
194 ; CHECK-NEXT: popq %rbp
197 br i1 %cond, label %t, label %f
200 %ov = icmp ult i64 %x, %y
201 call void @call(i1 %ov)
202 br i1 %ov, label %end, label %f
209 store i64 %s, i64* %p
213 define void @PR41129(i64* %p64) {
214 ; CHECK-LABEL: PR41129:
215 ; CHECK: # %bb.0: # %entry
216 ; CHECK-NEXT: movq (%rdi), %rax
217 ; CHECK-NEXT: testq %rax, %rax
218 ; CHECK-NEXT: je .LBB10_2
219 ; CHECK-NEXT: # %bb.1: # %false
220 ; CHECK-NEXT: andl $7, %eax
221 ; CHECK-NEXT: movq %rax, (%rdi)
223 ; CHECK-NEXT: .LBB10_2: # %true
224 ; CHECK-NEXT: decq %rax
225 ; CHECK-NEXT: movq %rax, (%rdi)
228 %key = load i64, i64* %p64, align 8
229 %cond17 = icmp eq i64 %key, 0
230 br i1 %cond17, label %true, label %false
233 %andval = and i64 %key, 7
234 store i64 %andval, i64* %p64
238 %svalue = add i64 %key, -1
239 store i64 %svalue, i64* %p64
246 define i32 @PR42571(i32 %x, i32 %y) {
247 ; CHECK-LABEL: PR42571:
249 ; CHECK-NEXT: movl %edi, %eax
250 ; CHECK-NEXT: subl $1, %eax
251 ; CHECK-NEXT: andl %edi, %eax
252 ; CHECK-NEXT: cmpl $1, %edi
253 ; CHECK-NEXT: cmovbl %esi, %eax
255 %tobool = icmp eq i32 %x, 0
256 %sub = add nsw i32 %x, -1
257 %and = and i32 %sub, %x
258 %cond = select i1 %tobool, i32 %y, i32 %and