[ARM] Adjust how NEON shifts are lowered
[llvm-core.git] / test / CodeGen / X86 / cgp-usubo.ll
blob6733a8258f8d61bd75efeaa63edb7cd713538061
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:
8 ; CHECK:       # %bb.0:
9 ; CHECK-NEXT:    subq %rsi, %rdi
10 ; CHECK-NEXT:    setb %al
11 ; CHECK-NEXT:    movq %rdi, (%rdx)
12 ; CHECK-NEXT:    retq
13   %s = sub i64 %x, %y
14   store i64 %s, i64* %p
15   %ov = icmp ult i64 %x, %y
16   ret i1 %ov
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:
23 ; CHECK:       # %bb.0:
24 ; CHECK-NEXT:    subl %esi, %edi
25 ; CHECK-NEXT:    setb %al
26 ; CHECK-NEXT:    movl %edi, (%rdx)
27 ; CHECK-NEXT:    retq
28   %ov = icmp ugt i32 %y, %x
29   %s = sub i32 %x, %y
30   store i32 %s, i32* %p
31   ret i1 %ov
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:
38 ; CHECK:       # %bb.0:
39 ; CHECK-NEXT:    movb $42, %cl
40 ; CHECK-NEXT:    subb %dil, %cl
41 ; CHECK-NEXT:    setb %al
42 ; CHECK-NEXT:    movb %cl, (%rsi)
43 ; CHECK-NEXT:    retq
44   %s = sub i8 42, %x
45   %ov = icmp ugt i8 %x, 42
46   store i8 %s, i8* %p
47   ret i1 %ov
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:
54 ; CHECK:       # %bb.0:
55 ; CHECK-NEXT:    movw $43, %cx
56 ; CHECK-NEXT:    subw %di, %cx
57 ; CHECK-NEXT:    setb %al
58 ; CHECK-NEXT:    movw %cx, (%rsi)
59 ; CHECK-NEXT:    retq
60   %s = sub i16 43, %x
61   %ov = icmp ult i16 43, %x
62   store i16 %s, i16* %p
63   ret i1 %ov
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:
70 ; CHECK:       # %bb.0:
71 ; CHECK-NEXT:    subw $44, %di
72 ; CHECK-NEXT:    setb %al
73 ; CHECK-NEXT:    movw %di, (%rsi)
74 ; CHECK-NEXT:    retq
75   %s = add i16 %x, -44
76   %ov = icmp ult i16 %x, 44
77   store i16 %s, i16* %p
78   ret i1 %ov
81 define i1 @usubo_ugt_constant_op1_i8(i8 %x, i8* %p) nounwind {
82 ; CHECK-LABEL: usubo_ugt_constant_op1_i8:
83 ; CHECK:       # %bb.0:
84 ; CHECK-NEXT:    subb $45, %dil
85 ; CHECK-NEXT:    setb %al
86 ; CHECK-NEXT:    movb %dil, (%rsi)
87 ; CHECK-NEXT:    retq
88   %ov = icmp ugt i8 45, %x
89   %s = add i8 %x, -45
90   store i8 %s, i8* %p
91   ret i1 %ov
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:
98 ; CHECK:       # %bb.0:
99 ; CHECK-NEXT:    subl $1, %edi
100 ; CHECK-NEXT:    setb %al
101 ; CHECK-NEXT:    movl %edi, (%rsi)
102 ; CHECK-NEXT:    retq
103   %s = add i32 %x, -1
104   %ov = icmp eq i32 %x, 0
105   store i32 %s, i32* %p
106   ret i1 %ov
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:
113 ; CHECK:       # %bb.0:
114 ; CHECK-NEXT:    negl %edi
115 ; CHECK-NEXT:    setb %al
116 ; CHECK-NEXT:    movl %edi, (%rsi)
117 ; CHECK-NEXT:    retq
118   %s = sub i32 0, %x
119   %ov = icmp ne i32 %x, 0
120   store i32 %s, i32* %p
121   ret i1 %ov
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
142 ; CHECK-NEXT:    retq
143 ; CHECK-NEXT:  .LBB8_2: # %f
144 ; CHECK-NEXT:    movl %ecx, %eax
145 ; CHECK-NEXT:    retq
146 entry:
147   br i1 %cond, label %t, label %f
150   %s = sub i64 %x, %y
151   store i64 %s, i64* %p
152   br i1 %cond, label %end, label %f
155   ret i1 %cond
157 end:
158   %ov = icmp ult i64 %x, %y
159   ret i1 %ov
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
195 ; CHECK-NEXT:    retq
196 entry:
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
205   ret i1 %cond
207 end:
208   %s = sub i64 %x, %y
209   store i64 %s, i64* %p
210   ret i1 %ov
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)
222 ; CHECK-NEXT:    retq
223 ; CHECK-NEXT:  .LBB10_2: # %true
224 ; CHECK-NEXT:    decq %rax
225 ; CHECK-NEXT:    movq %rax, (%rdi)
226 ; CHECK-NEXT:    retq
227 entry:
228   %key = load i64, i64* %p64, align 8
229   %cond17 = icmp eq i64 %key, 0
230   br i1 %cond17, label %true, label %false
232 false:
233   %andval = and i64 %key, 7
234   store i64 %andval, i64* %p64
235   br label %exit
237 true:
238   %svalue = add i64 %key, -1
239   store i64 %svalue, i64* %p64
240   br label %exit
242 exit:
243   ret void
246 define i32 @PR42571(i32 %x, i32 %y) {
247 ; CHECK-LABEL: PR42571:
248 ; CHECK:       # %bb.0:
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
254 ; CHECK-NEXT:    retq
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
259   ret i32 %cond