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