[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / InstCombine / shl-unsigned-cmp-const.ll
blobdb51ccf40d8b1b21e826ad236ff80e5c1c6af737
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 ; Simplify 'shl' inequality test into 'and' equality test.
5 ;   (X l<< C2) u</u>= C1 iff C1 is power of 2 -> X & (-C1 l>> C2) ==/!= 0
7 ; Scalar tests
9 ; C2 Shift amount smaller than C1 trailing zeros.
10 define i1 @scalar_i8_shl_ult_const_1(i8 %x) {
11 ; CHECK-LABEL: @scalar_i8_shl_ult_const_1(
12 ; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[X:%.*]], 6
13 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[TMP1]], 0
14 ; CHECK-NEXT:    ret i1 [[CMP]]
16   %shl = shl i8 %x, 5
17   %cmp = icmp ult i8 %shl, 64
18   ret i1 %cmp
21 ; C2 Shift amount equal to C1 trailing zeros.
22 define i1 @scalar_i8_shl_ult_const_2(i8 %x) {
23 ; CHECK-LABEL: @scalar_i8_shl_ult_const_2(
24 ; CHECK-NEXT:    [[SHL_MASK:%.*]] = and i8 [[X:%.*]], 3
25 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[SHL_MASK]], 0
26 ; CHECK-NEXT:    ret i1 [[CMP]]
28   %shl = shl i8 %x, 6
29   %cmp = icmp ult i8 %shl, 64
30   ret i1 %cmp
33 ; C2 Shift amount greater than C1 trailing zeros.
34 define i1 @scalar_i8_shl_ult_const_3(i8 %x) {
35 ; CHECK-LABEL: @scalar_i8_shl_ult_const_3(
36 ; CHECK-NEXT:    [[SHL_MASK:%.*]] = and i8 [[X:%.*]], 1
37 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[SHL_MASK]], 0
38 ; CHECK-NEXT:    ret i1 [[CMP]]
40   %shl = shl i8 %x, 7
41   %cmp = icmp ult i8 %shl, 64
42   ret i1 %cmp
45 ; C2 Shift amount smaller than C1 trailing zeros.
46 define i1 @scalar_i16_shl_ult_const(i16 %x) {
47 ; CHECK-LABEL: @scalar_i16_shl_ult_const(
48 ; CHECK-NEXT:    [[TMP1:%.*]] = and i16 [[X:%.*]], 252
49 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i16 [[TMP1]], 0
50 ; CHECK-NEXT:    ret i1 [[CMP]]
52   %shl = shl i16 %x, 8
53   %cmp = icmp ult i16 %shl, 1024
54   ret i1 %cmp
57 define i1 @scalar_i32_shl_ult_const(i32 %x) {
58 ; CHECK-LABEL: @scalar_i32_shl_ult_const(
59 ; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[X:%.*]], 2097088
60 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
61 ; CHECK-NEXT:    ret i1 [[CMP]]
63   %shl = shl i32 %x, 11
64   %cmp = icmp ult i32 %shl, 131072
65   ret i1 %cmp
68 define i1 @scalar_i64_shl_ult_const(i64 %x) {
69 ; CHECK-LABEL: @scalar_i64_shl_ult_const(
70 ; CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[X:%.*]], 549755813632
71 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[TMP1]], 0
72 ; CHECK-NEXT:    ret i1 [[CMP]]
74   %shl = shl i64 %x, 25
75   %cmp = icmp ult i64 %shl, 8589934592
76   ret i1 %cmp
79 ; Check 'uge' predicate
80 define i1 @scalar_i8_shl_uge_const(i8 %x) {
81 ; CHECK-LABEL: @scalar_i8_shl_uge_const(
82 ; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[X:%.*]], 6
83 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[TMP1]], 0
84 ; CHECK-NEXT:    ret i1 [[CMP]]
86   %shl = shl i8 %x, 5
87   %cmp = icmp uge i8 %shl, 64
88   ret i1 %cmp
91 ; Check 'ule' predicate
92 define i1 @scalar_i8_shl_ule_const(i8 %x) {
93 ; CHECK-LABEL: @scalar_i8_shl_ule_const(
94 ; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[X:%.*]], 6
95 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[TMP1]], 0
96 ; CHECK-NEXT:    ret i1 [[CMP]]
98   %shl = shl i8 %x, 5
99   %cmp = icmp ule i8 %shl, 63
100   ret i1 %cmp
103 ; Check 'ugt' predicate
104 define i1 @scalar_i8_shl_ugt_const(i8 %x) {
105 ; CHECK-LABEL: @scalar_i8_shl_ugt_const(
106 ; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[X:%.*]], 6
107 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[TMP1]], 0
108 ; CHECK-NEXT:    ret i1 [[CMP]]
110   %shl = shl i8 %x, 5
111   %cmp = icmp ugt i8 %shl, 63
112   ret i1 %cmp
115 ; Vector tests
117 define <4 x i1> @vector_4xi32_shl_ult_const(<4 x i32> %x) {
118 ; CHECK-LABEL: @vector_4xi32_shl_ult_const(
119 ; CHECK-NEXT:    [[TMP1:%.*]] = and <4 x i32> [[X:%.*]], <i32 2097088, i32 2097088, i32 2097088, i32 2097088>
120 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <4 x i32> [[TMP1]], zeroinitializer
121 ; CHECK-NEXT:    ret <4 x i1> [[CMP]]
123   %shl = shl <4 x i32> %x, <i32 11, i32 11, i32 11, i32 11>
124   %cmp = icmp ult <4 x i32> %shl, <i32 131072, i32 131072, i32 131072, i32 131072>
125   ret <4 x i1> %cmp
128 define <4 x i1> @vector_4xi32_shl_ult_const_undef1(<4 x i32> %x) {
129 ; CHECK-LABEL: @vector_4xi32_shl_ult_const_undef1(
130 ; CHECK-NEXT:    [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], <i32 11, i32 11, i32 undef, i32 11>
131 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult <4 x i32> [[SHL]], <i32 131072, i32 131072, i32 131072, i32 131072>
132 ; CHECK-NEXT:    ret <4 x i1> [[CMP]]
134   %shl = shl <4 x i32> %x, <i32 11, i32 11, i32 undef, i32 11>
135   %cmp = icmp ult <4 x i32> %shl, <i32 131072, i32 131072, i32 131072, i32 131072>
136   ret <4 x i1> %cmp
139 define <4 x i1> @vector_4xi32_shl_ult_const_undef2(<4 x i32> %x) {
140 ; CHECK-LABEL: @vector_4xi32_shl_ult_const_undef2(
141 ; CHECK-NEXT:    [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], <i32 11, i32 11, i32 11, i32 11>
142 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult <4 x i32> [[SHL]], <i32 131072, i32 131072, i32 131072, i32 undef>
143 ; CHECK-NEXT:    ret <4 x i1> [[CMP]]
145   %shl = shl <4 x i32> %x, <i32 11, i32 11, i32 11, i32 11>
146   %cmp = icmp ult <4 x i32> %shl, <i32 131072, i32 131072, i32 131072, i32 undef>
147   ret <4 x i1> %cmp
150 define <4 x i1> @vector_4xi32_shl_ult_const_undef3(<4 x i32> %x) {
151 ; CHECK-LABEL: @vector_4xi32_shl_ult_const_undef3(
152 ; CHECK-NEXT:    [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], <i32 11, i32 11, i32 undef, i32 11>
153 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult <4 x i32> [[SHL]], <i32 undef, i32 131072, i32 131072, i32 131072>
154 ; CHECK-NEXT:    ret <4 x i1> [[CMP]]
156   %shl = shl <4 x i32> %x, <i32 11, i32 11, i32 undef, i32 11>
157   %cmp = icmp ult <4 x i32> %shl, <i32 undef, i32 131072, i32 131072, i32 131072>
158   ret <4 x i1> %cmp
161 ; Check 'uge' predicate
162 define <4 x i1> @vector_4xi32_shl_uge_const(<4 x i32> %x) {
163 ; CHECK-LABEL: @vector_4xi32_shl_uge_const(
164 ; CHECK-NEXT:    [[TMP1:%.*]] = and <4 x i32> [[X:%.*]], <i32 2097088, i32 2097088, i32 2097088, i32 2097088>
165 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <4 x i32> [[TMP1]], zeroinitializer
166 ; CHECK-NEXT:    ret <4 x i1> [[CMP]]
168   %shl = shl <4 x i32> %x, <i32 11, i32 11, i32 11, i32 11>
169   %cmp = icmp uge <4 x i32> %shl, <i32 131072, i32 131072, i32 131072, i32 131072>
170   ret <4 x i1> %cmp
173 ; Check 'ule' predicate
174 define <4 x i1> @vector_4xi32_shl_ule_const(<4 x i32> %x) {
175 ; CHECK-LABEL: @vector_4xi32_shl_ule_const(
176 ; CHECK-NEXT:    [[TMP1:%.*]] = and <4 x i32> [[X:%.*]], <i32 2097088, i32 2097088, i32 2097088, i32 2097088>
177 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <4 x i32> [[TMP1]], zeroinitializer
178 ; CHECK-NEXT:    ret <4 x i1> [[CMP]]
180   %shl = shl <4 x i32> %x, <i32 11, i32 11, i32 11, i32 11>
181   %cmp = icmp ule <4 x i32> %shl, <i32 131071, i32 131071, i32 131071, i32 131071>
182   ret <4 x i1> %cmp
185 ; Check 'ugt' predicate
186 define <4 x i1> @vector_4xi32_shl_ugt_const(<4 x i32> %x) {
187 ; CHECK-LABEL: @vector_4xi32_shl_ugt_const(
188 ; CHECK-NEXT:    [[TMP1:%.*]] = and <4 x i32> [[X:%.*]], <i32 2097088, i32 2097088, i32 2097088, i32 2097088>
189 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <4 x i32> [[TMP1]], zeroinitializer
190 ; CHECK-NEXT:    ret <4 x i1> [[CMP]]
192   %shl = shl <4 x i32> %x, <i32 11, i32 11, i32 11, i32 11>
193   %cmp = icmp ugt <4 x i32> %shl, <i32 131071, i32 131071, i32 131071, i32 131071>
194   ret <4 x i1> %cmp
197 ; Extra use
199 ; Not simplified
200 define i1 @scalar_i8_shl_ult_const_extra_use_shl(i8 %x, i8* %p) {
201 ; CHECK-LABEL: @scalar_i8_shl_ult_const_extra_use_shl(
202 ; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X:%.*]], 5
203 ; CHECK-NEXT:    store i8 [[SHL]], i8* [[P:%.*]], align 1
204 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[SHL]], 64
205 ; CHECK-NEXT:    ret i1 [[CMP]]
207   %shl = shl i8 %x, 5
208   store i8 %shl, i8* %p
209   %cmp = icmp ult i8 %shl, 64
210   ret i1 %cmp
213 ; Negative tests
215 ; Check 'slt' predicate
216 define i1 @scalar_i8_shl_slt_const(i8 %x) {
217 ; CHECK-LABEL: @scalar_i8_shl_slt_const(
218 ; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X:%.*]], 5
219 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[SHL]], 64
220 ; CHECK-NEXT:    ret i1 [[CMP]]
222   %shl = shl i8 %x, 5
223   %cmp = icmp slt i8 %shl, 64
224   ret i1 %cmp
227 define i1 @scalar_i8_shl_ugt_const_not_power_of_2(i8 %x) {
228 ; CHECK-LABEL: @scalar_i8_shl_ugt_const_not_power_of_2(
229 ; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X:%.*]], 5
230 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[SHL]], 66
231 ; CHECK-NEXT:    ret i1 [[CMP]]
233   %shl = shl i8 %x, 5
234   %cmp = icmp ugt i8 %shl, 66
235   ret i1 %cmp