[InstCombine] Signed saturation patterns
[llvm-core.git] / test / CodeGen / ARM / ssat.ll
blobf1e11dd33d1fb0c6d1d2e15a053746a4ede01547
1 ; RUN: llc -mtriple=armv4t-eabi %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=V4T
2 ; RUN: llc -mtriple=armv6t2-eabi %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=V6T2
4 ; Check for several conditions that should result in SSAT.
5 ; For example, the base test is equivalent to
6 ; x < -k ? -k : (x > k ? k : x) in C. All patterns that bound x
7 ; to the interval [-k, k] where k is a power of 2 can be
8 ; transformed into SSAT. At the end there are some tests
9 ; checking that conditionals are not transformed if they don't
10 ; match the right pattern.
13 ; Base tests with different bit widths
16 ; x < -k ? -k : (x > k ? k : x)
17 ; 32-bit base test
18 define i32 @sat_base_32bit(i32 %x) #0 {
19 ; CHECK-LABEL: sat_base_32bit:
20 ; V6T2: ssat r0, #24, r0
21 ; V4T-NOT: ssat
22 entry:
23   %cmpLow = icmp slt i32 %x, -8388608
24   %cmpUp = icmp sgt i32 %x, 8388607
25   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %x
26   %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %saturateUp
27   ret i32 %saturateLow
30 ; x < -k ? -k : (x > k ? k : x)
31 ; 16-bit base test
32 define i16 @sat_base_16bit(i16 %x) #0 {
33 ; CHECK-LABEL: sat_base_16bit:
34 ; V6T2: ssat r0, #12, r0
35 ; V4T-NOT: ssat
36 entry:
37   %cmpLow = icmp slt i16 %x, -2048
38   %cmpUp = icmp sgt i16 %x, 2047
39   %saturateUp = select i1 %cmpUp, i16 2047, i16 %x
40   %saturateLow = select i1 %cmpLow, i16 -2048, i16 %saturateUp
41   ret i16 %saturateLow
44 ; x < -k ? -k : (x > k ? k : x)
45 ; 8-bit base test
46 define i8 @sat_base_8bit(i8 %x) #0 {
47 ; CHECK-LABEL: sat_base_8bit:
48 ; V6T2: ssat r0, #6, r0
49 ; V4T-NOT: ssat
50 entry:
51   %cmpLow = icmp slt i8 %x, -32
52   %cmpUp = icmp sgt i8 %x, 31
53   %saturateUp = select i1 %cmpUp, i8 31, i8 %x
54   %saturateLow = select i1 %cmpLow, i8 -32, i8 %saturateUp
55   ret i8 %saturateLow
59 ; Tests where the conditionals that check for upper and lower bounds,
60 ; or the < and > operators, are arranged in different ways. Only some
61 ; of the possible combinations that lead to SSAT are tested.
64 ; x < -k ? -k : (x < k ? x : k)
65 define i32 @sat_lower_upper_1(i32 %x) #0 {
66 ; CHECK-LABEL: sat_lower_upper_1:
67 ; V6T2: ssat r0, #24, r0
68 ; V4T-NOT: ssat
69 entry:
70   %cmpLow = icmp slt i32 %x, -8388608
71   %cmpUp = icmp slt i32 %x, 8388607
72   %saturateUp = select i1 %cmpUp, i32 %x, i32 8388607
73   %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %saturateUp
74   ret i32 %saturateLow
77 ; x > -k ? (x > k ? k : x) : -k
78 define i32 @sat_lower_upper_2(i32 %x) #0 {
79 ; CHECK-LABEL: sat_lower_upper_2:
80 ; V6T2: ssat    r0, #24, r0
81 ; V4T-NOT: ssat
82 entry:
83   %cmpLow = icmp sgt i32 %x, -8388608
84   %cmpUp = icmp sgt i32 %x, 8388607
85   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %x
86   %saturateLow = select i1 %cmpLow, i32 %saturateUp, i32 -8388608
87   ret i32 %saturateLow
90 ; x < k ? (x < -k ? -k : x) : k
91 define i32 @sat_upper_lower_1(i32 %x) #0 {
92 ; CHECK-LABEL: sat_upper_lower_1:
93 ; V6T2: ssat    r0, #24, r0
94 ; V4T-NOT: ssat
95 entry:
96   %cmpUp = icmp slt i32 %x, 8388607
97   %cmpLow = icmp slt i32 %x, -8388608
98   %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
99   %saturateUp = select i1 %cmpUp, i32 %saturateLow, i32 8388607
100   ret i32 %saturateUp
103 ; x > k ? k : (x < -k ? -k : x)
104 define i32 @sat_upper_lower_2(i32 %x) #0 {
105 ; CHECK-LABEL: sat_upper_lower_2:
106 ; V6T2: ssat    r0, #24, r0
107 ; V4T-NOT: ssat
108 entry:
109   %cmpUp = icmp sgt i32 %x, 8388607
110   %cmpLow = icmp slt i32 %x, -8388608
111   %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
112   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
113   ret i32 %saturateUp
116 ; k < x ? k : (x > -k ? x : -k)
117 define i32 @sat_upper_lower_3(i32 %x) #0 {
118 ; CHECK-LABEL: sat_upper_lower_3:
119 ; V6T2: ssat    r0, #24, r0
120 ; V4T-NOT: ssat
121 entry:
122   %cmpUp = icmp slt i32 8388607, %x
123   %cmpLow = icmp sgt i32 %x, -8388608
124   %saturateLow = select i1 %cmpLow, i32 %x, i32 -8388608
125   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
126   ret i32 %saturateUp
130 ; Miscellanea
133 ; Check that >= and <= work the same as > and <
134 ; k <= x ? k : (x >= -k ? x : -k)
135 define i32 @sat_le_ge(i32 %x) #0 {
136 ; CHECK-LABEL: sat_le_ge:
137 ; V6T2: ssat    r0, #24, r0
138 ; V4T-NOT: ssat
139 entry:
140   %cmpUp = icmp sle i32 8388607, %x
141   %cmpLow = icmp sge i32 %x, -8388608
142   %saturateLow = select i1 %cmpLow, i32 %x, i32 -8388608
143   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
144   ret i32 %saturateUp
148 ; The following tests check for patterns that should not transform
149 ; into SSAT but are similar enough that could confuse the selector.
152 ; x > k ? k : (x > -k ? -k : x)
153 ; First condition upper-saturates, second doesn't lower-saturate.
154 define i32 @no_sat_missing_lower(i32 %x) #0 {
155 ; CHECK-LABEL: no_sat_missing_lower
156 ; CHECK-NOT: ssat
157 entry:
158   %cmpUp = icmp sgt i32 %x, 8388607
159   %cmpLow = icmp sgt i32 %x, -8388608
160   %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
161   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
162   ret i32 %saturateUp
165 ; x < k ? k : (x < -k ? -k : x)
166 ; Second condition lower-saturates, first doesn't upper-saturate.
167 define i32 @no_sat_missing_upper(i32 %x) #0 {
168 ; CHECK-LABEL: no_sat_missing_upper:
169 ; CHECK-NOT: ssat
170 entry:
171   %cmpUp = icmp slt i32 %x, 8388607
172   %cmpLow = icmp slt i32 %x, -8388608
173   %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
174   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
175   ret i32 %saturateUp
178 ; Lower constant is different in the select and in the compare
179 define i32 @no_sat_incorrect_constant(i32 %x) #0 {
180 ; CHECK-LABEL: no_sat_incorrect_constant:
181 ; CHECK-NOT: ssat
182 entry:
183   %cmpUp = icmp sgt i32 %x, 8388607
184   %cmpLow = icmp slt i32 %x, -8388608
185   %saturateLow = select i1 %cmpLow, i32 -8388607, i32 %x
186   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
187   ret i32 %saturateUp
190 ; The interval is not [k, ~k]
191 define i32 @no_sat_incorrect_interval(i32 %x) #0 {
192 ; CHECK-LABEL: no_sat_incorrect_interval:
193 ; CHECK-NOT: ssat
194 entry:
195   %cmpUp = icmp sgt i32 %x, 8388607
196   %cmpLow = icmp slt i32 %x, -19088744
197   %saturateLow = select i1 %cmpLow, i32 -19088744, i32 %x
198   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
199   ret i32 %saturateUp
202 ; The returned value (y) is not the same as the tested value (x).
203 define i32 @no_sat_incorrect_return(i32 %x, i32 %y) #0 {
204 ; CHECK-LABEL: no_sat_incorrect_return:
205 ; CHECK-NOT: ssat
206 entry:
207   %cmpUp = icmp sgt i32 %x, 8388607
208   %cmpLow = icmp slt i32 %x, -8388608
209   %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %y
210   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
211   ret i32 %saturateUp
214 ; One of the values in a compare (y) is not the same as the rest
215 ; of the compare and select values (x).
216 define i32 @no_sat_incorrect_compare(i32 %x, i32 %y) #0 {
217 ; CHECK-LABEL: no_sat_incorrect_compare:
218 ; CHECK-NOT: ssat
219 entry:
220   %cmpUp = icmp sgt i32 %x, 8388607
221   %cmpLow = icmp slt i32 %y, -8388608
222   %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
223   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
224   ret i32 %saturateUp