1539 lines · plain
1// RUN: mlir-opt -split-input-file -convert-arith-to-spirv -verify-diagnostics %s | FileCheck %s2 3//===----------------------------------------------------------------------===//4// arithmetic ops5//===----------------------------------------------------------------------===//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_scalar14func.func @int32_scalar(%lhs: i32, %rhs: i32) {15 // CHECK: spirv.IAdd %{{.*}}, %{{.*}}: i3216 %0 = arith.addi %lhs, %rhs: i3217 // CHECK: spirv.ISub %{{.*}}, %{{.*}}: i3218 %1 = arith.subi %lhs, %rhs: i3219 // CHECK: spirv.IMul %{{.*}}, %{{.*}}: i3220 %2 = arith.muli %lhs, %rhs: i3221 // CHECK: spirv.SDiv %{{.*}}, %{{.*}}: i3222 %3 = arith.divsi %lhs, %rhs: i3223 // CHECK: spirv.UDiv %{{.*}}, %{{.*}}: i3224 %4 = arith.divui %lhs, %rhs: i3225 // CHECK: spirv.UMod %{{.*}}, %{{.*}}: i3226 %5 = arith.remui %lhs, %rhs: i3227 return28}29 30// CHECK-LABEL: @int32_scalar_srem31// CHECK-SAME: (%[[LHS:.+]]: i32, %[[RHS:.+]]: i32)32func.func @int32_scalar_srem(%lhs: i32, %rhs: i32) {33 // CHECK: %[[LABS:.+]] = spirv.GL.SAbs %[[LHS]] : i3234 // CHECK: %[[RABS:.+]] = spirv.GL.SAbs %[[RHS]] : i3235 // CHECK: %[[ABS:.+]] = spirv.UMod %[[LABS]], %[[RABS]] : i3236 // CHECK: %[[POS:.+]] = spirv.IEqual %[[LHS]], %[[LABS]] : i3237 // CHECK: %[[NEG:.+]] = spirv.SNegate %[[ABS]] : i3238 // CHECK: %{{.+}} = spirv.Select %[[POS]], %[[ABS]], %[[NEG]] : i1, i3239 %0 = arith.remsi %lhs, %rhs: i3240 return41}42 43// CHECK-LABEL: @index_scalar44func.func @index_scalar(%lhs: index, %rhs: index) {45 // CHECK: spirv.IAdd %{{.*}}, %{{.*}}: i3246 %0 = arith.addi %lhs, %rhs: index47 // CHECK: spirv.ISub %{{.*}}, %{{.*}}: i3248 %1 = arith.subi %lhs, %rhs: index49 // CHECK: spirv.IMul %{{.*}}, %{{.*}}: i3250 %2 = arith.muli %lhs, %rhs: index51 // CHECK: spirv.SDiv %{{.*}}, %{{.*}}: i3252 %3 = arith.divsi %lhs, %rhs: index53 // CHECK: spirv.UDiv %{{.*}}, %{{.*}}: i3254 %4 = arith.divui %lhs, %rhs: index55 // CHECK: spirv.UMod %{{.*}}, %{{.*}}: i3256 %5 = arith.remui %lhs, %rhs: index57 return58}59 60// CHECK-LABEL: @index_scalar_srem61// 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 i3264 // CHECK-DAG: %[[RHS:.+]] = builtin.unrealized_conversion_cast %[[B]] : index to i3265 // CHECK: %[[LABS:.+]] = spirv.GL.SAbs %[[LHS]] : i3266 // CHECK: %[[RABS:.+]] = spirv.GL.SAbs %[[RHS]] : i3267 // CHECK: %[[ABS:.+]] = spirv.UMod %[[LABS]], %[[RABS]] : i3268 // CHECK: %[[POS:.+]] = spirv.IEqual %[[LHS]], %[[LABS]] : i3269 // CHECK: %[[NEG:.+]] = spirv.SNegate %[[ABS]] : i3270 // CHECK: %{{.+}} = spirv.Select %[[POS]], %[[ABS]], %[[NEG]] : i1, i3271 %0 = arith.remsi %lhs, %rhs: index72 return73}74 75// Check integer add-with-carry conversions.76// CHECK-LABEL: @int32_scalar_addui_extended77// 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 : i3283 // CHECK-NEXT: %[[C1:.+]] = spirv.IEqual %[[C0]], %[[ONE]] : i3284 // CHECK-NEXT: return %[[SUM]], %[[C1]] : i32, i185 %sum, %overflow = arith.addui_extended %lhs, %rhs: i32, i186 return %sum, %overflow : i32, i187}88 89// CHECK-LABEL: @int32_vector_addui_extended90// 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_extended104// 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, i32110 %low, %high = arith.mulsi_extended %lhs, %rhs: i32111 return %low, %high : i32, i32112}113 114// CHECK-LABEL: @int32_vector_mulsi_extended115// 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_extended127// 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, i32133 %low, %high = arith.mului_extended %lhs, %rhs: i32134 return %low, %high : i32, i32135}136 137// CHECK-LABEL: @int32_vector_mului_extended138// 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_scalar150func.func @float32_unary_scalar(%arg0: f32) {151 // CHECK: spirv.FNegate %{{.*}}: f32152 %0 = arith.negf %arg0 : f32153 return154}155 156// Check float binary operation conversions.157// CHECK-LABEL: @float32_binary_scalar158func.func @float32_binary_scalar(%lhs: f32, %rhs: f32) {159 // CHECK: spirv.FAdd %{{.*}}, %{{.*}}: f32160 %0 = arith.addf %lhs, %rhs: f32161 // CHECK: spirv.FSub %{{.*}}, %{{.*}}: f32162 %1 = arith.subf %lhs, %rhs: f32163 // CHECK: spirv.FMul %{{.*}}, %{{.*}}: f32164 %2 = arith.mulf %lhs, %rhs: f32165 // CHECK: spirv.FDiv %{{.*}}, %{{.*}}: f32166 %3 = arith.divf %lhs, %rhs: f32167 // CHECK: spirv.FRem %{{.*}}, %{{.*}}: f32168 %4 = arith.remf %lhs, %rhs: f32169 return170}171 172// Check int vector types.173// CHECK-LABEL: @int_vector234174func.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 return180}181 182// CHECK-LABEL: @index_vector183func.func @index_vector(%arg0: vector<4xindex>) {184 // CHECK: spirv.UMod %{{.*}}, %{{.*}}: vector<4xi32>185 %0 = arith.remui %arg0, %arg0: vector<4xindex>186 return187}188 189// CHECK-LABEL: @vector_srem190// 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 return200}201 202// Check float vector types.203// CHECK-LABEL: @float_vector234204func.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 return210}211 212// CHECK-LABEL: @one_elem_vector213func.func @one_elem_vector(%arg0: vector<1xi32>) {214 // CHECK: spirv.IAdd %{{.+}}, %{{.+}}: i32215 %0 = arith.addi %arg0, %arg0: vector<1xi32>216 return217}218 219} // end module220 221// -----222 223//===----------------------------------------------------------------------===//224// Bit ops225//===----------------------------------------------------------------------===//226 227module attributes {228 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [], []>, #spirv.resource_limits<>>229} {230 231// CHECK-LABEL: @bitwise_scalar232func.func @bitwise_scalar(%arg0 : i32, %arg1 : i32) {233 // CHECK: spirv.BitwiseAnd234 %0 = arith.andi %arg0, %arg1 : i32235 // CHECK: spirv.BitwiseOr236 %1 = arith.ori %arg0, %arg1 : i32237 // CHECK: spirv.BitwiseXor238 %2 = arith.xori %arg0, %arg1 : i32239 return240}241 242// CHECK-LABEL: @bitwise_vector243func.func @bitwise_vector(%arg0 : vector<4xi32>, %arg1 : vector<4xi32>) {244 // CHECK: spirv.BitwiseAnd245 %0 = arith.andi %arg0, %arg1 : vector<4xi32>246 // CHECK: spirv.BitwiseOr247 %1 = arith.ori %arg0, %arg1 : vector<4xi32>248 // CHECK: spirv.BitwiseXor249 %2 = arith.xori %arg0, %arg1 : vector<4xi32>250 return251}252 253// CHECK-LABEL: @logical_scalar254func.func @logical_scalar(%arg0 : i1, %arg1 : i1) {255 // CHECK: spirv.LogicalAnd256 %0 = arith.andi %arg0, %arg1 : i1257 // CHECK: spirv.LogicalOr258 %1 = arith.ori %arg0, %arg1 : i1259 // CHECK: spirv.LogicalNotEqual260 %2 = arith.xori %arg0, %arg1 : i1261 return262}263 264// CHECK-LABEL: @logical_vector265func.func @logical_vector(%arg0 : vector<4xi1>, %arg1 : vector<4xi1>) {266 // CHECK: spirv.LogicalAnd267 %0 = arith.andi %arg0, %arg1 : vector<4xi1>268 // CHECK: spirv.LogicalOr269 %1 = arith.ori %arg0, %arg1 : vector<4xi1>270 // CHECK: spirv.LogicalNotEqual271 %2 = arith.xori %arg0, %arg1 : vector<4xi1>272 return273}274 275// CHECK-LABEL: @shift_scalar276func.func @shift_scalar(%arg0 : i32, %arg1 : i32) {277 // CHECK: spirv.ShiftLeftLogical278 %0 = arith.shli %arg0, %arg1 : i32279 // CHECK: spirv.ShiftRightArithmetic280 %1 = arith.shrsi %arg0, %arg1 : i32281 // CHECK: spirv.ShiftRightLogical282 %2 = arith.shrui %arg0, %arg1 : i32283 return284}285 286// CHECK-LABEL: @shift_vector287func.func @shift_vector(%arg0 : vector<4xi32>, %arg1 : vector<4xi32>) {288 // CHECK: spirv.ShiftLeftLogical289 %0 = arith.shli %arg0, %arg1 : vector<4xi32>290 // CHECK: spirv.ShiftRightArithmetic291 %1 = arith.shrsi %arg0, %arg1 : vector<4xi32>292 // CHECK: spirv.ShiftRightLogical293 %2 = arith.shrui %arg0, %arg1 : vector<4xi32>294 return295}296 297} // end module298 299// -----300 301//===----------------------------------------------------------------------===//302// arith.cmpf303//===----------------------------------------------------------------------===//304 305module attributes {306 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [], []>, #spirv.resource_limits<>>307} {308 309// CHECK-LABEL: @cmpf310func.func @cmpf(%arg0 : f32, %arg1 : f32) {311 // CHECK: spirv.FOrdEqual312 %1 = arith.cmpf oeq, %arg0, %arg1 : f32313 // CHECK: spirv.FOrdGreaterThan314 %2 = arith.cmpf ogt, %arg0, %arg1 : f32315 // CHECK: spirv.FOrdGreaterThanEqual316 %3 = arith.cmpf oge, %arg0, %arg1 : f32317 // CHECK: spirv.FOrdLessThan318 %4 = arith.cmpf olt, %arg0, %arg1 : f32319 // CHECK: spirv.FOrdLessThanEqual320 %5 = arith.cmpf ole, %arg0, %arg1 : f32321 // CHECK: spirv.FOrdNotEqual322 %6 = arith.cmpf one, %arg0, %arg1 : f32323 // CHECK: spirv.FUnordEqual324 %7 = arith.cmpf ueq, %arg0, %arg1 : f32325 // CHECK: spirv.FUnordGreaterThan326 %8 = arith.cmpf ugt, %arg0, %arg1 : f32327 // CHECK: spirv.FUnordGreaterThanEqual328 %9 = arith.cmpf uge, %arg0, %arg1 : f32329 // CHECK: spirv.FUnordLessThan330 %10 = arith.cmpf ult, %arg0, %arg1 : f32331 // CHECK: FUnordLessThanEqual332 %11 = arith.cmpf ule, %arg0, %arg1 : f32333 // CHECK: spirv.FUnordNotEqual334 %12 = arith.cmpf une, %arg0, %arg1 : f32335 return336}337 338// CHECK-LABEL: @vec1cmpf339func.func @vec1cmpf(%arg0 : vector<1xf32>, %arg1 : vector<1xf32>) {340 // CHECK: spirv.FOrdGreaterThan341 %0 = arith.cmpf ogt, %arg0, %arg1 : vector<1xf32>342 // CHECK: spirv.FUnordLessThan343 %1 = arith.cmpf ult, %arg0, %arg1 : vector<1xf32>344 return345}346 347} // end module348 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: @cmpf357func.func @cmpf(%arg0 : f32, %arg1 : f32) {358 // CHECK: spirv.Ordered359 %0 = arith.cmpf ord, %arg0, %arg1 : f32360 // CHECK: spirv.Unordered361 %1 = arith.cmpf uno, %arg0, %arg1 : f32362 return363}364 365} // end module366 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: @cmpf375// CHECK-SAME: %[[LHS:.+]]: f32, %[[RHS:.+]]: f32376func.func @cmpf(%arg0 : f32, %arg1 : f32) {377 // CHECK: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : f32378 // CHECK-NEXT: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : f32379 // CHECK-NEXT: %[[OR:.+]] = spirv.LogicalOr %[[LHS_NAN]], %[[RHS_NAN]] : i1380 // CHECK-NEXT: %{{.+}} = spirv.LogicalNot %[[OR]] : i1381 %0 = arith.cmpf ord, %arg0, %arg1 : f32382 383 // CHECK-NEXT: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : f32384 // CHECK-NEXT: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : f32385 // CHECK-NEXT: %{{.+}} = spirv.LogicalOr %[[LHS_NAN]], %[[RHS_NAN]] : i1386 %1 = arith.cmpf uno, %arg0, %arg1 : f32387 return388}389 390} // end module391 392// -----393 394//===----------------------------------------------------------------------===//395// arith.cmpi396//===----------------------------------------------------------------------===//397 398module attributes {399 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [], []>, #spirv.resource_limits<>>400} {401 402// CHECK-LABEL: @cmpi403func.func @cmpi(%arg0 : i32, %arg1 : i32) {404 // CHECK: spirv.IEqual405 %0 = arith.cmpi eq, %arg0, %arg1 : i32406 // CHECK: spirv.INotEqual407 %1 = arith.cmpi ne, %arg0, %arg1 : i32408 // CHECK: spirv.SLessThan409 %2 = arith.cmpi slt, %arg0, %arg1 : i32410 // CHECK: spirv.SLessThanEqual411 %3 = arith.cmpi sle, %arg0, %arg1 : i32412 // CHECK: spirv.SGreaterThan413 %4 = arith.cmpi sgt, %arg0, %arg1 : i32414 // CHECK: spirv.SGreaterThanEqual415 %5 = arith.cmpi sge, %arg0, %arg1 : i32416 // CHECK: spirv.ULessThan417 %6 = arith.cmpi ult, %arg0, %arg1 : i32418 // CHECK: spirv.ULessThanEqual419 %7 = arith.cmpi ule, %arg0, %arg1 : i32420 // CHECK: spirv.UGreaterThan421 %8 = arith.cmpi ugt, %arg0, %arg1 : i32422 // CHECK: spirv.UGreaterThanEqual423 %9 = arith.cmpi uge, %arg0, %arg1 : i32424 return425}426 427// CHECK-LABEL: @indexcmpi428func.func @indexcmpi(%arg0 : index, %arg1 : index) {429 // CHECK: spirv.IEqual430 %0 = arith.cmpi eq, %arg0, %arg1 : index431 // CHECK: spirv.INotEqual432 %1 = arith.cmpi ne, %arg0, %arg1 : index433 // CHECK: spirv.SLessThan434 %2 = arith.cmpi slt, %arg0, %arg1 : index435 // CHECK: spirv.SLessThanEqual436 %3 = arith.cmpi sle, %arg0, %arg1 : index437 // CHECK: spirv.SGreaterThan438 %4 = arith.cmpi sgt, %arg0, %arg1 : index439 // CHECK: spirv.SGreaterThanEqual440 %5 = arith.cmpi sge, %arg0, %arg1 : index441 // CHECK: spirv.ULessThan442 %6 = arith.cmpi ult, %arg0, %arg1 : index443 // CHECK: spirv.ULessThanEqual444 %7 = arith.cmpi ule, %arg0, %arg1 : index445 // CHECK: spirv.UGreaterThan446 %8 = arith.cmpi ugt, %arg0, %arg1 : index447 // CHECK: spirv.UGreaterThanEqual448 %9 = arith.cmpi uge, %arg0, %arg1 : index449 return450}451 452// CHECK-LABEL: @vec1cmpi453func.func @vec1cmpi(%arg0 : vector<1xi32>, %arg1 : vector<1xi32>) {454 // CHECK: spirv.ULessThan455 %0 = arith.cmpi ult, %arg0, %arg1 : vector<1xi32>456 // CHECK: spirv.SGreaterThan457 %1 = arith.cmpi sgt, %arg0, %arg1 : vector<1xi32>458 return459}460 461// CHECK-LABEL: @boolcmpi_equality462func.func @boolcmpi_equality(%arg0 : i1, %arg1 : i1) {463 // CHECK: spirv.LogicalEqual464 %0 = arith.cmpi eq, %arg0, %arg1 : i1465 // CHECK: spirv.LogicalNotEqual466 %1 = arith.cmpi ne, %arg0, %arg1 : i1467 return468}469 470// CHECK-LABEL: @boolcmpi_unsigned471func.func @boolcmpi_unsigned(%arg0 : i1, %arg1 : i1) {472 // CHECK-COUNT-2: spirv.Select473 // CHECK: spirv.UGreaterThanEqual474 %0 = arith.cmpi uge, %arg0, %arg1 : i1475 // CHECK-COUNT-2: spirv.Select476 // CHECK: spirv.ULessThan477 %1 = arith.cmpi ult, %arg0, %arg1 : i1478 return479}480 481// CHECK-LABEL: @vec1boolcmpi_equality482func.func @vec1boolcmpi_equality(%arg0 : vector<1xi1>, %arg1 : vector<1xi1>) {483 // CHECK: spirv.LogicalEqual484 %0 = arith.cmpi eq, %arg0, %arg1 : vector<1xi1>485 // CHECK: spirv.LogicalNotEqual486 %1 = arith.cmpi ne, %arg0, %arg1 : vector<1xi1>487 return488}489 490// CHECK-LABEL: @vec1boolcmpi_unsigned491func.func @vec1boolcmpi_unsigned(%arg0 : vector<1xi1>, %arg1 : vector<1xi1>) {492 // CHECK-COUNT-2: spirv.Select493 // CHECK: spirv.UGreaterThanEqual494 %0 = arith.cmpi uge, %arg0, %arg1 : vector<1xi1>495 // CHECK-COUNT-2: spirv.Select496 // CHECK: spirv.ULessThan497 %1 = arith.cmpi ult, %arg0, %arg1 : vector<1xi1>498 return499}500 501// CHECK-LABEL: @vecboolcmpi_equality502func.func @vecboolcmpi_equality(%arg0 : vector<4xi1>, %arg1 : vector<4xi1>) {503 // CHECK: spirv.LogicalEqual504 %0 = arith.cmpi eq, %arg0, %arg1 : vector<4xi1>505 // CHECK: spirv.LogicalNotEqual506 %1 = arith.cmpi ne, %arg0, %arg1 : vector<4xi1>507 return508}509 510// CHECK-LABEL: @vecboolcmpi_unsigned511func.func @vecboolcmpi_unsigned(%arg0 : vector<3xi1>, %arg1 : vector<3xi1>) {512 // CHECK-COUNT-2: spirv.Select513 // CHECK: spirv.UGreaterThanEqual514 %0 = arith.cmpi uge, %arg0, %arg1 : vector<3xi1>515 // CHECK-COUNT-2: spirv.Select516 // CHECK: spirv.ULessThan517 %1 = arith.cmpi ult, %arg0, %arg1 : vector<3xi1>518 return519}520 521 522} // end module523 524// -----525 526//===----------------------------------------------------------------------===//527// arith.constant528//===----------------------------------------------------------------------===//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: @constant536func.func @constant() {537 // CHECK: spirv.Constant true538 %0 = arith.constant true539 // CHECK: spirv.Constant 42 : i32540 %1 = arith.constant 42 : i32541 // CHECK: spirv.Constant 5.000000e-01 : f32542 %2 = arith.constant 0.5 : f32543 // CHECK: spirv.Constant dense<[2, 3]> : vector<2xi32>544 %3 = arith.constant dense<[2, 3]> : vector<2xi32>545 // CHECK: spirv.Constant 1 : i32546 %4 = arith.constant 1 : index547 // 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 return560}561 562// CHECK-LABEL: @constant_8bit_float563func.func @constant_8bit_float() {564 // CHECK: spirv.Constant 56 : i8565 %cst = arith.constant 1.0 : f8E4M3566 // CHECK: spirv.Constant 56 : i8567 %cst_i8 = arith.bitcast %cst : f8E4M3 to i8568 // CHECK: spirv.Constant dense<56> : vector<4xi8>569 %cst_vector = arith.constant dense<1.0> : vector<4xf8E4M3>570 // CHECK: spirv.Constant dense<56> : vector<4xi8>571 %cst_vector_i8 = arith.bitcast %cst_vector : vector<4xf8E4M3> to vector<4xi8>572 // CHECK: spirv.Constant dense<60> : tensor<4xi8> : !spirv.array<4 x i8>573 %cst_tensor = arith.constant dense<1.0> : tensor<4xf8E5M2>574 // CHECK: spirv.Constant dense<60> : tensor<4xi8> : !spirv.array<4 x i8>575 %cst_tensor_i8 = arith.bitcast %cst_tensor : tensor<4xf8E5M2> to tensor<4xi8>576 return577}578 579// CHECK-LABEL: @constant_16bit580func.func @constant_16bit() {581 // CHECK: spirv.Constant 4 : i16582 %0 = arith.constant 4 : i16583 // CHECK: spirv.Constant 5.000000e+00 : f16584 %1 = arith.constant 5.0 : f16585 // CHECK: spirv.Constant dense<[2, 3]> : vector<2xi16>586 %2 = arith.constant dense<[2, 3]> : vector<2xi16>587 // CHECK: spirv.Constant dense<4.000000e+00> : tensor<5xf16> : !spirv.array<5 x f16>588 %3 = arith.constant dense<4.0> : tensor<5xf16>589 return590}591 592// CHECK-LABEL: @constant_64bit593func.func @constant_64bit() {594 // CHECK: spirv.Constant 4 : i64595 %0 = arith.constant 4 : i64596 // CHECK: spirv.Constant 5.000000e+00 : f64597 %1 = arith.constant 5.0 : f64598 // CHECK: spirv.Constant dense<[2, 3]> : vector<2xi64>599 %2 = arith.constant dense<[2, 3]> : vector<2xi64>600 // CHECK: spirv.Constant dense<4.000000e+00> : tensor<5xf64> : !spirv.array<5 x f64>601 %3 = arith.constant dense<4.0> : tensor<5xf64>602 return603}604 605// CHECK-LABEL: @constant_size1606func.func @constant_size1() {607 // CHECK: spirv.Constant true608 %0 = arith.constant dense<true> : tensor<1xi1>609 // CHECK: spirv.Constant 4 : i64610 %1 = arith.constant dense<4> : vector<1xi64>611 // CHECK: spirv.Constant 5.000000e+00 : f64612 %2 = arith.constant dense<5.0> : tensor<1xf64>613 return614}615 616} // end module617 618// -----619 620// Check that constants are widened to 32-bit when no special capability.621module attributes {622 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [], []>, #spirv.resource_limits<>>623} {624 625// CHECK-LABEL: @constant_16bit626func.func @constant_16bit() {627 // CHECK: spirv.Constant 4 : i32628 %0 = arith.constant 4 : i16629 // CHECK: spirv.Constant 5.000000e+00 : f32630 %1 = arith.constant 5.0 : f16631 // CHECK: spirv.Constant dense<[2, 3]> : vector<2xi32>632 %2 = arith.constant dense<[2, 3]> : vector<2xi16>633 // CHECK: spirv.Constant dense<4.000000e+00> : tensor<5xf32> : !spirv.array<5 x f32>634 %3 = arith.constant dense<4.0> : tensor<5xf16>635 // CHECK: spirv.Constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00]> : tensor<4xf32> : !spirv.array<4 x f32>636 %4 = arith.constant dense<[[1.0, 2.0], [3.0, 4.0]]> : tensor<2x2xf16>637 return638}639 640// CHECK-LABEL: @constant_size1641func.func @constant_size1() {642 // CHECK: spirv.Constant 4 : i32643 %0 = arith.constant dense<4> : vector<1xi16>644 // CHECK: spirv.Constant 5.000000e+00 : f32645 %1 = arith.constant dense<5.0> : tensor<1xf16>646 return647}648 649// CHECK-LABEL: @corner_cases650func.func @corner_cases() {651 // CHECK: %{{.*}} = spirv.Constant -1 : i32652 %5 = arith.constant -1 : i16653 // CHECK: %{{.*}} = spirv.Constant -2 : i32654 %6 = arith.constant -2 : i16655 // CHECK: %{{.*}} = spirv.Constant -1 : i32656 %7 = arith.constant -1 : index657 // CHECK: %{{.*}} = spirv.Constant -2 : i32658 %8 = arith.constant -2 : index659 660 // CHECK: spirv.Constant false661 %9 = arith.constant false662 // CHECK: spirv.Constant true663 %10 = arith.constant true664 665 return666}667 668} // end module669 670// -----671 672//===----------------------------------------------------------------------===//673// Cast ops674//===----------------------------------------------------------------------===//675 676module attributes {677 spirv.target_env = #spirv.target_env<678 #spirv.vce<v1.0, [Int8, Int16, Int64, Float16, Float64], []>, #spirv.resource_limits<>>679} {680 681// CHECK-LABEL: index_cast1682func.func @index_cast1(%arg0: i16) {683 // CHECK: spirv.SConvert %{{.+}} : i16 to i32684 %0 = arith.index_cast %arg0 : i16 to index685 return686}687 688// CHECK-LABEL: index_cast2689func.func @index_cast2(%arg0: index) {690 // CHECK: spirv.SConvert %{{.+}} : i32 to i16691 %0 = arith.index_cast %arg0 : index to i16692 return693}694 695// CHECK-LABEL: index_cast3696func.func @index_cast3(%arg0: i32) {697 // CHECK-NOT: spirv.SConvert698 %0 = arith.index_cast %arg0 : i32 to index699 return700}701 702// CHECK-LABEL: index_cast4703func.func @index_cast4(%arg0: index) {704 // CHECK-NOT: spirv.UConvert705 %0 = arith.index_cast %arg0 : index to i32706 return707}708 709// CHECK-LABEL: index_castui1710func.func @index_castui1(%arg0: i16) {711 // CHECK: spirv.UConvert %{{.+}} : i16 to i32712 %0 = arith.index_castui %arg0 : i16 to index713 return714}715 716// CHECK-LABEL: index_castui2717func.func @index_castui2(%arg0: index) {718 // CHECK: spirv.UConvert %{{.+}} : i32 to i16719 %0 = arith.index_castui %arg0 : index to i16720 return721}722 723// CHECK-LABEL: index_castui3724func.func @index_castui3(%arg0: i32) {725 // CHECK-NOT: spirv.UConvert726 %0 = arith.index_castui %arg0 : i32 to index727 return728}729 730// CHECK-LABEL: index_castui4731func.func @index_castui4(%arg0: index) {732 // CHECK-NOT: spirv.UConvert733 %0 = arith.index_cast %arg0 : index to i32734 return735}736 737// CHECK-LABEL: index_castindexi1_1738func.func @index_castindexi1_1(%arg0: index) {739 // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32740 // CHECK: spirv.INotEqual %[[ZERO]], %{{.+}} : i32741 %0 = arith.index_cast %arg0 : index to i1742 return743}744 745// CHECK-LABEL: index_castindexi1_2746func.func @index_castindexi1_2(%arg0: vector<1xindex>) -> vector<1xi1> {747 // Single-element vectors do not exist in SPIRV.748 // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32749 // CHECK: spirv.INotEqual %[[ZERO]], %{{.+}} : i32750 %0 = arith.index_cast %arg0 : vector<1xindex> to vector<1xi1>751 return %0 : vector<1xi1>752}753 754// CHECK-LABEL: index_castindexi1_3755func.func @index_castindexi1_3(%arg0: vector<3xindex>) {756 // CHECK: %[[ZERO:.+]] = spirv.Constant dense<0> : vector<3xi32>757 // CHECK: spirv.INotEqual %[[ZERO]], %{{.+}} : vector<3xi32>758 %0 = arith.index_cast %arg0 : vector<3xindex> to vector<3xi1>759 return760}761 762// CHECK-LABEL: index_casti1index_1763func.func @index_casti1index_1(%arg0 : i1) {764 // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32765 // CHECK: %[[ONE:.+]] = spirv.Constant 1 : i32766 // CHECK: spirv.Select %{{.+}}, %[[ONE]], %[[ZERO]] : i1, i32767 %0 = arith.index_cast %arg0 : i1 to index768 return769}770 771// CHECK-LABEL: index_casti1index_2772func.func @index_casti1index_2(%arg0 : vector<1xi1>) -> vector<1xindex> {773 // Single-element vectors do not exist in SPIRV.774 // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32775 // CHECK: %[[ONE:.+]] = spirv.Constant 1 : i32776 // CHECK: spirv.Select %{{.+}}, %[[ONE]], %[[ZERO]] : i1, i32777 %0 = arith.index_cast %arg0 : vector<1xi1> to vector<1xindex>778 return %0 : vector<1xindex>779}780 781// CHECK-LABEL: index_casti1index_3782func.func @index_casti1index_3(%arg0 : vector<3xi1>) {783 // CHECK: %[[ZERO:.+]] = spirv.Constant dense<0> : vector<3xi32>784 // CHECK: %[[ONE:.+]] = spirv.Constant dense<1> : vector<3xi32>785 // CHECK: spirv.Select %{{.+}}, %[[ONE]], %[[ZERO]] : vector<3xi1>, vector<3xi32>786 %0 = arith.index_cast %arg0 : vector<3xi1> to vector<3xindex>787 return788}789 790// CHECK-LABEL: @bit_cast791func.func @bit_cast(%arg0: vector<2xf32>, %arg1: i64) {792 // CHECK: spirv.Bitcast %{{.+}} : vector<2xf32> to vector<2xi32>793 %0 = arith.bitcast %arg0 : vector<2xf32> to vector<2xi32>794 // CHECK: spirv.Bitcast %{{.+}} : i64 to f64795 %1 = arith.bitcast %arg1 : i64 to f64796 return797}798 799// CHECK-LABEL: @fpext1800func.func @fpext1(%arg0: f16) -> f64 {801 // CHECK: spirv.FConvert %{{.*}} : f16 to f64802 %0 = arith.extf %arg0 : f16 to f64803 return %0 : f64804}805 806// CHECK-LABEL: @fpext2807func.func @fpext2(%arg0 : f32) -> f64 {808 // CHECK: spirv.FConvert %{{.*}} : f32 to f64809 %0 = arith.extf %arg0 : f32 to f64810 return %0 : f64811}812 813// CHECK-LABEL: @fptrunc1814func.func @fptrunc1(%arg0 : f64) -> f16 {815 // CHECK: spirv.FConvert %{{.*}} : f64 to f16816 %0 = arith.truncf %arg0 : f64 to f16817 return %0 : f16818}819 820// CHECK-LABEL: @fptrunc2821func.func @fptrunc2(%arg0: f32) -> f16 {822 // CHECK: spirv.FConvert %{{.*}} : f32 to f16823 %0 = arith.truncf %arg0 : f32 to f16824 return %0 : f16825}826 827 828// CHECK-LABEL: @experimental_constrained_fptrunc829func.func @experimental_constrained_fptrunc(%arg0 : f64) {830 // CHECK: spirv.FConvert %arg0 {fp_rounding_mode = #spirv.fp_rounding_mode<RTE>} : f64 to f32831 %0 = arith.truncf %arg0 to_nearest_even : f64 to f32832 // CHECK: spirv.FConvert %arg0 {fp_rounding_mode = #spirv.fp_rounding_mode<RTN>} : f64 to f32833 %1 = arith.truncf %arg0 downward : f64 to f32834 // CHECK: spirv.FConvert %arg0 {fp_rounding_mode = #spirv.fp_rounding_mode<RTP>} : f64 to f32835 %2 = arith.truncf %arg0 upward : f64 to f32836 // CHECK: spirv.FConvert %arg0 {fp_rounding_mode = #spirv.fp_rounding_mode<RTZ>} : f64 to f32837 %3 = arith.truncf %arg0 toward_zero : f64 to f32838 return839}840 841 842// CHECK-LABEL: @sitofp1843func.func @sitofp1(%arg0 : i32) -> f32 {844 // CHECK: spirv.ConvertSToF %{{.*}} : i32 to f32845 %0 = arith.sitofp %arg0 : i32 to f32846 return %0 : f32847}848 849// CHECK-LABEL: @sitofp2850func.func @sitofp2(%arg0 : i64) -> f64 {851 // CHECK: spirv.ConvertSToF %{{.*}} : i64 to f64852 %0 = arith.sitofp %arg0 : i64 to f64853 return %0 : f64854}855 856// CHECK-LABEL: @uitofp_i16_f32857func.func @uitofp_i16_f32(%arg0: i16) -> f32 {858 // CHECK: spirv.ConvertUToF %{{.*}} : i16 to f32859 %0 = arith.uitofp %arg0 : i16 to f32860 return %0 : f32861}862 863// CHECK-LABEL: @uitofp_i32_f32864func.func @uitofp_i32_f32(%arg0 : i32) -> f32 {865 // CHECK: spirv.ConvertUToF %{{.*}} : i32 to f32866 %0 = arith.uitofp %arg0 : i32 to f32867 return %0 : f32868}869 870// CHECK-LABEL: @uitofp_i1_f32871func.func @uitofp_i1_f32(%arg0 : i1) -> f32 {872 // CHECK: %[[ZERO:.+]] = spirv.Constant 0.000000e+00 : f32873 // CHECK: %[[ONE:.+]] = spirv.Constant 1.000000e+00 : f32874 // CHECK: spirv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : i1, f32875 %0 = arith.uitofp %arg0 : i1 to f32876 return %0 : f32877}878 879// CHECK-LABEL: @uitofp_i1_f64880func.func @uitofp_i1_f64(%arg0 : i1) -> f64 {881 // CHECK: %[[ZERO:.+]] = spirv.Constant 0.000000e+00 : f64882 // CHECK: %[[ONE:.+]] = spirv.Constant 1.000000e+00 : f64883 // CHECK: spirv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : i1, f64884 %0 = arith.uitofp %arg0 : i1 to f64885 return %0 : f64886}887 888// CHECK-LABEL: @uitofp_vec_i1_f32889func.func @uitofp_vec_i1_f32(%arg0 : vector<4xi1>) -> vector<4xf32> {890 // CHECK: %[[ZERO:.+]] = spirv.Constant dense<0.000000e+00> : vector<4xf32>891 // CHECK: %[[ONE:.+]] = spirv.Constant dense<1.000000e+00> : vector<4xf32>892 // CHECK: spirv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : vector<4xi1>, vector<4xf32>893 %0 = arith.uitofp %arg0 : vector<4xi1> to vector<4xf32>894 return %0 : vector<4xf32>895}896 897// CHECK-LABEL: @uitofp_vec_i1_f64898spirv.func @uitofp_vec_i1_f64(%arg0: vector<4xi1>) -> vector<4xf64> "None" {899 // CHECK: %[[ZERO:.+]] = spirv.Constant dense<0.000000e+00> : vector<4xf64>900 // CHECK: %[[ONE:.+]] = spirv.Constant dense<1.000000e+00> : vector<4xf64>901 // CHECK: spirv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : vector<4xi1>, vector<4xf64>902 %0 = spirv.Constant dense<0.000000e+00> : vector<4xf64>903 %1 = spirv.Constant dense<1.000000e+00> : vector<4xf64>904 %2 = spirv.Select %arg0, %1, %0 : vector<4xi1>, vector<4xf64>905 spirv.ReturnValue %2 : vector<4xf64>906}907 908// CHECK-LABEL: @sexti1909func.func @sexti1(%arg0: i16) -> i64 {910 // CHECK: spirv.SConvert %{{.*}} : i16 to i64911 %0 = arith.extsi %arg0 : i16 to i64912 return %0 : i64913}914 915// CHECK-LABEL: @sexti2916func.func @sexti2(%arg0 : i32) -> i64 {917 // CHECK: spirv.SConvert %{{.*}} : i32 to i64918 %0 = arith.extsi %arg0 : i32 to i64919 return %0 : i64920}921 922// CHECK-LABEL: @sext_bool_scalar923// CHECK-SAME: ([[ARG:%.+]]: i1) -> i32924func.func @sext_bool_scalar(%arg0 : i1) -> i32 {925 // CHECK-DAG: [[ONES:%.+]] = spirv.Constant -1 : i32926 // CHECK-DAG: [[ZERO:%.+]] = spirv.Constant 0 : i32927 // CHECK: [[SEL:%.+]] = spirv.Select [[ARG]], [[ONES]], [[ZERO]] : i1, i32928 // CHECK-NEXT: return [[SEL]] : i32929 %0 = arith.extsi %arg0 : i1 to i32930 return %0 : i32931}932 933// CHECK-LABEL: @sext_bool_vector934// CHECK-SAME: ([[ARG:%.+]]: vector<3xi1>) -> vector<3xi32>935func.func @sext_bool_vector(%arg0 : vector<3xi1>) -> vector<3xi32> {936 // CHECK-DAG: [[ONES:%.+]] = spirv.Constant dense<-1> : vector<3xi32>937 // CHECK-DAG: [[ZERO:%.+]] = spirv.Constant dense<0> : vector<3xi32>938 // CHECK: [[SEL:%.+]] = spirv.Select [[ARG]], [[ONES]], [[ZERO]] : vector<3xi1>, vector<3xi32>939 // CHECK-NEXT: return [[SEL]] : vector<3xi32>940 %0 = arith.extsi %arg0 : vector<3xi1> to vector<3xi32>941 return %0 : vector<3xi32>942}943 944// CHECK-LABEL: @zexti1945func.func @zexti1(%arg0: i16) -> i64 {946 // CHECK: spirv.UConvert %{{.*}} : i16 to i64947 %0 = arith.extui %arg0 : i16 to i64948 return %0 : i64949}950 951// CHECK-LABEL: @zexti2952func.func @zexti2(%arg0 : i32) -> i64 {953 // CHECK: spirv.UConvert %{{.*}} : i32 to i64954 %0 = arith.extui %arg0 : i32 to i64955 return %0 : i64956}957 958// CHECK-LABEL: @zexti3959func.func @zexti3(%arg0 : i1) -> i32 {960 // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32961 // CHECK: %[[ONE:.+]] = spirv.Constant 1 : i32962 // CHECK: spirv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : i1, i32963 %0 = arith.extui %arg0 : i1 to i32964 return %0 : i32965}966 967// CHECK-LABEL: @zexti4968func.func @zexti4(%arg0 : vector<4xi1>) -> vector<4xi32> {969 // CHECK: %[[ZERO:.+]] = spirv.Constant dense<0> : vector<4xi32>970 // CHECK: %[[ONE:.+]] = spirv.Constant dense<1> : vector<4xi32>971 // CHECK: spirv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : vector<4xi1>, vector<4xi32>972 %0 = arith.extui %arg0 : vector<4xi1> to vector<4xi32>973 return %0 : vector<4xi32>974}975 976// CHECK-LABEL: @zexti5977func.func @zexti5(%arg0 : vector<4xi1>) -> vector<4xi64> {978 // CHECK: %[[ZERO:.+]] = spirv.Constant dense<0> : vector<4xi64>979 // CHECK: %[[ONE:.+]] = spirv.Constant dense<1> : vector<4xi64>980 // CHECK: spirv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : vector<4xi1>, vector<4xi64>981 %0 = arith.extui %arg0 : vector<4xi1> to vector<4xi64>982 return %0 : vector<4xi64>983}984 985// CHECK-LABEL: @trunci1986func.func @trunci1(%arg0 : i64) -> i16 {987 // CHECK: spirv.SConvert %{{.*}} : i64 to i16988 %0 = arith.trunci %arg0 : i64 to i16989 return %0 : i16990}991 992// CHECK-LABEL: @trunci2993func.func @trunci2(%arg0: i32) -> i16 {994 // CHECK: spirv.SConvert %{{.*}} : i32 to i16995 %0 = arith.trunci %arg0 : i32 to i16996 return %0 : i16997}998 999// CHECK-LABEL: @trunc_to_i11000func.func @trunc_to_i1(%arg0: i32) -> i1 {1001 // CHECK: %[[MASK:.*]] = spirv.Constant 1 : i321002 // CHECK: %[[MASKED_SRC:.*]] = spirv.BitwiseAnd %{{.*}}, %[[MASK]] : i321003 // CHECK: %[[IS_ONE:.*]] = spirv.IEqual %[[MASKED_SRC]], %[[MASK]] : i321004 // CHECK-DAG: %[[TRUE:.*]] = spirv.Constant true1005 // CHECK-DAG: %[[FALSE:.*]] = spirv.Constant false1006 // CHECK: spirv.Select %[[IS_ONE]], %[[TRUE]], %[[FALSE]] : i1, i11007 %0 = arith.trunci %arg0 : i32 to i11008 return %0 : i11009}1010 1011// CHECK-LABEL: @trunc_to_veci11012func.func @trunc_to_veci1(%arg0: vector<4xi32>) -> vector<4xi1> {1013 // CHECK: %[[MASK:.*]] = spirv.Constant dense<1> : vector<4xi32>1014 // CHECK: %[[MASKED_SRC:.*]] = spirv.BitwiseAnd %{{.*}}, %[[MASK]] : vector<4xi32>1015 // CHECK: %[[IS_ONE:.*]] = spirv.IEqual %[[MASKED_SRC]], %[[MASK]] : vector<4xi32>1016 // CHECK-DAG: %[[TRUE:.*]] = spirv.Constant dense<true> : vector<4xi1>1017 // CHECK-DAG: %[[FALSE:.*]] = spirv.Constant dense<false> : vector<4xi1>1018 // CHECK: spirv.Select %[[IS_ONE]], %[[TRUE]], %[[FALSE]] : vector<4xi1>, vector<4xi1>1019 %0 = arith.trunci %arg0 : vector<4xi32> to vector<4xi1>1020 return %0 : vector<4xi1>1021}1022 1023// CHECK-LABEL: @fptoui11024func.func @fptoui1(%arg0 : f32) -> i32 {1025 // CHECK: spirv.ConvertFToU %{{.*}} : f32 to i321026 %0 = arith.fptoui %arg0 : f32 to i321027 return %0 : i321028}1029 1030// CHECK-LABEL: @fptoui21031func.func @fptoui2(%arg0 : f16) -> i16 {1032 // CHECK: spirv.ConvertFToU %{{.*}} : f16 to i161033 %0 = arith.fptoui %arg0 : f16 to i161034 return %0 : i161035}1036 1037// CHECK-LABEL: @fptosi11038func.func @fptosi1(%arg0 : f32) -> i32 {1039 // CHECK: spirv.ConvertFToS %{{.*}} : f32 to i321040 %0 = arith.fptosi %arg0 : f32 to i321041 return %0 : i321042}1043 1044// CHECK-LABEL: @fptosi21045func.func @fptosi2(%arg0 : f16) -> i16 {1046 // CHECK: spirv.ConvertFToS %{{.*}} : f16 to i161047 %0 = arith.fptosi %arg0 : f16 to i161048 return %0 : i161049}1050 1051} // end module1052 1053// -----1054 1055// Checks that cast types will be adjusted when missing special capabilities for1056// certain non-32-bit scalar types.1057module attributes {1058 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Float64], []>, #spirv.resource_limits<>>1059} {1060 1061// CHECK-LABEL: @fpext11062// CHECK-SAME: %[[A:.*]]: f161063func.func @fpext1(%arg0: f16) -> f64 {1064 // CHECK: %[[ARG:.+]] = builtin.unrealized_conversion_cast %[[A]] : f16 to f321065 // CHECK-NEXT: spirv.FConvert %[[ARG]] : f32 to f641066 %0 = arith.extf %arg0 : f16 to f641067 return %0: f641068}1069 1070// CHECK-LABEL: @fpext21071// CHECK-SAME: %[[ARG:.*]]: f321072func.func @fpext2(%arg0 : f32) -> f64 {1073 // CHECK-NEXT: spirv.FConvert %[[ARG]] : f32 to f641074 %0 = arith.extf %arg0 : f32 to f641075 return %0: f641076}1077 1078// CHECK-LABEL: @trunci4_scalar1079// CHECK-SAME: %[[ARG:.*]]: i321080func.func @trunci4_scalar(%arg0 : i32) -> i4 {1081 // CHECK: %[[MASK:.+]] = spirv.Constant 15 : i321082 // CHECK: %[[AND:.+]] = spirv.BitwiseAnd %[[ARG]], %[[MASK]] : i321083 %0 = arith.trunci %arg0 : i32 to i41084 // CHECK: %[[RET:.+]] = builtin.unrealized_conversion_cast %[[AND]] : i32 to i41085 // CHECK: return %[[RET]] : i41086 return %0 : i41087}1088 1089// CHECK-LABEL: @trunci4_vector1090// CHECK-SAME: %[[ARG:.*]]: vector<2xi32>1091func.func @trunci4_vector(%arg0 : vector<2xi32>) -> vector<2xi4> {1092 // CHECK: %[[MASK:.+]] = spirv.Constant dense<15> : vector<2xi32>1093 // CHECK: %[[AND:.+]] = spirv.BitwiseAnd %[[ARG]], %[[MASK]] : vector<2xi32>1094 %0 = arith.trunci %arg0 : vector<2xi32> to vector<2xi4>1095 // CHECK: %[[RET:.+]] = builtin.unrealized_conversion_cast %[[AND]] : vector<2xi32> to vector<2xi4>1096 // CHECK: return %[[RET]] : vector<2xi4>1097 return %0 : vector<2xi4>1098}1099 1100// CHECK-LABEL: @zexti4_scalar1101func.func @zexti4_scalar(%arg0: i4) -> i32 {1102 // CHECK: %[[INPUT:.+]] = builtin.unrealized_conversion_cast %{{.+}} : i4 to i321103 // CHECK: %[[MASK:.+]] = spirv.Constant 15 : i321104 // CHECK: %[[AND:.+]] = spirv.BitwiseAnd %[[INPUT]], %[[MASK]] : i321105 %0 = arith.extui %arg0 : i4 to i321106 // CHECK: return %[[AND]] : i321107 return %0 : i321108}1109 1110// CHECK-LABEL: @zexti4_vector1111func.func @zexti4_vector(%arg0: vector<3xi4>) -> vector<3xi32> {1112 // CHECK: %[[INPUT:.+]] = builtin.unrealized_conversion_cast %{{.+}} : vector<3xi4> to vector<3xi32>1113 // CHECK: %[[MASK:.+]] = spirv.Constant dense<15> : vector<3xi32>1114 // CHECK: %[[AND:.+]] = spirv.BitwiseAnd %[[INPUT]], %[[MASK]] : vector<3xi32>1115 %0 = arith.extui %arg0 : vector<3xi4> to vector<3xi32>1116 // CHECK: return %[[AND]] : vector<3xi32>1117 return %0 : vector<3xi32>1118}1119 1120// CHECK-LABEL: @sexti4_scalar1121func.func @sexti4_scalar(%arg0: i4) -> i32 {1122 // CHECK: %[[INPUT:.+]] = builtin.unrealized_conversion_cast %arg0 : i4 to i321123 // CHECK: %[[SIZE:.+]] = spirv.Constant 28 : i321124 // CHECK: %[[SL:.+]] = spirv.ShiftLeftLogical %[[INPUT]], %[[SIZE]] : i32, i321125 // CHECK: %[[SR:.+]] = spirv.ShiftRightArithmetic %[[SL]], %[[SIZE]] : i32, i321126 %0 = arith.extsi %arg0 : i4 to i321127 // CHECK: return %[[SR]] : i321128 return %0 : i321129}1130 1131// CHECK-LABEL: @sexti4_vector1132func.func @sexti4_vector(%arg0: vector<4xi4>) -> vector<4xi32> {1133 // CHECK: %[[INPUT:.+]] = builtin.unrealized_conversion_cast %arg0 : vector<4xi4> to vector<4xi32>1134 // CHECK: %[[SIZE:.+]] = spirv.Constant dense<28> : vector<4xi32>1135 // CHECK: %[[SL:.+]] = spirv.ShiftLeftLogical %[[INPUT]], %[[SIZE]] : vector<4xi32>, vector<4xi32>1136 // CHECK: %[[SR:.+]] = spirv.ShiftRightArithmetic %[[SL]], %[[SIZE]] : vector<4xi32>, vector<4xi32>1137 %0 = arith.extsi %arg0 : vector<4xi4> to vector<4xi32>1138 // CHECK: return %[[SR]] : vector<4xi32>1139 return %0 : vector<4xi32>1140}1141 1142} // end module1143 1144// -----1145 1146// Checks that cast types will be adjusted when missing special capabilities for1147// certain non-32-bit scalar types.1148module attributes {1149 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Float16], []>, #spirv.resource_limits<>>1150} {1151 1152// CHECK-LABEL: @fptrunc11153// CHECK-SAME: %[[ARG:.*]]: f321154func.func @fptrunc1(%arg0: f32) -> f16 {1155 // CHECK-NEXT: spirv.FConvert %[[ARG]] : f32 to f161156 %0 = arith.truncf %arg0 : f32 to f161157 return %0: f161158}1159 1160} // end module1161 1162// -----1163 1164// Check various lowerings for OpenCL.1165module attributes {1166 spirv.target_env = #spirv.target_env<1167 #spirv.vce<v1.0, [Int16, Kernel], []>, #spirv.resource_limits<>>1168} {1169 1170// Check integer operation conversions.1171// CHECK-LABEL: @int32_scalar1172func.func @int32_scalar(%lhs: i32, %rhs: i32) {1173 // CHECK: spirv.IAdd %{{.*}}, %{{.*}}: i321174 %0 = arith.addi %lhs, %rhs: i321175 // CHECK: spirv.ISub %{{.*}}, %{{.*}}: i321176 %1 = arith.subi %lhs, %rhs: i321177 // CHECK: spirv.IMul %{{.*}}, %{{.*}}: i321178 %2 = arith.muli %lhs, %rhs: i321179 // CHECK: spirv.SDiv %{{.*}}, %{{.*}}: i321180 %3 = arith.divsi %lhs, %rhs: i321181 // CHECK: spirv.UDiv %{{.*}}, %{{.*}}: i321182 %4 = arith.divui %lhs, %rhs: i321183 // CHECK: spirv.UMod %{{.*}}, %{{.*}}: i321184 %5 = arith.remui %lhs, %rhs: i321185 // CHECK: spirv.CL.s_max %{{.*}}, %{{.*}}: i321186 %6 = arith.maxsi %lhs, %rhs : i321187 // CHECK: spirv.CL.u_max %{{.*}}, %{{.*}}: i321188 %7 = arith.maxui %lhs, %rhs : i321189 // CHECK: spirv.CL.s_min %{{.*}}, %{{.*}}: i321190 %8 = arith.minsi %lhs, %rhs : i321191 // CHECK: spirv.CL.u_min %{{.*}}, %{{.*}}: i321192 %9 = arith.minui %lhs, %rhs : i321193 return1194}1195 1196// Check float binary operation conversions.1197// CHECK-LABEL: @float32_binary_scalar1198func.func @float32_binary_scalar(%lhs: f32, %rhs: f32) {1199 // CHECK: spirv.FAdd %{{.*}}, %{{.*}}: f321200 %0 = arith.addf %lhs, %rhs: f321201 // CHECK: spirv.FSub %{{.*}}, %{{.*}}: f321202 %1 = arith.subf %lhs, %rhs: f321203 // CHECK: spirv.FMul %{{.*}}, %{{.*}}: f321204 %2 = arith.mulf %lhs, %rhs: f321205 // CHECK: spirv.FDiv %{{.*}}, %{{.*}}: f321206 %3 = arith.divf %lhs, %rhs: f321207 // CHECK: spirv.FRem %{{.*}}, %{{.*}}: f321208 %4 = arith.remf %lhs, %rhs: f321209 return1210}1211 1212// CHECK-LABEL: @float32_minimumf_scalar1213// CHECK-SAME: %[[LHS:.+]]: f32, %[[RHS:.+]]: f321214func.func @float32_minimumf_scalar(%arg0 : f32, %arg1 : f32) -> f32 {1215 // CHECK: %[[MIN:.+]] = spirv.CL.fmin %arg0, %arg1 : f321216 // CHECK: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : f321217 // CHECK: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : f321218 // CHECK: %[[SELECT1:.+]] = spirv.Select %[[LHS_NAN]], %[[LHS]], %[[MIN]]1219 // CHECK: %[[SELECT2:.+]] = spirv.Select %[[RHS_NAN]], %[[RHS]], %[[SELECT1]]1220 %0 = arith.minimumf %arg0, %arg1 : f321221 // CHECK: return %[[SELECT2]]1222 return %0: f321223}1224 1225// CHECK-LABEL: @float32_minnumf_scalar1226// CHECK-SAME: %[[LHS:.+]]: f32, %[[RHS:.+]]: f321227func.func @float32_minnumf_scalar(%arg0 : f32, %arg1 : f32) -> f32 {1228 // CHECK: %[[MIN:.+]] = spirv.CL.fmin %arg0, %arg1 : f321229 %0 = arith.minnumf %arg0, %arg1 : f321230 // CHECK: return %[[MIN]]1231 return %0: f321232}1233 1234// CHECK-LABEL: @float32_maximumf_scalar1235// CHECK-SAME: %[[LHS:.+]]: vector<2xf32>, %[[RHS:.+]]: vector<2xf32>1236func.func @float32_maximumf_scalar(%arg0 : vector<2xf32>, %arg1 : vector<2xf32>) -> vector<2xf32> {1237 // CHECK: %[[MAX:.+]] = spirv.CL.fmax %arg0, %arg1 : vector<2xf32>1238 // CHECK: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : vector<2xf32>1239 // CHECK: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : vector<2xf32>1240 // CHECK: %[[SELECT1:.+]] = spirv.Select %[[LHS_NAN]], %[[LHS]], %[[MAX]]1241 // CHECK: %[[SELECT2:.+]] = spirv.Select %[[RHS_NAN]], %[[RHS]], %[[SELECT1]]1242 %0 = arith.maximumf %arg0, %arg1 : vector<2xf32>1243 // CHECK: return %[[SELECT2]]1244 return %0: vector<2xf32>1245}1246 1247// CHECK-LABEL: @float32_maxnumf_scalar1248// CHECK-SAME: %[[LHS:.+]]: vector<2xf32>, %[[RHS:.+]]: vector<2xf32>1249func.func @float32_maxnumf_scalar(%arg0 : vector<2xf32>, %arg1 : vector<2xf32>) -> vector<2xf32> {1250 // CHECK: %[[MAX:.+]] = spirv.CL.fmax %arg0, %arg1 : vector<2xf32>1251 %0 = arith.maxnumf %arg0, %arg1 : vector<2xf32>1252 // CHECK: return %[[MAX]]1253 return %0: vector<2xf32>1254}1255 1256 1257// CHECK-LABEL: @scalar_srem1258// CHECK-SAME: (%[[LHS:.+]]: i32, %[[RHS:.+]]: i32)1259func.func @scalar_srem(%lhs: i32, %rhs: i32) {1260 // CHECK: %[[LABS:.+]] = spirv.CL.s_abs %[[LHS]] : i321261 // CHECK: %[[RABS:.+]] = spirv.CL.s_abs %[[RHS]] : i321262 // CHECK: %[[ABS:.+]] = spirv.UMod %[[LABS]], %[[RABS]] : i321263 // CHECK: %[[POS:.+]] = spirv.IEqual %[[LHS]], %[[LABS]] : i321264 // CHECK: %[[NEG:.+]] = spirv.SNegate %[[ABS]] : i321265 // CHECK: %{{.+}} = spirv.Select %[[POS]], %[[ABS]], %[[NEG]] : i1, i321266 %0 = arith.remsi %lhs, %rhs: i321267 return1268}1269 1270// CHECK-LABEL: @vector_srem1271// CHECK-SAME: (%[[LHS:.+]]: vector<3xi16>, %[[RHS:.+]]: vector<3xi16>)1272func.func @vector_srem(%arg0: vector<3xi16>, %arg1: vector<3xi16>) {1273 // CHECK: %[[LABS:.+]] = spirv.CL.s_abs %[[LHS]] : vector<3xi16>1274 // CHECK: %[[RABS:.+]] = spirv.CL.s_abs %[[RHS]] : vector<3xi16>1275 // CHECK: %[[ABS:.+]] = spirv.UMod %[[LABS]], %[[RABS]] : vector<3xi16>1276 // CHECK: %[[POS:.+]] = spirv.IEqual %[[LHS]], %[[LABS]] : vector<3xi16>1277 // CHECK: %[[NEG:.+]] = spirv.SNegate %[[ABS]] : vector<3xi16>1278 // CHECK: %{{.+}} = spirv.Select %[[POS]], %[[ABS]], %[[NEG]] : vector<3xi1>, vector<3xi16>1279 %0 = arith.remsi %arg0, %arg1: vector<3xi16>1280 return1281}1282 1283} // end module1284 1285// -----1286 1287module attributes {1288 spirv.target_env = #spirv.target_env<1289 #spirv.vce<v1.0, [Shader, Int8, Int16, Int64, Float16, Float64],1290 [SPV_KHR_storage_buffer_storage_class]>, #spirv.resource_limits<>>1291} {1292 1293// CHECK-LABEL: @select1294func.func @select(%arg0 : i32, %arg1 : i32) {1295 %0 = arith.cmpi sle, %arg0, %arg1 : i321296 // CHECK: spirv.Select1297 %1 = arith.select %0, %arg0, %arg1 : i321298 return1299}1300 1301} // end module1302 1303// -----1304 1305//===----------------------------------------------------------------------===//1306// arith.select1307//===----------------------------------------------------------------------===//1308 1309module attributes {1310 spirv.target_env = #spirv.target_env<1311 #spirv.vce<v1.0, [Int8, Int16, Int64, Float16, Float64, Shader], []>, #spirv.resource_limits<>>1312} {1313 1314// Check integer operation conversions.1315// CHECK-LABEL: @int32_scalar1316func.func @int32_scalar(%lhs: i32, %rhs: i32) {1317 // CHECK: spirv.IAdd %{{.*}}, %{{.*}}: i321318 %0 = arith.addi %lhs, %rhs: i321319 // CHECK: spirv.ISub %{{.*}}, %{{.*}}: i321320 %1 = arith.subi %lhs, %rhs: i321321 // CHECK: spirv.IMul %{{.*}}, %{{.*}}: i321322 %2 = arith.muli %lhs, %rhs: i321323 // CHECK: spirv.SDiv %{{.*}}, %{{.*}}: i321324 %3 = arith.divsi %lhs, %rhs: i321325 // CHECK: spirv.UDiv %{{.*}}, %{{.*}}: i321326 %4 = arith.divui %lhs, %rhs: i321327 // CHECK: spirv.UMod %{{.*}}, %{{.*}}: i321328 %5 = arith.remui %lhs, %rhs: i321329 // CHECK: spirv.GL.SMax %{{.*}}, %{{.*}}: i321330 %6 = arith.maxsi %lhs, %rhs : i321331 // CHECK: spirv.GL.UMax %{{.*}}, %{{.*}}: i321332 %7 = arith.maxui %lhs, %rhs : i321333 // CHECK: spirv.GL.SMin %{{.*}}, %{{.*}}: i321334 %8 = arith.minsi %lhs, %rhs : i321335 // CHECK: spirv.GL.UMin %{{.*}}, %{{.*}}: i321336 %9 = arith.minui %lhs, %rhs : i321337 return1338}1339 1340// CHECK-LABEL: @scalar_srem1341// CHECK-SAME: (%[[LHS:.+]]: i32, %[[RHS:.+]]: i32)1342func.func @scalar_srem(%lhs: i32, %rhs: i32) {1343 // CHECK: %[[LABS:.+]] = spirv.GL.SAbs %[[LHS]] : i321344 // CHECK: %[[RABS:.+]] = spirv.GL.SAbs %[[RHS]] : i321345 // CHECK: %[[ABS:.+]] = spirv.UMod %[[LABS]], %[[RABS]] : i321346 // CHECK: %[[POS:.+]] = spirv.IEqual %[[LHS]], %[[LABS]] : i321347 // CHECK: %[[NEG:.+]] = spirv.SNegate %[[ABS]] : i321348 // CHECK: %{{.+}} = spirv.Select %[[POS]], %[[ABS]], %[[NEG]] : i1, i321349 %0 = arith.remsi %lhs, %rhs: i321350 return1351}1352 1353// Check float unary operation conversions.1354// CHECK-LABEL: @float32_unary_scalar1355func.func @float32_unary_scalar(%arg0: f32) {1356 // CHECK: spirv.FNegate %{{.*}}: f321357 %5 = arith.negf %arg0 : f321358 return1359}1360 1361// Check float binary operation conversions.1362// CHECK-LABEL: @float32_binary_scalar1363func.func @float32_binary_scalar(%lhs: f32, %rhs: f32) {1364 // CHECK: spirv.FAdd %{{.*}}, %{{.*}}: f321365 %0 = arith.addf %lhs, %rhs: f321366 // CHECK: spirv.FSub %{{.*}}, %{{.*}}: f321367 %1 = arith.subf %lhs, %rhs: f321368 // CHECK: spirv.FMul %{{.*}}, %{{.*}}: f321369 %2 = arith.mulf %lhs, %rhs: f321370 // CHECK: spirv.FDiv %{{.*}}, %{{.*}}: f321371 %3 = arith.divf %lhs, %rhs: f321372 // CHECK: spirv.FRem %{{.*}}, %{{.*}}: f321373 %4 = arith.remf %lhs, %rhs: f321374 return1375}1376 1377// CHECK-LABEL: @float32_minimumf_scalar1378// CHECK-SAME: %[[LHS:.+]]: f32, %[[RHS:.+]]: f321379func.func @float32_minimumf_scalar(%arg0 : f32, %arg1 : f32) -> f32 {1380 // CHECK: %[[MIN:.+]] = spirv.GL.FMin %arg0, %arg1 : f321381 // CHECK: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : f321382 // CHECK: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : f321383 // CHECK: %[[SELECT1:.+]] = spirv.Select %[[LHS_NAN]], %[[LHS]], %[[MIN]]1384 // CHECK: %[[SELECT2:.+]] = spirv.Select %[[RHS_NAN]], %[[RHS]], %[[SELECT1]]1385 %0 = arith.minimumf %arg0, %arg1 : f321386 // CHECK: return %[[SELECT2]]1387 return %0: f321388}1389 1390// CHECK-LABEL: @float32_minnumf_scalar1391// CHECK-SAME: %[[LHS:.+]]: f32, %[[RHS:.+]]: f321392func.func @float32_minnumf_scalar(%arg0 : f32, %arg1 : f32) -> f32 {1393 // CHECK: %[[MIN:.+]] = spirv.GL.FMin %arg0, %arg1 : f321394 // CHECK: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : f321395 // CHECK: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : f321396 // CHECK: %[[SELECT1:.+]] = spirv.Select %[[LHS_NAN]], %[[RHS]], %[[MIN]]1397 // CHECK: %[[SELECT2:.+]] = spirv.Select %[[RHS_NAN]], %[[LHS]], %[[SELECT1]]1398 %0 = arith.minnumf %arg0, %arg1 : f321399 // CHECK: return %[[SELECT2]]1400 return %0: f321401}1402 1403// CHECK-LABEL: @float32_maximumf_scalar1404// CHECK-SAME: %[[LHS:.+]]: vector<2xf32>, %[[RHS:.+]]: vector<2xf32>1405func.func @float32_maximumf_scalar(%arg0 : vector<2xf32>, %arg1 : vector<2xf32>) -> vector<2xf32> {1406 // CHECK: %[[MAX:.+]] = spirv.GL.FMax %arg0, %arg1 : vector<2xf32>1407 // CHECK: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : vector<2xf32>1408 // CHECK: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : vector<2xf32>1409 // CHECK: %[[SELECT1:.+]] = spirv.Select %[[LHS_NAN]], %[[LHS]], %[[MAX]]1410 // CHECK: %[[SELECT2:.+]] = spirv.Select %[[RHS_NAN]], %[[RHS]], %[[SELECT1]]1411 %0 = arith.maximumf %arg0, %arg1 : vector<2xf32>1412 // CHECK: return %[[SELECT2]]1413 return %0: vector<2xf32>1414}1415 1416// CHECK-LABEL: @float32_maxnumf_scalar1417// CHECK-SAME: %[[LHS:.+]]: vector<2xf32>, %[[RHS:.+]]: vector<2xf32>1418func.func @float32_maxnumf_scalar(%arg0 : vector<2xf32>, %arg1 : vector<2xf32>) -> vector<2xf32> {1419 // CHECK: %[[MAX:.+]] = spirv.GL.FMax %arg0, %arg1 : vector<2xf32>1420 // CHECK: %[[LHS_NAN:.+]] = spirv.IsNan %[[LHS]] : vector<2xf32>1421 // CHECK: %[[RHS_NAN:.+]] = spirv.IsNan %[[RHS]] : vector<2xf32>1422 // CHECK: %[[SELECT1:.+]] = spirv.Select %[[LHS_NAN]], %[[RHS]], %[[MAX]]1423 // CHECK: %[[SELECT2:.+]] = spirv.Select %[[RHS_NAN]], %[[LHS]], %[[SELECT1]]1424 %0 = arith.maxnumf %arg0, %arg1 : vector<2xf32>1425 // CHECK: return %[[SELECT2]]1426 return %0: vector<2xf32>1427}1428 1429// Check int vector types.1430// CHECK-LABEL: @int_vector2341431func.func @int_vector234(%arg0: vector<2xi8>, %arg1: vector<4xi64>) {1432 // CHECK: spirv.SDiv %{{.*}}, %{{.*}}: vector<2xi8>1433 %0 = arith.divsi %arg0, %arg0: vector<2xi8>1434 // CHECK: spirv.UDiv %{{.*}}, %{{.*}}: vector<4xi64>1435 %1 = arith.divui %arg1, %arg1: vector<4xi64>1436 return1437}1438 1439// CHECK-LABEL: @vector_srem1440// CHECK-SAME: (%[[LHS:.+]]: vector<3xi16>, %[[RHS:.+]]: vector<3xi16>)1441func.func @vector_srem(%arg0: vector<3xi16>, %arg1: vector<3xi16>) {1442 // CHECK: %[[LABS:.+]] = spirv.GL.SAbs %[[LHS]] : vector<3xi16>1443 // CHECK: %[[RABS:.+]] = spirv.GL.SAbs %[[RHS]] : vector<3xi16>1444 // CHECK: %[[ABS:.+]] = spirv.UMod %[[LABS]], %[[RABS]] : vector<3xi16>1445 // CHECK: %[[POS:.+]] = spirv.IEqual %[[LHS]], %[[LABS]] : vector<3xi16>1446 // CHECK: %[[NEG:.+]] = spirv.SNegate %[[ABS]] : vector<3xi16>1447 // CHECK: %{{.+}} = spirv.Select %[[POS]], %[[ABS]], %[[NEG]] : vector<3xi1>, vector<3xi16>1448 %0 = arith.remsi %arg0, %arg1: vector<3xi16>1449 return1450}1451 1452// Check float vector types.1453// CHECK-LABEL: @float_vector2341454func.func @float_vector234(%arg0: vector<2xf16>, %arg1: vector<3xf64>) {1455 // CHECK: spirv.FAdd %{{.*}}, %{{.*}}: vector<2xf16>1456 %0 = arith.addf %arg0, %arg0: vector<2xf16>1457 // CHECK: spirv.FMul %{{.*}}, %{{.*}}: vector<3xf64>1458 %1 = arith.mulf %arg1, %arg1: vector<3xf64>1459 return1460}1461 1462// CHECK-LABEL: @one_elem_vector1463func.func @one_elem_vector(%arg0: vector<1xi32>) {1464 // CHECK: spirv.IAdd %{{.+}}, %{{.+}}: i321465 %0 = arith.addi %arg0, %arg0: vector<1xi32>1466 return1467}1468 1469} // end module1470 1471// -----1472 1473// Check that types are converted to 32-bit when no special capabilities.1474module attributes {1475 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [], []>, #spirv.resource_limits<>>1476} {1477 1478// CHECK-LABEL: @int_vector231479func.func @int_vector23(%arg0: vector<2xi8>, %arg1: vector<3xi16>) {1480 // CHECK: spirv.SDiv %{{.*}}, %{{.*}}: vector<2xi32>1481 %0 = arith.divsi %arg0, %arg0: vector<2xi8>1482 // CHECK: spirv.SDiv %{{.*}}, %{{.*}}: vector<3xi32>1483 %1 = arith.divsi %arg1, %arg1: vector<3xi16>1484 return1485}1486 1487// CHECK-LABEL: @float_scalar1488func.func @float_scalar(%arg0: f16) {1489 // CHECK: spirv.FAdd %{{.*}}, %{{.*}}: f321490 %0 = arith.addf %arg0, %arg0: f161491 return1492}1493 1494} // end module1495 1496// -----1497 1498module attributes {1499 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<>>1500} {1501 1502// CHECK-LABEL: @ops_flags1503func.func @ops_flags(%arg0: i64, %arg1: i64) {1504 // CHECK: %{{.*}} = spirv.IAdd %{{.*}}, %{{.*}} {no_signed_wrap} : i641505 %0 = arith.addi %arg0, %arg1 overflow<nsw> : i641506 // CHECK: %{{.*}} = spirv.ISub %{{.*}}, %{{.*}} {no_unsigned_wrap} : i641507 %1 = arith.subi %arg0, %arg1 overflow<nuw> : i641508 // CHECK: %{{.*}} = spirv.IMul %{{.*}}, %{{.*}} {no_signed_wrap, no_unsigned_wrap} : i641509 %2 = arith.muli %arg0, %arg1 overflow<nsw, nuw> : i641510 // CHECK: %{{.*}} = spirv.ShiftLeftLogical %{{.*}}, %{{.*}} {no_signed_wrap, no_unsigned_wrap} : i641511 %3 = arith.shli %arg0, %arg1 overflow<nsw, nuw> : i641512 return1513}1514 1515} // end module1516 1517 1518// -----1519 1520module attributes {1521 spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Int8, Int16, Int64, Float16, Float64], []>, #spirv.resource_limits<>>1522} {1523 1524// No decorations should be generated is corresponding Extensions/Capabilities are missing1525// CHECK-LABEL: @ops_flags1526func.func @ops_flags(%arg0: i64, %arg1: i64) {1527 // CHECK: %{{.*}} = spirv.IAdd %{{.*}}, %{{.*}} : i641528 %0 = arith.addi %arg0, %arg1 overflow<nsw> : i641529 // CHECK: %{{.*}} = spirv.ISub %{{.*}}, %{{.*}} : i641530 %1 = arith.subi %arg0, %arg1 overflow<nuw> : i641531 // CHECK: %{{.*}} = spirv.IMul %{{.*}}, %{{.*}} : i641532 %2 = arith.muli %arg0, %arg1 overflow<nsw, nuw> : i641533 // CHECK: %{{.*}} = spirv.IMul %{{.*}}, %{{.*}} : i641534 %3 = arith.muli %arg0, %arg1 overflow<nsw, nuw> : i641535 return1536}1537 1538} // end module1539