[Github] Bump max ccache size for premerge
[llvm-project.git] / mlir / test / Conversion / ArithToLLVM / arith-to-llvm.mlir
blob1dabacfd8a47cce7736ceaba2a8552561490b940
1 // RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-arith-to-llvm))" %s -split-input-file | FileCheck %s
3 // Same below, but using the `ConvertToLLVMPatternInterface` entry point
4 // and the generic `convert-to-llvm` pass.
5 // RUN: mlir-opt --convert-to-llvm="filter-dialects=arith" --split-input-file %s | FileCheck %s
7 // CHECK-LABEL: @vector_ops
8 func.func @vector_ops(%arg0: vector<4xf32>, %arg1: vector<4xi1>, %arg2: vector<4xi64>, %arg3: vector<4xi64>) -> vector<4xf32> {
9 // CHECK-NEXT:  %0 = llvm.mlir.constant(dense<4.200000e+01> : vector<4xf32>) : vector<4xf32>
10   %0 = arith.constant dense<42.> : vector<4xf32>
11 // CHECK-NEXT:  %1 = llvm.fadd %arg0, %0 : vector<4xf32>
12   %1 = arith.addf %arg0, %0 : vector<4xf32>
13 // CHECK-NEXT:  %2 = llvm.sdiv %arg2, %arg2 : vector<4xi64>
14   %3 = arith.divsi %arg2, %arg2 : vector<4xi64>
15 // CHECK-NEXT:  %3 = llvm.udiv %arg2, %arg2 : vector<4xi64>
16   %4 = arith.divui %arg2, %arg2 : vector<4xi64>
17 // CHECK-NEXT:  %4 = llvm.srem %arg2, %arg2 : vector<4xi64>
18   %5 = arith.remsi %arg2, %arg2 : vector<4xi64>
19 // CHECK-NEXT:  %5 = llvm.urem %arg2, %arg2 : vector<4xi64>
20   %6 = arith.remui %arg2, %arg2 : vector<4xi64>
21 // CHECK-NEXT:  %6 = llvm.fdiv %arg0, %0 : vector<4xf32>
22   %7 = arith.divf %arg0, %0 : vector<4xf32>
23 // CHECK-NEXT:  %7 = llvm.frem %arg0, %0 : vector<4xf32>
24   %8 = arith.remf %arg0, %0 : vector<4xf32>
25 // CHECK-NEXT:  %8 = llvm.and %arg2, %arg3 : vector<4xi64>
26   %9 = arith.andi %arg2, %arg3 : vector<4xi64>
27 // CHECK-NEXT:  %9 = llvm.or %arg2, %arg3 : vector<4xi64>
28   %10 = arith.ori %arg2, %arg3 : vector<4xi64>
29 // CHECK-NEXT:  %10 = llvm.xor %arg2, %arg3 : vector<4xi64>
30   %11 = arith.xori %arg2, %arg3 : vector<4xi64>
31 // CHECK-NEXT:  %11 = llvm.shl %arg2, %arg2 : vector<4xi64>
32   %12 = arith.shli %arg2, %arg2 : vector<4xi64>
33 // CHECK-NEXT:  %12 = llvm.ashr %arg2, %arg2 : vector<4xi64>
34   %13 = arith.shrsi %arg2, %arg2 : vector<4xi64>
35 // CHECK-NEXT:  %13 = llvm.lshr %arg2, %arg2 : vector<4xi64>
36   %14 = arith.shrui %arg2, %arg2 : vector<4xi64>
37   return %1 : vector<4xf32>
40 // -----
42 // CHECK-LABEL: @ops
43 func.func @ops(f32, f32, i32, i32, f64) -> (f32, i32) {
44 ^bb0(%arg0: f32, %arg1: f32, %arg2: i32, %arg3: i32, %arg4: f64):
45 // CHECK:  = llvm.fsub %arg0, %arg1 : f32
46   %0 = arith.subf %arg0, %arg1: f32
47 // CHECK: = llvm.sub %arg2, %arg3 : i32
48   %1 = arith.subi %arg2, %arg3: i32
49 // CHECK: = llvm.icmp "slt" %arg2, %1 : i32
50   %2 = arith.cmpi slt, %arg2, %1 : i32
51 // CHECK: = llvm.icmp "sle" %arg2, %1 : i32
52   %3 = arith.cmpi sle, %arg2, %1 : i32
53 // CHECK: = llvm.icmp "sgt" %arg2, %1 : i32
54   %4 = arith.cmpi sgt, %arg2, %1 : i32
55 // CHECK: = llvm.icmp "ult" %arg2, %1 : i32
56   %5 = arith.cmpi ult, %arg2, %1 : i32
57 // CHECK: = llvm.icmp "ule" %arg2, %1 : i32
58   %6 = arith.cmpi ule, %arg2, %1 : i32
59 // CHECK: = llvm.icmp "ugt" %arg2, %1 : i32
60   %7 = arith.cmpi ugt, %arg2, %1 : i32
61 // CHECK: = llvm.icmp "eq" %arg2, %1 : i32
62   %8 = arith.cmpi eq, %arg2, %1 : i32
63 // CHECK: = llvm.sdiv %arg2, %arg3 : i32
64   %9 = arith.divsi %arg2, %arg3 : i32
65 // CHECK: = llvm.udiv %arg2, %arg3 : i32
66   %10 = arith.divui %arg2, %arg3 : i32
67 // CHECK: = llvm.srem %arg2, %arg3 : i32
68   %11 = arith.remsi %arg2, %arg3 : i32
69 // CHECK: = llvm.urem %arg2, %arg3 : i32
70   %12 = arith.remui %arg2, %arg3 : i32
71 // CHECK: = llvm.fdiv %arg0, %arg1 : f32
72   %13 = arith.divf %arg0, %arg1 : f32
73 // CHECK: = llvm.frem %arg0, %arg1 : f32
74   %14 = arith.remf %arg0, %arg1 : f32
75 // CHECK: = llvm.and %arg2, %arg3 : i32
76   %15 = arith.andi %arg2, %arg3 : i32
77 // CHECK: = llvm.or %arg2, %arg3 : i32
78   %16 = arith.ori %arg2, %arg3 : i32
79 // CHECK: = llvm.xor %arg2, %arg3 : i32
80   %17 = arith.xori %arg2, %arg3 : i32
81 // CHECK: = llvm.mlir.constant(7.900000e-01 : f64) : f64
82   %18 = arith.constant 7.9e-01 : f64
83 // CHECK: = llvm.shl %arg2, %arg3 : i32
84   %19 = arith.shli %arg2, %arg3 : i32
85 // CHECK: = llvm.ashr %arg2, %arg3 : i32
86   %20 = arith.shrsi %arg2, %arg3 : i32
87 // CHECK: = llvm.lshr %arg2, %arg3 : i32
88   %21 = arith.shrui %arg2, %arg3 : i32
89 // CHECK: arith.constant 2.000000e+00 : tf32
90   // There is no type conversion rule for tf32.
91   %22 = arith.constant 2.0 : tf32
92   return %0, %10 : f32, i32
95 // -----
97 // Checking conversion of index types to integers using i1, assuming no target
98 // system would have a 1-bit address space.  Otherwise, we would have had to
99 // make this test dependent on the pointer size on the target system.
100 // CHECK-LABEL: @index_cast
101 func.func @index_cast(%arg0: index, %arg1: i1) {
102 // CHECK: = llvm.trunc %0 : i{{.*}} to i1
103   %0 = arith.index_cast %arg0: index to i1
104 // CHECK-NEXT: = llvm.sext %arg1 : i1 to i{{.*}}
105   %1 = arith.index_cast %arg1: i1 to index
106   return
109 // -----
111 // CHECK-LABEL: @vector_index_cast
112 func.func @vector_index_cast(%arg0: vector<2xindex>, %arg1: vector<2xi1>) {
113 // CHECK: = llvm.trunc %{{.*}} : vector<2xi{{.*}}> to vector<2xi1>
114   %0 = arith.index_cast %arg0: vector<2xindex> to vector<2xi1>
115 // CHECK-NEXT: = llvm.sext %{{.*}} : vector<2xi1> to vector<2xi{{.*}}>
116   %1 = arith.index_cast %arg1: vector<2xi1> to vector<2xindex>
117   return
120 // -----
122 func.func @index_castui(%arg0: index, %arg1: i1) {
123 // CHECK: = llvm.trunc %0 : i{{.*}} to i1
124   %0 = arith.index_castui %arg0: index to i1
125 // CHECK-NEXT: = llvm.zext %arg1 : i1 to i{{.*}}
126   %1 = arith.index_castui %arg1: i1 to index
127   return
130 // -----
132 // CHECK-LABEL: @vector_index_castui
133 func.func @vector_index_castui(%arg0: vector<2xindex>, %arg1: vector<2xi1>) {
134 // CHECK: = llvm.trunc %{{.*}} : vector<2xi{{.*}}> to vector<2xi1>
135   %0 = arith.index_castui %arg0: vector<2xindex> to vector<2xi1>
136 // CHECK-NEXT: = llvm.zext %{{.*}} : vector<2xi1> to vector<2xi{{.*}}>
137   %1 = arith.index_castui %arg1: vector<2xi1> to vector<2xindex>
138   return
141 // -----
143 // Checking conversion of signed integer types to floating point.
144 // CHECK-LABEL: @sitofp
145 func.func @sitofp(%arg0 : i32, %arg1 : i64) {
146 // CHECK-NEXT: = llvm.sitofp {{.*}} : i32 to f32
147   %0 = arith.sitofp %arg0: i32 to f32
148 // CHECK-NEXT: = llvm.sitofp {{.*}} : i32 to f64
149   %1 = arith.sitofp %arg0: i32 to f64
150 // CHECK-NEXT: = llvm.sitofp {{.*}} : i64 to f32
151   %2 = arith.sitofp %arg1: i64 to f32
152 // CHECK-NEXT: = llvm.sitofp {{.*}} : i64 to f64
153   %3 = arith.sitofp %arg1: i64 to f64
154   return
157 // -----
159 // Checking conversion of integer vectors to floating point vector types.
160 // CHECK-LABEL: @sitofp_vector
161 func.func @sitofp_vector(%arg0 : vector<2xi16>, %arg1 : vector<2xi32>, %arg2 : vector<2xi64>) {
162 // CHECK-NEXT: = llvm.sitofp {{.*}} : vector<2xi16> to vector<2xf32>
163   %0 = arith.sitofp %arg0: vector<2xi16> to vector<2xf32>
164 // CHECK-NEXT: = llvm.sitofp {{.*}} : vector<2xi16> to vector<2xf64>
165   %1 = arith.sitofp %arg0: vector<2xi16> to vector<2xf64>
166 // CHECK-NEXT: = llvm.sitofp {{.*}} : vector<2xi32> to vector<2xf32>
167   %2 = arith.sitofp %arg1: vector<2xi32> to vector<2xf32>
168 // CHECK-NEXT: = llvm.sitofp {{.*}} : vector<2xi32> to vector<2xf64>
169   %3 = arith.sitofp %arg1: vector<2xi32> to vector<2xf64>
170 // CHECK-NEXT: = llvm.sitofp {{.*}} : vector<2xi64> to vector<2xf32>
171   %4 = arith.sitofp %arg2: vector<2xi64> to vector<2xf32>
172 // CHECK-NEXT: = llvm.sitofp {{.*}} : vector<2xi64> to vector<2xf64>
173   %5 = arith.sitofp %arg2: vector<2xi64> to vector<2xf64>
174   return
177 // -----
179 // Checking conversion of unsigned integer types to floating point.
180 // CHECK-LABEL: @uitofp
181 func.func @uitofp(%arg0 : i32, %arg1 : i64) {
182 // CHECK-NEXT: = llvm.uitofp {{.*}} : i32 to f32
183   %0 = arith.uitofp %arg0: i32 to f32
184 // CHECK-NEXT: = llvm.uitofp {{.*}} : i32 to f64
185   %1 = arith.uitofp %arg0: i32 to f64
186 // CHECK-NEXT: = llvm.uitofp {{.*}} : i64 to f32
187   %2 = arith.uitofp %arg1: i64 to f32
188 // CHECK-NEXT: = llvm.uitofp {{.*}} : i64 to f64
189   %3 = arith.uitofp %arg1: i64 to f64
190   return
193 // -----
195 // Checking conversion of integer types to floating point.
196 // CHECK-LABEL: @fpext
197 func.func @fpext(%arg0 : f16, %arg1 : f32) {
198 // CHECK-NEXT: = llvm.fpext {{.*}} : f16 to f32
199   %0 = arith.extf %arg0: f16 to f32
200 // CHECK-NEXT: = llvm.fpext {{.*}} : f16 to f64
201   %1 = arith.extf %arg0: f16 to f64
202 // CHECK-NEXT: = llvm.fpext {{.*}} : f32 to f64
203   %2 = arith.extf %arg1: f32 to f64
204   return
207 // -----
209 // Checking conversion of integer types to floating point.
210 // CHECK-LABEL: @fpext
211 func.func @fpext_vector(%arg0 : vector<2xf16>, %arg1 : vector<2xf32>) {
212 // CHECK-NEXT: = llvm.fpext {{.*}} : vector<2xf16> to vector<2xf32>
213   %0 = arith.extf %arg0: vector<2xf16> to vector<2xf32>
214 // CHECK-NEXT: = llvm.fpext {{.*}} : vector<2xf16> to vector<2xf64>
215   %1 = arith.extf %arg0: vector<2xf16> to vector<2xf64>
216 // CHECK-NEXT: = llvm.fpext {{.*}} : vector<2xf32> to vector<2xf64>
217   %2 = arith.extf %arg1: vector<2xf32> to vector<2xf64>
218   return
221 // -----
223 // Checking conversion of floating point to integer types.
224 // CHECK-LABEL: @fptosi
225 func.func @fptosi(%arg0 : f32, %arg1 : f64) {
226 // CHECK-NEXT: = llvm.fptosi {{.*}} : f32 to i32
227   %0 = arith.fptosi %arg0: f32 to i32
228 // CHECK-NEXT: = llvm.fptosi {{.*}} : f32 to i64
229   %1 = arith.fptosi %arg0: f32 to i64
230 // CHECK-NEXT: = llvm.fptosi {{.*}} : f64 to i32
231   %2 = arith.fptosi %arg1: f64 to i32
232 // CHECK-NEXT: = llvm.fptosi {{.*}} : f64 to i64
233   %3 = arith.fptosi %arg1: f64 to i64
234   return
237 // -----
239 // Checking conversion of floating point vectors to integer vector types.
240 // CHECK-LABEL: @fptosi_vector
241 func.func @fptosi_vector(%arg0 : vector<2xf16>, %arg1 : vector<2xf32>, %arg2 : vector<2xf64>) {
242 // CHECK-NEXT: = llvm.fptosi {{.*}} : vector<2xf16> to vector<2xi32>
243   %0 = arith.fptosi %arg0: vector<2xf16> to vector<2xi32>
244 // CHECK-NEXT: = llvm.fptosi {{.*}} : vector<2xf16> to vector<2xi64>
245   %1 = arith.fptosi %arg0: vector<2xf16> to vector<2xi64>
246 // CHECK-NEXT: = llvm.fptosi {{.*}} : vector<2xf32> to vector<2xi32>
247   %2 = arith.fptosi %arg1: vector<2xf32> to vector<2xi32>
248 // CHECK-NEXT: = llvm.fptosi {{.*}} : vector<2xf32> to vector<2xi64>
249   %3 = arith.fptosi %arg1: vector<2xf32> to vector<2xi64>
250 // CHECK-NEXT: = llvm.fptosi {{.*}} : vector<2xf64> to vector<2xi32>
251   %4 = arith.fptosi %arg2: vector<2xf64> to vector<2xi32>
252 // CHECK-NEXT: = llvm.fptosi {{.*}} : vector<2xf64> to vector<2xi64>
253   %5 = arith.fptosi %arg2: vector<2xf64> to vector<2xi64>
254   return
257 // -----
259 // Checking conversion of floating point to integer types.
260 // CHECK-LABEL: @fptoui
261 func.func @fptoui(%arg0 : f32, %arg1 : f64) {
262 // CHECK-NEXT: = llvm.fptoui {{.*}} : f32 to i32
263   %0 = arith.fptoui %arg0: f32 to i32
264 // CHECK-NEXT: = llvm.fptoui {{.*}} : f32 to i64
265   %1 = arith.fptoui %arg0: f32 to i64
266 // CHECK-NEXT: = llvm.fptoui {{.*}} : f64 to i32
267   %2 = arith.fptoui %arg1: f64 to i32
268 // CHECK-NEXT: = llvm.fptoui {{.*}} : f64 to i64
269   %3 = arith.fptoui %arg1: f64 to i64
270   return
273 // -----
275 // Checking conversion of floating point vectors to integer vector types.
276 // CHECK-LABEL: @fptoui_vector
277 func.func @fptoui_vector(%arg0 : vector<2xf16>, %arg1 : vector<2xf32>, %arg2 : vector<2xf64>) {
278 // CHECK-NEXT: = llvm.fptoui {{.*}} : vector<2xf16> to vector<2xi32>
279   %0 = arith.fptoui %arg0: vector<2xf16> to vector<2xi32>
280 // CHECK-NEXT: = llvm.fptoui {{.*}} : vector<2xf16> to vector<2xi64>
281   %1 = arith.fptoui %arg0: vector<2xf16> to vector<2xi64>
282 // CHECK-NEXT: = llvm.fptoui {{.*}} : vector<2xf32> to vector<2xi32>
283   %2 = arith.fptoui %arg1: vector<2xf32> to vector<2xi32>
284 // CHECK-NEXT: = llvm.fptoui {{.*}} : vector<2xf32> to vector<2xi64>
285   %3 = arith.fptoui %arg1: vector<2xf32> to vector<2xi64>
286 // CHECK-NEXT: = llvm.fptoui {{.*}} : vector<2xf64> to vector<2xi32>
287   %4 = arith.fptoui %arg2: vector<2xf64> to vector<2xi32>
288 // CHECK-NEXT: = llvm.fptoui {{.*}} : vector<2xf64> to vector<2xi64>
289   %5 = arith.fptoui %arg2: vector<2xf64> to vector<2xi64>
290   return
293 // -----
295 // Checking conversion of integer vectors to floating point vector types.
296 // CHECK-LABEL: @uitofp_vector
297 func.func @uitofp_vector(%arg0 : vector<2xi16>, %arg1 : vector<2xi32>, %arg2 : vector<2xi64>) {
298 // CHECK-NEXT: = llvm.uitofp {{.*}} : vector<2xi16> to vector<2xf32>
299   %0 = arith.uitofp %arg0: vector<2xi16> to vector<2xf32>
300 // CHECK-NEXT: = llvm.uitofp {{.*}} : vector<2xi16> to vector<2xf64>
301   %1 = arith.uitofp %arg0: vector<2xi16> to vector<2xf64>
302 // CHECK-NEXT: = llvm.uitofp {{.*}} : vector<2xi32> to vector<2xf32>
303   %2 = arith.uitofp %arg1: vector<2xi32> to vector<2xf32>
304 // CHECK-NEXT: = llvm.uitofp {{.*}} : vector<2xi32> to vector<2xf64>
305   %3 = arith.uitofp %arg1: vector<2xi32> to vector<2xf64>
306 // CHECK-NEXT: = llvm.uitofp {{.*}} : vector<2xi64> to vector<2xf32>
307   %4 = arith.uitofp %arg2: vector<2xi64> to vector<2xf32>
308 // CHECK-NEXT: = llvm.uitofp {{.*}} : vector<2xi64> to vector<2xf64>
309   %5 = arith.uitofp %arg2: vector<2xi64> to vector<2xf64>
310   return
313 // -----
315 // Checking conversion of integer types to floating point.
316 // CHECK-LABEL: @fptrunc
317 func.func @fptrunc(%arg0 : f32, %arg1 : f64) {
318 // CHECK-NEXT: = llvm.fptrunc {{.*}} : f32 to f16
319   %0 = arith.truncf %arg0: f32 to f16
320 // CHECK-NEXT: = llvm.fptrunc {{.*}} : f64 to f16
321   %1 = arith.truncf %arg1: f64 to f16
322 // CHECK-NEXT: = llvm.fptrunc {{.*}} : f64 to f32
323   %2 = arith.truncf %arg1: f64 to f32
324   return
327 // -----
329 // Checking conversion of integer types to floating point.
330 // CHECK-LABEL: @fptrunc
331 func.func @fptrunc_vector(%arg0 : vector<2xf32>, %arg1 : vector<2xf64>) {
332 // CHECK-NEXT: = llvm.fptrunc {{.*}} : vector<2xf32> to vector<2xf16>
333   %0 = arith.truncf %arg0: vector<2xf32> to vector<2xf16>
334 // CHECK-NEXT: = llvm.fptrunc {{.*}} : vector<2xf64> to vector<2xf16>
335   %1 = arith.truncf %arg1: vector<2xf64> to vector<2xf16>
336 // CHECK-NEXT: = llvm.fptrunc {{.*}} : vector<2xf64> to vector<2xf32>
337   %2 = arith.truncf %arg1: vector<2xf64> to vector<2xf32>
338   return
341 // -----
343 // CHECK-LABEL: experimental_constrained_fptrunc
344 func.func @experimental_constrained_fptrunc(%arg0 : f64) {
345 // CHECK-NEXT: = llvm.intr.experimental.constrained.fptrunc {{.*}} tonearest ignore : f64 to f32
346   %0 = arith.truncf %arg0 to_nearest_even : f64 to f32
347 // CHECK-NEXT: = llvm.intr.experimental.constrained.fptrunc {{.*}} downward ignore : f64 to f32
348   %1 = arith.truncf %arg0 downward : f64 to f32
349 // CHECK-NEXT: = llvm.intr.experimental.constrained.fptrunc {{.*}} upward ignore : f64 to f32
350   %2 = arith.truncf %arg0 upward : f64 to f32
351 // CHECK-NEXT: = llvm.intr.experimental.constrained.fptrunc {{.*}} towardzero ignore : f64 to f32
352   %3 = arith.truncf %arg0 toward_zero : f64 to f32
353 // CHECK-NEXT: = llvm.intr.experimental.constrained.fptrunc {{.*}} tonearestaway ignore : f64 to f32
354   %4 = arith.truncf %arg0 to_nearest_away : f64 to f32
355   return
358 // -----
360 // Check sign and zero extension and truncation of integers.
361 // CHECK-LABEL: @integer_extension_and_truncation
362 func.func @integer_extension_and_truncation(%arg0 : i3) {
363 // CHECK-NEXT: = llvm.sext %arg0 : i3 to i6
364   %0 = arith.extsi %arg0 : i3 to i6
365 // CHECK-NEXT: = llvm.zext %arg0 : i3 to i6
366   %1 = arith.extui %arg0 : i3 to i6
367 // CHECK-NEXT: = llvm.trunc %arg0 : i3 to i2
368    %2 = arith.trunci %arg0 : i3 to i2
369   return
372 // -----
374 // CHECK-LABEL: @integer_cast_0d_vector
375 func.func @integer_cast_0d_vector(%arg0 : vector<i3>) {
376 // CHECK: %[[ARG0:.*]] = builtin.unrealized_conversion_cast
377 // CHECK-NEXT: = llvm.sext %[[ARG0]] : vector<1xi3> to vector<1xi6>
378   %0 = arith.extsi %arg0 : vector<i3> to vector<i6>
379 // CHECK-NEXT: = llvm.zext %[[ARG0]] : vector<1xi3> to vector<1xi6>
380   %1 = arith.extui %arg0 : vector<i3> to vector<i6>
381 // CHECK-NEXT: = llvm.trunc %[[ARG0]] : vector<1xi3> to vector<1xi2>
382   %2 = arith.trunci %arg0 : vector<i3> to vector<i2>
383   return
386 // -----
388 // CHECK-LABEL: func @fcmp(%arg0: f32, %arg1: f32) {
389 func.func @fcmp(f32, f32) -> () {
390 ^bb0(%arg0: f32, %arg1: f32):
391   // CHECK:      llvm.fcmp "oeq" %arg0, %arg1 : f32
392   // CHECK-NEXT: llvm.fcmp "ogt" %arg0, %arg1 : f32
393   // CHECK-NEXT: llvm.fcmp "oge" %arg0, %arg1 : f32
394   // CHECK-NEXT: llvm.fcmp "olt" %arg0, %arg1 : f32
395   // CHECK-NEXT: llvm.fcmp "ole" %arg0, %arg1 : f32
396   // CHECK-NEXT: llvm.fcmp "one" %arg0, %arg1 : f32
397   // CHECK-NEXT: llvm.fcmp "ord" %arg0, %arg1 : f32
398   // CHECK-NEXT: llvm.fcmp "ueq" %arg0, %arg1 : f32
399   // CHECK-NEXT: llvm.fcmp "ugt" %arg0, %arg1 : f32
400   // CHECK-NEXT: llvm.fcmp "uge" %arg0, %arg1 : f32
401   // CHECK-NEXT: llvm.fcmp "ult" %arg0, %arg1 : f32
402   // CHECK-NEXT: llvm.fcmp "ule" %arg0, %arg1 : f32
403   // CHECK-NEXT: llvm.fcmp "une" %arg0, %arg1 : f32
404   // CHECK-NEXT: llvm.fcmp "uno" %arg0, %arg1 : f32
405   // CHECK-NEXT: llvm.fcmp "oeq" %arg0, %arg1 {fastmathFlags = #llvm.fastmath<fast>} : f32
406   // CHECK-NEXT: return
407   %1 = arith.cmpf oeq, %arg0, %arg1 : f32
408   %2 = arith.cmpf ogt, %arg0, %arg1 : f32
409   %3 = arith.cmpf oge, %arg0, %arg1 : f32
410   %4 = arith.cmpf olt, %arg0, %arg1 : f32
411   %5 = arith.cmpf ole, %arg0, %arg1 : f32
412   %6 = arith.cmpf one, %arg0, %arg1 : f32
413   %7 = arith.cmpf ord, %arg0, %arg1 : f32
414   %8 = arith.cmpf ueq, %arg0, %arg1 : f32
415   %9 = arith.cmpf ugt, %arg0, %arg1 : f32
416   %10 = arith.cmpf uge, %arg0, %arg1 : f32
417   %11 = arith.cmpf ult, %arg0, %arg1 : f32
418   %12 = arith.cmpf ule, %arg0, %arg1 : f32
419   %13 = arith.cmpf une, %arg0, %arg1 : f32
420   %14 = arith.cmpf uno, %arg0, %arg1 : f32
422   %15 = arith.cmpf oeq, %arg0, %arg1 {fastmath = #arith.fastmath<fast>} : f32
424   return
427 // -----
429 // CHECK-LABEL: @index_vector
430 func.func @index_vector(%arg0: vector<4xindex>) {
431   // CHECK: %[[CST:.*]] = llvm.mlir.constant(dense<[0, 1, 2, 3]> : vector<4xindex>) : vector<4xi64>
432   %0 = arith.constant dense<[0, 1, 2, 3]> : vector<4xindex>
433   // CHECK: %[[V:.*]] = llvm.add %{{.*}}, %[[CST]] : vector<4xi64>
434   %1 = arith.addi %arg0, %0 : vector<4xindex>
435   func.return
438 // -----
440 // CHECK-LABEL: @bitcast_1d
441 func.func @bitcast_1d(%arg0: vector<2xf32>) {
442   // CHECK: llvm.bitcast %{{.*}} : vector<2xf32> to vector<2xi32>
443   arith.bitcast %arg0 : vector<2xf32> to vector<2xi32>
444   return
447 // -----
449 // CHECK-LABEL: @addui_extended_scalar
450 // CHECK-SAME:    ([[ARG0:%.+]]: i32, [[ARG1:%.+]]: i32) -> (i32, i1)
451 func.func @addui_extended_scalar(%arg0: i32, %arg1: i32) -> (i32, i1) {
452   // CHECK-NEXT: [[RES:%.+]] = "llvm.intr.uadd.with.overflow"([[ARG0]], [[ARG1]]) : (i32, i32) -> !llvm.struct<(i32, i1)>
453   // CHECK-NEXT: [[SUM:%.+]] = llvm.extractvalue [[RES]][0] : !llvm.struct<(i32, i1)>
454   // CHECK-NEXT: [[CARRY:%.+]] = llvm.extractvalue [[RES]][1] : !llvm.struct<(i32, i1)>
455   %sum, %carry = arith.addui_extended %arg0, %arg1 : i32, i1
456   // CHECK-NEXT: return [[SUM]], [[CARRY]] : i32, i1
457   return %sum, %carry : i32, i1
460 // CHECK-LABEL: @addui_extended_vector1d
461 // CHECK-SAME:    ([[ARG0:%.+]]: vector<3xi16>, [[ARG1:%.+]]: vector<3xi16>) -> (vector<3xi16>, vector<3xi1>)
462 func.func @addui_extended_vector1d(%arg0: vector<3xi16>, %arg1: vector<3xi16>) -> (vector<3xi16>, vector<3xi1>) {
463   // CHECK-NEXT: [[RES:%.+]] = "llvm.intr.uadd.with.overflow"([[ARG0]], [[ARG1]]) : (vector<3xi16>, vector<3xi16>) -> !llvm.struct<(vector<3xi16>, vector<3xi1>)>
464   // CHECK-NEXT: [[SUM:%.+]] = llvm.extractvalue [[RES]][0] : !llvm.struct<(vector<3xi16>, vector<3xi1>)>
465   // CHECK-NEXT: [[CARRY:%.+]] = llvm.extractvalue [[RES]][1] : !llvm.struct<(vector<3xi16>, vector<3xi1>)>
466   %sum, %carry = arith.addui_extended %arg0, %arg1 : vector<3xi16>, vector<3xi1>
467   // CHECK-NEXT: return [[SUM]], [[CARRY]] : vector<3xi16>, vector<3xi1>
468   return %sum, %carry : vector<3xi16>, vector<3xi1>
471 // -----
473 // CHECK-LABEL: @mulsi_extended_scalar
474 // CHECK-SAME:    ([[ARG0:%.+]]: i32, [[ARG1:%.+]]: i32) -> (i32, i32)
475 func.func @mulsi_extended_scalar(%arg0: i32, %arg1: i32) -> (i32, i32) {
476   // CHECK-NEXT: [[LHS:%.+]]  = llvm.sext [[ARG0]] : i32 to i64
477   // CHECK-NEXT: [[RHS:%.+]]  = llvm.sext [[ARG1]] : i32 to i64
478   // CHECK-NEXT: [[MUL:%.+]]  = llvm.mul [[LHS]], [[RHS]] : i64
479   // CHECK-NEXT: [[LOW:%.+]]  = llvm.trunc [[MUL]] : i64 to i32
480   // CHECK-NEXT: [[C32:%.+]]  = llvm.mlir.constant(32 : i64) : i64
481   // CHECK-NEXT: [[SHL:%.+]]  = llvm.lshr [[MUL]], [[C32]] : i64
482   // CHECK-NEXT: [[HIGH:%.+]] = llvm.trunc [[SHL]] : i64 to i32
483   %low, %high = arith.mulsi_extended %arg0, %arg1 : i32
484   // CHECK-NEXT: return [[LOW]], [[HIGH]] : i32, i32
485   return %low, %high : i32, i32
488 // CHECK-LABEL: @mulsi_extended_vector1d
489 // CHECK-SAME:    ([[ARG0:%.+]]: vector<3xi64>, [[ARG1:%.+]]: vector<3xi64>) -> (vector<3xi64>, vector<3xi64>)
490 func.func @mulsi_extended_vector1d(%arg0: vector<3xi64>, %arg1: vector<3xi64>) -> (vector<3xi64>, vector<3xi64>) {
491   // CHECK-NEXT: [[LHS:%.+]]  = llvm.sext [[ARG0]] : vector<3xi64> to vector<3xi128>
492   // CHECK-NEXT: [[RHS:%.+]]  = llvm.sext [[ARG1]] : vector<3xi64> to vector<3xi128>
493   // CHECK-NEXT: [[MUL:%.+]]  = llvm.mul [[LHS]], [[RHS]] : vector<3xi128>
494   // CHECK-NEXT: [[LOW:%.+]]  = llvm.trunc [[MUL]] : vector<3xi128> to vector<3xi64>
495   // CHECK-NEXT: [[C64:%.+]]  = llvm.mlir.constant(dense<64> : vector<3xi128>) : vector<3xi128>
496   // CHECK-NEXT: [[SHL:%.+]]  = llvm.lshr [[MUL]], [[C64]] : vector<3xi128>
497   // CHECK-NEXT: [[HIGH:%.+]] = llvm.trunc [[SHL]] : vector<3xi128> to vector<3xi64>
498   %low, %high = arith.mulsi_extended %arg0, %arg1 : vector<3xi64>
499   // CHECK-NEXT: return [[LOW]], [[HIGH]] : vector<3xi64>, vector<3xi64>
500   return %low, %high : vector<3xi64>, vector<3xi64>
503 // -----
505 // CHECK-LABEL: @mului_extended_scalar
506 // CHECK-SAME:    ([[ARG0:%.+]]: i32, [[ARG1:%.+]]: i32) -> (i32, i32)
507 func.func @mului_extended_scalar(%arg0: i32, %arg1: i32) -> (i32, i32) {
508   // CHECK-NEXT: [[LHS:%.+]]  = llvm.zext [[ARG0]] : i32 to i64
509   // CHECK-NEXT: [[RHS:%.+]]  = llvm.zext [[ARG1]] : i32 to i64
510   // CHECK-NEXT: [[MUL:%.+]]  = llvm.mul [[LHS]], [[RHS]] : i64
511   // CHECK-NEXT: [[LOW:%.+]]  = llvm.trunc [[MUL]] : i64 to i32
512   // CHECK-NEXT: [[C32:%.+]]  = llvm.mlir.constant(32 : i64) : i64
513   // CHECK-NEXT: [[SHL:%.+]]  = llvm.lshr [[MUL]], [[C32]] : i64
514   // CHECK-NEXT: [[HIGH:%.+]] = llvm.trunc [[SHL]] : i64 to i32
515   %low, %high = arith.mului_extended %arg0, %arg1 : i32
516   // CHECK-NEXT: return [[LOW]], [[HIGH]] : i32, i32
517   return %low, %high : i32, i32
520 // CHECK-LABEL: @mului_extended_vector1d
521 // CHECK-SAME:    ([[ARG0:%.+]]: vector<3xi64>, [[ARG1:%.+]]: vector<3xi64>) -> (vector<3xi64>, vector<3xi64>)
522 func.func @mului_extended_vector1d(%arg0: vector<3xi64>, %arg1: vector<3xi64>) -> (vector<3xi64>, vector<3xi64>) {
523   // CHECK-NEXT: [[LHS:%.+]]  = llvm.zext [[ARG0]] : vector<3xi64> to vector<3xi128>
524   // CHECK-NEXT: [[RHS:%.+]]  = llvm.zext [[ARG1]] : vector<3xi64> to vector<3xi128>
525   // CHECK-NEXT: [[MUL:%.+]]  = llvm.mul [[LHS]], [[RHS]] : vector<3xi128>
526   // CHECK-NEXT: [[LOW:%.+]]  = llvm.trunc [[MUL]] : vector<3xi128> to vector<3xi64>
527   // CHECK-NEXT: [[C64:%.+]]  = llvm.mlir.constant(dense<64> : vector<3xi128>) : vector<3xi128>
528   // CHECK-NEXT: [[SHL:%.+]]  = llvm.lshr [[MUL]], [[C64]] : vector<3xi128>
529   // CHECK-NEXT: [[HIGH:%.+]] = llvm.trunc [[SHL]] : vector<3xi128> to vector<3xi64>
530   %low, %high = arith.mului_extended %arg0, %arg1 : vector<3xi64>
531   // CHECK-NEXT: return [[LOW]], [[HIGH]] : vector<3xi64>, vector<3xi64>
532   return %low, %high : vector<3xi64>, vector<3xi64>
535 // -----
537 // CHECK-LABEL: func @cmpf_2dvector(
538 //  CHECK-SAME:     %[[OARG0:.*]]: vector<4x3xf32>, %[[OARG1:.*]]: vector<4x3xf32>)
539 func.func @cmpf_2dvector(%arg0 : vector<4x3xf32>, %arg1 : vector<4x3xf32>) {
540   // CHECK-DAG: %[[ARG0:.*]] = builtin.unrealized_conversion_cast %[[OARG0]]
541   // CHECK-DAG: %[[ARG1:.*]] = builtin.unrealized_conversion_cast %[[OARG1]]
542   // CHECK: %[[EXTRACT1:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.array<4 x vector<3xf32>>
543   // CHECK: %[[EXTRACT2:.*]] = llvm.extractvalue %[[ARG1]][0] : !llvm.array<4 x vector<3xf32>>
544   // CHECK: %[[CMP:.*]] = llvm.fcmp "olt" %[[EXTRACT1]], %[[EXTRACT2]] : vector<3xf32>
545   // CHECK: %[[INSERT:.*]] = llvm.insertvalue %[[CMP]], %2[0] : !llvm.array<4 x vector<3xi1>>
546   %0 = arith.cmpf olt, %arg0, %arg1 : vector<4x3xf32>
547   func.return
550 // -----
552 // CHECK-LABEL: func @cmpi_0dvector(
553 //  CHECK-SAME:     %[[OARG0:.*]]: vector<i32>, %[[OARG1:.*]]: vector<i32>)
554 func.func @cmpi_0dvector(%arg0 : vector<i32>, %arg1 : vector<i32>) {
555   // CHECK-DAG: %[[ARG0:.*]] = builtin.unrealized_conversion_cast %[[OARG0]]
556   // CHECK-DAG: %[[ARG1:.*]] = builtin.unrealized_conversion_cast %[[OARG1]]
557   // CHECK: %[[CMP:.*]] = llvm.icmp "ult" %[[ARG0]], %[[ARG1]] : vector<1xi32>
558   %0 = arith.cmpi ult, %arg0, %arg1 : vector<i32>
559   func.return
562 // -----
564 // CHECK-LABEL: func @cmpi_2dvector(
565 //  CHECK-SAME:     %[[OARG0:.*]]: vector<4x3xi32>, %[[OARG1:.*]]: vector<4x3xi32>)
566 func.func @cmpi_2dvector(%arg0 : vector<4x3xi32>, %arg1 : vector<4x3xi32>) {
567   // CHECK-DAG: %[[ARG0:.*]] = builtin.unrealized_conversion_cast %[[OARG0]]
568   // CHECK-DAG: %[[ARG1:.*]] = builtin.unrealized_conversion_cast %[[OARG1]]
569   // CHECK: %[[EXTRACT1:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.array<4 x vector<3xi32>>
570   // CHECK: %[[EXTRACT2:.*]] = llvm.extractvalue %[[ARG1]][0] : !llvm.array<4 x vector<3xi32>>
571   // CHECK: %[[CMP:.*]] = llvm.icmp "ult" %[[EXTRACT1]], %[[EXTRACT2]] : vector<3xi32>
572   // CHECK: %[[INSERT:.*]] = llvm.insertvalue %[[CMP]], %2[0] : !llvm.array<4 x vector<3xi1>>
573   %0 = arith.cmpi ult, %arg0, %arg1 : vector<4x3xi32>
574   func.return
577 // -----
579 // CHECK-LABEL: @select
580 func.func @select(%arg0 : i1, %arg1 : i32, %arg2 : i32) -> i32 {
581   // CHECK: = llvm.select %arg0, %arg1, %arg2 : i1, i32
582   %0 = arith.select %arg0, %arg1, %arg2 : i32
583   return %0 : i32
586 // -----
588 // CHECK-LABEL: @ceildivsi
589 // CHECK-SAME: %[[ARG0:.*]]: i64) -> i64
590 func.func @ceildivsi(%arg0 : i64) -> i64 {
591   // CHECK: %[[CST0:.*]] = llvm.mlir.constant(1 : i64) : i64
592   // CHECK: %[[CST1:.*]] = llvm.mlir.constant(0 : i64) : i64
593   // CHECK: %[[CST2:.*]] = llvm.mlir.constant(-1 : i64) : i64
594   // CHECK: %[[CMP0:.*]] = llvm.icmp "sgt" %[[ARG0]], %[[CST1]] : i64
595   // CHECK: %[[SEL0:.*]] = llvm.select %[[CMP0]], %[[CST2]], %[[CST0]] : i1, i64
596   // CHECK: %[[ADD0:.*]] = llvm.add %[[SEL0]], %[[ARG0]] : i64
597   // CHECK: %[[DIV0:.*]] = llvm.sdiv %[[ADD0]], %[[ARG0]] : i64
598   // CHECK: %[[ADD1:.*]] = llvm.add %[[DIV0]], %[[CST0]] : i64
599   // CHECK: %[[SUB0:.*]] = llvm.sub %[[CST1]], %[[ARG0]] : i64
600   // CHECK: %[[DIV1:.*]] = llvm.sdiv %[[SUB0]], %[[ARG0]] : i64
601   // CHECK: %[[SUB1:.*]] = llvm.sub %[[CST1]], %[[DIV1]] : i64
602   // CHECK: %[[CMP1:.*]] = llvm.icmp "slt" %[[ARG0]], %[[CST1]] : i64
603   // CHECK: %[[CMP2:.*]] = llvm.icmp "sgt" %[[ARG0]], %[[CST1]] : i64
604   // CHECK: %[[CMP3:.*]] = llvm.icmp "slt" %[[ARG0]], %[[CST1]] : i64
605   // CHECK: %[[CMP4:.*]] = llvm.icmp "sgt" %[[ARG0]], %[[CST1]] : i64
606   // CHECK: %[[AND0:.*]] = llvm.and %[[CMP1]], %[[CMP3]] : i1
607   // CHECK: %[[AND1:.*]] = llvm.and %[[CMP2]], %[[CMP4]] : i1
608   // CHECK: %[[OR:.*]] = llvm.or %[[AND0]], %[[AND1]] : i1
609   // CHECK: %[[SEL1:.*]] = llvm.select %[[OR]], %[[ADD1]], %[[SUB1]] : i1, i64
610   %0 = arith.ceildivsi %arg0, %arg0 : i64
611   return %0: i64
614 // CHECK-LABEL: @ceildivui
615 // CHECK-SAME: %[[ARG0:.*]]: i32) -> i32
616 func.func @ceildivui(%arg0 : i32) -> i32 {
617 // CHECK: %[[CST0:.*]] = llvm.mlir.constant(0 : i32) : i32
618 // CHECK: %[[CMP0:.*]] = llvm.icmp "eq" %[[ARG0]], %[[CST0]] : i32
619 // CHECK: %[[CST1:.*]] = llvm.mlir.constant(1 : i32) : i32
620 // CHECK: %[[SUB0:.*]] = llvm.sub %[[ARG0]], %[[CST1]] : i32
621 // CHECK: %[[DIV0:.*]] = llvm.udiv %[[SUB0]], %[[ARG0]] : i32
622 // CHECK: %[[ADD0:.*]] = llvm.add %[[DIV0]], %[[CST1]] : i32
623 // CHECK: %[[SEL0:.*]] = llvm.select %[[CMP0]], %[[CST0]], %[[ADD0]] : i1, i32
624   %0 = arith.ceildivui %arg0, %arg0 : i32
625   return %0: i32
628 // -----
630 // CHECK-LABEL: @floordivsi
631 // CHECK-SAME: %[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32) -> i32
632 func.func @floordivsi(%arg0 : i32, %arg1 : i32) -> i32 {
633   // CHECK: %[[SDIV:.*]] = llvm.sdiv %[[ARG0]], %[[ARG1]] : i32
634   // CHECK: %[[MUL0:.*]] = llvm.mul %[[SDIV]], %[[ARG1]] : i32
635   // CHECK: %[[CMP0:.*]] = llvm.icmp "ne" %[[ARG0]], %[[MUL0]] : i32
636   // CHECK: %[[CST0:.*]] = llvm.mlir.constant(0 : i32) : i32
637   // CHECK: %[[CMP1:.*]] = llvm.icmp "slt" %[[ARG0]], %[[CST0]] : i32
638   // CHECK: %[[CMP2:.*]] = llvm.icmp "slt" %[[ARG1]], %[[CST0]] : i32
639   // CHECK: %[[CMP3:.*]] = llvm.icmp "ne" %[[CMP1]], %[[CMP2]] : i1
640   // CHECK: %[[AND:.*]] = llvm.and %[[CMP0]], %[[CMP3]] : i1
641   // CHECK: %[[CST1:.*]] = llvm.mlir.constant(-1 : i32) : i32
642   // CHECK: %[[ADD:.*]] = llvm.add %[[SDIV]], %[[CST1]] : i32
643   // CHECK: %[[SEL:.*]] = llvm.select %[[AND]], %[[ADD]], %[[SDIV]] : i1, i32
644   %0 = arith.floordivsi %arg0, %arg1 : i32
645   return %0 : i32
648 // -----
650 // CHECK-LABEL: @minmaxi
651 func.func @minmaxi(%arg0 : i32, %arg1 : i32) -> i32 {
652   // CHECK: = llvm.intr.smin(%arg0, %arg1) : (i32, i32) -> i32
653   %0 = arith.minsi %arg0, %arg1 : i32
654   // CHECK: = llvm.intr.smax(%arg0, %arg1) : (i32, i32) -> i32
655   %1 = arith.maxsi %arg0, %arg1 : i32
656   // CHECK: = llvm.intr.umin(%arg0, %arg1) : (i32, i32) -> i32
657   %2 = arith.minui %arg0, %arg1 : i32
658   // CHECK: = llvm.intr.umax(%arg0, %arg1) : (i32, i32) -> i32
659   %3 = arith.maxui %arg0, %arg1 : i32
660   return %0 : i32
663 // CHECK-LABEL: @minmaxf
664 func.func @minmaxf(%arg0 : f32, %arg1 : f32) -> f32 {
665   // CHECK: = llvm.intr.minimum(%arg0, %arg1) : (f32, f32) -> f32
666   %0 = arith.minimumf %arg0, %arg1 : f32
667   // CHECK: = llvm.intr.maximum(%arg0, %arg1) : (f32, f32) -> f32
668   %1 = arith.maximumf %arg0, %arg1 : f32
669   // CHECK: = llvm.intr.minnum(%arg0, %arg1) : (f32, f32) -> f32
670   %2 = arith.minnumf %arg0, %arg1 : f32
671   // CHECK: = llvm.intr.maxnum(%arg0, %arg1) : (f32, f32) -> f32
672   %3 = arith.maxnumf %arg0, %arg1 : f32
673   return %0 : f32
676 // -----
678 // CHECK-LABEL: @fastmath
679 func.func @fastmath(%arg0: f32, %arg1: f32, %arg2: i32) {
680 // CHECK: llvm.fadd %arg0, %arg1  {fastmathFlags = #llvm.fastmath<fast>} : f32
681 // CHECK: llvm.fmul %arg0, %arg1  {fastmathFlags = #llvm.fastmath<fast>} : f32
682 // CHECK: llvm.fneg %arg0  {fastmathFlags = #llvm.fastmath<fast>} : f32
683 // CHECK: llvm.fadd %arg0, %arg1  : f32
684 // CHECK: llvm.fadd %arg0, %arg1  {fastmathFlags = #llvm.fastmath<nnan, ninf>} : f32
685   %0 = arith.addf %arg0, %arg1 fastmath<fast> : f32
686   %1 = arith.mulf %arg0, %arg1 fastmath<fast> : f32
687   %2 = arith.negf %arg0 fastmath<fast> : f32
688   %3 = arith.addf %arg0, %arg1 fastmath<none> : f32
689   %4 = arith.addf %arg0, %arg1 fastmath<nnan,ninf> : f32
690   return
693 // -----
695 // CHECK-LABEL: @ops_supporting_fastmath
696 func.func @ops_supporting_fastmath(%arg0: f32, %arg1: f32, %arg2: i32) {
697 // CHECK: llvm.fadd %arg0, %arg1  {fastmathFlags = #llvm.fastmath<fast>} : f32
698   %0 = arith.addf %arg0, %arg1 fastmath<fast> : f32
699 // CHECK: llvm.fdiv %arg0, %arg1  {fastmathFlags = #llvm.fastmath<fast>} : f32
700   %1 = arith.divf %arg0, %arg1 fastmath<fast> : f32
701 // CHECK: llvm.intr.maximum(%arg0, %arg1) {fastmathFlags = #llvm.fastmath<fast>} : (f32, f32) -> f32
702   %2 = arith.maximumf %arg0, %arg1 fastmath<fast> : f32
703 // CHECK: llvm.intr.minimum(%arg0, %arg1) {fastmathFlags = #llvm.fastmath<fast>} : (f32, f32) -> f32
704   %3 = arith.minimumf %arg0, %arg1 fastmath<fast> : f32
705 // CHECK: llvm.fmul %arg0, %arg1  {fastmathFlags = #llvm.fastmath<fast>} : f32
706   %4 = arith.mulf %arg0, %arg1 fastmath<fast> : f32
707 // CHECK: llvm.fneg %arg0  {fastmathFlags = #llvm.fastmath<fast>} : f32
708   %5 = arith.negf %arg0 fastmath<fast> : f32
709 // CHECK: llvm.frem %arg0, %arg1  {fastmathFlags = #llvm.fastmath<fast>} : f32
710   %6 = arith.remf %arg0, %arg1 fastmath<fast> : f32
711 // CHECK: llvm.fsub %arg0, %arg1  {fastmathFlags = #llvm.fastmath<fast>} : f32
712   %7 = arith.subf %arg0, %arg1 fastmath<fast> : f32
713   return
716 // -----
718 // CHECK-LABEL: @ops_supporting_overflow
719 func.func @ops_supporting_overflow(%arg0: i64, %arg1: i64) {
720   // CHECK: %{{.*}} = llvm.add %{{.*}}, %{{.*}} overflow<nsw> : i64
721   %0 = arith.addi %arg0, %arg1 overflow<nsw> : i64
722   // CHECK: %{{.*}} = llvm.sub %{{.*}}, %{{.*}} overflow<nuw> : i64
723   %1 = arith.subi %arg0, %arg1 overflow<nuw> : i64
724   // CHECK: %{{.*}} = llvm.mul %{{.*}}, %{{.*}} overflow<nsw, nuw> : i64
725   %2 = arith.muli %arg0, %arg1 overflow<nsw, nuw> : i64
726   // CHECK: %{{.*}} = llvm.shl %{{.*}}, %{{.*}} overflow<nsw, nuw> : i64
727   %3 = arith.shli %arg0, %arg1 overflow<nsw, nuw> : i64
728   return