1// RUN: mlir-opt -split-input-file -convert-arith-to-spirv -verify-diagnostics %s | FileCheck %s 2 3//===----------------------------------------------------------------------===// 4// arithmetic ops 5//===----------------------------------------------------------------------===// 6 7module attributes { 8 spirv.target_env = #spirv.target_env< 9 #spirv.vce<v1.0, [Int8, Int16, Int64, Float16, Float64, Shader], []>, #spirv.resource_limits<>> 10} { 11 12// Check integer operation conversions. 13// CHECK-LABEL: @int32_scalar 14func.func @int32_scalar(%lhs: i32, %rhs: i32) { 15 // CHECK: spirv.IAdd %{{.*}}, %{{.*}}: i32 16 %0 = arith.addi %lhs, %rhs: i32 17 // CHECK: spirv.ISub %{{.*}}, %{{.*}}: i32 18 %1 = arith.subi %lhs, %rhs: i32 19 // CHECK: spirv.IMul %{{.*}}, %{{.*}}: i32 20 %2 = arith.muli %lhs, %rhs: i32 21 // CHECK: spirv.SDiv %{{.*}}, %{{.*}}: i32 22 %3 = arith.divsi %lhs, %rhs: i32 23 // CHECK: spirv.UDiv %{{.*}}, %{{.*}}: i32 24 %4 = arith.divui %lhs, %rhs: i32 25 // CHECK: spirv.UMod %{{.*}}, %{{.*}}: i32 26 %5 = arith.remui %lhs, %rhs: i32 27 return 28} 29 30// CHECK-LABEL: @int32_scalar_srem 31// CHECK-SAME: (%[[LHS:.+]]: i32, %[[RHS:.+]]: i32) 32func.func @int32_scalar_srem(%lhs: i32, %rhs: i32) { 33 // CHECK: %[[LABS:.+]] = spirv.GL.SAbs %[[LHS]] : i32 34 // CHECK: %[[RABS:.+]] = spirv.GL.SAbs %[[RHS]] : i32 35 // CHECK: %[[ABS:.+]] = spirv.UMod %[[LABS]], %[[RABS]] : i32 36 // CHECK: %[[POS:.+]] = spirv.IEqual %[[LHS]], %[[LABS]] : i32 37 // CHECK: %[[NEG:.+]] = spirv.SNegate %[[ABS]] : i32 38 // CHECK: %{{.+}} = spirv.Select %[[POS]], %[[ABS]], %[[NEG]] : i1, i32 39 %0 = arith.remsi %lhs, %rhs: i32 40 return 41} 42 43// CHECK-LABEL: @index_scalar 44func.func @index_scalar(%lhs: index, %rhs: index) { 45 // CHECK: spirv.IAdd %{{.*}}, %{{.*}}: i32 46 %0 = arith.addi %lhs, %rhs: index 47 // CHECK: spirv.ISub %{{.*}}, %{{.*}}: i32 48 %1 = arith.subi %lhs, %rhs: index 49 // CHECK: spirv.IMul %{{.*}}, %{{.*}}: i32 50 %2 = arith.muli %lhs, %rhs: index 51 // CHECK: spirv.SDiv %{{.*}}, %{{.*}}: i32 52 %3 = arith.divsi %lhs, %rhs: index 53 // CHECK: spirv.UDiv %{{.*}}, %{{.*}}: i32 54 %4 = arith.divui %lhs, %rhs: index 55 // CHECK: spirv.UMod %{{.*}}, %{{.*}}: i32 56 %5 = arith.remui %lhs, %rhs: index 57 return 58} 59 60// CHECK-LABEL: @index_scalar_srem 61// CHECK-SAME: (%[[A:.+]]: index, %[[B:.+]]: index) 62func.func @index_scalar_srem(%lhs: index, %rhs: index) { 63 // CHECK-DAG: %[[LHS:.+]] = builtin.unrealized_conversion_cast %[[A]] : index to i32 64 // CHECK-DAG: %[[RHS:.+]] = builtin.unrealized_conversion_cast %[[B]] : index to i32 65 // CHECK: %[[LABS:.+]] = spirv.GL.SAbs %[[LHS]] : i32 66 // CHECK: %[[RABS:.+]] = spirv.GL.SAbs %[[RHS]] : i32 67 // CHECK: %[[ABS:.+]] = spirv.UMod %[[LABS]], %[[RABS]] : i32 68 // CHECK: %[[POS:.+]] = spirv.IEqual %[[LHS]], %[[LABS]] : i32 69 // CHECK: %[[NEG:.+]] = spirv.SNegate %[[ABS]] : i32 70 // CHECK: %{{.+}} = spirv.Select %[[POS]], %[[ABS]], %[[NEG]] : i1, i32 71 %0 = arith.remsi %lhs, %rhs: index 72 return 73} 74 75// Check integer add-with-carry conversions. 76// CHECK-LABEL: @int32_scalar_addui_extended 77// CHECK-SAME: (%[[LHS:.+]]: i32, %[[RHS:.+]]: i32) 78func.func @int32_scalar_addui_extended(%lhs: i32, %rhs: i32) -> (i32, i1) { 79 // CHECK-NEXT: %[[IAC:.+]] = spirv.IAddCarry %[[LHS]], %[[RHS]] : !spirv.struct<(i32, i32)> 80 // CHECK-DAG: %[[SUM:.+]] = spirv.CompositeExtract %[[IAC]][0 : i32] : !spirv.struct<(i32, i32)> 81 // CHECK-DAG: %[[C0:.+]] = spirv.CompositeExtract %[[IAC]][1 : i32] : !spirv.struct<(i32, i32)> 82 // CHECK-DAG: %[[ONE:.+]] = spirv.Constant 1 : i32 83 // CHECK-NEXT: %[[C1:.+]] = spirv.IEqual %[[C0]], %[[ONE]] : i32 84 // CHECK-NEXT: return %[[SUM]], %[[C1]] : i32, i1 85 %sum, %overflow = arith.addui_extended %lhs, %rhs: i32, i1 86 return %sum, %overflow : i32, i1 87} 88 89// CHECK-LABEL: @int32_vector_addui_extended 90// CHECK-SAME: (%[[LHS:.+]]: vector<4xi32>, %[[RHS:.+]]: vector<4xi32>) 91func.func @int32_vector_addui_extended(%lhs: vector<4xi32>, %rhs: vector<4xi32>) -> (vector<4xi32>, vector<4xi1>) { 92 // CHECK-NEXT: %[[IAC:.+]] = spirv.IAddCarry %[[LHS]], %[[RHS]] : !spirv.struct<(vector<4xi32>, vector<4xi32>)> 93 // CHECK-DAG: %[[SUM:.+]] = spirv.CompositeExtract %[[IAC]][0 : i32] : !spirv.struct<(vector<4xi32>, vector<4xi32>)> 94 // CHECK-DAG: %[[C0:.+]] = spirv.CompositeExtract %[[IAC]][1 : i32] : !spirv.struct<(vector<4xi32>, vector<4xi32>)> 95 // CHECK-DAG: %[[ONE:.+]] = spirv.Constant dense<1> : vector<4xi32> 96 // CHECK-NEXT: %[[C1:.+]] = spirv.IEqual %[[C0]], %[[ONE]] : vector<4xi32> 97 // CHECK-NEXT: return %[[SUM]], %[[C1]] : vector<4xi32>, vector<4xi1> 98 %sum, %overflow = arith.addui_extended %lhs, %rhs: vector<4xi32>, vector<4xi1> 99 return %sum, %overflow : vector<4xi32>, vector<4xi1> 100} 101 102// Check extended signed integer multiplication conversions. 103// CHECK-LABEL: @int32_scalar_mulsi_extended 104// CHECK-SAME: (%[[LHS:.+]]: i32, %[[RHS:.+]]: i32) 105func.func @int32_scalar_mulsi_extended(%lhs: i32, %rhs: i32) -> (i32, i32) { 106 // CHECK-NEXT: %[[MUL:.+]] = spirv.SMulExtended %[[LHS]], %[[RHS]] : !spirv.struct<(i32, i32)> 107 // CHECK-DAG: %[[LOW:.+]] = spirv.CompositeExtract %[[MUL]][0 : i32] : !spirv.struct<(i32, i32)> 108 // CHECK-DAG: %[[HIGH:.+]] = spirv.CompositeExtract %[[MUL]][1 : i32] : !spirv.struct<(i32, i32)> 109 // CHECK-NEXT: return %[[LOW]], %[[HIGH]] : i32, i32 110 %low, %high = arith.mulsi_extended %lhs, %rhs: i32 111 return %low, %high : i32, i32 112} 113 114// CHECK-LABEL: @int32_vector_mulsi_extended 115// CHECK-SAME: (%[[LHS:.+]]: vector<4xi32>, %[[RHS:.+]]: vector<4xi32>) 116func.func @int32_vector_mulsi_extended(%lhs: vector<4xi32>, %rhs: vector<4xi32>) -> (vector<4xi32>, vector<4xi32>) { 117 // CHECK-NEXT: %[[MUL:.+]] = spirv.SMulExtended %[[LHS]], %[[RHS]] : !spirv.struct<(vector<4xi32>, vector<4xi32>)> 118 // CHECK-DAG: %[[LOW:.+]] = spirv.CompositeExtract %[[MUL]][0 : i32] : !spirv.struct<(vector<4xi32>, vector<4xi32>)> 119 // CHECK-DAG: %[[HIGH:.+]] = spirv.CompositeExtract %[[MUL]][1 : i32] : !spirv.struct<(vector<4xi32>, vector<4xi32>)> 120 // CHECK-NEXT: return %[[LOW]], %[[HIGH]] : vector<4xi32>, vector<4xi32> 121 %low, %high = arith.mulsi_extended %lhs, %rhs: vector<4xi32> 122 return %low, %high : vector<4xi32>, vector<4xi32> 123} 124 125// Check extended unsigned integer multiplication conversions. 126// CHECK-LABEL: @int32_scalar_mului_extended 127// CHECK-SAME: (%[[LHS:.+]]: i32, %[[RHS:.+]]: i32) 128func.func @int32_scalar_mului_extended(%lhs: i32, %rhs: i32) -> (i32, i32) { 129 // CHECK-NEXT: %[[MUL:.+]] = spirv.UMulExtended %[[LHS]], %[[RHS]] : !spirv.struct<(i32, i32)> 130 // CHECK-DAG: %[[LOW:.+]] = spirv.CompositeExtract %[[MUL]][0 : i32] : !spirv.struct<(i32, i32)> 131 // CHECK-DAG: %[[HIGH:.+]] = spirv.CompositeExtract %[[MUL]][1 : i32] : !spirv.struct<(i32, i32)> 132 // CHECK-NEXT: return %[[LOW]], %[[HIGH]] : i32, i32 133 %low, %high = arith.mului_extended %lhs, %rhs: i32 134 return %low, %high : i32, i32 135} 136 137// CHECK-LABEL: @int32_vector_mului_extended 138// CHECK-SAME: (%[[LHS:.+]]: vector<4xi32>, %[[RHS:.+]]: vector<4xi32>) 139func.func @int32_vector_mului_extended(%lhs: vector<4xi32>, %rhs: vector<4xi32>) -> (vector<4xi32>, vector<4xi32>) { 140 // CHECK-NEXT: %[[MUL:.+]] = spirv.UMulExtended %[[LHS]], %[[RHS]] : !spirv.struct<(vector<4xi32>, vector<4xi32>)> 141 // CHECK-DAG: %[[LOW:.+]] = spirv.CompositeExtract %[[MUL]][0 : i32] : !spirv.struct<(vector<4xi32>, vector<4xi32>)> 142 // CHECK-DAG: %[[HIGH:.+]] = spirv.CompositeExtract %[[MUL]][1 : i32] : !spirv.struct<(vector<4xi32>, vector<4xi32>)> 143 // CHECK-NEXT: return %[[LOW]], %[[HIGH]] : vector<4xi32>, vector<4xi32> 144 %low, %high = arith.mului_extended %lhs, %rhs: vector<4xi32> 145 return %low, %high : vector<4xi32>, vector<4xi32> 146} 147 148// Check float unary operation conversions. 149// CHECK-LABEL: @float32_unary_scalar 150func.func @float32_unary_scalar(%arg0: f32) { 151 // CHECK: spirv.FNegate %{{.*}}: f32 152 %0 = arith.negf %arg0 : f32 153 return 154} 155 156// Check float binary operation conversions. 157// CHECK-LABEL: @float32_binary_scalar 158func.func @float32_binary_scalar(%lhs: f32, %rhs: f32) { 159 // CHECK: spirv.FAdd %{{.*}}, %{{.*}}: f32 160 %0 = arith.addf %lhs, %rhs: f32 161 // CHECK: spirv.FSub %{{.*}}, %{{.*}}: f32 162 %1 = arith.subf %lhs, %rhs: f32 163 // CHECK: spirv.FMul %{{.*}}, %{{.*}}: f32 164 %2 = arith.mulf %lhs, %rhs: f32 165 // CHECK: spirv.FDiv %{{.*}}, %{{.*}}: f32 166 %3 = arith.divf %lhs, %rhs: f32 167 // CHECK: spirv.FRem %{{.*}}, %{{.*}}: f32 168 %4 = arith.remf %lhs, %rhs: f32 169 return 170} 171 172// Check int vector types. 173// CHECK-LABEL: @int_vector234 174func.func @int_vector234(%arg0: vector<2xi8>, %arg1: vector<4xi64>) { 175 // CHECK: spirv.SDiv %{{.*}}, %{{.*}}: vector<2xi8> 176 %0 = arith.divsi %arg0, %arg0: vector<2xi8> 177 // CHECK: spirv.UDiv %{{.*}}, %{{.*}}: vector<4xi64> 178 %1 = arith.divui %arg1, %arg1: vector<4xi64> 179 return 180} 181 182// CHECK-LABEL: @index_vector 183func.func @index_vector(%arg0: vector<4xindex>) { 184 // CHECK: spirv.UMod %{{.*}}, %{{.*}}: vector<4xi32> 185 %0 = arith.remui %arg0, %arg0: vector<4xindex> 186 return 187} 188 189// CHECK-LABEL: @vector_srem 190// CHECK-SAME: (%[[LHS:.+]]: vector<3xi16>, %[[RHS:.+]]: vector<3xi16>) 191func.func @vector_srem(%arg0: vector<3xi16>, %arg1: vector<3xi16>) { 192 // CHECK: %[[LABS:.+]] = spirv.GL.SAbs %[[LHS]] : vector<3xi16> 193 // CHECK: %[[RABS:.+]] = spirv.GL.SAbs %[[RHS]] : vector<3xi16> 194 // CHECK: %[[ABS:.+]] = spirv.UMod %[[LABS]], %[[RABS]] : vector<3xi16> 195 // CHECK: %[[POS:.+]] = spirv.IEqual %[[LHS]], %[[LABS]] : vector<3xi16> 196 // CHECK: %[[NEG:.+]] = spirv.SNegate %[[ABS]] : vector<3xi16> 197 // CHECK: %{{.+}} = spirv.Select %[[POS]], %[[ABS]], %[[NEG]] : vector<3xi1>, vector<3xi16> 198 %0 = arith.remsi %arg0, %arg1: vector<3xi16> 199 return 200} 201 202// Check float vector types. 203// CHECK-LABEL: @float_vector234 204func.func @float_vector234(%arg0: vector<2xf16>, %arg1: vector<3xf64>) { 205 // CHECK: spirv.FAdd %{{.*}}, %{{.*}}: vector<2xf16> 206 %0 = arith.addf %arg0, %arg0: vector<2xf16> 207 // CHECK: spirv.FMul %{{.*}}, %{{.*}}: vector<3xf64> 208 %1 = arith.mulf %arg1, %arg1: vector<3xf64> 209 return 210} 211 212// CHECK-LABEL: @one_elem_vector 213func.func @one_elem_vector(%arg0: vector<1xi32>) { 214 // CHECK: spirv.IAdd %{{.+}}, %{{.+}}: i32 215 %0 = arith.addi %arg0, %arg0: vector<1xi32> 216 return 217} 218 219} // end module 220 221// ----- 222 223//===----------------------------------------------------------------------===// 224// Bit ops 225//===----------------------------------------------------------------------===// 226 227module attributes { 228 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [], []>, #spirv.resource_limits<>> 229} { 230 231// CHECK-LABEL: @bitwise_scalar 232func.func @bitwise_scalar(%arg0 : i32, %arg1 : i32) { 233 // CHECK: spirv.BitwiseAnd 234 %0 = arith.andi %arg0, %arg1 : i32 235 // CHECK: spirv.BitwiseOr 236 %1 = arith.ori %arg0, %arg1 : i32 237 // CHECK: spirv.BitwiseXor 238 %2 = arith.xori %arg0, %arg1 : i32 239 return 240} 241 242// CHECK-LABEL: @bitwise_vector 243func.func @bitwise_vector(%arg0 : vector<4xi32>, %arg1 : vector<4xi32>) { 244 // CHECK: spirv.BitwiseAnd 245 %0 = arith.andi %arg0, %arg1 : vector<4xi32> 246 // CHECK: spirv.BitwiseOr 247 %1 = arith.ori %arg0, %arg1 : vector<4xi32> 248 // CHECK: spirv.BitwiseXor 249 %2 = arith.xori %arg0, %arg1 : vector<4xi32> 250 return 251} 252 253// CHECK-LABEL: @logical_scalar 254func.func @logical_scalar(%arg0 : i1, %arg1 : i1) { 255 // CHECK: spirv.LogicalAnd 256 %0 = arith.andi %arg0, %arg1 : i1 257 // CHECK: spirv.LogicalOr 258 %1 = arith.ori %arg0, %arg1 : i1 259 // CHECK: spirv.LogicalNotEqual 260 %2 = arith.xori %arg0, %arg1 : i1 261 return 262} 263 264// CHECK-LABEL: @logical_vector 265func.func @logical_vector(%arg0 : vector<4xi1>, %arg1 : vector<4xi1>) { 266 // CHECK: spirv.LogicalAnd 267 %0 = arith.andi %arg0, %arg1 : vector<4xi1> 268 // CHECK: spirv.LogicalOr 269 %1 = arith.ori %arg0, %arg1 : vector<4xi1> 270 // CHECK: spirv.LogicalNotEqual 271 %2 = arith.xori %arg0, %arg1 : vector<4xi1> 272 return 273} 274 275// CHECK-LABEL: @shift_scalar 276func.func @shift_scalar(%arg0 : i32, %arg1 : i32) { 277 // CHECK: spirv.ShiftLeftLogical 278 %0 = arith.shli %arg0, %arg1 : i32 279 // CHECK: spirv.ShiftRightArithmetic 280 %1 = arith.shrsi %arg0, %arg1 : i32 281 // CHECK: spirv.ShiftRightLogical 282 %2 = arith.shrui %arg0, %arg1 : i32 283 return 284} 285 286// CHECK-LABEL: @shift_vector 287func.func @shift_vector(%arg0 : vector<4xi32>, %arg1 : vector<4xi32>) { 288 // CHECK: spirv.ShiftLeftLogical 289 %0 = arith.shli %arg0, %arg1 : vector<4xi32> 290 // CHECK: spirv.ShiftRightArithmetic 291 %1 = arith.shrsi %arg0, %arg1 : vector<4xi32> 292 // CHECK: spirv.ShiftRightLogical 293 %2 = arith.shrui %arg0, %arg1 : vector<4xi32> 294 return 295} 296 297} // end module 298 299// ----- 300 301//===----------------------------------------------------------------------===// 302// arith.cmpf 303//===----------------------------------------------------------------------===// 304 305module attributes { 306 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [], []>, #spirv.resource_limits<>> 307} { 308 309// CHECK-LABEL: @cmpf 310func.func @cmpf(%arg0 : f32, %arg1 : f32) { 311 // CHECK: spirv.FOrdEqual 312 %1 = arith.cmpf oeq, %arg0, %arg1 : f32 313 // CHECK: spirv.FOrdGreaterThan 314 %2 = arith.cmpf ogt, %arg0, %arg1 : f32 315 // CHECK: spirv.FOrdGreaterThanEqual 316 %3 = arith.cmpf oge, %arg0, %arg1 : f32 317 // CHECK: spirv.FOrdLessThan 318 %4 = arith.cmpf olt, %arg0, %arg1 : f32 319 // CHECK: spirv.FOrdLessThanEqual 320 %5 = arith.cmpf ole, %arg0, %arg1 : f32 321 // CHECK: spirv.FOrdNotEqual 322 %6 = arith.cmpf one, %arg0, %arg1 : f32 323 // CHECK: spirv.FUnordEqual 324 %7 = arith.cmpf ueq, %arg0, %arg1 : f32 325 // CHECK: spirv.FUnordGreaterThan 326 %8 = arith.cmpf ugt, %arg0, %arg1 : f32 327 // CHECK: spirv.FUnordGreaterThanEqual 328 %9 = arith.cmpf uge, %arg0, %arg1 : f32 329 // CHECK: spirv.FUnordLessThan 330 %10 = arith.cmpf ult, %arg0, %arg1 : f32 331 // CHECK: FUnordLessThanEqual 332 %11 = arith.cmpf ule, %arg0, %arg1 : f32 333 // CHECK: spirv.FUnordNotEqual 334 %12 = arith.cmpf une, %arg0, %arg1 : f32 335 return 336} 337 338// CHECK-LABEL: @vec1cmpf 339func.func @vec1cmpf(%arg0 : vector<1xf32>, %arg1 : vector<1xf32>) { 340 // CHECK: spirv.FOrdGreaterThan 341 %0 = arith.cmpf ogt, %arg0, %arg1 : vector<1xf32> 342 // CHECK: spirv.FUnordLessThan 343 %1 = arith.cmpf ult, %arg0, %arg1 : vector<1xf32> 344 return 345} 346 347} // end module 348 349// ----- 350 351// With Kernel capability, we can convert NaN check to spirv.Ordered/spirv.Unordered. 352module attributes { 353 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Kernel], []>, #spirv.resource_limits<>> 354} { 355 356// CHECK-LABEL: @cmpf 357func.func @cmpf(%arg0 : f32, %arg1 : f32) { 358 // CHECK: spirv.Ordered 359 %0 = arith.cmpf ord, %arg0, %arg1 : f32 360 // CHECK: spirv.Unordered 361 %1 = arith.cmpf uno, %arg0, %arg1 : f32 362 return 363} 364 365} // end module 366 367// ----- 368 369// Without Kernel capability, we need to convert NaN check to spirv.IsNan. 370module attributes { 371 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [], []>, #spirv.resource_limits<>> 372} { 373 374// CHECK-LABEL: @cmpf 375// CHECK-SAME: %[[LHS:.+]]: f32, %[[RHS:.+]]: f32 376func.func @cmpf(%arg0 : f32, %arg1 : f32) { 377 // CHECK: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : f32 378 // CHECK-NEXT: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : f32 379 // CHECK-NEXT: %[[OR:.+]] = spirv.LogicalOr %[[LHS_NAN]], %[[RHS_NAN]] : i1 380 // CHECK-NEXT: %{{.+}} = spirv.LogicalNot %[[OR]] : i1 381 %0 = arith.cmpf ord, %arg0, %arg1 : f32 382 383 // CHECK-NEXT: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : f32 384 // CHECK-NEXT: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : f32 385 // CHECK-NEXT: %{{.+}} = spirv.LogicalOr %[[LHS_NAN]], %[[RHS_NAN]] : i1 386 %1 = arith.cmpf uno, %arg0, %arg1 : f32 387 return 388} 389 390} // end module 391 392// ----- 393 394//===----------------------------------------------------------------------===// 395// arith.cmpi 396//===----------------------------------------------------------------------===// 397 398module attributes { 399 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [], []>, #spirv.resource_limits<>> 400} { 401 402// CHECK-LABEL: @cmpi 403func.func @cmpi(%arg0 : i32, %arg1 : i32) { 404 // CHECK: spirv.IEqual 405 %0 = arith.cmpi eq, %arg0, %arg1 : i32 406 // CHECK: spirv.INotEqual 407 %1 = arith.cmpi ne, %arg0, %arg1 : i32 408 // CHECK: spirv.SLessThan 409 %2 = arith.cmpi slt, %arg0, %arg1 : i32 410 // CHECK: spirv.SLessThanEqual 411 %3 = arith.cmpi sle, %arg0, %arg1 : i32 412 // CHECK: spirv.SGreaterThan 413 %4 = arith.cmpi sgt, %arg0, %arg1 : i32 414 // CHECK: spirv.SGreaterThanEqual 415 %5 = arith.cmpi sge, %arg0, %arg1 : i32 416 // CHECK: spirv.ULessThan 417 %6 = arith.cmpi ult, %arg0, %arg1 : i32 418 // CHECK: spirv.ULessThanEqual 419 %7 = arith.cmpi ule, %arg0, %arg1 : i32 420 // CHECK: spirv.UGreaterThan 421 %8 = arith.cmpi ugt, %arg0, %arg1 : i32 422 // CHECK: spirv.UGreaterThanEqual 423 %9 = arith.cmpi uge, %arg0, %arg1 : i32 424 return 425} 426 427// CHECK-LABEL: @indexcmpi 428func.func @indexcmpi(%arg0 : index, %arg1 : index) { 429 // CHECK: spirv.IEqual 430 %0 = arith.cmpi eq, %arg0, %arg1 : index 431 // CHECK: spirv.INotEqual 432 %1 = arith.cmpi ne, %arg0, %arg1 : index 433 // CHECK: spirv.SLessThan 434 %2 = arith.cmpi slt, %arg0, %arg1 : index 435 // CHECK: spirv.SLessThanEqual 436 %3 = arith.cmpi sle, %arg0, %arg1 : index 437 // CHECK: spirv.SGreaterThan 438 %4 = arith.cmpi sgt, %arg0, %arg1 : index 439 // CHECK: spirv.SGreaterThanEqual 440 %5 = arith.cmpi sge, %arg0, %arg1 : index 441 // CHECK: spirv.ULessThan 442 %6 = arith.cmpi ult, %arg0, %arg1 : index 443 // CHECK: spirv.ULessThanEqual 444 %7 = arith.cmpi ule, %arg0, %arg1 : index 445 // CHECK: spirv.UGreaterThan 446 %8 = arith.cmpi ugt, %arg0, %arg1 : index 447 // CHECK: spirv.UGreaterThanEqual 448 %9 = arith.cmpi uge, %arg0, %arg1 : index 449 return 450} 451 452// CHECK-LABEL: @vec1cmpi 453func.func @vec1cmpi(%arg0 : vector<1xi32>, %arg1 : vector<1xi32>) { 454 // CHECK: spirv.ULessThan 455 %0 = arith.cmpi ult, %arg0, %arg1 : vector<1xi32> 456 // CHECK: spirv.SGreaterThan 457 %1 = arith.cmpi sgt, %arg0, %arg1 : vector<1xi32> 458 return 459} 460 461// CHECK-LABEL: @boolcmpi_equality 462func.func @boolcmpi_equality(%arg0 : i1, %arg1 : i1) { 463 // CHECK: spirv.LogicalEqual 464 %0 = arith.cmpi eq, %arg0, %arg1 : i1 465 // CHECK: spirv.LogicalNotEqual 466 %1 = arith.cmpi ne, %arg0, %arg1 : i1 467 return 468} 469 470// CHECK-LABEL: @boolcmpi_unsigned 471func.func @boolcmpi_unsigned(%arg0 : i1, %arg1 : i1) { 472 // CHECK-COUNT-2: spirv.Select 473 // CHECK: spirv.UGreaterThanEqual 474 %0 = arith.cmpi uge, %arg0, %arg1 : i1 475 // CHECK-COUNT-2: spirv.Select 476 // CHECK: spirv.ULessThan 477 %1 = arith.cmpi ult, %arg0, %arg1 : i1 478 return 479} 480 481// CHECK-LABEL: @vec1boolcmpi_equality 482func.func @vec1boolcmpi_equality(%arg0 : vector<1xi1>, %arg1 : vector<1xi1>) { 483 // CHECK: spirv.LogicalEqual 484 %0 = arith.cmpi eq, %arg0, %arg1 : vector<1xi1> 485 // CHECK: spirv.LogicalNotEqual 486 %1 = arith.cmpi ne, %arg0, %arg1 : vector<1xi1> 487 return 488} 489 490// CHECK-LABEL: @vec1boolcmpi_unsigned 491func.func @vec1boolcmpi_unsigned(%arg0 : vector<1xi1>, %arg1 : vector<1xi1>) { 492 // CHECK-COUNT-2: spirv.Select 493 // CHECK: spirv.UGreaterThanEqual 494 %0 = arith.cmpi uge, %arg0, %arg1 : vector<1xi1> 495 // CHECK-COUNT-2: spirv.Select 496 // CHECK: spirv.ULessThan 497 %1 = arith.cmpi ult, %arg0, %arg1 : vector<1xi1> 498 return 499} 500 501// CHECK-LABEL: @vecboolcmpi_equality 502func.func @vecboolcmpi_equality(%arg0 : vector<4xi1>, %arg1 : vector<4xi1>) { 503 // CHECK: spirv.LogicalEqual 504 %0 = arith.cmpi eq, %arg0, %arg1 : vector<4xi1> 505 // CHECK: spirv.LogicalNotEqual 506 %1 = arith.cmpi ne, %arg0, %arg1 : vector<4xi1> 507 return 508} 509 510// CHECK-LABEL: @vecboolcmpi_unsigned 511func.func @vecboolcmpi_unsigned(%arg0 : vector<3xi1>, %arg1 : vector<3xi1>) { 512 // CHECK-COUNT-2: spirv.Select 513 // CHECK: spirv.UGreaterThanEqual 514 %0 = arith.cmpi uge, %arg0, %arg1 : vector<3xi1> 515 // CHECK-COUNT-2: spirv.Select 516 // CHECK: spirv.ULessThan 517 %1 = arith.cmpi ult, %arg0, %arg1 : vector<3xi1> 518 return 519} 520 521 522} // end module 523 524// ----- 525 526//===----------------------------------------------------------------------===// 527// arith.constant 528//===----------------------------------------------------------------------===// 529 530module attributes { 531 spirv.target_env = #spirv.target_env< 532 #spirv.vce<v1.0, [Int8, Int16, Int64, Float16, Float64], []>, #spirv.resource_limits<>> 533} { 534 535// CHECK-LABEL: @constant 536func.func @constant() { 537 // CHECK: spirv.Constant true 538 %0 = arith.constant true 539 // CHECK: spirv.Constant 42 : i32 540 %1 = arith.constant 42 : i32 541 // CHECK: spirv.Constant 5.000000e-01 : f32 542 %2 = arith.constant 0.5 : f32 543 // CHECK: spirv.Constant dense<[2, 3]> : vector<2xi32> 544 %3 = arith.constant dense<[2, 3]> : vector<2xi32> 545 // CHECK: spirv.Constant 1 : i32 546 %4 = arith.constant 1 : index 547 // CHECK: spirv.Constant dense<1> : tensor<6xi32> : !spirv.array<6 x i32> 548 %5 = arith.constant dense<1> : tensor<2x3xi32> 549 // CHECK: spirv.Constant dense<1.000000e+00> : tensor<6xf32> : !spirv.array<6 x f32> 550 %6 = arith.constant dense<1.0> : tensor<2x3xf32> 551 // CHECK: spirv.Constant dense<{{\[}}1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf32> : !spirv.array<6 x f32> 552 %7 = arith.constant dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf32> 553 // CHECK: spirv.Constant dense<{{\[}}1, 2, 3, 4, 5, 6]> : tensor<6xi32> : !spirv.array<6 x i32> 554 %8 = arith.constant dense<[[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi32> 555 // CHECK: spirv.Constant dense<{{\[}}1, 2, 3, 4, 5, 6]> : tensor<6xi32> : !spirv.array<6 x i32> 556 %9 = arith.constant dense<[[1, 2], [3, 4], [5, 6]]> : tensor<3x2xi32> 557 // CHECK: spirv.Constant dense<{{\[}}1, 2, 3, 4, 5, 6]> : tensor<6xi32> : !spirv.array<6 x i32> 558 %10 = arith.constant dense<[1, 2, 3, 4, 5, 6]> : tensor<6xi32> 559 return 560} 561 562// CHECK-LABEL: @constant_16bit 563func.func @constant_16bit() { 564 // CHECK: spirv.Constant 4 : i16 565 %0 = arith.constant 4 : i16 566 // CHECK: spirv.Constant 5.000000e+00 : f16 567 %1 = arith.constant 5.0 : f16 568 // CHECK: spirv.Constant dense<[2, 3]> : vector<2xi16> 569 %2 = arith.constant dense<[2, 3]> : vector<2xi16> 570 // CHECK: spirv.Constant dense<4.000000e+00> : tensor<5xf16> : !spirv.array<5 x f16> 571 %3 = arith.constant dense<4.0> : tensor<5xf16> 572 return 573} 574 575// CHECK-LABEL: @constant_64bit 576func.func @constant_64bit() { 577 // CHECK: spirv.Constant 4 : i64 578 %0 = arith.constant 4 : i64 579 // CHECK: spirv.Constant 5.000000e+00 : f64 580 %1 = arith.constant 5.0 : f64 581 // CHECK: spirv.Constant dense<[2, 3]> : vector<2xi64> 582 %2 = arith.constant dense<[2, 3]> : vector<2xi64> 583 // CHECK: spirv.Constant dense<4.000000e+00> : tensor<5xf64> : !spirv.array<5 x f64> 584 %3 = arith.constant dense<4.0> : tensor<5xf64> 585 return 586} 587 588// CHECK-LABEL: @constant_size1 589func.func @constant_size1() { 590 // CHECK: spirv.Constant true 591 %0 = arith.constant dense<true> : tensor<1xi1> 592 // CHECK: spirv.Constant 4 : i64 593 %1 = arith.constant dense<4> : vector<1xi64> 594 // CHECK: spirv.Constant 5.000000e+00 : f64 595 %2 = arith.constant dense<5.0> : tensor<1xf64> 596 return 597} 598 599} // end module 600 601// ----- 602 603// Check that constants are widened to 32-bit when no special capability. 604module attributes { 605 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [], []>, #spirv.resource_limits<>> 606} { 607 608// CHECK-LABEL: @constant_16bit 609func.func @constant_16bit() { 610 // CHECK: spirv.Constant 4 : i32 611 %0 = arith.constant 4 : i16 612 // CHECK: spirv.Constant 5.000000e+00 : f32 613 %1 = arith.constant 5.0 : f16 614 // CHECK: spirv.Constant dense<[2, 3]> : vector<2xi32> 615 %2 = arith.constant dense<[2, 3]> : vector<2xi16> 616 // CHECK: spirv.Constant dense<4.000000e+00> : tensor<5xf32> : !spirv.array<5 x f32> 617 %3 = arith.constant dense<4.0> : tensor<5xf16> 618 // CHECK: spirv.Constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00]> : tensor<4xf32> : !spirv.array<4 x f32> 619 %4 = arith.constant dense<[[1.0, 2.0], [3.0, 4.0]]> : tensor<2x2xf16> 620 return 621} 622 623// CHECK-LABEL: @constant_size1 624func.func @constant_size1() { 625 // CHECK: spirv.Constant 4 : i32 626 %0 = arith.constant dense<4> : vector<1xi16> 627 // CHECK: spirv.Constant 5.000000e+00 : f32 628 %1 = arith.constant dense<5.0> : tensor<1xf16> 629 return 630} 631 632// CHECK-LABEL: @corner_cases 633func.func @corner_cases() { 634 // CHECK: %{{.*}} = spirv.Constant -1 : i32 635 %5 = arith.constant -1 : i16 636 // CHECK: %{{.*}} = spirv.Constant -2 : i32 637 %6 = arith.constant -2 : i16 638 // CHECK: %{{.*}} = spirv.Constant -1 : i32 639 %7 = arith.constant -1 : index 640 // CHECK: %{{.*}} = spirv.Constant -2 : i32 641 %8 = arith.constant -2 : index 642 643 // CHECK: spirv.Constant false 644 %9 = arith.constant false 645 // CHECK: spirv.Constant true 646 %10 = arith.constant true 647 648 return 649} 650 651} // end module 652 653// ----- 654 655//===----------------------------------------------------------------------===// 656// Cast ops 657//===----------------------------------------------------------------------===// 658 659module attributes { 660 spirv.target_env = #spirv.target_env< 661 #spirv.vce<v1.0, [Int8, Int16, Int64, Float16, Float64], []>, #spirv.resource_limits<>> 662} { 663 664// CHECK-LABEL: index_cast1 665func.func @index_cast1(%arg0: i16) { 666 // CHECK: spirv.SConvert %{{.+}} : i16 to i32 667 %0 = arith.index_cast %arg0 : i16 to index 668 return 669} 670 671// CHECK-LABEL: index_cast2 672func.func @index_cast2(%arg0: index) { 673 // CHECK: spirv.SConvert %{{.+}} : i32 to i16 674 %0 = arith.index_cast %arg0 : index to i16 675 return 676} 677 678// CHECK-LABEL: index_cast3 679func.func @index_cast3(%arg0: i32) { 680 // CHECK-NOT: spirv.SConvert 681 %0 = arith.index_cast %arg0 : i32 to index 682 return 683} 684 685// CHECK-LABEL: index_cast4 686func.func @index_cast4(%arg0: index) { 687 // CHECK-NOT: spirv.UConvert 688 %0 = arith.index_cast %arg0 : index to i32 689 return 690} 691 692// CHECK-LABEL: index_castui1 693func.func @index_castui1(%arg0: i16) { 694 // CHECK: spirv.UConvert %{{.+}} : i16 to i32 695 %0 = arith.index_castui %arg0 : i16 to index 696 return 697} 698 699// CHECK-LABEL: index_castui2 700func.func @index_castui2(%arg0: index) { 701 // CHECK: spirv.UConvert %{{.+}} : i32 to i16 702 %0 = arith.index_castui %arg0 : index to i16 703 return 704} 705 706// CHECK-LABEL: index_castui3 707func.func @index_castui3(%arg0: i32) { 708 // CHECK-NOT: spirv.UConvert 709 %0 = arith.index_castui %arg0 : i32 to index 710 return 711} 712 713// CHECK-LABEL: index_castui4 714func.func @index_castui4(%arg0: index) { 715 // CHECK-NOT: spirv.UConvert 716 %0 = arith.index_cast %arg0 : index to i32 717 return 718} 719 720// CHECK-LABEL: @bit_cast 721func.func @bit_cast(%arg0: vector<2xf32>, %arg1: i64) { 722 // CHECK: spirv.Bitcast %{{.+}} : vector<2xf32> to vector<2xi32> 723 %0 = arith.bitcast %arg0 : vector<2xf32> to vector<2xi32> 724 // CHECK: spirv.Bitcast %{{.+}} : i64 to f64 725 %1 = arith.bitcast %arg1 : i64 to f64 726 return 727} 728 729// CHECK-LABEL: @fpext1 730func.func @fpext1(%arg0: f16) -> f64 { 731 // CHECK: spirv.FConvert %{{.*}} : f16 to f64 732 %0 = arith.extf %arg0 : f16 to f64 733 return %0 : f64 734} 735 736// CHECK-LABEL: @fpext2 737func.func @fpext2(%arg0 : f32) -> f64 { 738 // CHECK: spirv.FConvert %{{.*}} : f32 to f64 739 %0 = arith.extf %arg0 : f32 to f64 740 return %0 : f64 741} 742 743// CHECK-LABEL: @fptrunc1 744func.func @fptrunc1(%arg0 : f64) -> f16 { 745 // CHECK: spirv.FConvert %{{.*}} : f64 to f16 746 %0 = arith.truncf %arg0 : f64 to f16 747 return %0 : f16 748} 749 750// CHECK-LABEL: @fptrunc2 751func.func @fptrunc2(%arg0: f32) -> f16 { 752 // CHECK: spirv.FConvert %{{.*}} : f32 to f16 753 %0 = arith.truncf %arg0 : f32 to f16 754 return %0 : f16 755} 756 757 758// CHECK-LABEL: @experimental_constrained_fptrunc 759func.func @experimental_constrained_fptrunc(%arg0 : f64) { 760 // CHECK: spirv.FConvert %arg0 {fp_rounding_mode = #spirv.fp_rounding_mode<RTE>} : f64 to f32 761 %0 = arith.truncf %arg0 to_nearest_even : f64 to f32 762 // CHECK: spirv.FConvert %arg0 {fp_rounding_mode = #spirv.fp_rounding_mode<RTN>} : f64 to f32 763 %1 = arith.truncf %arg0 downward : f64 to f32 764 // CHECK: spirv.FConvert %arg0 {fp_rounding_mode = #spirv.fp_rounding_mode<RTP>} : f64 to f32 765 %2 = arith.truncf %arg0 upward : f64 to f32 766 // CHECK: spirv.FConvert %arg0 {fp_rounding_mode = #spirv.fp_rounding_mode<RTZ>} : f64 to f32 767 %3 = arith.truncf %arg0 toward_zero : f64 to f32 768 return 769} 770 771 772// CHECK-LABEL: @sitofp1 773func.func @sitofp1(%arg0 : i32) -> f32 { 774 // CHECK: spirv.ConvertSToF %{{.*}} : i32 to f32 775 %0 = arith.sitofp %arg0 : i32 to f32 776 return %0 : f32 777} 778 779// CHECK-LABEL: @sitofp2 780func.func @sitofp2(%arg0 : i64) -> f64 { 781 // CHECK: spirv.ConvertSToF %{{.*}} : i64 to f64 782 %0 = arith.sitofp %arg0 : i64 to f64 783 return %0 : f64 784} 785 786// CHECK-LABEL: @uitofp_i16_f32 787func.func @uitofp_i16_f32(%arg0: i16) -> f32 { 788 // CHECK: spirv.ConvertUToF %{{.*}} : i16 to f32 789 %0 = arith.uitofp %arg0 : i16 to f32 790 return %0 : f32 791} 792 793// CHECK-LABEL: @uitofp_i32_f32 794func.func @uitofp_i32_f32(%arg0 : i32) -> f32 { 795 // CHECK: spirv.ConvertUToF %{{.*}} : i32 to f32 796 %0 = arith.uitofp %arg0 : i32 to f32 797 return %0 : f32 798} 799 800// CHECK-LABEL: @uitofp_i1_f32 801func.func @uitofp_i1_f32(%arg0 : i1) -> f32 { 802 // CHECK: %[[ZERO:.+]] = spirv.Constant 0.000000e+00 : f32 803 // CHECK: %[[ONE:.+]] = spirv.Constant 1.000000e+00 : f32 804 // CHECK: spirv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : i1, f32 805 %0 = arith.uitofp %arg0 : i1 to f32 806 return %0 : f32 807} 808 809// CHECK-LABEL: @uitofp_i1_f64 810func.func @uitofp_i1_f64(%arg0 : i1) -> f64 { 811 // CHECK: %[[ZERO:.+]] = spirv.Constant 0.000000e+00 : f64 812 // CHECK: %[[ONE:.+]] = spirv.Constant 1.000000e+00 : f64 813 // CHECK: spirv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : i1, f64 814 %0 = arith.uitofp %arg0 : i1 to f64 815 return %0 : f64 816} 817 818// CHECK-LABEL: @uitofp_vec_i1_f32 819func.func @uitofp_vec_i1_f32(%arg0 : vector<4xi1>) -> vector<4xf32> { 820 // CHECK: %[[ZERO:.+]] = spirv.Constant dense<0.000000e+00> : vector<4xf32> 821 // CHECK: %[[ONE:.+]] = spirv.Constant dense<1.000000e+00> : vector<4xf32> 822 // CHECK: spirv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : vector<4xi1>, vector<4xf32> 823 %0 = arith.uitofp %arg0 : vector<4xi1> to vector<4xf32> 824 return %0 : vector<4xf32> 825} 826 827// CHECK-LABEL: @uitofp_vec_i1_f64 828spirv.func @uitofp_vec_i1_f64(%arg0: vector<4xi1>) -> vector<4xf64> "None" { 829 // CHECK: %[[ZERO:.+]] = spirv.Constant dense<0.000000e+00> : vector<4xf64> 830 // CHECK: %[[ONE:.+]] = spirv.Constant dense<1.000000e+00> : vector<4xf64> 831 // CHECK: spirv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : vector<4xi1>, vector<4xf64> 832 %0 = spirv.Constant dense<0.000000e+00> : vector<4xf64> 833 %1 = spirv.Constant dense<1.000000e+00> : vector<4xf64> 834 %2 = spirv.Select %arg0, %1, %0 : vector<4xi1>, vector<4xf64> 835 spirv.ReturnValue %2 : vector<4xf64> 836} 837 838// CHECK-LABEL: @sexti1 839func.func @sexti1(%arg0: i16) -> i64 { 840 // CHECK: spirv.SConvert %{{.*}} : i16 to i64 841 %0 = arith.extsi %arg0 : i16 to i64 842 return %0 : i64 843} 844 845// CHECK-LABEL: @sexti2 846func.func @sexti2(%arg0 : i32) -> i64 { 847 // CHECK: spirv.SConvert %{{.*}} : i32 to i64 848 %0 = arith.extsi %arg0 : i32 to i64 849 return %0 : i64 850} 851 852// CHECK-LABEL: @sext_bool_scalar 853// CHECK-SAME: ([[ARG:%.+]]: i1) -> i32 854func.func @sext_bool_scalar(%arg0 : i1) -> i32 { 855 // CHECK-DAG: [[ONES:%.+]] = spirv.Constant -1 : i32 856 // CHECK-DAG: [[ZERO:%.+]] = spirv.Constant 0 : i32 857 // CHECK: [[SEL:%.+]] = spirv.Select [[ARG]], [[ONES]], [[ZERO]] : i1, i32 858 // CHECK-NEXT: return [[SEL]] : i32 859 %0 = arith.extsi %arg0 : i1 to i32 860 return %0 : i32 861} 862 863// CHECK-LABEL: @sext_bool_vector 864// CHECK-SAME: ([[ARG:%.+]]: vector<3xi1>) -> vector<3xi32> 865func.func @sext_bool_vector(%arg0 : vector<3xi1>) -> vector<3xi32> { 866 // CHECK-DAG: [[ONES:%.+]] = spirv.Constant dense<-1> : vector<3xi32> 867 // CHECK-DAG: [[ZERO:%.+]] = spirv.Constant dense<0> : vector<3xi32> 868 // CHECK: [[SEL:%.+]] = spirv.Select [[ARG]], [[ONES]], [[ZERO]] : vector<3xi1>, vector<3xi32> 869 // CHECK-NEXT: return [[SEL]] : vector<3xi32> 870 %0 = arith.extsi %arg0 : vector<3xi1> to vector<3xi32> 871 return %0 : vector<3xi32> 872} 873 874// CHECK-LABEL: @zexti1 875func.func @zexti1(%arg0: i16) -> i64 { 876 // CHECK: spirv.UConvert %{{.*}} : i16 to i64 877 %0 = arith.extui %arg0 : i16 to i64 878 return %0 : i64 879} 880 881// CHECK-LABEL: @zexti2 882func.func @zexti2(%arg0 : i32) -> i64 { 883 // CHECK: spirv.UConvert %{{.*}} : i32 to i64 884 %0 = arith.extui %arg0 : i32 to i64 885 return %0 : i64 886} 887 888// CHECK-LABEL: @zexti3 889func.func @zexti3(%arg0 : i1) -> i32 { 890 // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32 891 // CHECK: %[[ONE:.+]] = spirv.Constant 1 : i32 892 // CHECK: spirv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : i1, i32 893 %0 = arith.extui %arg0 : i1 to i32 894 return %0 : i32 895} 896 897// CHECK-LABEL: @zexti4 898func.func @zexti4(%arg0 : vector<4xi1>) -> vector<4xi32> { 899 // CHECK: %[[ZERO:.+]] = spirv.Constant dense<0> : vector<4xi32> 900 // CHECK: %[[ONE:.+]] = spirv.Constant dense<1> : vector<4xi32> 901 // CHECK: spirv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : vector<4xi1>, vector<4xi32> 902 %0 = arith.extui %arg0 : vector<4xi1> to vector<4xi32> 903 return %0 : vector<4xi32> 904} 905 906// CHECK-LABEL: @zexti5 907func.func @zexti5(%arg0 : vector<4xi1>) -> vector<4xi64> { 908 // CHECK: %[[ZERO:.+]] = spirv.Constant dense<0> : vector<4xi64> 909 // CHECK: %[[ONE:.+]] = spirv.Constant dense<1> : vector<4xi64> 910 // CHECK: spirv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : vector<4xi1>, vector<4xi64> 911 %0 = arith.extui %arg0 : vector<4xi1> to vector<4xi64> 912 return %0 : vector<4xi64> 913} 914 915// CHECK-LABEL: @trunci1 916func.func @trunci1(%arg0 : i64) -> i16 { 917 // CHECK: spirv.SConvert %{{.*}} : i64 to i16 918 %0 = arith.trunci %arg0 : i64 to i16 919 return %0 : i16 920} 921 922// CHECK-LABEL: @trunci2 923func.func @trunci2(%arg0: i32) -> i16 { 924 // CHECK: spirv.SConvert %{{.*}} : i32 to i16 925 %0 = arith.trunci %arg0 : i32 to i16 926 return %0 : i16 927} 928 929// CHECK-LABEL: @trunc_to_i1 930func.func @trunc_to_i1(%arg0: i32) -> i1 { 931 // CHECK: %[[MASK:.*]] = spirv.Constant 1 : i32 932 // CHECK: %[[MASKED_SRC:.*]] = spirv.BitwiseAnd %{{.*}}, %[[MASK]] : i32 933 // CHECK: %[[IS_ONE:.*]] = spirv.IEqual %[[MASKED_SRC]], %[[MASK]] : i32 934 // CHECK-DAG: %[[TRUE:.*]] = spirv.Constant true 935 // CHECK-DAG: %[[FALSE:.*]] = spirv.Constant false 936 // CHECK: spirv.Select %[[IS_ONE]], %[[TRUE]], %[[FALSE]] : i1, i1 937 %0 = arith.trunci %arg0 : i32 to i1 938 return %0 : i1 939} 940 941// CHECK-LABEL: @trunc_to_veci1 942func.func @trunc_to_veci1(%arg0: vector<4xi32>) -> vector<4xi1> { 943 // CHECK: %[[MASK:.*]] = spirv.Constant dense<1> : vector<4xi32> 944 // CHECK: %[[MASKED_SRC:.*]] = spirv.BitwiseAnd %{{.*}}, %[[MASK]] : vector<4xi32> 945 // CHECK: %[[IS_ONE:.*]] = spirv.IEqual %[[MASKED_SRC]], %[[MASK]] : vector<4xi32> 946 // CHECK-DAG: %[[TRUE:.*]] = spirv.Constant dense<true> : vector<4xi1> 947 // CHECK-DAG: %[[FALSE:.*]] = spirv.Constant dense<false> : vector<4xi1> 948 // CHECK: spirv.Select %[[IS_ONE]], %[[TRUE]], %[[FALSE]] : vector<4xi1>, vector<4xi1> 949 %0 = arith.trunci %arg0 : vector<4xi32> to vector<4xi1> 950 return %0 : vector<4xi1> 951} 952 953// CHECK-LABEL: @fptoui1 954func.func @fptoui1(%arg0 : f32) -> i32 { 955 // CHECK: spirv.ConvertFToU %{{.*}} : f32 to i32 956 %0 = arith.fptoui %arg0 : f32 to i32 957 return %0 : i32 958} 959 960// CHECK-LABEL: @fptoui2 961func.func @fptoui2(%arg0 : f16) -> i16 { 962 // CHECK: spirv.ConvertFToU %{{.*}} : f16 to i16 963 %0 = arith.fptoui %arg0 : f16 to i16 964 return %0 : i16 965} 966 967// CHECK-LABEL: @fptosi1 968func.func @fptosi1(%arg0 : f32) -> i32 { 969 // CHECK: spirv.ConvertFToS %{{.*}} : f32 to i32 970 %0 = arith.fptosi %arg0 : f32 to i32 971 return %0 : i32 972} 973 974// CHECK-LABEL: @fptosi2 975func.func @fptosi2(%arg0 : f16) -> i16 { 976 // CHECK: spirv.ConvertFToS %{{.*}} : f16 to i16 977 %0 = arith.fptosi %arg0 : f16 to i16 978 return %0 : i16 979} 980 981} // end module 982 983// ----- 984 985// Checks that cast types will be adjusted when missing special capabilities for 986// certain non-32-bit scalar types. 987module attributes { 988 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Float64], []>, #spirv.resource_limits<>> 989} { 990 991// CHECK-LABEL: @fpext1 992// CHECK-SAME: %[[A:.*]]: f16 993func.func @fpext1(%arg0: f16) -> f64 { 994 // CHECK: %[[ARG:.+]] = builtin.unrealized_conversion_cast %[[A]] : f16 to f32 995 // CHECK-NEXT: spirv.FConvert %[[ARG]] : f32 to f64 996 %0 = arith.extf %arg0 : f16 to f64 997 return %0: f64 998} 999 1000// CHECK-LABEL: @fpext2 1001// CHECK-SAME: %[[ARG:.*]]: f32 1002func.func @fpext2(%arg0 : f32) -> f64 { 1003 // CHECK-NEXT: spirv.FConvert %[[ARG]] : f32 to f64 1004 %0 = arith.extf %arg0 : f32 to f64 1005 return %0: f64 1006} 1007 1008// CHECK-LABEL: @trunci4_scalar 1009// CHECK-SAME: %[[ARG:.*]]: i32 1010func.func @trunci4_scalar(%arg0 : i32) -> i4 { 1011 // CHECK: %[[MASK:.+]] = spirv.Constant 15 : i32 1012 // CHECK: %[[AND:.+]] = spirv.BitwiseAnd %[[ARG]], %[[MASK]] : i32 1013 %0 = arith.trunci %arg0 : i32 to i4 1014 // CHECK: %[[RET:.+]] = builtin.unrealized_conversion_cast %[[AND]] : i32 to i4 1015 // CHECK: return %[[RET]] : i4 1016 return %0 : i4 1017} 1018 1019// CHECK-LABEL: @trunci4_vector 1020// CHECK-SAME: %[[ARG:.*]]: vector<2xi32> 1021func.func @trunci4_vector(%arg0 : vector<2xi32>) -> vector<2xi4> { 1022 // CHECK: %[[MASK:.+]] = spirv.Constant dense<15> : vector<2xi32> 1023 // CHECK: %[[AND:.+]] = spirv.BitwiseAnd %[[ARG]], %[[MASK]] : vector<2xi32> 1024 %0 = arith.trunci %arg0 : vector<2xi32> to vector<2xi4> 1025 // CHECK: %[[RET:.+]] = builtin.unrealized_conversion_cast %[[AND]] : vector<2xi32> to vector<2xi4> 1026 // CHECK: return %[[RET]] : vector<2xi4> 1027 return %0 : vector<2xi4> 1028} 1029 1030// CHECK-LABEL: @zexti4_scalar 1031func.func @zexti4_scalar(%arg0: i4) -> i32 { 1032 // CHECK: %[[INPUT:.+]] = builtin.unrealized_conversion_cast %{{.+}} : i4 to i32 1033 // CHECK: %[[MASK:.+]] = spirv.Constant 15 : i32 1034 // CHECK: %[[AND:.+]] = spirv.BitwiseAnd %[[INPUT]], %[[MASK]] : i32 1035 %0 = arith.extui %arg0 : i4 to i32 1036 // CHECK: return %[[AND]] : i32 1037 return %0 : i32 1038} 1039 1040// CHECK-LABEL: @zexti4_vector 1041func.func @zexti4_vector(%arg0: vector<3xi4>) -> vector<3xi32> { 1042 // CHECK: %[[INPUT:.+]] = builtin.unrealized_conversion_cast %{{.+}} : vector<3xi4> to vector<3xi32> 1043 // CHECK: %[[MASK:.+]] = spirv.Constant dense<15> : vector<3xi32> 1044 // CHECK: %[[AND:.+]] = spirv.BitwiseAnd %[[INPUT]], %[[MASK]] : vector<3xi32> 1045 %0 = arith.extui %arg0 : vector<3xi4> to vector<3xi32> 1046 // CHECK: return %[[AND]] : vector<3xi32> 1047 return %0 : vector<3xi32> 1048} 1049 1050// CHECK-LABEL: @sexti4_scalar 1051func.func @sexti4_scalar(%arg0: i4) -> i32 { 1052 // CHECK: %[[INPUT:.+]] = builtin.unrealized_conversion_cast %arg0 : i4 to i32 1053 // CHECK: %[[SIZE:.+]] = spirv.Constant 28 : i32 1054 // CHECK: %[[SL:.+]] = spirv.ShiftLeftLogical %[[INPUT]], %[[SIZE]] : i32, i32 1055 // CHECK: %[[SR:.+]] = spirv.ShiftRightArithmetic %[[SL]], %[[SIZE]] : i32, i32 1056 %0 = arith.extsi %arg0 : i4 to i32 1057 // CHECK: return %[[SR]] : i32 1058 return %0 : i32 1059} 1060 1061// CHECK-LABEL: @sexti4_vector 1062func.func @sexti4_vector(%arg0: vector<4xi4>) -> vector<4xi32> { 1063 // CHECK: %[[INPUT:.+]] = builtin.unrealized_conversion_cast %arg0 : vector<4xi4> to vector<4xi32> 1064 // CHECK: %[[SIZE:.+]] = spirv.Constant dense<28> : vector<4xi32> 1065 // CHECK: %[[SL:.+]] = spirv.ShiftLeftLogical %[[INPUT]], %[[SIZE]] : vector<4xi32>, vector<4xi32> 1066 // CHECK: %[[SR:.+]] = spirv.ShiftRightArithmetic %[[SL]], %[[SIZE]] : vector<4xi32>, vector<4xi32> 1067 %0 = arith.extsi %arg0 : vector<4xi4> to vector<4xi32> 1068 // CHECK: return %[[SR]] : vector<4xi32> 1069 return %0 : vector<4xi32> 1070} 1071 1072} // end module 1073 1074// ----- 1075 1076// Checks that cast types will be adjusted when missing special capabilities for 1077// certain non-32-bit scalar types. 1078module attributes { 1079 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Float16], []>, #spirv.resource_limits<>> 1080} { 1081 1082// CHECK-LABEL: @fptrunc1 1083// CHECK-SAME: %[[ARG:.*]]: f32 1084func.func @fptrunc1(%arg0: f32) -> f16 { 1085 // CHECK-NEXT: spirv.FConvert %[[ARG]] : f32 to f16 1086 %0 = arith.truncf %arg0 : f32 to f16 1087 return %0: f16 1088} 1089 1090} // end module 1091 1092// ----- 1093 1094// Check various lowerings for OpenCL. 1095module attributes { 1096 spirv.target_env = #spirv.target_env< 1097 #spirv.vce<v1.0, [Int16, Kernel], []>, #spirv.resource_limits<>> 1098} { 1099 1100// Check integer operation conversions. 1101// CHECK-LABEL: @int32_scalar 1102func.func @int32_scalar(%lhs: i32, %rhs: i32) { 1103 // CHECK: spirv.IAdd %{{.*}}, %{{.*}}: i32 1104 %0 = arith.addi %lhs, %rhs: i32 1105 // CHECK: spirv.ISub %{{.*}}, %{{.*}}: i32 1106 %1 = arith.subi %lhs, %rhs: i32 1107 // CHECK: spirv.IMul %{{.*}}, %{{.*}}: i32 1108 %2 = arith.muli %lhs, %rhs: i32 1109 // CHECK: spirv.SDiv %{{.*}}, %{{.*}}: i32 1110 %3 = arith.divsi %lhs, %rhs: i32 1111 // CHECK: spirv.UDiv %{{.*}}, %{{.*}}: i32 1112 %4 = arith.divui %lhs, %rhs: i32 1113 // CHECK: spirv.UMod %{{.*}}, %{{.*}}: i32 1114 %5 = arith.remui %lhs, %rhs: i32 1115 // CHECK: spirv.CL.s_max %{{.*}}, %{{.*}}: i32 1116 %6 = arith.maxsi %lhs, %rhs : i32 1117 // CHECK: spirv.CL.u_max %{{.*}}, %{{.*}}: i32 1118 %7 = arith.maxui %lhs, %rhs : i32 1119 // CHECK: spirv.CL.s_min %{{.*}}, %{{.*}}: i32 1120 %8 = arith.minsi %lhs, %rhs : i32 1121 // CHECK: spirv.CL.u_min %{{.*}}, %{{.*}}: i32 1122 %9 = arith.minui %lhs, %rhs : i32 1123 return 1124} 1125 1126// Check float binary operation conversions. 1127// CHECK-LABEL: @float32_binary_scalar 1128func.func @float32_binary_scalar(%lhs: f32, %rhs: f32) { 1129 // CHECK: spirv.FAdd %{{.*}}, %{{.*}}: f32 1130 %0 = arith.addf %lhs, %rhs: f32 1131 // CHECK: spirv.FSub %{{.*}}, %{{.*}}: f32 1132 %1 = arith.subf %lhs, %rhs: f32 1133 // CHECK: spirv.FMul %{{.*}}, %{{.*}}: f32 1134 %2 = arith.mulf %lhs, %rhs: f32 1135 // CHECK: spirv.FDiv %{{.*}}, %{{.*}}: f32 1136 %3 = arith.divf %lhs, %rhs: f32 1137 // CHECK: spirv.FRem %{{.*}}, %{{.*}}: f32 1138 %4 = arith.remf %lhs, %rhs: f32 1139 return 1140} 1141 1142// CHECK-LABEL: @float32_minimumf_scalar 1143// CHECK-SAME: %[[LHS:.+]]: f32, %[[RHS:.+]]: f32 1144func.func @float32_minimumf_scalar(%arg0 : f32, %arg1 : f32) -> f32 { 1145 // CHECK: %[[MIN:.+]] = spirv.CL.fmin %arg0, %arg1 : f32 1146 // CHECK: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : f32 1147 // CHECK: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : f32 1148 // CHECK: %[[SELECT1:.+]] = spirv.Select %[[LHS_NAN]], %[[LHS]], %[[MIN]] 1149 // CHECK: %[[SELECT2:.+]] = spirv.Select %[[RHS_NAN]], %[[RHS]], %[[SELECT1]] 1150 %0 = arith.minimumf %arg0, %arg1 : f32 1151 // CHECK: return %[[SELECT2]] 1152 return %0: f32 1153} 1154 1155// CHECK-LABEL: @float32_minnumf_scalar 1156// CHECK-SAME: %[[LHS:.+]]: f32, %[[RHS:.+]]: f32 1157func.func @float32_minnumf_scalar(%arg0 : f32, %arg1 : f32) -> f32 { 1158 // CHECK: %[[MIN:.+]] = spirv.CL.fmin %arg0, %arg1 : f32 1159 %0 = arith.minnumf %arg0, %arg1 : f32 1160 // CHECK: return %[[MIN]] 1161 return %0: f32 1162} 1163 1164// CHECK-LABEL: @float32_maximumf_scalar 1165// CHECK-SAME: %[[LHS:.+]]: vector<2xf32>, %[[RHS:.+]]: vector<2xf32> 1166func.func @float32_maximumf_scalar(%arg0 : vector<2xf32>, %arg1 : vector<2xf32>) -> vector<2xf32> { 1167 // CHECK: %[[MAX:.+]] = spirv.CL.fmax %arg0, %arg1 : vector<2xf32> 1168 // CHECK: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : vector<2xf32> 1169 // CHECK: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : vector<2xf32> 1170 // CHECK: %[[SELECT1:.+]] = spirv.Select %[[LHS_NAN]], %[[LHS]], %[[MAX]] 1171 // CHECK: %[[SELECT2:.+]] = spirv.Select %[[RHS_NAN]], %[[RHS]], %[[SELECT1]] 1172 %0 = arith.maximumf %arg0, %arg1 : vector<2xf32> 1173 // CHECK: return %[[SELECT2]] 1174 return %0: vector<2xf32> 1175} 1176 1177// CHECK-LABEL: @float32_maxnumf_scalar 1178// CHECK-SAME: %[[LHS:.+]]: vector<2xf32>, %[[RHS:.+]]: vector<2xf32> 1179func.func @float32_maxnumf_scalar(%arg0 : vector<2xf32>, %arg1 : vector<2xf32>) -> vector<2xf32> { 1180 // CHECK: %[[MAX:.+]] = spirv.CL.fmax %arg0, %arg1 : vector<2xf32> 1181 %0 = arith.maxnumf %arg0, %arg1 : vector<2xf32> 1182 // CHECK: return %[[MAX]] 1183 return %0: vector<2xf32> 1184} 1185 1186 1187// CHECK-LABEL: @scalar_srem 1188// CHECK-SAME: (%[[LHS:.+]]: i32, %[[RHS:.+]]: i32) 1189func.func @scalar_srem(%lhs: i32, %rhs: i32) { 1190 // CHECK: %[[LABS:.+]] = spirv.CL.s_abs %[[LHS]] : i32 1191 // CHECK: %[[RABS:.+]] = spirv.CL.s_abs %[[RHS]] : i32 1192 // CHECK: %[[ABS:.+]] = spirv.UMod %[[LABS]], %[[RABS]] : i32 1193 // CHECK: %[[POS:.+]] = spirv.IEqual %[[LHS]], %[[LABS]] : i32 1194 // CHECK: %[[NEG:.+]] = spirv.SNegate %[[ABS]] : i32 1195 // CHECK: %{{.+}} = spirv.Select %[[POS]], %[[ABS]], %[[NEG]] : i1, i32 1196 %0 = arith.remsi %lhs, %rhs: i32 1197 return 1198} 1199 1200// CHECK-LABEL: @vector_srem 1201// CHECK-SAME: (%[[LHS:.+]]: vector<3xi16>, %[[RHS:.+]]: vector<3xi16>) 1202func.func @vector_srem(%arg0: vector<3xi16>, %arg1: vector<3xi16>) { 1203 // CHECK: %[[LABS:.+]] = spirv.CL.s_abs %[[LHS]] : vector<3xi16> 1204 // CHECK: %[[RABS:.+]] = spirv.CL.s_abs %[[RHS]] : vector<3xi16> 1205 // CHECK: %[[ABS:.+]] = spirv.UMod %[[LABS]], %[[RABS]] : vector<3xi16> 1206 // CHECK: %[[POS:.+]] = spirv.IEqual %[[LHS]], %[[LABS]] : vector<3xi16> 1207 // CHECK: %[[NEG:.+]] = spirv.SNegate %[[ABS]] : vector<3xi16> 1208 // CHECK: %{{.+}} = spirv.Select %[[POS]], %[[ABS]], %[[NEG]] : vector<3xi1>, vector<3xi16> 1209 %0 = arith.remsi %arg0, %arg1: vector<3xi16> 1210 return 1211} 1212 1213} // end module 1214 1215// ----- 1216 1217module attributes { 1218 spirv.target_env = #spirv.target_env< 1219 #spirv.vce<v1.0, [Shader, Int8, Int16, Int64, Float16, Float64], 1220 [SPV_KHR_storage_buffer_storage_class]>, #spirv.resource_limits<>> 1221} { 1222 1223// CHECK-LABEL: @select 1224func.func @select(%arg0 : i32, %arg1 : i32) { 1225 %0 = arith.cmpi sle, %arg0, %arg1 : i32 1226 // CHECK: spirv.Select 1227 %1 = arith.select %0, %arg0, %arg1 : i32 1228 return 1229} 1230 1231} // end module 1232 1233// ----- 1234 1235//===----------------------------------------------------------------------===// 1236// arith.select 1237//===----------------------------------------------------------------------===// 1238 1239module attributes { 1240 spirv.target_env = #spirv.target_env< 1241 #spirv.vce<v1.0, [Int8, Int16, Int64, Float16, Float64, Shader], []>, #spirv.resource_limits<>> 1242} { 1243 1244// Check integer operation conversions. 1245// CHECK-LABEL: @int32_scalar 1246func.func @int32_scalar(%lhs: i32, %rhs: i32) { 1247 // CHECK: spirv.IAdd %{{.*}}, %{{.*}}: i32 1248 %0 = arith.addi %lhs, %rhs: i32 1249 // CHECK: spirv.ISub %{{.*}}, %{{.*}}: i32 1250 %1 = arith.subi %lhs, %rhs: i32 1251 // CHECK: spirv.IMul %{{.*}}, %{{.*}}: i32 1252 %2 = arith.muli %lhs, %rhs: i32 1253 // CHECK: spirv.SDiv %{{.*}}, %{{.*}}: i32 1254 %3 = arith.divsi %lhs, %rhs: i32 1255 // CHECK: spirv.UDiv %{{.*}}, %{{.*}}: i32 1256 %4 = arith.divui %lhs, %rhs: i32 1257 // CHECK: spirv.UMod %{{.*}}, %{{.*}}: i32 1258 %5 = arith.remui %lhs, %rhs: i32 1259 // CHECK: spirv.GL.SMax %{{.*}}, %{{.*}}: i32 1260 %6 = arith.maxsi %lhs, %rhs : i32 1261 // CHECK: spirv.GL.UMax %{{.*}}, %{{.*}}: i32 1262 %7 = arith.maxui %lhs, %rhs : i32 1263 // CHECK: spirv.GL.SMin %{{.*}}, %{{.*}}: i32 1264 %8 = arith.minsi %lhs, %rhs : i32 1265 // CHECK: spirv.GL.UMin %{{.*}}, %{{.*}}: i32 1266 %9 = arith.minui %lhs, %rhs : i32 1267 return 1268} 1269 1270// CHECK-LABEL: @scalar_srem 1271// CHECK-SAME: (%[[LHS:.+]]: i32, %[[RHS:.+]]: i32) 1272func.func @scalar_srem(%lhs: i32, %rhs: i32) { 1273 // CHECK: %[[LABS:.+]] = spirv.GL.SAbs %[[LHS]] : i32 1274 // CHECK: %[[RABS:.+]] = spirv.GL.SAbs %[[RHS]] : i32 1275 // CHECK: %[[ABS:.+]] = spirv.UMod %[[LABS]], %[[RABS]] : i32 1276 // CHECK: %[[POS:.+]] = spirv.IEqual %[[LHS]], %[[LABS]] : i32 1277 // CHECK: %[[NEG:.+]] = spirv.SNegate %[[ABS]] : i32 1278 // CHECK: %{{.+}} = spirv.Select %[[POS]], %[[ABS]], %[[NEG]] : i1, i32 1279 %0 = arith.remsi %lhs, %rhs: i32 1280 return 1281} 1282 1283// Check float unary operation conversions. 1284// CHECK-LABEL: @float32_unary_scalar 1285func.func @float32_unary_scalar(%arg0: f32) { 1286 // CHECK: spirv.FNegate %{{.*}}: f32 1287 %5 = arith.negf %arg0 : f32 1288 return 1289} 1290 1291// Check float binary operation conversions. 1292// CHECK-LABEL: @float32_binary_scalar 1293func.func @float32_binary_scalar(%lhs: f32, %rhs: f32) { 1294 // CHECK: spirv.FAdd %{{.*}}, %{{.*}}: f32 1295 %0 = arith.addf %lhs, %rhs: f32 1296 // CHECK: spirv.FSub %{{.*}}, %{{.*}}: f32 1297 %1 = arith.subf %lhs, %rhs: f32 1298 // CHECK: spirv.FMul %{{.*}}, %{{.*}}: f32 1299 %2 = arith.mulf %lhs, %rhs: f32 1300 // CHECK: spirv.FDiv %{{.*}}, %{{.*}}: f32 1301 %3 = arith.divf %lhs, %rhs: f32 1302 // CHECK: spirv.FRem %{{.*}}, %{{.*}}: f32 1303 %4 = arith.remf %lhs, %rhs: f32 1304 return 1305} 1306 1307// CHECK-LABEL: @float32_minimumf_scalar 1308// CHECK-SAME: %[[LHS:.+]]: f32, %[[RHS:.+]]: f32 1309func.func @float32_minimumf_scalar(%arg0 : f32, %arg1 : f32) -> f32 { 1310 // CHECK: %[[MIN:.+]] = spirv.GL.FMin %arg0, %arg1 : f32 1311 // CHECK: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : f32 1312 // CHECK: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : f32 1313 // CHECK: %[[SELECT1:.+]] = spirv.Select %[[LHS_NAN]], %[[LHS]], %[[MIN]] 1314 // CHECK: %[[SELECT2:.+]] = spirv.Select %[[RHS_NAN]], %[[RHS]], %[[SELECT1]] 1315 %0 = arith.minimumf %arg0, %arg1 : f32 1316 // CHECK: return %[[SELECT2]] 1317 return %0: f32 1318} 1319 1320// CHECK-LABEL: @float32_minnumf_scalar 1321// CHECK-SAME: %[[LHS:.+]]: f32, %[[RHS:.+]]: f32 1322func.func @float32_minnumf_scalar(%arg0 : f32, %arg1 : f32) -> f32 { 1323 // CHECK: %[[MIN:.+]] = spirv.GL.FMin %arg0, %arg1 : f32 1324 // CHECK: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : f32 1325 // CHECK: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : f32 1326 // CHECK: %[[SELECT1:.+]] = spirv.Select %[[LHS_NAN]], %[[RHS]], %[[MIN]] 1327 // CHECK: %[[SELECT2:.+]] = spirv.Select %[[RHS_NAN]], %[[LHS]], %[[SELECT1]] 1328 %0 = arith.minnumf %arg0, %arg1 : f32 1329 // CHECK: return %[[SELECT2]] 1330 return %0: f32 1331} 1332 1333// CHECK-LABEL: @float32_maximumf_scalar 1334// CHECK-SAME: %[[LHS:.+]]: vector<2xf32>, %[[RHS:.+]]: vector<2xf32> 1335func.func @float32_maximumf_scalar(%arg0 : vector<2xf32>, %arg1 : vector<2xf32>) -> vector<2xf32> { 1336 // CHECK: %[[MAX:.+]] = spirv.GL.FMax %arg0, %arg1 : vector<2xf32> 1337 // CHECK: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : vector<2xf32> 1338 // CHECK: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : vector<2xf32> 1339 // CHECK: %[[SELECT1:.+]] = spirv.Select %[[LHS_NAN]], %[[LHS]], %[[MAX]] 1340 // CHECK: %[[SELECT2:.+]] = spirv.Select %[[RHS_NAN]], %[[RHS]], %[[SELECT1]] 1341 %0 = arith.maximumf %arg0, %arg1 : vector<2xf32> 1342 // CHECK: return %[[SELECT2]] 1343 return %0: vector<2xf32> 1344} 1345 1346// CHECK-LABEL: @float32_maxnumf_scalar 1347// CHECK-SAME: %[[LHS:.+]]: vector<2xf32>, %[[RHS:.+]]: vector<2xf32> 1348func.func @float32_maxnumf_scalar(%arg0 : vector<2xf32>, %arg1 : vector<2xf32>) -> vector<2xf32> { 1349 // CHECK: %[[MAX:.+]] = spirv.GL.FMax %arg0, %arg1 : vector<2xf32> 1350 // CHECK: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : vector<2xf32> 1351 // CHECK: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : vector<2xf32> 1352 // CHECK: %[[SELECT1:.+]] = spirv.Select %[[LHS_NAN]], %[[RHS]], %[[MAX]] 1353 // CHECK: %[[SELECT2:.+]] = spirv.Select %[[RHS_NAN]], %[[LHS]], %[[SELECT1]] 1354 %0 = arith.maxnumf %arg0, %arg1 : vector<2xf32> 1355 // CHECK: return %[[SELECT2]] 1356 return %0: vector<2xf32> 1357} 1358 1359// Check int vector types. 1360// CHECK-LABEL: @int_vector234 1361func.func @int_vector234(%arg0: vector<2xi8>, %arg1: vector<4xi64>) { 1362 // CHECK: spirv.SDiv %{{.*}}, %{{.*}}: vector<2xi8> 1363 %0 = arith.divsi %arg0, %arg0: vector<2xi8> 1364 // CHECK: spirv.UDiv %{{.*}}, %{{.*}}: vector<4xi64> 1365 %1 = arith.divui %arg1, %arg1: vector<4xi64> 1366 return 1367} 1368 1369// CHECK-LABEL: @vector_srem 1370// CHECK-SAME: (%[[LHS:.+]]: vector<3xi16>, %[[RHS:.+]]: vector<3xi16>) 1371func.func @vector_srem(%arg0: vector<3xi16>, %arg1: vector<3xi16>) { 1372 // CHECK: %[[LABS:.+]] = spirv.GL.SAbs %[[LHS]] : vector<3xi16> 1373 // CHECK: %[[RABS:.+]] = spirv.GL.SAbs %[[RHS]] : vector<3xi16> 1374 // CHECK: %[[ABS:.+]] = spirv.UMod %[[LABS]], %[[RABS]] : vector<3xi16> 1375 // CHECK: %[[POS:.+]] = spirv.IEqual %[[LHS]], %[[LABS]] : vector<3xi16> 1376 // CHECK: %[[NEG:.+]] = spirv.SNegate %[[ABS]] : vector<3xi16> 1377 // CHECK: %{{.+}} = spirv.Select %[[POS]], %[[ABS]], %[[NEG]] : vector<3xi1>, vector<3xi16> 1378 %0 = arith.remsi %arg0, %arg1: vector<3xi16> 1379 return 1380} 1381 1382// Check float vector types. 1383// CHECK-LABEL: @float_vector234 1384func.func @float_vector234(%arg0: vector<2xf16>, %arg1: vector<3xf64>) { 1385 // CHECK: spirv.FAdd %{{.*}}, %{{.*}}: vector<2xf16> 1386 %0 = arith.addf %arg0, %arg0: vector<2xf16> 1387 // CHECK: spirv.FMul %{{.*}}, %{{.*}}: vector<3xf64> 1388 %1 = arith.mulf %arg1, %arg1: vector<3xf64> 1389 return 1390} 1391 1392// CHECK-LABEL: @one_elem_vector 1393func.func @one_elem_vector(%arg0: vector<1xi32>) { 1394 // CHECK: spirv.IAdd %{{.+}}, %{{.+}}: i32 1395 %0 = arith.addi %arg0, %arg0: vector<1xi32> 1396 return 1397} 1398 1399} // end module 1400 1401// ----- 1402 1403// Check that types are converted to 32-bit when no special capabilities. 1404module attributes { 1405 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [], []>, #spirv.resource_limits<>> 1406} { 1407 1408// CHECK-LABEL: @int_vector23 1409func.func @int_vector23(%arg0: vector<2xi8>, %arg1: vector<3xi16>) { 1410 // CHECK: spirv.SDiv %{{.*}}, %{{.*}}: vector<2xi32> 1411 %0 = arith.divsi %arg0, %arg0: vector<2xi8> 1412 // CHECK: spirv.SDiv %{{.*}}, %{{.*}}: vector<3xi32> 1413 %1 = arith.divsi %arg1, %arg1: vector<3xi16> 1414 return 1415} 1416 1417// CHECK-LABEL: @float_scalar 1418func.func @float_scalar(%arg0: f16) { 1419 // CHECK: spirv.FAdd %{{.*}}, %{{.*}}: f32 1420 %0 = arith.addf %arg0, %arg0: f16 1421 return 1422} 1423 1424} // end module 1425 1426// ----- 1427 1428module attributes { 1429 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Int8, Int16, Int64, Float16, Float64, Kernel], [SPV_KHR_no_integer_wrap_decoration]>, #spirv.resource_limits<>> 1430} { 1431 1432// CHECK-LABEL: @ops_flags 1433func.func @ops_flags(%arg0: i64, %arg1: i64) { 1434 // CHECK: %{{.*}} = spirv.IAdd %{{.*}}, %{{.*}} {no_signed_wrap} : i64 1435 %0 = arith.addi %arg0, %arg1 overflow<nsw> : i64 1436 // CHECK: %{{.*}} = spirv.ISub %{{.*}}, %{{.*}} {no_unsigned_wrap} : i64 1437 %1 = arith.subi %arg0, %arg1 overflow<nuw> : i64 1438 // CHECK: %{{.*}} = spirv.IMul %{{.*}}, %{{.*}} {no_signed_wrap, no_unsigned_wrap} : i64 1439 %2 = arith.muli %arg0, %arg1 overflow<nsw, nuw> : i64 1440 // CHECK: %{{.*}} = spirv.ShiftLeftLogical %{{.*}}, %{{.*}} {no_signed_wrap, no_unsigned_wrap} : i64 1441 %3 = arith.shli %arg0, %arg1 overflow<nsw, nuw> : i64 1442 return 1443} 1444 1445} // end module 1446 1447 1448// ----- 1449 1450module attributes { 1451 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Int8, Int16, Int64, Float16, Float64], []>, #spirv.resource_limits<>> 1452} { 1453 1454// No decorations should be generated is corresponding Extensions/Capabilities are missing 1455// CHECK-LABEL: @ops_flags 1456func.func @ops_flags(%arg0: i64, %arg1: i64) { 1457 // CHECK: %{{.*}} = spirv.IAdd %{{.*}}, %{{.*}} : i64 1458 %0 = arith.addi %arg0, %arg1 overflow<nsw> : i64 1459 // CHECK: %{{.*}} = spirv.ISub %{{.*}}, %{{.*}} : i64 1460 %1 = arith.subi %arg0, %arg1 overflow<nuw> : i64 1461 // CHECK: %{{.*}} = spirv.IMul %{{.*}}, %{{.*}} : i64 1462 %2 = arith.muli %arg0, %arg1 overflow<nsw, nuw> : i64 1463 // CHECK: %{{.*}} = spirv.IMul %{{.*}}, %{{.*}} : i64 1464 %3 = arith.muli %arg0, %arg1 overflow<nsw, nuw> : i64 1465 return 1466} 1467 1468} // end module 1469