1 ; RUN: opt < %s -instcombine -S | FileCheck %s
3 define i16 @narrow_sext_and(i16 %x16, i32 %y32) {
4 ; CHECK-LABEL: @narrow_sext_and(
5 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 %y32 to i16
6 ; CHECK-NEXT: [[R:%.*]] = and i16 [[TMP1]], %x16
7 ; CHECK-NEXT: ret i16 [[R]]
9 %x32 = sext i16 %x16 to i32
10 %b = and i32 %x32, %y32
11 %r = trunc i32 %b to i16
15 define i16 @narrow_zext_and(i16 %x16, i32 %y32) {
16 ; CHECK-LABEL: @narrow_zext_and(
17 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 %y32 to i16
18 ; CHECK-NEXT: [[R:%.*]] = and i16 [[TMP1]], %x16
19 ; CHECK-NEXT: ret i16 [[R]]
21 %x32 = zext i16 %x16 to i32
22 %b = and i32 %x32, %y32
23 %r = trunc i32 %b to i16
27 define i16 @narrow_sext_or(i16 %x16, i32 %y32) {
28 ; CHECK-LABEL: @narrow_sext_or(
29 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 %y32 to i16
30 ; CHECK-NEXT: [[R:%.*]] = or i16 [[TMP1]], %x16
31 ; CHECK-NEXT: ret i16 [[R]]
33 %x32 = sext i16 %x16 to i32
34 %b = or i32 %x32, %y32
35 %r = trunc i32 %b to i16
39 define i16 @narrow_zext_or(i16 %x16, i32 %y32) {
40 ; CHECK-LABEL: @narrow_zext_or(
41 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 %y32 to i16
42 ; CHECK-NEXT: [[R:%.*]] = or i16 [[TMP1]], %x16
43 ; CHECK-NEXT: ret i16 [[R]]
45 %x32 = zext i16 %x16 to i32
46 %b = or i32 %x32, %y32
47 %r = trunc i32 %b to i16
51 define i16 @narrow_sext_xor(i16 %x16, i32 %y32) {
52 ; CHECK-LABEL: @narrow_sext_xor(
53 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 %y32 to i16
54 ; CHECK-NEXT: [[R:%.*]] = xor i16 [[TMP1]], %x16
55 ; CHECK-NEXT: ret i16 [[R]]
57 %x32 = sext i16 %x16 to i32
58 %b = xor i32 %x32, %y32
59 %r = trunc i32 %b to i16
63 define i16 @narrow_zext_xor(i16 %x16, i32 %y32) {
64 ; CHECK-LABEL: @narrow_zext_xor(
65 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 %y32 to i16
66 ; CHECK-NEXT: [[R:%.*]] = xor i16 [[TMP1]], %x16
67 ; CHECK-NEXT: ret i16 [[R]]
69 %x32 = zext i16 %x16 to i32
70 %b = xor i32 %x32, %y32
71 %r = trunc i32 %b to i16
75 define i16 @narrow_sext_add(i16 %x16, i32 %y32) {
76 ; CHECK-LABEL: @narrow_sext_add(
77 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 %y32 to i16
78 ; CHECK-NEXT: [[R:%.*]] = add i16 [[TMP1]], %x16
79 ; CHECK-NEXT: ret i16 [[R]]
81 %x32 = sext i16 %x16 to i32
82 %b = add i32 %x32, %y32
83 %r = trunc i32 %b to i16
87 define i16 @narrow_zext_add(i16 %x16, i32 %y32) {
88 ; CHECK-LABEL: @narrow_zext_add(
89 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 %y32 to i16
90 ; CHECK-NEXT: [[R:%.*]] = add i16 [[TMP1]], %x16
91 ; CHECK-NEXT: ret i16 [[R]]
93 %x32 = zext i16 %x16 to i32
94 %b = add i32 %x32, %y32
95 %r = trunc i32 %b to i16
99 define i16 @narrow_sext_sub(i16 %x16, i32 %y32) {
100 ; CHECK-LABEL: @narrow_sext_sub(
101 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 %y32 to i16
102 ; CHECK-NEXT: [[R:%.*]] = sub i16 %x16, [[TMP1]]
103 ; CHECK-NEXT: ret i16 [[R]]
105 %x32 = sext i16 %x16 to i32
106 %b = sub i32 %x32, %y32
107 %r = trunc i32 %b to i16
111 define i16 @narrow_zext_sub(i16 %x16, i32 %y32) {
112 ; CHECK-LABEL: @narrow_zext_sub(
113 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 %y32 to i16
114 ; CHECK-NEXT: [[R:%.*]] = sub i16 %x16, [[TMP1]]
115 ; CHECK-NEXT: ret i16 [[R]]
117 %x32 = zext i16 %x16 to i32
118 %b = sub i32 %x32, %y32
119 %r = trunc i32 %b to i16
123 define i16 @narrow_sext_mul(i16 %x16, i32 %y32) {
124 ; CHECK-LABEL: @narrow_sext_mul(
125 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 %y32 to i16
126 ; CHECK-NEXT: [[R:%.*]] = mul i16 [[TMP1]], %x16
127 ; CHECK-NEXT: ret i16 [[R]]
129 %x32 = sext i16 %x16 to i32
130 %b = mul i32 %x32, %y32
131 %r = trunc i32 %b to i16
135 define i16 @narrow_zext_mul(i16 %x16, i32 %y32) {
136 ; CHECK-LABEL: @narrow_zext_mul(
137 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 %y32 to i16
138 ; CHECK-NEXT: [[R:%.*]] = mul i16 [[TMP1]], %x16
139 ; CHECK-NEXT: ret i16 [[R]]
141 %x32 = zext i16 %x16 to i32
142 %b = mul i32 %x32, %y32
143 %r = trunc i32 %b to i16
147 ; Verify that the commuted patterns work. The div is to ensure that complexity-based
148 ; canonicalization doesn't swap the binop operands. Use vector types to show those work too.
150 define <2 x i16> @narrow_sext_and_commute(<2 x i16> %x16, <2 x i32> %y32) {
151 ; CHECK-LABEL: @narrow_sext_and_commute(
152 ; CHECK-NEXT: [[Y32OP0:%.*]] = sdiv <2 x i32> %y32, <i32 7, i32 -17>
153 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[Y32OP0]] to <2 x i16>
154 ; CHECK-NEXT: [[R:%.*]] = and <2 x i16> [[TMP1]], %x16
155 ; CHECK-NEXT: ret <2 x i16> [[R]]
157 %y32op0 = sdiv <2 x i32> %y32, <i32 7, i32 -17>
158 %x32 = sext <2 x i16> %x16 to <2 x i32>
159 %b = and <2 x i32> %y32op0, %x32
160 %r = trunc <2 x i32> %b to <2 x i16>
164 define <2 x i16> @narrow_zext_and_commute(<2 x i16> %x16, <2 x i32> %y32) {
165 ; CHECK-LABEL: @narrow_zext_and_commute(
166 ; CHECK-NEXT: [[Y32OP0:%.*]] = sdiv <2 x i32> %y32, <i32 7, i32 -17>
167 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[Y32OP0]] to <2 x i16>
168 ; CHECK-NEXT: [[R:%.*]] = and <2 x i16> [[TMP1]], %x16
169 ; CHECK-NEXT: ret <2 x i16> [[R]]
171 %y32op0 = sdiv <2 x i32> %y32, <i32 7, i32 -17>
172 %x32 = zext <2 x i16> %x16 to <2 x i32>
173 %b = and <2 x i32> %y32op0, %x32
174 %r = trunc <2 x i32> %b to <2 x i16>
178 define <2 x i16> @narrow_sext_or_commute(<2 x i16> %x16, <2 x i32> %y32) {
179 ; CHECK-LABEL: @narrow_sext_or_commute(
180 ; CHECK-NEXT: [[Y32OP0:%.*]] = sdiv <2 x i32> %y32, <i32 7, i32 -17>
181 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[Y32OP0]] to <2 x i16>
182 ; CHECK-NEXT: [[R:%.*]] = or <2 x i16> [[TMP1]], %x16
183 ; CHECK-NEXT: ret <2 x i16> [[R]]
185 %y32op0 = sdiv <2 x i32> %y32, <i32 7, i32 -17>
186 %x32 = sext <2 x i16> %x16 to <2 x i32>
187 %b = or <2 x i32> %y32op0, %x32
188 %r = trunc <2 x i32> %b to <2 x i16>
192 define <2 x i16> @narrow_zext_or_commute(<2 x i16> %x16, <2 x i32> %y32) {
193 ; CHECK-LABEL: @narrow_zext_or_commute(
194 ; CHECK-NEXT: [[Y32OP0:%.*]] = sdiv <2 x i32> %y32, <i32 7, i32 -17>
195 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[Y32OP0]] to <2 x i16>
196 ; CHECK-NEXT: [[R:%.*]] = or <2 x i16> [[TMP1]], %x16
197 ; CHECK-NEXT: ret <2 x i16> [[R]]
199 %y32op0 = sdiv <2 x i32> %y32, <i32 7, i32 -17>
200 %x32 = zext <2 x i16> %x16 to <2 x i32>
201 %b = or <2 x i32> %y32op0, %x32
202 %r = trunc <2 x i32> %b to <2 x i16>
206 define <2 x i16> @narrow_sext_xor_commute(<2 x i16> %x16, <2 x i32> %y32) {
207 ; CHECK-LABEL: @narrow_sext_xor_commute(
208 ; CHECK-NEXT: [[Y32OP0:%.*]] = sdiv <2 x i32> %y32, <i32 7, i32 -17>
209 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[Y32OP0]] to <2 x i16>
210 ; CHECK-NEXT: [[R:%.*]] = xor <2 x i16> [[TMP1]], %x16
211 ; CHECK-NEXT: ret <2 x i16> [[R]]
213 %y32op0 = sdiv <2 x i32> %y32, <i32 7, i32 -17>
214 %x32 = sext <2 x i16> %x16 to <2 x i32>
215 %b = xor <2 x i32> %y32op0, %x32
216 %r = trunc <2 x i32> %b to <2 x i16>
220 define <2 x i16> @narrow_zext_xor_commute(<2 x i16> %x16, <2 x i32> %y32) {
221 ; CHECK-LABEL: @narrow_zext_xor_commute(
222 ; CHECK-NEXT: [[Y32OP0:%.*]] = sdiv <2 x i32> %y32, <i32 7, i32 -17>
223 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[Y32OP0]] to <2 x i16>
224 ; CHECK-NEXT: [[R:%.*]] = xor <2 x i16> [[TMP1]], %x16
225 ; CHECK-NEXT: ret <2 x i16> [[R]]
227 %y32op0 = sdiv <2 x i32> %y32, <i32 7, i32 -17>
228 %x32 = zext <2 x i16> %x16 to <2 x i32>
229 %b = xor <2 x i32> %y32op0, %x32
230 %r = trunc <2 x i32> %b to <2 x i16>
234 define <2 x i16> @narrow_sext_add_commute(<2 x i16> %x16, <2 x i32> %y32) {
235 ; CHECK-LABEL: @narrow_sext_add_commute(
236 ; CHECK-NEXT: [[Y32OP0:%.*]] = sdiv <2 x i32> %y32, <i32 7, i32 -17>
237 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[Y32OP0]] to <2 x i16>
238 ; CHECK-NEXT: [[R:%.*]] = add <2 x i16> [[TMP1]], %x16
239 ; CHECK-NEXT: ret <2 x i16> [[R]]
241 %y32op0 = sdiv <2 x i32> %y32, <i32 7, i32 -17>
242 %x32 = sext <2 x i16> %x16 to <2 x i32>
243 %b = add <2 x i32> %y32op0, %x32
244 %r = trunc <2 x i32> %b to <2 x i16>
248 define <2 x i16> @narrow_zext_add_commute(<2 x i16> %x16, <2 x i32> %y32) {
249 ; CHECK-LABEL: @narrow_zext_add_commute(
250 ; CHECK-NEXT: [[Y32OP0:%.*]] = sdiv <2 x i32> %y32, <i32 7, i32 -17>
251 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[Y32OP0]] to <2 x i16>
252 ; CHECK-NEXT: [[R:%.*]] = add <2 x i16> [[TMP1]], %x16
253 ; CHECK-NEXT: ret <2 x i16> [[R]]
255 %y32op0 = sdiv <2 x i32> %y32, <i32 7, i32 -17>
256 %x32 = zext <2 x i16> %x16 to <2 x i32>
257 %b = add <2 x i32> %y32op0, %x32
258 %r = trunc <2 x i32> %b to <2 x i16>
262 define <2 x i16> @narrow_sext_sub_commute(<2 x i16> %x16, <2 x i32> %y32) {
263 ; CHECK-LABEL: @narrow_sext_sub_commute(
264 ; CHECK-NEXT: [[Y32OP0:%.*]] = sdiv <2 x i32> %y32, <i32 7, i32 -17>
265 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[Y32OP0]] to <2 x i16>
266 ; CHECK-NEXT: [[R:%.*]] = sub <2 x i16> [[TMP1]], %x16
267 ; CHECK-NEXT: ret <2 x i16> [[R]]
269 %y32op0 = sdiv <2 x i32> %y32, <i32 7, i32 -17>
270 %x32 = sext <2 x i16> %x16 to <2 x i32>
271 %b = sub <2 x i32> %y32op0, %x32
272 %r = trunc <2 x i32> %b to <2 x i16>
276 define <2 x i16> @narrow_zext_sub_commute(<2 x i16> %x16, <2 x i32> %y32) {
277 ; CHECK-LABEL: @narrow_zext_sub_commute(
278 ; CHECK-NEXT: [[Y32OP0:%.*]] = sdiv <2 x i32> %y32, <i32 7, i32 -17>
279 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[Y32OP0]] to <2 x i16>
280 ; CHECK-NEXT: [[R:%.*]] = sub <2 x i16> [[TMP1]], %x16
281 ; CHECK-NEXT: ret <2 x i16> [[R]]
283 %y32op0 = sdiv <2 x i32> %y32, <i32 7, i32 -17>
284 %x32 = zext <2 x i16> %x16 to <2 x i32>
285 %b = sub <2 x i32> %y32op0, %x32
286 %r = trunc <2 x i32> %b to <2 x i16>
290 define <2 x i16> @narrow_sext_mul_commute(<2 x i16> %x16, <2 x i32> %y32) {
291 ; CHECK-LABEL: @narrow_sext_mul_commute(
292 ; CHECK-NEXT: [[Y32OP0:%.*]] = sdiv <2 x i32> %y32, <i32 7, i32 -17>
293 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[Y32OP0]] to <2 x i16>
294 ; CHECK-NEXT: [[R:%.*]] = mul <2 x i16> [[TMP1]], %x16
295 ; CHECK-NEXT: ret <2 x i16> [[R]]
297 %y32op0 = sdiv <2 x i32> %y32, <i32 7, i32 -17>
298 %x32 = sext <2 x i16> %x16 to <2 x i32>
299 %b = mul <2 x i32> %y32op0, %x32
300 %r = trunc <2 x i32> %b to <2 x i16>
304 define <2 x i16> @narrow_zext_mul_commute(<2 x i16> %x16, <2 x i32> %y32) {
305 ; CHECK-LABEL: @narrow_zext_mul_commute(
306 ; CHECK-NEXT: [[Y32OP0:%.*]] = sdiv <2 x i32> %y32, <i32 7, i32 -17>
307 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[Y32OP0]] to <2 x i16>
308 ; CHECK-NEXT: [[R:%.*]] = mul <2 x i16> [[TMP1]], %x16
309 ; CHECK-NEXT: ret <2 x i16> [[R]]
311 %y32op0 = sdiv <2 x i32> %y32, <i32 7, i32 -17>
312 %x32 = zext <2 x i16> %x16 to <2 x i32>
313 %b = mul <2 x i32> %y32op0, %x32
314 %r = trunc <2 x i32> %b to <2 x i16>