xref: /llvm-project/mlir/test/Dialect/Math/expand-math.mlir (revision 3a3377579f137a0a6e14b60d891a9736707e7e8d)
1// RUN: mlir-opt %s --split-input-file -test-expand-math | FileCheck %s
2
3// CHECK-LABEL: func @tanh
4func.func @tanh(%arg: f32) -> f32 {
5  %res = math.tanh %arg : f32
6  return %res : f32
7}
8// CHECK-DAG: %[[ZERO:.+]] = arith.constant 0.000000e+00 : f32
9// CHECK-DAG: %[[ONE:.+]] = arith.constant 1.000000e+00 : f32
10// CHECK-DAG: %[[TWO:.+]] = arith.constant -2.000000e+00 : f32
11// CHECK: %[[VAL0:.+]] = arith.cmpf olt, %arg0, %[[ZERO]] : f32
12// CHECK: %[[VAL1:.+]] = arith.uitofp %[[VAL0]] : i1 to f32
13// CHECK: %[[VAL2:.+]] = arith.mulf %[[VAL1]], %[[TWO]] : f32
14// CHECK: %[[SIGN:.+]] = arith.addf %[[VAL2]], %[[ONE]] : f32
15// CHECK: %[[POSX:.+]] = arith.mulf %[[SIGN]], %arg0 : f32
16// CHECK: %[[NEGDOUBLEDX:.+]] = arith.mulf %[[POSX]], %[[TWO]] : f32
17// CHECK: %[[EXP1:.+]] = math.exp %[[NEGDOUBLEDX]] : f32
18// CHECK: %[[DIVIDEND1:.+]] = arith.subf %[[ONE]], %[[EXP1]] : f32
19// CHECK: %[[DIVISOR1:.+]] = arith.addf %[[EXP1]], %[[ONE]] : f32
20// CHECK: %[[POSRES:.+]] = arith.divf %[[DIVIDEND1]], %[[DIVISOR1]] : f32
21// CHECK: %[[RESULT:.+]] = arith.mulf %[[SIGN]], %[[POSRES]] : f32
22// CHECK: return %[[RESULT]]
23
24// -----
25
26
27// CHECK-LABEL: func @vector_tanh
28func.func @vector_tanh(%arg: vector<4xf32>) -> vector<4xf32> {
29  // CHECK-NOT: math.tanh
30  %res = math.tanh %arg : vector<4xf32>
31  return %res : vector<4xf32>
32}
33
34// -----
35
36// CHECK-LABEL: func @tan
37func.func @tan(%arg: f32) -> f32 {
38  %res = math.tan %arg : f32
39  return %res : f32
40}
41
42// CHECK-SAME: %[[ARG0:.+]]: f32
43// CHECK: %[[SIN:.+]] = math.sin %[[ARG0]]
44// CHECK: %[[COS:.+]] = math.cos %[[ARG0]]
45// CHECK: %[[DIV:.+]] = arith.divf %[[SIN]], %[[COS]]
46
47
48// -----
49
50// CHECK-LABEL: func @vector_tan
51func.func @vector_tan(%arg: vector<4xf32>) -> vector<4xf32> {
52  %res = math.tan %arg : vector<4xf32>
53  return %res : vector<4xf32>
54}
55
56// CHECK-NOT: math.tan
57
58// -----
59
60func.func @ctlz(%arg: i32) -> i32 {
61  %res = math.ctlz %arg : i32
62  return %res : i32
63}
64
65// CHECK-LABEL: @ctlz
66// CHECK-SAME: %[[ARG0:.+]]: i32
67// CHECK-DAG: %[[C0:.+]] = arith.constant 0 : i32
68// CHECK-DAG: %[[C16:.+]] = arith.constant 16 : i32
69// CHECK-DAG: %[[C65535:.+]] = arith.constant 65535 : i32
70// CHECK-DAG: %[[C8:.+]] = arith.constant 8 : i32
71// CHECK-DAG: %[[C16777215:.+]] = arith.constant 16777215 : i32
72// CHECK-DAG: %[[C4:.+]] = arith.constant 4 : i32
73// CHECK-DAG: %[[C268435455:.+]] = arith.constant 268435455 : i32
74// CHECK-DAG: %[[C2:.+]] = arith.constant 2 : i32
75// CHECK-DAG: %[[C1073741823:.+]] = arith.constant 1073741823 : i32
76// CHECK-DAG: %[[C1:.+]] = arith.constant 1 : i32
77// CHECK-DAG: %[[C2147483647:.+]] = arith.constant 2147483647 : i32
78// CHECK-DAG: %[[C32:.+]] = arith.constant 32 : i32
79
80// CHECK: %[[PRED:.+]] = arith.cmpi ule, %[[ARG0]], %[[C65535]]
81// CHECK: %[[SHL:.+]] = arith.shli %[[ARG0]], %[[C16]]
82// CHECK: %[[SELX0:.+]] = arith.select %[[PRED]], %[[SHL]], %[[ARG0]]
83// CHECK: %[[SELY0:.+]] = arith.select %[[PRED]], %[[C16]], %[[C0]]
84
85// CHECK: %[[PRED:.+]] = arith.cmpi ule, %[[SELX0]], %[[C16777215]]
86// CHECK: %[[ADD:.+]] = arith.addi %[[SELY0]], %[[C8]]
87// CHECK: %[[SHL:.+]] = arith.shli %[[SELX0]], %[[C8]]
88// CHECK: %[[SELX1:.+]] = arith.select %[[PRED]], %[[SHL]], %[[SELX0]]
89// CHECK: %[[SELY1:.+]] = arith.select %[[PRED]], %[[ADD]], %[[SELY0]]
90
91// CHECK: %[[PRED:.+]] = arith.cmpi ule, %[[SELX1]], %[[C268435455]] : i32
92// CHECK: %[[ADD:.+]] = arith.addi %[[SELY1]], %[[C4]]
93// CHECK: %[[SHL:.+]] = arith.shli %[[SELX1]], %[[C4]]
94// CHECK: %[[SELX2:.+]] = arith.select %[[PRED]], %[[SHL]], %[[SELX1]]
95// CHECK: %[[SELY2:.+]] = arith.select %[[PRED]], %[[ADD]], %[[SELY1]]
96
97
98// CHECK: %[[PRED:.+]] = arith.cmpi ule, %[[SELX2]], %[[C1073741823]] : i32
99// CHECK: %[[ADD:.+]] = arith.addi %[[SELY2]], %[[C2]]
100// CHECK: %[[SHL:.+]] = arith.shli %[[SELX2]], %[[C2]]
101// CHECK: %[[SELX3:.+]] = arith.select %[[PRED]], %[[SHL]], %[[SELX2]]
102// CHECK: %[[SELY3:.+]] = arith.select %[[PRED]], %[[ADD]], %[[SELY2]]
103
104// CHECK: %[[PRED:.+]] = arith.cmpi ule, %[[SELX3]], %[[C2147483647]] : i32
105// CHECK: %[[ADD:.+]] = arith.addi %[[SELY3]], %[[C1]]
106// CHECK: %[[SELY4:.+]] = arith.select %[[PRED]], %[[ADD]], %[[SELY3]]
107
108// CHECK: %[[PRED:.+]] = arith.cmpi eq, %[[ARG0]], %[[C0]] : i32
109// CHECK: %[[SEL:.+]] = arith.select %[[PRED]], %[[C32]], %[[SELY4]] : i32
110// CHECK: return %[[SEL]]
111
112// -----
113
114func.func @ctlz_vector(%arg: vector<4xi32>) -> vector<4xi32> {
115  %res = math.ctlz %arg : vector<4xi32>
116  return %res : vector<4xi32>
117}
118
119// CHECK-LABEL: @ctlz_vector
120// CHECK-NOT: math.ctlz
121
122// -----
123
124// CHECK-LABEL:    func @fmaf_func
125// CHECK-SAME:     ([[ARG0:%.+]]: f64, [[ARG1:%.+]]: f64, [[ARG2:%.+]]: f64) -> f64
126func.func @fmaf_func(%a: f64, %b: f64, %c: f64) -> f64 {
127  // CHECK-NEXT:     [[MULF:%.+]] = arith.mulf [[ARG0]], [[ARG1]]
128  // CHECK-NEXT:     [[ADDF:%.+]] = arith.addf [[MULF]], [[ARG2]]
129  // CHECK-NEXT:     return [[ADDF]]
130  %ret = math.fma %a, %b, %c : f64
131  return %ret : f64
132}
133
134// -----
135
136// CHECK-LABEL:     func @ceilf_func
137// CHECK-SAME:      ([[ARG0:%.+]]: f64) -> f64
138func.func @ceilf_func(%a: f64) -> f64 {
139  // CHECK-DAG:   [[CST:%.+]] = arith.constant 0.000
140  // CHECK-DAG:   [[CST_0:%.+]] = arith.constant 1.000
141  // CHECK-NEXT:   [[CVTI:%.+]] = arith.fptosi [[ARG0]]
142  // CHECK-NEXT:   [[CVTF:%.+]] = arith.sitofp [[CVTI]]
143  // CHECK-NEXT:   [[COPYSIGN:%.+]] = math.copysign [[CVTF]], [[ARG0]]
144  // CHECK-NEXT:   [[COMP:%.+]] = arith.cmpf ogt, [[ARG0]], [[COPYSIGN]]
145  // CHECK-NEXT:   [[INCR:%.+]] = arith.select [[COMP]], [[CST_0]], [[CST]]
146  // CHECK-NEXT:   [[ADDF:%.+]] = arith.addf [[COPYSIGN]], [[INCR]]
147  // CHECK-NEXT:   return [[ADDF]]
148  %ret = math.ceil %a : f64
149  return %ret : f64
150}
151
152// -----
153
154// CHECK-LABEL:     func @exp2f_func
155// CHECK-SAME:      ([[ARG0:%.+]]: f64) -> f64
156func.func @exp2f_func(%a: f64) -> f64 {
157  // CHECK-DAG:     [[CST:%.+]]  = arith.constant 0.69314718055994529
158  // CHECK:         [[MULF:%.+]] = arith.mulf [[ARG0]], [[CST]]
159  // CHECK:         [[EXP:%.+]]  = math.exp [[MULF]]
160  // CHECK:         return [[EXP]]
161  %ret = math.exp2 %a : f64
162  return %ret : f64
163}
164
165// CHECK-LABEL:     func @exp2f_func_tensor
166// CHECK-SAME:      ([[ARG0:%.+]]: tensor<1xf32>) -> tensor<1xf32>
167func.func @exp2f_func_tensor(%a: tensor<1xf32>) -> tensor<1xf32> {
168  // CHECK-DAG:     [[CST:%.+]]  = arith.constant dense<0.693147182>
169  // CHECK:         [[MULF:%.+]] = arith.mulf [[ARG0]], [[CST]]
170  // CHECK:         [[EXP:%.+]]  = math.exp [[MULF]]
171  // CHECK:         return [[EXP]]
172  %ret = math.exp2 %a : tensor<1xf32>
173  return %ret : tensor<1xf32>
174}
175
176// -----
177
178// CHECK-LABEL:      func @roundf_func
179// CHECK-SAME:      (%[[ARG0:.*]]: f32) -> f32
180func.func @roundf_func(%a: f32) -> f32 {
181  // CHECK-DAG:       %[[HALF:.*]] = arith.constant 5.000000e-01
182  // CHECK-DAG:       %[[C23:.*]] = arith.constant 23
183  // CHECK-DAG:       %[[C127:.*]] = arith.constant 127
184  // CHECK-DAG:       %[[EXP_MASK:.*]] = arith.constant 255
185  // CHECK-DAG:       %[[SHIFT:.*]] = math.copysign %[[HALF]], %[[ARG0]]
186  // CHECK-DAG:       %[[ARG_SHIFTED:.*]] = arith.addf %[[ARG0]], %[[SHIFT]]
187  // CHECK-DAG:       %[[FIXED_CONVERT:.*]] = arith.fptosi %[[ARG_SHIFTED]]
188  // CHECK-DAG:       %[[FP_FIXED_CONVERT_0:.*]] = arith.sitofp %[[FIXED_CONVERT]]
189  // CHECK-DAG:       %[[FP_FIXED_CONVERT_1:.*]] = math.copysign %[[FP_FIXED_CONVERT_0]], %[[ARG_SHIFTED]]
190  // CHECK-DAG:       %[[ARG_BITCAST:.*]] = arith.bitcast %[[ARG0]] : f32 to i32
191  // CHECK-DAG:       %[[ARG_BITCAST_SHIFTED:.*]] = arith.shrui %[[ARG_BITCAST]], %[[C23]]
192  // CHECK-DAG:       %[[ARG_EXP:.*]] = arith.andi %[[ARG_BITCAST_SHIFTED]], %[[EXP_MASK]]
193  // CHECK-DAG:       %[[ARG_BIASED_EXP:.*]] = arith.subi %[[ARG_EXP]], %[[C127]]
194  // CHECK-DAG:       %[[IS_SPECIAL_VAL:.*]] = arith.cmpi sge, %[[ARG_BIASED_EXP]], %[[C23]]
195  // CHECK-DAG:       %[[RESULT:.*]] = arith.select %[[IS_SPECIAL_VAL]], %[[ARG0]], %[[FP_FIXED_CONVERT_1]]
196  // CHECK:           return %[[RESULT]]
197  %ret = math.round %a : f32
198  return %ret : f32
199}
200
201// -----
202
203// CHECK-LABEL:   func @powf_func
204// CHECK-SAME:    ([[ARG0:%.+]]: f64, [[ARG1:%.+]]: f64)
205func.func @powf_func(%a: f64, %b: f64) -> f64 {
206  // CHECK-DAG: [[CST0:%.+]] = arith.constant 0.000000e+00
207  // CHECK-DAG: [[CST1:%.+]] = arith.constant 1.0
208  // CHECK: [[LOGA:%.+]] = math.log [[ARG0]]
209  // CHECK: [[MULB:%.+]] = arith.mulf [[ARG1]], [[LOGA]]
210  // CHECK: [[EXP:%.+]] = math.exp [[MULB]]
211  // CHECK: [[CMPF:%.+]] = arith.cmpf oeq, [[ARG1]], [[CST0]]
212  // CHECK: [[SEL:%.+]] = arith.select [[CMPF]], [[CST1]], [[EXP]]
213  // CHECK: return [[SEL]]
214  %ret = math.powf %a, %b : f64
215  return %ret : f64
216}
217
218// -----
219
220// CHECK-LABEL:   func.func @roundeven64
221func.func @roundeven64(%arg: f64) -> f64 {
222  %res = math.roundeven %arg : f64
223  return %res : f64
224}
225
226// CHECK-SAME:                   %[[VAL_0:.*]]: f64) -> f64 {
227// CHECK-DAG: %[[C_0:.*]] = arith.constant 0 : i64
228// CHECK-DAG: %[[C_1:.*]] = arith.constant 1 : i64
229// CHECK-DAG: %[[C_NEG_1:.*]] = arith.constant -1 : i64
230// CHECK-DAG: %[[C_1_FLOAT:.*]] = arith.constant 1.000000e+00 : f64
231// CHECK-DAG: %[[C_52:.*]] = arith.constant 52 : i64
232// CHECK-DAG: %[[C_63:.*]] = arith.constant 63 : i64
233// CHECK-DAG: %[[C_1023:.*]] = arith.constant 1023 : i64
234// CHECK-DAG: %[[C_2251799813685248:.*]] = arith.constant 2251799813685248 : i64
235// CHECK-DAG: %[[C_4503599627370495:.*]] = arith.constant 4503599627370495 : i64
236// CHECK-DAG: %[[EXP_MASK:.*]] = arith.constant 2047 : i64
237// CHECK:     %[[OPERAND_BITCAST:.*]] = arith.bitcast %[[VAL_0]] : f64 to i64
238// CHECK:     %[[ROUND:.*]] = math.round %[[VAL_0]] : f64
239// CHECK:     %[[ROUND_BITCAST:.*]] = arith.bitcast %[[ROUND]] : f64 to i64
240
241// Get biased exponents of `round` and `operand`
242// CHECK:     %[[SHIFTED_OPERAND_BITCAST:.*]] = arith.shrui %[[OPERAND_BITCAST]], %[[C_52]] : i64
243// CHECK:     %[[OPERAND_EXP:.*]] = arith.andi %[[SHIFTED_OPERAND_BITCAST]], %[[EXP_MASK]] : i64
244// CHECK:     %[[OPERAND_BIASED_EXP:.*]] = arith.subi %[[OPERAND_EXP]], %[[C_1023]] : i64
245// CHECK:     %[[SHIFTED_ROUND_BITCAST:.*]] = arith.shrui %[[ROUND_BITCAST]], %[[C_52]] : i64
246// CHECK:     %[[ROUND_EXP:.*]] = arith.andi %[[SHIFTED_ROUND_BITCAST]], %[[EXP_MASK]] : i64
247// CHECK:     %[[ROUND_BIASED_EXP:.*]] = arith.subi %[[ROUND_EXP]], %[[C_1023]] : i64
248
249// Determine if `ROUND_BITCAST` is an even whole number or a special value
250// +-inf, +-nan.
251//   Mask mantissa of `ROUND_BITCAST` with a mask shifted to the right by
252//   `ROUND_BIASED_EXP - 1`
253//   CHECK-DAG: %[[ROUND_BIASED_EXP_MINUS_1:.*]] = arith.subi %[[ROUND_BIASED_EXP]], %[[C_1]] : i64
254//   CHECK-DAG: %[[CLAMPED_SHIFT_0:.*]] = arith.maxsi %[[ROUND_BIASED_EXP_MINUS_1]], %[[C_0]] : i64
255//   CHECK-DAG: %[[CLAMPED_SHIFT_1:.*]] = arith.minsi %[[CLAMPED_SHIFT_0]], %[[C_63]] : i64
256//   CHECK-DAG: %[[SHIFTED_MANTISSA_MASK_0:.*]] = arith.shrui %[[C_4503599627370495]], %[[CLAMPED_SHIFT_1]] : i64
257//   CHECK-DAG: %[[ROUND_MASKED_MANTISSA:.*]] = arith.andi %[[ROUND_BITCAST]], %[[SHIFTED_MANTISSA_MASK_0]] : i64
258
259//   `ROUND_BITCAST` is not even whole number or special value if masked
260//   mantissa is != 0 or `ROUND_BIASED_EXP == 0`
261//   CHECK-DAG: %[[ROUND_IS_NOT_EVEN_OR_SPECIAL_0:.*]] = arith.cmpi ne, %[[ROUND_MASKED_MANTISSA]], %[[C_0]] : i64
262//   CHECK-DAG: %[[ROUND_BIASED_EXP_EQ_0:.*]] = arith.cmpi eq, %[[ROUND_BIASED_EXP]], %[[C_0]] : i64
263//   CHECK-DAG: %[[ROUND_IS_NOT_EVEN_OR_SPECIAL_1:.*]] = arith.ori %[[ROUND_IS_NOT_EVEN_OR_SPECIAL_0]], %[[ROUND_BIASED_EXP_EQ_0]] : i1
264
265// Determine if operand is halfway between two integer values
266// CHECK:     %[[OPERAND_BIASED_EXP_EQ_NEG_1:.*]] = arith.cmpi eq, %[[OPERAND_BIASED_EXP]], %[[C_NEG_1]] : i64
267// CHECK:     %[[CLAMPED_SHIFT_2:.*]] = arith.maxsi %[[OPERAND_BIASED_EXP]], %[[C_0]] : i64
268// CHECK:     %[[CLAMPED_SHIFT_3:.*]] = arith.minsi %[[CLAMPED_SHIFT_2]], %[[C_63]] : i64
269// CHECK:     %[[SHIFTED_2_TO_9:.*]] = arith.shrui %[[C_2251799813685248]], %[[CLAMPED_SHIFT_3]] : i64
270
271//   CHECK:     %[[EXPECTED_OPERAND_MASKED_MANTISSA:.*]] = arith.select %[[OPERAND_BIASED_EXP_EQ_NEG_1]], %[[C_0]], %[[SHIFTED_2_TO_9]] : i64
272
273//   Mask mantissa of `OPERAND_BITCAST` with a mask shifted to the right by
274//   `OPERAND_BIASED_EXP`
275//   CHECK:     %[[CLAMPED_SHIFT_4:.*]] = arith.maxsi %[[OPERAND_BIASED_EXP]], %[[C_0]] : i64
276//   CHECK:     %[[CLAMPED_SHIFT_5:.*]] = arith.minsi %[[CLAMPED_SHIFT_4]], %[[C_63]] : i64
277//   CHECK:     %[[SHIFTED_MANTISSA_MASK_1:.*]] = arith.shrui %[[C_4503599627370495]], %[[CLAMPED_SHIFT_5]] : i64
278//   CHECK:     %[[OPERAND_MASKED_MANTISSA:.*]] = arith.andi %[[OPERAND_BITCAST]], %[[SHIFTED_MANTISSA_MASK_1]] : i64
279
280//   The operand is halfway between two integers if the masked mantissa is equal
281//   to the expected mantissa and the biased exponent is in the range
282//   [-1,  52).
283//   CHECK-DAG: %[[OPERAND_BIASED_EXP_GE_NEG_1:.*]] = arith.cmpi sge, %[[OPERAND_BIASED_EXP]], %[[C_NEG_1]] : i64
284//   CHECK-DAG: %[[OPERAND_BIASED_EXP_LT_10:.*]] = arith.cmpi slt, %[[OPERAND_BIASED_EXP]], %[[C_52]] : i64
285//   CHECK-DAG: %[[OPERAND_IS_HALFWAY_0:.*]] = arith.cmpi eq, %[[OPERAND_MASKED_MANTISSA]], %[[EXPECTED_OPERAND_MASKED_MANTISSA]] : i64
286//   CHECK-DAG: %[[OPERAND_IS_HALFWAY_1:.*]] = arith.andi %[[OPERAND_IS_HALFWAY_0]], %[[OPERAND_BIASED_EXP_LT_10]] : i1
287//   CHECK-DAG: %[[OPERAND_IS_HALFWAY_2:.*]] = arith.andi %[[OPERAND_IS_HALFWAY_1]], %[[OPERAND_BIASED_EXP_GE_NEG_1]] : i1
288
289// Adjust rounded operand with `round(operand) - sign(operand)` to correct the
290// case where `round` rounded in the oppositve direction of `roundeven`.
291// CHECK:     %[[SIGN:.*]] = math.copysign %[[C_1_FLOAT]], %[[VAL_0]] : f64
292// CHECK:     %[[ROUND_SHIFTED:.*]] = arith.subf %[[ROUND]], %[[SIGN]] : f64
293// CHECK:     %[[NEEDS_SHIFT:.*]] = arith.andi %[[ROUND_IS_NOT_EVEN_OR_SPECIAL_1]], %[[OPERAND_IS_HALFWAY_2]] : i1
294// CHECK:     %[[RESULT:.*]] = arith.select %[[NEEDS_SHIFT]], %[[ROUND_SHIFTED]], %[[ROUND]] : f64
295
296// The `x - sign` adjustment does not preserve the sign when we are adjusting the value -1 to -0.
297// CHECK:     %[[COPYSIGN:.*]] = math.copysign %[[RESULT]], %[[VAL_0]] : f64
298
299// CHECK: return %[[COPYSIGN]] : f64
300
301// -----
302
303// CHECK-LABEL:   func.func @roundeven32
304func.func @roundeven32(%arg: f32) -> f32 {
305  %res = math.roundeven %arg : f32
306  return %res : f32
307}
308
309// CHECK-SAME:                   %[[VAL_0:.*]]: f32) -> f32 {
310// CHECK-DAG: %[[C_0:.*]] = arith.constant 0 : i32
311// CHECK-DAG: %[[C_1:.*]] = arith.constant 1 : i32
312// CHECK-DAG: %[[C_NEG_1:.*]] = arith.constant -1 : i32
313// CHECK-DAG: %[[C_1_FLOAT:.*]] = arith.constant 1.000000e+00 : f32
314// CHECK-DAG: %[[C_23:.*]] = arith.constant 23 : i32
315// CHECK-DAG: %[[C_31:.*]] = arith.constant 31 : i32
316// CHECK-DAG: %[[C_127:.*]] = arith.constant 127 : i32
317// CHECK-DAG: %[[C_4194304:.*]] = arith.constant 4194304 : i32
318// CHECK-DAG: %[[C_8388607:.*]] = arith.constant 8388607 : i32
319// CHECK-DAG: %[[EXP_MASK:.*]] = arith.constant 255 : i32
320// CHECK-DAG: %[[HALF:.*]] = arith.constant 5.000000e-01
321
322// CHECK:     %[[OPERAND_BITCAST:.*]] = arith.bitcast %[[VAL_0]] : f32 to i32
323
324// Calculate `math.round(operand)` using expansion pattern for `round` and
325// bitcast result to i32
326// CHECK:     %[[SHIFT:.*]] = math.copysign %[[HALF]], %[[VAL_0]]
327// CHECK:     %[[ARG_SHIFTED:.*]] = arith.addf %[[VAL_0]], %[[SHIFT]]
328// CHECK:     %[[FIXED_CONVERT:.*]] = arith.fptosi %[[ARG_SHIFTED]]
329// CHECK:     %[[FP_FIXED_CONVERT_0:.*]] = arith.sitofp %[[FIXED_CONVERT]]
330// CHECK:     %[[FP_FIXED_CONVERT_1:.*]] = math.copysign %[[FP_FIXED_CONVERT_0]], %[[ARG_SHIFTED]]
331// CHECK:     %[[ARG_BITCAST:.*]] = arith.bitcast %[[VAL_0]] : f32 to i32
332// CHECK:     %[[ARG_BITCAST_SHIFTED:.*]] = arith.shrui %[[ARG_BITCAST]], %[[C_23]]
333// CHECK:     %[[ARG_EXP:.*]] = arith.andi %[[ARG_BITCAST_SHIFTED]], %[[EXP_MASK]]
334// CHECK:     %[[ARG_BIASED_EXP:.*]] = arith.subi %[[ARG_EXP]], %[[C_127]]
335// CHECK:     %[[IS_SPECIAL_VAL:.*]] = arith.cmpi sge, %[[ARG_BIASED_EXP]], %[[C_23]]
336// CHECK:     %[[ROUND:.*]] = arith.select %[[IS_SPECIAL_VAL]], %[[VAL_0]], %[[FP_FIXED_CONVERT_1]]
337// CHECK:     %[[ROUND_BITCAST:.*]] = arith.bitcast %[[ROUND]] : f32 to i32
338
339// Get biased exponents of `round` and `operand`
340// CHECK:     %[[SHIFTED_OPERAND_BITCAST:.*]] = arith.shrui %[[OPERAND_BITCAST]], %[[C_23]] : i32
341// CHECK:     %[[OPERAND_EXP:.*]] = arith.andi %[[SHIFTED_OPERAND_BITCAST]], %[[EXP_MASK]] : i32
342// CHECK:     %[[OPERAND_BIASED_EXP:.*]] = arith.subi %[[OPERAND_EXP]], %[[C_127]] : i32
343// CHECK:     %[[SHIFTED_ROUND_BITCAST:.*]] = arith.shrui %[[ROUND_BITCAST]], %[[C_23]] : i32
344// CHECK:     %[[ROUND_EXP:.*]] = arith.andi %[[SHIFTED_ROUND_BITCAST]], %[[EXP_MASK]] : i32
345// CHECK:     %[[ROUND_BIASED_EXP:.*]] = arith.subi %[[ROUND_EXP]], %[[C_127]] : i32
346
347// Determine if `ROUND_BITCAST` is an even whole number or a special value
348// +-inf, +-nan.
349//   Mask mantissa of `ROUND_BITCAST` with a mask shifted to the right by
350//   `ROUND_BIASED_EXP - 1`
351//   CHECK-DAG: %[[ROUND_BIASED_EXP_MINUS_1:.*]] = arith.subi %[[ROUND_BIASED_EXP]], %[[C_1]] : i32
352//   CHECK-DAG: %[[CLAMPED_SHIFT_0:.*]] = arith.maxsi %[[ROUND_BIASED_EXP_MINUS_1]], %[[C_0]] : i32
353//   CHECK-DAG: %[[CLAMPED_SHIFT_1:.*]] = arith.minsi %[[CLAMPED_SHIFT_0]], %[[C_31]] : i32
354//   CHECK-DAG: %[[SHIFTED_MANTISSA_MASK_0:.*]] = arith.shrui %[[C_8388607]], %[[CLAMPED_SHIFT_1]] : i32
355//   CHECK-DAG: %[[ROUND_MASKED_MANTISSA:.*]] = arith.andi %[[ROUND_BITCAST]], %[[SHIFTED_MANTISSA_MASK_0]] : i32
356
357//   `ROUND_BITCAST` is not even whole number or special value if masked
358//   mantissa is != 0 or `ROUND_BIASED_EXP == 0`
359//   CHECK-DAG: %[[ROUND_IS_NOT_EVEN_OR_SPECIAL_0:.*]] = arith.cmpi ne, %[[ROUND_MASKED_MANTISSA]], %[[C_0]] : i32
360//   CHECK-DAG: %[[ROUND_BIASED_EXP_EQ_0:.*]] = arith.cmpi eq, %[[ROUND_BIASED_EXP]], %[[C_0]] : i32
361//   CHECK-DAG: %[[ROUND_IS_NOT_EVEN_OR_SPECIAL_1:.*]] = arith.ori %[[ROUND_IS_NOT_EVEN_OR_SPECIAL_0]], %[[ROUND_BIASED_EXP_EQ_0]] : i1
362
363// Determine if operand is halfway between two integer values
364// CHECK:     %[[OPERAND_BIASED_EXP_EQ_NEG_1:.*]] = arith.cmpi eq, %[[OPERAND_BIASED_EXP]], %[[C_NEG_1]] : i32
365// CHECK:     %[[CLAMPED_SHIFT_2:.*]] = arith.maxsi %[[OPERAND_BIASED_EXP]], %[[C_0]] : i32
366// CHECK:     %[[CLAMPED_SHIFT_3:.*]] = arith.minsi %[[CLAMPED_SHIFT_2]], %[[C_31]] : i32
367// CHECK:     %[[SHIFTED_2_TO_22:.*]] = arith.shrui %[[C_4194304]], %[[CLAMPED_SHIFT_3]] : i32
368
369//   A value with `0 <= BIASED_EXP < 23` is halfway between two consecutive
370//   integers if the bit at index `BIASED_EXP` starting from the left in the
371//   mantissa is 1 and all the bits to the right are zero. For the case where
372//   `BIASED_EXP == -1, the expected mantissa is all zeros.
373//   CHECK:     %[[EXPECTED_OPERAND_MASKED_MANTISSA:.*]] = arith.select %[[OPERAND_BIASED_EXP_EQ_NEG_1]], %[[C_0]], %[[SHIFTED_2_TO_22]] : i32
374
375//   Mask mantissa of `OPERAND_BITCAST` with a mask shifted to the right by
376//   `OPERAND_BIASED_EXP`
377//   CHECK:     %[[CLAMPED_SHIFT_4:.*]] = arith.maxsi %[[OPERAND_BIASED_EXP]], %[[C_0]] : i32
378//   CHECK:     %[[CLAMPED_SHIFT_5:.*]] = arith.minsi %[[CLAMPED_SHIFT_4]], %[[C_31]] : i32
379//   CHECK:     %[[SHIFTED_MANTISSA_MASK_1:.*]] = arith.shrui %[[C_8388607]], %[[CLAMPED_SHIFT_5]] : i32
380//   CHECK:     %[[OPERAND_MASKED_MANTISSA:.*]] = arith.andi %[[OPERAND_BITCAST]], %[[SHIFTED_MANTISSA_MASK_1]] : i32
381
382//   The operand is halfway between two integers if the masked mantissa is equal
383//   to the expected mantissa and the biased exponent is in the range
384//   [-1,  23).
385//   CHECK-DAG: %[[OPERAND_BIASED_EXP_GE_NEG_1:.*]] = arith.cmpi sge, %[[OPERAND_BIASED_EXP]], %[[C_NEG_1]] : i32
386//   CHECK-DAG: %[[OPERAND_BIASED_EXP_LT_23:.*]] = arith.cmpi slt, %[[OPERAND_BIASED_EXP]], %[[C_23]] : i32
387//   CHECK-DAG: %[[OPERAND_IS_HALFWAY_0:.*]] = arith.cmpi eq, %[[OPERAND_MASKED_MANTISSA]], %[[EXPECTED_OPERAND_MASKED_MANTISSA]] : i32
388//   CHECK-DAG: %[[OPERAND_IS_HALFWAY_1:.*]] = arith.andi %[[OPERAND_IS_HALFWAY_0]], %[[OPERAND_BIASED_EXP_LT_23]] : i1
389//   CHECK-DAG: %[[OPERAND_IS_HALFWAY_2:.*]] = arith.andi %[[OPERAND_IS_HALFWAY_1]], %[[OPERAND_BIASED_EXP_GE_NEG_1]] : i1
390
391// Adjust rounded operand with `round(operand) - sign(operand)` to correct the
392// case where `round` rounded in the oppositve direction of `roundeven`.
393// CHECK:     %[[SIGN:.*]] = math.copysign %[[C_1_FLOAT]], %[[VAL_0]] : f32
394// CHECK:     %[[ROUND_SHIFTED:.*]] = arith.subf %[[ROUND]], %[[SIGN]] : f32
395// CHECK:     %[[NEEDS_SHIFT:.*]] = arith.andi %[[ROUND_IS_NOT_EVEN_OR_SPECIAL_1]], %[[OPERAND_IS_HALFWAY_2]] : i1
396// CHECK:     %[[RESULT:.*]] = arith.select %[[NEEDS_SHIFT]], %[[ROUND_SHIFTED]], %[[ROUND]] : f32
397
398// The `x - sign` adjustment does not preserve the sign when we are adjusting the value -1 to -0.
399// CHECK:     %[[COPYSIGN:.*]] = math.copysign %[[RESULT]], %[[VAL_0]] : f32
400
401// CHECK: return %[[COPYSIGN]] : f32
402
403// -----
404
405// CHECK-LABEL:   func.func @roundeven16
406func.func @roundeven16(%arg: f16) -> f16 {
407  %res = math.roundeven %arg : f16
408  return %res : f16
409}
410
411// CHECK-SAME:                   %[[VAL_0:.*]]: f16) -> f16 {
412// CHECK-DAG: %[[C_0:.*]] = arith.constant 0 : i16
413// CHECK-DAG: %[[C_1:.*]] = arith.constant 1 : i16
414// CHECK-DAG: %[[C_NEG_1:.*]] = arith.constant -1 : i16
415// CHECK-DAG: %[[C_1_FLOAT:.*]] = arith.constant 1.000000e+00 : f16
416// CHECK-DAG: %[[C_10:.*]] = arith.constant 10 : i16
417// CHECK-DAG: %[[C_15:.*]] = arith.constant 15 : i16
418// CHECK-DAG: %[[C_512:.*]] = arith.constant 512 : i16
419// CHECK-DAG: %[[C_1023:.*]] = arith.constant 1023 : i16
420// CHECK-DAG: %[[EXP_MASK:.*]] = arith.constant 31 : i16
421
422// CHECK:     %[[OPERAND_BITCAST:.*]] = arith.bitcast %[[VAL_0]] : f16 to i16
423// CHECK:     %[[ROUND:.*]] = math.round %[[VAL_0]] : f16
424// CHECK:     %[[ROUND_BITCAST:.*]] = arith.bitcast %[[ROUND]] : f16 to i16
425
426// Get biased exponents of `round` and `operand`
427// CHECK:     %[[SHIFTED_OPERAND_BITCAST:.*]] = arith.shrui %[[OPERAND_BITCAST]], %[[C_10]] : i16
428// CHECK:     %[[OPERAND_EXP:.*]] = arith.andi %[[SHIFTED_OPERAND_BITCAST]], %[[EXP_MASK]] : i16
429// CHECK:     %[[OPERAND_BIASED_EXP:.*]] = arith.subi %[[OPERAND_EXP]], %[[C_15]] : i16
430// CHECK:     %[[SHIFTED_ROUND_BITCAST:.*]] = arith.shrui %[[ROUND_BITCAST]], %[[C_10]] : i16
431// CHECK:     %[[ROUND_EXP:.*]] = arith.andi %[[SHIFTED_ROUND_BITCAST]], %[[EXP_MASK]] : i16
432// CHECK:     %[[ROUND_BIASED_EXP:.*]] = arith.subi %[[ROUND_EXP]], %[[C_15]] : i16
433
434// Determine if `ROUND_BITCAST` is an even whole number or a special value
435// +-inf, +-nan.
436//   Mask mantissa of `ROUND_BITCAST` with a mask shifted to the right by
437//   `ROUND_BIASED_EXP - 1`
438//   CHECK-DAG: %[[ROUND_BIASED_EXP_MINUS_1:.*]] = arith.subi %[[ROUND_BIASED_EXP]], %[[C_1]] : i16
439//   CHECK-DAG: %[[CLAMPED_SHIFT_0:.*]] = arith.maxsi %[[ROUND_BIASED_EXP_MINUS_1]], %[[C_0]] : i16
440//   CHECK-DAG: %[[CLAMPED_SHIFT_1:.*]] = arith.minsi %[[CLAMPED_SHIFT_0]], %[[C_15]] : i16
441//   CHECK-DAG: %[[SHIFTED_MANTISSA_MASK_0:.*]] = arith.shrui %[[C_1023]], %[[CLAMPED_SHIFT_1]] : i16
442//   CHECK-DAG: %[[ROUND_MASKED_MANTISSA:.*]] = arith.andi %[[ROUND_BITCAST]], %[[SHIFTED_MANTISSA_MASK_0]] : i16
443
444//   `ROUND_BITCAST` is not even whole number or special value if masked
445//   mantissa is != 0 or `ROUND_BIASED_EXP == 0`
446//   CHECK-DAG: %[[ROUND_IS_NOT_EVEN_OR_SPECIAL_0:.*]] = arith.cmpi ne, %[[ROUND_MASKED_MANTISSA]], %[[C_0]] : i16
447//   CHECK-DAG: %[[ROUND_BIASED_EXP_EQ_0:.*]] = arith.cmpi eq, %[[ROUND_BIASED_EXP]], %[[C_0]] : i16
448//   CHECK-DAG: %[[ROUND_IS_NOT_EVEN_OR_SPECIAL_1:.*]] = arith.ori %[[ROUND_IS_NOT_EVEN_OR_SPECIAL_0]], %[[ROUND_BIASED_EXP_EQ_0]] : i1
449
450// Determine if operand is halfway between two integer values
451// CHECK:     %[[OPERAND_BIASED_EXP_EQ_NEG_1:.*]] = arith.cmpi eq, %[[OPERAND_BIASED_EXP]], %[[C_NEG_1]] : i16
452// CHECK:     %[[CLAMPED_SHIFT_2:.*]] = arith.maxsi %[[OPERAND_BIASED_EXP]], %[[C_0]] : i16
453// CHECK:     %[[CLAMPED_SHIFT_3:.*]] = arith.minsi %[[CLAMPED_SHIFT_2]], %[[C_15]] : i16
454// CHECK:     %[[SHIFTED_2_TO_9:.*]] = arith.shrui %[[C_512]], %[[CLAMPED_SHIFT_3]] : i16
455
456//   A value with `0 <= BIASED_EXP < 10` is halfway between two consecutive
457//   integers if the bit at index `BIASED_EXP` starting from the left in the
458//   mantissa is 1 and all the bits to the right are zero. For the case where
459//   `BIASED_EXP == -1, the expected mantissa is all zeros.
460//   CHECK:     %[[EXPECTED_OPERAND_MASKED_MANTISSA:.*]] = arith.select %[[OPERAND_BIASED_EXP_EQ_NEG_1]], %[[C_0]], %[[SHIFTED_2_TO_9]] : i16
461
462//   Mask mantissa of `OPERAND_BITCAST` with a mask shifted to the right by
463//   `OPERAND_BIASED_EXP`
464//   CHECK:     %[[CLAMPED_SHIFT_4:.*]] = arith.maxsi %[[OPERAND_BIASED_EXP]], %[[C_0]] : i16
465//   CHECK:     %[[CLAMPED_SHIFT_5:.*]] = arith.minsi %[[CLAMPED_SHIFT_4]], %[[C_15]] : i16
466//   CHECK:     %[[SHIFTED_MANTISSA_MASK_1:.*]] = arith.shrui %[[C_1023]], %[[CLAMPED_SHIFT_5]] : i16
467//   CHECK:     %[[OPERAND_MASKED_MANTISSA:.*]] = arith.andi %[[OPERAND_BITCAST]], %[[SHIFTED_MANTISSA_MASK_1]] : i16
468
469//   The operand is halfway between two integers if the masked mantissa is equal
470//   to the expected mantissa and the biased exponent is in the range
471//   [-1,  23).
472//   CHECK-DAG: %[[OPERAND_BIASED_EXP_GE_NEG_1:.*]] = arith.cmpi sge, %[[OPERAND_BIASED_EXP]], %[[C_NEG_1]] : i16
473//   CHECK-DAG: %[[OPERAND_BIASED_EXP_LT_10:.*]] = arith.cmpi slt, %[[OPERAND_BIASED_EXP]], %[[C_10]] : i16
474//   CHECK-DAG: %[[OPERAND_IS_HALFWAY_0:.*]] = arith.cmpi eq, %[[OPERAND_MASKED_MANTISSA]], %[[EXPECTED_OPERAND_MASKED_MANTISSA]] : i16
475//   CHECK-DAG: %[[OPERAND_IS_HALFWAY_1:.*]] = arith.andi %[[OPERAND_IS_HALFWAY_0]], %[[OPERAND_BIASED_EXP_LT_10]] : i1
476//   CHECK-DAG: %[[OPERAND_IS_HALFWAY_2:.*]] = arith.andi %[[OPERAND_IS_HALFWAY_1]], %[[OPERAND_BIASED_EXP_GE_NEG_1]] : i1
477
478// Adjust rounded operand with `round(operand) - sign(operand)` to correct the
479// case where `round` rounded in the oppositve direction of `roundeven`.
480// CHECK:     %[[SIGN:.*]] = math.copysign %[[C_1_FLOAT]], %[[VAL_0]] : f16
481// CHECK:     %[[ROUND_SHIFTED:.*]] = arith.subf %[[ROUND]], %[[SIGN]] : f16
482// CHECK:     %[[NEEDS_SHIFT:.*]] = arith.andi %[[ROUND_IS_NOT_EVEN_OR_SPECIAL_1]], %[[OPERAND_IS_HALFWAY_2]] : i1
483// CHECK:     %[[RESULT:.*]] = arith.select %[[NEEDS_SHIFT]], %[[ROUND_SHIFTED]], %[[ROUND]] : f16
484
485// The `x - sign` adjustment does not preserve the sign when we are adjusting the value -1 to -0.
486// CHECK:     %[[COPYSIGN:.*]] = math.copysign %[[RESULT]], %[[VAL_0]] : f16
487
488// CHECK: return %[[COPYSIGN]] : f16
489
490// -----
491
492// CHECK-LABEL:   func.func @math_fpowi_neg_odd_power
493func.func @math_fpowi_neg_odd_power(%0 : tensor<8xf32>) -> tensor<8xf32> {
494  %1 = arith.constant dense<-3> : tensor<8xi64>
495  %2 = math.fpowi %0, %1 : tensor<8xf32>, tensor<8xi64>
496  return %2 : tensor<8xf32>
497}
498//  CHECK-SAME: (%[[ARG0:.*]]: tensor<8xf32>) -> tensor<8xf32> {
499//  CHECK-DAG:    %[[CST1:.*]] = arith.constant dense<1.000000e+00> : tensor<8xf32>
500//  CHECK-DAG:    %[[CST0:.*]] = arith.constant dense<0.000000e+00> : tensor<8xf32>
501//  CHECK-DAG:    %[[CSTNEG0:.*]] = arith.constant dense<-0.000000e+00> : tensor<8xf32>
502//  CHECK-DAG:    %[[CSTINF:.*]] = arith.constant dense<0x7F800000> : tensor<8xf32>
503//  CHECK-DAG:    %[[CSTNEGINF:.*]] = arith.constant dense<0xFF800000> : tensor<8xf32>
504//  CHECK:        %[[SQ:.*]] = arith.mulf %[[ARG0]], %[[ARG0]] : tensor<8xf32>
505//  CHECK:        %[[CUBE:.*]] = arith.mulf %[[SQ]], %[[ARG0]] : tensor<8xf32>
506//  CHECK:        %[[CMP0:.*]] = arith.cmpf oeq, %[[CUBE]], %[[CST0]] : tensor<8xf32>
507//  CHECK:        %[[CMPNEG0:.*]] = arith.cmpf oeq, %[[CUBE]], %[[CSTNEG0]] : tensor<8xf32>
508//  CHECK:        %[[INV:.*]] = arith.divf %[[CST1]], %[[CUBE]] : tensor<8xf32>
509//  CHECK:        %[[UB1:.*]] = arith.select %[[CMP0]], %[[CSTINF]], %[[INV]] : tensor<8xi1>, tensor<8xf32>
510//  CHECK:        %[[UB2:.*]] = arith.select %[[CMPNEG0]], %[[CSTNEGINF]], %[[UB1]] : tensor<8xi1>, tensor<8xf32>
511//  CHECK:      return %[[UB2]] : tensor<8xf32>
512
513// -----
514
515// CHECK-LABEL:   func.func @math_fpowi_neg_even_power
516func.func @math_fpowi_neg_even_power(%0 : tensor<8xf32>) -> tensor<8xf32> {
517  %1 = arith.constant dense<-4> : tensor<8xi64>
518  %2 = math.fpowi %0, %1 : tensor<8xf32>, tensor<8xi64>
519  return %2 : tensor<8xf32>
520}
521//  CHECK-SAME: (%[[ARG0:.*]]: tensor<8xf32>) -> tensor<8xf32> {
522//  CHECK-DAG:    %[[CST1:.*]] = arith.constant dense<1.000000e+00> : tensor<8xf32>
523//  CHECK-DAG:    %[[CST0:.*]] = arith.constant dense<0.000000e+00> : tensor<8xf32>
524//  CHECK-DAG:    %[[CSTNEG0:.*]] = arith.constant dense<-0.000000e+00> : tensor<8xf32>
525//  CHECK-DAG:    %[[CSTINF:.*]] = arith.constant dense<0x7F800000> : tensor<8xf32>
526//  CHECK-DAG:    %[[CSTNEGINF:.*]] = arith.constant dense<0xFF800000> : tensor<8xf32>
527//  CHECK:        %[[SQ:.*]] = arith.mulf %[[ARG0]], %[[ARG0]] : tensor<8xf32>
528//  CHECK:        %[[PW4:.*]] = arith.mulf %[[SQ]], %[[SQ]] : tensor<8xf32>
529//  CHECK:        %[[CMP0:.*]] = arith.cmpf oeq, %[[PW4]], %[[CST0]] : tensor<8xf32>
530//  CHECK:        %[[CMPNEG0:.*]] = arith.cmpf oeq, %[[PW4]], %[[CSTNEG0]] : tensor<8xf32>
531//  CHECK:        %[[INV:.*]] = arith.divf %[[CST1]], %[[PW4]] : tensor<8xf32>
532//  CHECK:        %[[UB1:.*]] = arith.select %[[CMP0]], %[[CSTINF]], %[[INV]] : tensor<8xi1>, tensor<8xf32>
533//  CHECK:        %[[UB2:.*]] = arith.select %[[CMPNEG0]], %[[CSTNEGINF]], %[[UB1]] : tensor<8xi1>, tensor<8xf32>
534//  CHECK:      return %[[UB2]] : tensor<8xf32>
535
536// -----
537
538// CHECK-LABEL:   func.func @math_fpowi_pos_odd_power
539func.func @math_fpowi_pos_odd_power(%0 : tensor<8xf32>) -> tensor<8xf32> {
540  %1 = arith.constant dense<5> : tensor<8xi64>
541  %2 = math.fpowi %0, %1 : tensor<8xf32>, tensor<8xi64>
542  return %2 : tensor<8xf32>
543}
544//  CHECK-SAME: (%[[ARG0:.*]]: tensor<8xf32>) -> tensor<8xf32> {
545//  CHECK:        %[[SQ:.*]] = arith.mulf %[[ARG0]], %[[ARG0]] : tensor<8xf32>
546//  CHECK:        %[[PW4:.*]] = arith.mulf %[[SQ]], %[[SQ]] : tensor<8xf32>
547//  CHECK:        %[[PW5:.*]] = arith.mulf %[[PW4]], %[[ARG0]] : tensor<8xf32>
548//  CHECK:      return %[[PW5]] : tensor<8xf32>
549
550// -----
551
552// CHECK-LABEL:   func.func @math_fpowi_pos_even_power
553func.func @math_fpowi_pos_even_power(%0 : tensor<8xf32>) -> tensor<8xf32> {
554  %1 = arith.constant dense<4> : tensor<8xi64>
555  %2 = math.fpowi %0, %1 : tensor<8xf32>, tensor<8xi64>
556  return %2 : tensor<8xf32>
557}
558//  CHECK-SAME: (%[[ARG0:.*]]: tensor<8xf32>) -> tensor<8xf32> {
559//  CHECK:        %[[SQ:.*]] = arith.mulf %[[ARG0]], %[[ARG0]] : tensor<8xf32>
560//  CHECK:        %[[PW4:.*]] = arith.mulf %[[SQ]], %[[SQ]] : tensor<8xf32>
561//  CHECK:      return %[[PW4]] : tensor<8xf32>
562
563// -----
564
565// CHECK-LABEL:   func.func @math_fpowi_even_scalar
566func.func @math_fpowi_even_scalar(%0 : f32) -> f32 {
567  %pow = arith.constant 2 : i64
568  %2 = math.fpowi %0, %pow : f32, i64
569  return %2 : f32
570}
571//  CHECK-SAME: (%[[ARG0:.*]]: f32) -> f32 {
572//  CHECK:         %[[SQ:.*]] = arith.mulf %[[ARG0]], %[[ARG0]] : f32
573//  CHECK:         return %[[SQ]] : f32
574
575// -----
576
577// CHECK-LABEL:   func.func @math_fpowi_scalar_zero
578func.func @math_fpowi_scalar_zero(%0 : f32) -> f32 {
579  %pow = arith.constant 0 : i64
580  %2 = math.fpowi %0, %pow : f32, i64
581  return %2 : f32
582}
583//  CHECK-SAME: (%[[ARG0:.*]]: f32) -> f32 {
584//  CHECK:         %[[RET:.*]] = arith.constant 1.000000e+00 : f32
585//  CHECK:         return %[[RET]] : f32
586
587// -----
588
589// CHECK-LABEL:   func.func @math_fpowi_to_powf_tensor
590func.func @math_fpowi_to_powf_tensor(%0 : tensor<8xf32>, %1: tensor<8xi32>) -> tensor<8xf32> {
591  %2 = math.fpowi %0, %1 : tensor<8xf32>, tensor<8xi32>
592  return %2 : tensor<8xf32>
593}
594// CHECK-SAME: (%[[ARG0:.*]]: tensor<8xf32>, %[[ARG1:.*]]: tensor<8xi32>) -> tensor<8xf32> {
595// CHECK-DAG:    %[[CST1:.+]] = arith.constant dense<1.000000e+00> : tensor<8xf32>
596// CHECK-DAG:    %[[CST0:.*]] = arith.constant dense<0.000000e+00> : tensor<8xf32>
597// CHECK: %[[TOFP:.*]] = arith.sitofp %[[ARG1]] : tensor<8xi32> to tensor<8xf32>
598// CHECK: %[[LOGA:.*]] = math.log %[[ARG0]] : tensor<8xf32>
599// CHECK: %[[MUL:.*]] = arith.mulf %[[TOFP]], %[[LOGA]] : tensor<8xf32>
600// CHECK: %[[EXP:.*]] = math.exp %[[MUL]] : tensor<8xf32>
601// CHECK: %[[CMP:.*]] = arith.cmpf oeq, %[[TOFP]], %[[CST0]] : tensor<8xf32>
602// CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[CST1]], %[[EXP]] : tensor<8xi1>, tensor<8xf32>
603// CHECK: return %[[SEL]]
604// -----
605
606// CHECK-LABEL:   func.func @math_fpowi_to_powf_scalar
607func.func @math_fpowi_to_powf_scalar(%0 : f32, %1: i64) -> f32 {
608  %2 = math.fpowi %0, %1 : f32, i64
609  return %2 : f32
610}
611// CHECK-SAME: (%[[ARG0:.*]]: f32, %[[ARG1:.*]]: i64) -> f32 {
612// CHECK-DAG:    %[[CST0:.*]] = arith.constant 0.000000e+00 : f32
613// CHECK-DAG:    %[[CST1:.+]] = arith.constant 1.000000e+00 : f32
614// CHECK:        %[[TOFP:.*]] = arith.sitofp %[[ARG1]] : i64 to f32
615// CHECK:        %[[LOGA:.*]] = math.log %[[ARG0]] : f32
616// CHECK:        %[[MUL:.*]] = arith.mulf %[[TOFP]], %[[LOGA]] : f32
617// CHECK:        %[[EXP:.*]] = math.exp %[[MUL]] : f32
618// CHECK:        %[[CMP:.*]] = arith.cmpf oeq, %[[TOFP]], %[[CST0]] : f32
619// CHECK:        %[[SEL:.*]] = arith.select %[[CMP]], %[[CST1]], %[[EXP]] : f32
620// CHECK:       return %[[SEL]] : f32
621
622// -----
623
624// CHECK-LABEL:   func.func @rsqrt
625// CHECK-SAME:     (%[[ARG:.*]]: f16)
626// CHECK-SAME:    -> f16
627// CHECK-DAG:     %[[CST:.*]] = arith.constant 1.000000e+00 : f16
628// CHECK-DAG:     %[[SQRT:.*]] = math.sqrt %[[ARG]] : f16
629// CHECK-DAG:     %[[DIV:.*]] = arith.divf %[[CST]], %[[SQRT]] : f16
630// CHECK:         return %[[DIV]] : f16
631func.func @rsqrt16(%float: f16) -> (f16)  {
632  %float_result = math.rsqrt %float : f16
633  return %float_result : f16
634}
635
636// -----
637
638// CHECK-LABEL:   func.func @rsqrt
639// CHECK-SAME:     (%[[ARG:.*]]: f32)
640// CHECK-SAME:    -> f32
641// CHECK-DAG:     %[[CST:.*]] = arith.constant 1.000000e+00 : f32
642// CHECK-DAG:     %[[SQRT:.*]] = math.sqrt %[[ARG]] : f32
643// CHECK-DAG:     %[[DIV:.*]] = arith.divf %[[CST]], %[[SQRT]] : f32
644// CHECK:         return %[[DIV]] : f32
645func.func @rsqrt32(%float: f32) -> (f32)  {
646  %float_result = math.rsqrt %float : f32
647  return %float_result : f32
648}
649
650// -----
651
652// CHECK-LABEL:   func.func @rsqrt
653// CHECK-SAME:     (%[[ARG:.*]]: f64)
654// CHECK-SAME:    -> f64
655// CHECK-DAG:     %[[CST:.*]] = arith.constant 1.000000e+00 : f64
656// CHECK-DAG:     %[[SQRT:.*]] = math.sqrt %[[ARG]] : f64
657// CHECK-DAG:     %[[DIV:.*]] = arith.divf %[[CST]], %[[SQRT]] : f64
658// CHECK:         return %[[DIV]] : f64
659func.func @rsqrt64(%float: f64) -> (f64)  {
660  %float_result = math.rsqrt %float : f64
661  return %float_result : f64
662}
663
664// -----
665
666// CHECK-LABEL:   func.func @rsqrt_vec
667// CHECK-SAME:     (%[[ARG:.*]]: vector<5xf32>)
668// CHECK-SAME:    -> vector<5xf32>
669// CHECK-DAG:     %[[CST:.*]] = arith.constant dense<1.000000e+00> : vector<5xf32>
670// CHECK-DAG:     %[[SQRT:.*]] = math.sqrt %[[ARG]] : vector<5xf32>
671// CHECK-DAG:     %[[DIV:.*]] = arith.divf %[[CST]], %[[SQRT]] : vector<5xf32>
672// CHECK:         return %[[DIV]] : vector<5xf32>
673func.func @rsqrt_vec(%float: vector<5xf32>) -> (vector<5xf32>)  {
674  %float_result = math.rsqrt %float : vector<5xf32>
675  return %float_result : vector<5xf32>
676}
677
678// -----
679
680// CHECK-LABEL:   func.func @rsqrt_tns
681// CHECK-SAME:     (%[[ARG:.*]]: tensor<5x8xf32>)
682// CHECK-SAME:    -> tensor<5x8xf32>
683// CHECK-DAG:     %[[CST:.*]] = arith.constant dense<1.000000e+00> : tensor<5x8xf32>
684// CHECK-DAG:     %[[SQRT:.*]] = math.sqrt %[[ARG]] : tensor<5x8xf32>
685// CHECK-DAG:     %[[DIV:.*]] = arith.divf %[[CST]], %[[SQRT]] : tensor<5x8xf32>
686// CHECK:         return %[[DIV]] : tensor<5x8xf32>
687func.func @rsqrt_tns(%float: tensor<5x8xf32>) -> (tensor<5x8xf32>)  {
688  %float_result = math.rsqrt %float : tensor<5x8xf32>
689  return %float_result : tensor<5x8xf32>
690}
691