1// RUN: mlir-opt -split-input-file -verify-diagnostics %s | FileCheck %s 2 3//===----------------------------------------------------------------------===// 4// spv.AccessChain 5//===----------------------------------------------------------------------===// 6 7func @access_chain_struct() -> () { 8 %0 = spv.constant 1: i32 9 %1 = spv.Variable : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function> 10 // CHECK: spv.AccessChain {{.*}}[{{.*}}, {{.*}}] : !spv.ptr<!spv.struct<f32, !spv.array<4 x f32>>, Function> 11 %2 = spv.AccessChain %1[%0, %0] : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function> 12 return 13} 14 15func @access_chain_1D_array(%arg0 : i32) -> () { 16 %0 = spv.Variable : !spv.ptr<!spv.array<4xf32>, Function> 17 // CHECK: spv.AccessChain {{.*}}[{{.*}}] : !spv.ptr<!spv.array<4 x f32>, Function> 18 %1 = spv.AccessChain %0[%arg0] : !spv.ptr<!spv.array<4xf32>, Function> 19 return 20} 21 22func @access_chain_2D_array_1(%arg0 : i32) -> () { 23 %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function> 24 // CHECK: spv.AccessChain {{.*}}[{{.*}}, {{.*}}] : !spv.ptr<!spv.array<4 x !spv.array<4 x f32>>, Function> 25 %1 = spv.AccessChain %0[%arg0, %arg0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function> 26 %2 = spv.Load "Function" %1 ["Volatile"] : f32 27 return 28} 29 30func @access_chain_2D_array_2(%arg0 : i32) -> () { 31 %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function> 32 // CHECK: spv.AccessChain {{.*}}[{{.*}}] : !spv.ptr<!spv.array<4 x !spv.array<4 x f32>>, Function> 33 %1 = spv.AccessChain %0[%arg0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function> 34 %2 = spv.Load "Function" %1 ["Volatile"] : !spv.array<4xf32> 35 return 36} 37 38func @access_chain_rtarray(%arg0 : i32) -> () { 39 %0 = spv.Variable : !spv.ptr<!spv.rtarray<f32>, Function> 40 // CHECK: spv.AccessChain {{.*}}[{{.*}}] : !spv.ptr<!spv.rtarray<f32>, Function> 41 %1 = spv.AccessChain %0[%arg0] : !spv.ptr<!spv.rtarray<f32>, Function> 42 %2 = spv.Load "Function" %1 ["Volatile"] : f32 43 return 44} 45 46// ----- 47 48func @access_chain_non_composite() -> () { 49 %0 = spv.constant 1: i32 50 %1 = spv.Variable : !spv.ptr<f32, Function> 51 // expected-error @+1 {{cannot extract from non-composite type 'f32' with index 0}} 52 %2 = spv.AccessChain %1[%0] : !spv.ptr<f32, Function> 53 return 54} 55 56// ----- 57 58func @access_chain_no_indices(%index0 : i32) -> () { 59 %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function> 60 // expected-error @+1 {{expected at least one index}} 61 %1 = spv.AccessChain %0[] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function> 62 return 63} 64 65// ----- 66 67func @access_chain_invalid_type(%index0 : i32) -> () { 68 %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function> 69 %1 = spv.Load "Function" %0 ["Volatile"] : !spv.array<4x!spv.array<4xf32>> 70 // expected-error @+1 {{expected a pointer to composite type, but provided '!spv.array<4 x !spv.array<4 x f32>>'}} 71 %2 = spv.AccessChain %1[%index0] : !spv.array<4x!spv.array<4xf32>> 72 return 73} 74 75// ----- 76 77func @access_chain_invalid_index_1(%index0 : i32) -> () { 78 %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function> 79 // expected-error @+1 {{expected SSA operand}} 80 %1 = spv.AccessChain %0[%index, 4] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function> 81 return 82} 83 84// ----- 85 86func @access_chain_invalid_index_2(%index0 : i32) -> () { 87 %0 = spv.Variable : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function> 88 // expected-error @+1 {{index must be an integer spv.constant to access element of spv.struct}} 89 %1 = spv.AccessChain %0[%index0, %index0] : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function> 90 return 91} 92 93// ----- 94 95func @access_chain_invalid_constant_type_1() -> () { 96 %0 = std.constant 1: i32 97 %1 = spv.Variable : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function> 98 // expected-error @+1 {{index must be an integer spv.constant to access element of spv.struct, but provided std.constant}} 99 %2 = spv.AccessChain %1[%0, %0] : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function> 100 return 101} 102 103// ----- 104 105func @access_chain_out_of_bounds() -> () { 106 %index0 = "spv.constant"() { value = 12: i32} : () -> i32 107 %0 = spv.Variable : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function> 108 // expected-error @+1 {{'spv.AccessChain' op index 12 out of bounds for '!spv.struct<f32, !spv.array<4 x f32>>'}} 109 %1 = spv.AccessChain %0[%index0, %index0] : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function> 110 return 111} 112 113// ----- 114 115func @access_chain_invalid_accessing_type(%index0 : i32) -> () { 116 %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function> 117 // expected-error @+1 {{cannot extract from non-composite type 'f32' with index 0}} 118 %1 = spv.AccessChain %0[%index, %index0, %index0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function> 119 return 120 121// ----- 122 123//===----------------------------------------------------------------------===// 124// spv.Bitcast 125//===----------------------------------------------------------------------===// 126 127func @cast1(%arg0 : f32) { 128 // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : f32 to i32 129 %0 = spv.Bitcast %arg0 : f32 to i32 130 return 131} 132 133func @cast2(%arg0 : vector<2xf32>) { 134 // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : vector<2xf32> to vector<2xi32> 135 %0 = spv.Bitcast %arg0 : vector<2xf32> to vector<2xi32> 136 return 137} 138 139func @cast3(%arg0 : vector<2xf32>) { 140 // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : vector<2xf32> to i64 141 %0 = spv.Bitcast %arg0 : vector<2xf32> to i64 142 return 143} 144 145func @cast4(%arg0 : !spv.ptr<f32, Function>) { 146 // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : !spv.ptr<f32, Function> to !spv.ptr<i32, Function> 147 %0 = spv.Bitcast %arg0 : !spv.ptr<f32, Function> to !spv.ptr<i32, Function> 148 return 149} 150 151func @cast5(%arg0 : !spv.ptr<f32, Function>) { 152 // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : !spv.ptr<f32, Function> to !spv.ptr<vector<2xi32>, Function> 153 %0 = spv.Bitcast %arg0 : !spv.ptr<f32, Function> to !spv.ptr<vector<2xi32>, Function> 154 return 155} 156 157func @cast6(%arg0 : vector<4xf32>) { 158 // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : vector<4xf32> to vector<2xi64> 159 %0 = spv.Bitcast %arg0 : vector<4xf32> to vector<2xi64> 160 return 161} 162 163// ----- 164 165func @cast1(%arg0 : f32) { 166 // expected-error @+1 {{result type must be different from operand type}} 167 %0 = spv.Bitcast %arg0 : f32 to f32 168 return 169} 170 171// ----- 172 173func @cast1(%arg0 : f32) { 174 // expected-error @+1 {{mismatch in result type bitwidth 64 and operand type bitwidth 32}} 175 %0 = spv.Bitcast %arg0 : f32 to i64 176 return 177} 178 179// ----- 180 181func @cast1(%arg0 : vector<2xf32>) { 182 // expected-error @+1 {{mismatch in result type bitwidth 96 and operand type bitwidth 64}} 183 %0 = spv.Bitcast %arg0 : vector<2xf32> to vector<3xf32> 184 return 185} 186 187// ----- 188 189func @cast3(%arg0 : !spv.ptr<f32, Function>) { 190 // expected-error @+1 {{unhandled bit cast conversion from pointer type to non-pointer type}} 191 %0 = spv.Bitcast %arg0 : !spv.ptr<f32, Function> to i64 192 return 193} 194 195// ----- 196 197func @cast3(%arg0 : i64) { 198 // expected-error @+1 {{unhandled bit cast conversion from non-pointer type to pointer type}} 199 %0 = spv.Bitcast %arg0 : i64 to !spv.ptr<f32, Function> 200 return 201} 202 203// ----- 204 205//===----------------------------------------------------------------------===// 206// spv.BitCount 207//===----------------------------------------------------------------------===// 208 209func @bitcount(%arg: i32) -> i32 { 210 // CHECK: spv.BitCount {{%.*}} : i32 211 %0 = spv.BitCount %arg : i32 212 spv.ReturnValue %0 : i32 213} 214 215// ----- 216 217//===----------------------------------------------------------------------===// 218// spv.BitFieldInsert 219//===----------------------------------------------------------------------===// 220 221func @bit_field_insert_vec(%base: vector<3xi32>, %insert: vector<3xi32>, %offset: i32, %count: i16) -> vector<3xi32> { 222 // CHECK: {{%.*}} = spv.BitFieldInsert {{%.*}}, {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi32>, i32, i16 223 %0 = spv.BitFieldInsert %base, %insert, %offset, %count : vector<3xi32>, i32, i16 224 spv.ReturnValue %0 : vector<3xi32> 225} 226 227// ----- 228 229func @bit_field_insert_invalid_insert_type(%base: vector<3xi32>, %insert: vector<2xi32>, %offset: i32, %count: i16) -> vector<3xi32> { 230 // expected-error @+1 {{expected the same type for the base operand, insert operand, and result, but provided 'vector<3xi32>', 'vector<2xi32>' and 'vector<3xi32>'}} 231 %0 = "spv.BitFieldInsert" (%base, %insert, %offset, %count) : (vector<3xi32>, vector<2xi32>, i32, i16) -> vector<3xi32> 232 spv.ReturnValue %0 : vector<3xi32> 233} 234 235// ----- 236 237//===----------------------------------------------------------------------===// 238// spv.BitFieldSExtract 239//===----------------------------------------------------------------------===// 240 241func @bit_field_s_extract_vec(%base: vector<3xi32>, %offset: i8, %count: i8) -> vector<3xi32> { 242 // CHECK: {{%.*}} = spv.BitFieldSExtract {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi32>, i8, i8 243 %0 = spv.BitFieldSExtract %base, %offset, %count : vector<3xi32>, i8, i8 244 spv.ReturnValue %0 : vector<3xi32> 245} 246 247//===----------------------------------------------------------------------===// 248// spv.BitFieldUExtract 249//===----------------------------------------------------------------------===// 250 251func @bit_field_u_extract_vec(%base: vector<3xi32>, %offset: i8, %count: i8) -> vector<3xi32> { 252 // CHECK: {{%.*}} = spv.BitFieldUExtract {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi32>, i8, i8 253 %0 = spv.BitFieldUExtract %base, %offset, %count : vector<3xi32>, i8, i8 254 spv.ReturnValue %0 : vector<3xi32> 255} 256 257// ----- 258 259func @bit_field_u_extract_invalid_result_type(%base: vector<3xi32>, %offset: i32, %count: i16) -> vector<4xi32> { 260 // expected-error @+1 {{expected the same type for the first operand and result, but provided 'vector<3xi32>' and 'vector<4xi32>'}} 261 %0 = "spv.BitFieldUExtract" (%base, %offset, %count) : (vector<3xi32>, i32, i16) -> vector<4xi32> 262 spv.ReturnValue %0 : vector<4xi32> 263} 264 265// ----- 266 267//===----------------------------------------------------------------------===// 268// spv.BitReverse 269//===----------------------------------------------------------------------===// 270 271func @bitreverse(%arg: i32) -> i32 { 272 // CHECK: spv.BitReverse {{%.*}} : i32 273 %0 = spv.BitReverse %arg : i32 274 spv.ReturnValue %0 : i32 275} 276 277// ----- 278 279//===----------------------------------------------------------------------===// 280// spv.ControlBarrier 281//===----------------------------------------------------------------------===// 282 283func @control_barrier_0() -> () { 284 // CHECK: spv.ControlBarrier "Workgroup", "Device", "Acquire|UniformMemory" 285 spv.ControlBarrier "Workgroup", "Device", "Acquire|UniformMemory" 286 return 287} 288 289// ----- 290 291func @control_barrier_1() -> () { 292 // expected-error @+1 {{invalid scope attribute specification: "Something"}} 293 spv.ControlBarrier "Something", "Device", "Acquire|UniformMemory" 294 return 295} 296 297// ----- 298 299//===----------------------------------------------------------------------===// 300// spv.ConvertFToS 301//===----------------------------------------------------------------------===// 302 303func @convert_f_to_s_scalar(%arg0 : f32) -> i32 { 304 // CHECK: {{%.*}} = spv.ConvertFToS {{%.*}} : f32 to i32 305 %0 = spv.ConvertFToS %arg0 : f32 to i32 306 spv.ReturnValue %0 : i32 307} 308 309// ----- 310 311//===----------------------------------------------------------------------===// 312// spv.ConvertFToU 313//===----------------------------------------------------------------------===// 314 315func @convert_f_to_u_scalar(%arg0 : f32) -> i32 { 316 // CHECK: {{%.*}} = spv.ConvertFToU {{%.*}} : f32 to i32 317 %0 = spv.ConvertFToU %arg0 : f32 to i32 318 spv.ReturnValue %0 : i32 319} 320 321// ----- 322 323func @convert_f_to_u_vector(%arg0 : vector<3xf32>) -> vector<3xi32> { 324 // CHECK: {{%.*}} = spv.ConvertFToU {{%.*}} : vector<3xf32> to vector<3xi32> 325 %0 = spv.ConvertFToU %arg0 : vector<3xf32> to vector<3xi32> 326 spv.ReturnValue %0 : vector<3xi32> 327} 328 329// ----- 330 331func @convert_f_to_u_scalar_invalid(%arg0 : f16) -> i32 { 332 // expected-error @+1 {{expected the same bit widths for operand type and result type, but provided 'f16' and 'i32'}} 333 %0 = spv.ConvertFToU %arg0 : f16 to i32 334 spv.ReturnValue %0 : i32 335} 336 337// ----- 338 339//===----------------------------------------------------------------------===// 340// spv.ConvertSToF 341//===----------------------------------------------------------------------===// 342 343func @convert_s_to_f_scalar(%arg0 : i32) -> f32 { 344 // CHECK: {{%.*}} = spv.ConvertSToF {{%.*}} : i32 to f32 345 %0 = spv.ConvertSToF %arg0 : i32 to f32 346 spv.ReturnValue %0 : f32 347} 348 349// ----- 350 351//===----------------------------------------------------------------------===// 352// spv.ConvertUToF 353//===----------------------------------------------------------------------===// 354 355func @convert_u_to_f_scalar(%arg0 : i32) -> f32 { 356 // CHECK: {{%.*}} = spv.ConvertUToF {{%.*}} : i32 to f32 357 %0 = spv.ConvertUToF %arg0 : i32 to f32 358 spv.ReturnValue %0 : f32 359} 360 361// ----- 362 363//===----------------------------------------------------------------------===// 364// spv.FConvert 365//===----------------------------------------------------------------------===// 366 367func @f_convert_scalar(%arg0 : f32) -> f64 { 368 // CHECK: {{%.*}} = spv.FConvert {{%.*}} : f32 to f64 369 %0 = spv.FConvert %arg0 : f32 to f64 370 spv.ReturnValue %0 : f64 371} 372 373// ----- 374 375func @f_convert_vector(%arg0 : vector<3xf32>) -> vector<3xf64> { 376 // CHECK: {{%.*}} = spv.FConvert {{%.*}} : vector<3xf32> to vector<3xf64> 377 %0 = spv.FConvert %arg0 : vector<3xf32> to vector<3xf64> 378 spv.ReturnValue %0 : vector<3xf64> 379} 380 381// ----- 382 383func @f_convert_vector(%arg0 : f32) -> f32 { 384 // expected-error @+1 {{expected the different bit widths for operand type and result type, but provided 'f32' and 'f32'}} 385 %0 = spv.FConvert %arg0 : f32 to f32 386 spv.ReturnValue %0 : f32 387} 388 389// ----- 390 391//===----------------------------------------------------------------------===// 392// spv.SConvert 393//===----------------------------------------------------------------------===// 394 395func @s_convert_scalar(%arg0 : i32) -> i64 { 396 // CHECK: {{%.*}} = spv.SConvert {{%.*}} : i32 to i64 397 %0 = spv.SConvert %arg0 : i32 to i64 398 spv.ReturnValue %0 : i64 399} 400 401// ----- 402 403//===----------------------------------------------------------------------===// 404// spv.UConvert 405//===----------------------------------------------------------------------===// 406 407func @u_convert_scalar(%arg0 : i32) -> i64 { 408 // CHECK: {{%.*}} = spv.UConvert {{%.*}} : i32 to i64 409 %0 = spv.UConvert %arg0 : i32 to i64 410 spv.ReturnValue %0 : i64 411} 412 413// ----- 414 415//===----------------------------------------------------------------------===// 416// spv.ExecutionMode 417//===----------------------------------------------------------------------===// 418 419spv.module "Logical" "GLSL450" { 420 func @do_nothing() -> () { 421 spv.Return 422 } 423 spv.EntryPoint "GLCompute" @do_nothing 424 // CHECK: spv.ExecutionMode {{@.*}} "ContractionOff" 425 spv.ExecutionMode @do_nothing "ContractionOff" 426} 427 428spv.module "Logical" "GLSL450" { 429 func @do_nothing() -> () { 430 spv.Return 431 } 432 spv.EntryPoint "GLCompute" @do_nothing 433 // CHECK: spv.ExecutionMode {{@.*}} "LocalSizeHint", 3, 4, 5 434 spv.ExecutionMode @do_nothing "LocalSizeHint", 3, 4, 5 435} 436 437// ----- 438 439spv.module "Logical" "GLSL450" { 440 func @do_nothing() -> () { 441 spv.Return 442 } 443 spv.EntryPoint "GLCompute" @do_nothing 444 // expected-error @+1 {{custom op 'spv.ExecutionMode' invalid execution_mode attribute specification: "GLCompute"}} 445 spv.ExecutionMode @do_nothing "GLCompute", 3, 4, 5 446} 447 448// ----- 449 450//===----------------------------------------------------------------------===// 451// spv.LoadOp 452//===----------------------------------------------------------------------===// 453 454// CHECK-LABEL: @simple_load 455func @simple_load() -> () { 456 %0 = spv.Variable : !spv.ptr<f32, Function> 457 // CHECK: spv.Load "Function" %{{.*}} : f32 458 %1 = spv.Load "Function" %0 : f32 459 return 460} 461 462// CHECK-LABEL: @load_none_access 463func @load_none_access() -> () { 464 %0 = spv.Variable : !spv.ptr<f32, Function> 465 // CHECK: spv.Load "Function" %{{.*}} ["None"] : f32 466 %1 = spv.Load "Function" %0 ["None"] : f32 467 return 468} 469 470// CHECK-LABEL: @volatile_load 471func @volatile_load() -> () { 472 %0 = spv.Variable : !spv.ptr<f32, Function> 473 // CHECK: spv.Load "Function" %{{.*}} ["Volatile"] : f32 474 %1 = spv.Load "Function" %0 ["Volatile"] : f32 475 return 476} 477 478// CHECK-LABEL: @aligned_load 479func @aligned_load() -> () { 480 %0 = spv.Variable : !spv.ptr<f32, Function> 481 // CHECK: spv.Load "Function" %{{.*}} ["Aligned", 4] : f32 482 %1 = spv.Load "Function" %0 ["Aligned", 4] : f32 483 return 484} 485 486// CHECK-LABEL: @volatile_aligned_load 487func @volatile_aligned_load() -> () { 488 %0 = spv.Variable : !spv.ptr<f32, Function> 489 // CHECK: spv.Load "Function" %{{.*}} ["Volatile|Aligned", 4] : f32 490 %1 = spv.Load "Function" %0 ["Volatile|Aligned", 4] : f32 491 return 492} 493 494// ----- 495 496// CHECK-LABEL: load_none_access 497func @load_none_access() -> () { 498 %0 = spv.Variable : !spv.ptr<f32, Function> 499 // CHECK: spv.Load 500 // CHECK-SAME: ["None"] 501 %1 = "spv.Load"(%0) {memory_access = 0 : i32} : (!spv.ptr<f32, Function>) -> (f32) 502 return 503} 504 505// CHECK-LABEL: volatile_load 506func @volatile_load() -> () { 507 %0 = spv.Variable : !spv.ptr<f32, Function> 508 // CHECK: spv.Load 509 // CHECK-SAME: ["Volatile"] 510 %1 = "spv.Load"(%0) {memory_access = 1 : i32} : (!spv.ptr<f32, Function>) -> (f32) 511 return 512} 513 514// CHECK-LABEL: aligned_load 515func @aligned_load() -> () { 516 %0 = spv.Variable : !spv.ptr<f32, Function> 517 // CHECK: spv.Load 518 // CHECK-SAME: ["Aligned", 4] 519 %1 = "spv.Load"(%0) {memory_access = 2 : i32, alignment = 4 : i32} : (!spv.ptr<f32, Function>) -> (f32) 520 return 521} 522 523// CHECK-LABEL: volatile_aligned_load 524func @volatile_aligned_load() -> () { 525 %0 = spv.Variable : !spv.ptr<f32, Function> 526 // CHECK: spv.Load 527 // CHECK-SAME: ["Volatile|Aligned", 4] 528 %1 = "spv.Load"(%0) {memory_access = 3 : i32, alignment = 4 : i32} : (!spv.ptr<f32, Function>) -> (f32) 529 return 530} 531 532// ----- 533 534func @simple_load_missing_storageclass() -> () { 535 %0 = spv.Variable : !spv.ptr<f32, Function> 536 // expected-error @+1 {{expected non-function type}} 537 %1 = spv.Load %0 : f32 538 return 539} 540 541// ----- 542 543func @simple_load_missing_operand() -> () { 544 %0 = spv.Variable : !spv.ptr<f32, Function> 545 // expected-error @+1 {{expected SSA operand}} 546 %1 = spv.Load "Function" : f32 547 return 548} 549 550// ----- 551 552func @simple_load_missing_rettype() -> () { 553 %0 = spv.Variable : !spv.ptr<f32, Function> 554 // expected-error @+2 {{expected ':'}} 555 %1 = spv.Load "Function" %0 556 return 557} 558 559// ----- 560 561func @volatile_load_missing_lbrace() -> () { 562 %0 = spv.Variable : !spv.ptr<f32, Function> 563 // expected-error @+1 {{expected ':'}} 564 %1 = spv.Load "Function" %0 "Volatile"] : f32 565 return 566} 567 568// ----- 569 570func @volatile_load_missing_rbrace() -> () { 571 %0 = spv.Variable : !spv.ptr<f32, Function> 572 // expected-error @+1 {{expected ']'}} 573 %1 = spv.Load "Function" %0 ["Volatile"} : f32 574 return 575} 576 577// ----- 578 579func @aligned_load_missing_alignment() -> () { 580 %0 = spv.Variable : !spv.ptr<f32, Function> 581 // expected-error @+1 {{expected ','}} 582 %1 = spv.Load "Function" %0 ["Aligned"] : f32 583 return 584} 585 586// ----- 587 588func @aligned_load_missing_comma() -> () { 589 %0 = spv.Variable : !spv.ptr<f32, Function> 590 // expected-error @+1 {{expected ','}} 591 %1 = spv.Load "Function" %0 ["Aligned" 4] : f32 592 return 593} 594 595// ----- 596 597func @load_incorrect_attributes() -> () { 598 %0 = spv.Variable : !spv.ptr<f32, Function> 599 // expected-error @+1 {{expected ']'}} 600 %1 = spv.Load "Function" %0 ["Volatile", 4] : f32 601 return 602} 603 604// ----- 605 606func @load_unknown_memory_access() -> () { 607 %0 = spv.Variable : !spv.ptr<f32, Function> 608 // expected-error @+1 {{custom op 'spv.Load' invalid memory_access attribute specification: "Something"}} 609 %1 = spv.Load "Function" %0 ["Something"] : f32 610 return 611} 612 613// ----- 614 615func @load_unknown_memory_access() -> () { 616 %0 = spv.Variable : !spv.ptr<f32, Function> 617 // expected-error @+1 {{custom op 'spv.Load' invalid memory_access attribute specification: "Volatile|Something"}} 618 %1 = spv.Load "Function" %0 ["Volatile|Something"] : f32 619 return 620} 621 622// ----- 623 624func @load_unknown_memory_access() -> () { 625 %0 = spv.Variable : !spv.ptr<f32, Function> 626 // expected-error @+1 {{failed to satisfy constraint: valid SPIR-V MemoryAccess}} 627 %1 = "spv.Load"(%0) {memory_access = 0x80000000 : i32} : (!spv.ptr<f32, Function>) -> (f32) 628 return 629} 630 631// ----- 632 633func @aligned_load_incorrect_attributes() -> () { 634 %0 = spv.Variable : !spv.ptr<f32, Function> 635 // expected-error @+1 {{expected ']'}} 636 %1 = spv.Load "Function" %0 ["Aligned", 4, 23] : f32 637 return 638} 639 640// ----- 641 642spv.module "Logical" "GLSL450" { 643 spv.globalVariable @var0 : !spv.ptr<f32, Input> 644 // CHECK_LABEL: @simple_load 645 func @simple_load() -> () { 646 // CHECK: spv.Load "Input" {{%.*}} : f32 647 %0 = spv._address_of @var0 : !spv.ptr<f32, Input> 648 %1 = spv.Load "Input" %0 : f32 649 spv.Return 650 } 651} 652 653// ----- 654 655//===----------------------------------------------------------------------===// 656// spv.LogicalAnd 657//===----------------------------------------------------------------------===// 658 659func @logicalBinary(%arg0 : i1, %arg1 : i1, %arg2 : i1) 660{ 661 // CHECK: [[TMP:%.*]] = spv.LogicalAnd {{%.*}}, {{%.*}} : i1 662 %0 = spv.LogicalAnd %arg0, %arg1 : i1 663 // CHECK: {{%.*}} = spv.LogicalAnd [[TMP]], {{%.*}} : i1 664 %1 = spv.LogicalAnd %0, %arg2 : i1 665 return 666} 667 668func @logicalBinary2(%arg0 : vector<4xi1>, %arg1 : vector<4xi1>) 669{ 670 // CHECK: {{%.*}} = spv.LogicalAnd {{%.*}}, {{%.*}} : vector<4xi1> 671 %0 = spv.LogicalAnd %arg0, %arg1 : vector<4xi1> 672 return 673} 674 675// ----- 676 677func @logicalBinary(%arg0 : i1, %arg1 : i1) 678{ 679 // expected-error @+2 {{expected ':'}} 680 %0 = spv.LogicalAnd %arg0, %arg1 681 return 682} 683 684// ----- 685 686func @logicalBinary(%arg0 : i1, %arg1 : i1) 687{ 688 // expected-error @+2 {{expected non-function type}} 689 %0 = spv.LogicalAnd %arg0, %arg1 : 690 return 691} 692 693// ----- 694 695func @logicalBinary(%arg0 : i1, %arg1 : i1) 696{ 697 // expected-error @+1 {{custom op 'spv.LogicalAnd' expected 2 operands}} 698 %0 = spv.LogicalAnd %arg0 : i1 699 return 700} 701 702// ----- 703 704//===----------------------------------------------------------------------===// 705// spv.LogicalNot 706//===----------------------------------------------------------------------===// 707 708func @logicalUnary(%arg0 : i1, %arg1 : i1) 709{ 710 // CHECK: [[TMP:%.*]] = spv.LogicalNot {{%.*}} : i1 711 %0 = spv.LogicalNot %arg0 : i1 712 // CHECK: {{%.*}} = spv.LogicalNot [[TMP]] : i1 713 %1 = spv.LogicalNot %0 : i1 714 return 715} 716 717func @logicalUnary2(%arg0 : vector<4xi1>) 718{ 719 // CHECK: {{%.*}} = spv.LogicalNot {{%.*}} : vector<4xi1> 720 %0 = spv.LogicalNot %arg0 : vector<4xi1> 721 return 722} 723 724// ----- 725 726func @logicalUnary(%arg0 : i1) 727{ 728 // expected-error @+2 {{expected ':'}} 729 %0 = spv.LogicalNot %arg0 730 return 731} 732 733// ----- 734 735func @logicalUnary(%arg0 : i1) 736{ 737 // expected-error @+2 {{expected non-function type}} 738 %0 = spv.LogicalNot %arg0 : 739 return 740} 741 742// ----- 743 744func @logicalUnary(%arg0 : i1) 745{ 746 // expected-error @+1 {{expected SSA operand}} 747 %0 = spv.LogicalNot : i1 748 return 749} 750 751// ----- 752 753func @logicalUnary(%arg0 : i32) 754{ 755 // expected-error @+1 {{'spv.LogicalNot' op operand #0 must be 1-bit integer or vector of 1-bit integer values of length 2/3/4, but got 'i32'}} 756 %0 = spv.LogicalNot %arg0 : i32 757 return 758} 759 760// ----- 761 762//===----------------------------------------------------------------------===// 763// spv.MemoryBarrier 764//===----------------------------------------------------------------------===// 765 766func @memory_barrier_0() -> () { 767 // CHECK: spv.MemoryBarrier "Device", "Acquire|UniformMemory" 768 spv.MemoryBarrier "Device", "Acquire|UniformMemory" 769 return 770} 771 772// ----- 773 774func @memory_barrier_1() -> () { 775 // CHECK: spv.MemoryBarrier "Workgroup", "Acquire" 776 spv.MemoryBarrier "Workgroup", "Acquire" 777 return 778} 779 780// ----- 781 782func @memory_barrier_2() -> () { 783 // expected-error @+1 {{expected at most one of these four memory constraints to be set: `Acquire`, `Release`,`AcquireRelease` or `SequentiallyConsistent`}} 784 spv.MemoryBarrier "Device", "Acquire|Release" 785 return 786} 787 788// ----- 789 790//===----------------------------------------------------------------------===// 791// spv.Not 792//===----------------------------------------------------------------------===// 793 794func @not(%arg: i32) -> i32 { 795 // CHECK: spv.Not {{%.*}} : i32 796 %0 = spv.Not %arg : i32 797 spv.ReturnValue %0 : i32 798} 799 800// ----- 801 802//===----------------------------------------------------------------------===// 803// spv.SelectOp 804//===----------------------------------------------------------------------===// 805 806func @select_op_bool(%arg0: i1) -> () { 807 %0 = spv.constant true 808 %1 = spv.constant false 809 // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, i1 810 %2 = spv.Select %arg0, %0, %1 : i1, i1 811 return 812} 813 814func @select_op_int(%arg0: i1) -> () { 815 %0 = spv.constant 2 : i32 816 %1 = spv.constant 3 : i32 817 // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, i32 818 %2 = spv.Select %arg0, %0, %1 : i1, i32 819 return 820} 821 822func @select_op_float(%arg0: i1) -> () { 823 %0 = spv.constant 2.0 : f32 824 %1 = spv.constant 3.0 : f32 825 // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, f32 826 %2 = spv.Select %arg0, %0, %1 : i1, f32 827 return 828} 829 830func @select_op_ptr(%arg0: i1) -> () { 831 %0 = spv.Variable : !spv.ptr<f32, Function> 832 %1 = spv.Variable : !spv.ptr<f32, Function> 833 // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, !spv.ptr<f32, Function> 834 %2 = spv.Select %arg0, %0, %1 : i1, !spv.ptr<f32, Function> 835 return 836} 837 838func @select_op_vec(%arg0: i1) -> () { 839 %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32> 840 %1 = spv.constant dense<[5.0, 6.0, 7.0]> : vector<3xf32> 841 // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, vector<3xf32> 842 %2 = spv.Select %arg0, %0, %1 : i1, vector<3xf32> 843 return 844} 845 846func @select_op_vec_condn_vec(%arg0: vector<3xi1>) -> () { 847 %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32> 848 %1 = spv.constant dense<[5.0, 6.0, 7.0]> : vector<3xf32> 849 // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi1>, vector<3xf32> 850 %2 = spv.Select %arg0, %0, %1 : vector<3xi1>, vector<3xf32> 851 return 852} 853 854// ----- 855 856func @select_op(%arg0: i1) -> () { 857 %0 = spv.constant 2 : i32 858 %1 = spv.constant 3 : i32 859 // expected-error @+1 {{need exactly two trailing types for select condition and object}} 860 %2 = spv.Select %arg0, %0, %1 : i1 861 return 862} 863 864// ----- 865 866func @select_op(%arg1: vector<3xi1>) -> () { 867 %0 = spv.constant 2 : i32 868 %1 = spv.constant 3 : i32 869 // expected-error @+1 {{result expected to be of vector type when condition is of vector type}} 870 %2 = spv.Select %arg1, %0, %1 : vector<3xi1>, i32 871 return 872} 873 874// ----- 875 876func @select_op(%arg1: vector<4xi1>) -> () { 877 %0 = spv.constant dense<[2, 3, 4]> : vector<3xi32> 878 %1 = spv.constant dense<[5, 6, 7]> : vector<3xi32> 879 // expected-error @+1 {{result should have the same number of elements as the condition when condition is of vector type}} 880 %2 = spv.Select %arg1, %0, %1 : vector<4xi1>, vector<3xi32> 881 return 882} 883 884// ----- 885 886func @select_op(%arg1: vector<4xi1>) -> () { 887 %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32> 888 %1 = spv.constant dense<[5, 6, 7]> : vector<3xi32> 889 // expected-error @+1 {{op result type and true value type must be the same}} 890 %2 = "spv.Select"(%arg1, %0, %1) : (vector<4xi1>, vector<3xf32>, vector<3xi32>) -> vector<3xi32> 891 return 892} 893 894// ----- 895 896func @select_op(%arg1: vector<4xi1>) -> () { 897 %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32> 898 %1 = spv.constant dense<[5, 6, 7]> : vector<3xi32> 899 // expected-error @+1 {{op result type and false value type must be the same}} 900 %2 = "spv.Select"(%arg1, %1, %0) : (vector<4xi1>, vector<3xi32>, vector<3xf32>) -> vector<3xi32> 901 return 902} 903 904// ----- 905 906//===----------------------------------------------------------------------===// 907// spv.ShiftLeftLogical 908//===----------------------------------------------------------------------===// 909 910func @shift_left_logical(%arg0: i32, %arg1 : i16) -> i32 { 911 // CHECK: {{%.*}} = spv.ShiftLeftLogical {{%.*}}, {{%.*}} : i32, i16 912 %0 = spv.ShiftLeftLogical %arg0, %arg1: i32, i16 913 spv.ReturnValue %0 : i32 914} 915 916// ----- 917 918func @shift_left_logical_invalid_result_type(%arg0: i32, %arg1 : i16) -> i16 { 919 // expected-error @+1 {{expected the same type for the first operand and result, but provided 'i32' and 'i16'}} 920 %0 = "spv.ShiftLeftLogical" (%arg0, %arg1) : (i32, i16) -> (i16) 921 spv.ReturnValue %0 : i16 922} 923 924// ----- 925 926//===----------------------------------------------------------------------===// 927// spv.ShiftRightArithmetic 928//===----------------------------------------------------------------------===// 929 930func @shift_right_arithmetic(%arg0: vector<4xi32>, %arg1 : vector<4xi8>) -> vector<4xi32> { 931 // CHECK: {{%.*}} = spv.ShiftRightArithmetic {{%.*}}, {{%.*}} : vector<4xi32>, vector<4xi8> 932 %0 = spv.ShiftRightArithmetic %arg0, %arg1: vector<4xi32>, vector<4xi8> 933 spv.ReturnValue %0 : vector<4xi32> 934} 935 936// ----- 937 938//===----------------------------------------------------------------------===// 939// spv.ShiftRightLogical 940//===----------------------------------------------------------------------===// 941 942func @shift_right_logical(%arg0: vector<2xi32>, %arg1 : vector<2xi8>) -> vector<2xi32> { 943 // CHECK: {{%.*}} = spv.ShiftRightLogical {{%.*}}, {{%.*}} : vector<2xi32>, vector<2xi8> 944 %0 = spv.ShiftRightLogical %arg0, %arg1: vector<2xi32>, vector<2xi8> 945 spv.ReturnValue %0 : vector<2xi32> 946} 947 948// ----- 949 950//===----------------------------------------------------------------------===// 951// spv.StoreOp 952//===----------------------------------------------------------------------===// 953 954func @simple_store(%arg0 : f32) -> () { 955 %0 = spv.Variable : !spv.ptr<f32, Function> 956 // CHECK: spv.Store "Function" %0, %arg0 : f32 957 spv.Store "Function" %0, %arg0 : f32 958 return 959} 960 961// CHECK_LABEL: @volatile_store 962func @volatile_store(%arg0 : f32) -> () { 963 %0 = spv.Variable : !spv.ptr<f32, Function> 964 // CHECK: spv.Store "Function" %0, %arg0 ["Volatile"] : f32 965 spv.Store "Function" %0, %arg0 ["Volatile"] : f32 966 return 967} 968 969// CHECK_LABEL: @aligned_store 970func @aligned_store(%arg0 : f32) -> () { 971 %0 = spv.Variable : !spv.ptr<f32, Function> 972 // CHECK: spv.Store "Function" %0, %arg0 ["Aligned", 4] : f32 973 spv.Store "Function" %0, %arg0 ["Aligned", 4] : f32 974 return 975} 976 977// ----- 978 979func @simple_store_missing_ptr_type(%arg0 : f32) -> () { 980 %0 = spv.Variable : !spv.ptr<f32, Function> 981 // expected-error @+1 {{expected non-function type}} 982 spv.Store %0, %arg0 : f32 983 return 984} 985 986// ----- 987 988func @simple_store_missing_operand(%arg0 : f32) -> () { 989 %0 = spv.Variable : !spv.ptr<f32, Function> 990 // expected-error @+1 {{custom op 'spv.Store' invalid operand}} : f32 991 spv.Store "Function" , %arg0 : f32 992 return 993} 994 995// ----- 996 997func @simple_store_missing_operand(%arg0 : f32) -> () { 998 %0 = spv.Variable : !spv.ptr<f32, Function> 999 // expected-error @+1 {{custom op 'spv.Store' expected 2 operands}} : f32 1000 spv.Store "Function" %0 : f32 1001 return 1002} 1003 1004// ----- 1005 1006func @volatile_store_missing_lbrace(%arg0 : f32) -> () { 1007 %0 = spv.Variable : !spv.ptr<f32, Function> 1008 // expected-error @+1 {{expected ':'}} 1009 spv.Store "Function" %0, %arg0 "Volatile"] : f32 1010 return 1011} 1012 1013// ----- 1014 1015func @volatile_store_missing_rbrace(%arg0 : f32) -> () { 1016 %0 = spv.Variable : !spv.ptr<f32, Function> 1017 // expected-error @+1 {{expected ']'}} 1018 spv.Store "Function" %0, %arg0 ["Volatile"} : f32 1019 return 1020} 1021 1022// ----- 1023 1024func @aligned_store_missing_alignment(%arg0 : f32) -> () { 1025 %0 = spv.Variable : !spv.ptr<f32, Function> 1026 // expected-error @+1 {{expected ','}} 1027 spv.Store "Function" %0, %arg0 ["Aligned"] : f32 1028 return 1029} 1030 1031// ----- 1032 1033func @aligned_store_missing_comma(%arg0 : f32) -> () { 1034 %0 = spv.Variable : !spv.ptr<f32, Function> 1035 // expected-error @+1 {{expected ','}} 1036 spv.Store "Function" %0, %arg0 ["Aligned" 4] : f32 1037 return 1038} 1039 1040// ----- 1041 1042func @load_incorrect_attributes(%arg0 : f32) -> () { 1043 %0 = spv.Variable : !spv.ptr<f32, Function> 1044 // expected-error @+1 {{expected ']'}} 1045 spv.Store "Function" %0, %arg0 ["Volatile", 4] : f32 1046 return 1047} 1048 1049// ----- 1050 1051func @aligned_store_incorrect_attributes(%arg0 : f32) -> () { 1052 %0 = spv.Variable : !spv.ptr<f32, Function> 1053 // expected-error @+1 {{expected ']'}} 1054 spv.Store "Function" %0, %arg0 ["Aligned", 4, 23] : f32 1055 return 1056} 1057 1058// ----- 1059 1060spv.module "Logical" "GLSL450" { 1061 spv.globalVariable @var0 : !spv.ptr<f32, Input> 1062 func @simple_store(%arg0 : f32) -> () { 1063 %0 = spv._address_of @var0 : !spv.ptr<f32, Input> 1064 // CHECK: spv.Store "Input" {{%.*}}, {{%.*}} : f32 1065 spv.Store "Input" %0, %arg0 : f32 1066 spv.Return 1067 } 1068} 1069 1070// ----- 1071 1072//===----------------------------------------------------------------------===// 1073// spv.SubgroupBallotKHR 1074//===----------------------------------------------------------------------===// 1075 1076func @subgroup_ballot(%predicate: i1) -> vector<4xi32> { 1077 %0 = spv.SubgroupBallotKHR %predicate: vector<4xi32> 1078 return %0: vector<4xi32> 1079} 1080 1081// ----- 1082 1083//===----------------------------------------------------------------------===// 1084// spv.undef 1085//===----------------------------------------------------------------------===// 1086 1087func @undef() -> () { 1088 %0 = spv.undef : f32 1089 %1 = spv.undef : vector<4xf32> 1090 spv.Return 1091} 1092 1093// ----- 1094 1095func @undef() -> () { 1096 // expected-error @+2{{expected non-function type}} 1097 %0 = spv.undef : 1098 spv.Return 1099} 1100 1101// ----- 1102 1103func @undef() -> () { 1104 // expected-error @+2{{expected ':'}} 1105 %0 = spv.undef 1106 spv.Return 1107} 1108 1109// ----- 1110 1111 1112//===----------------------------------------------------------------------===// 1113// spv.Variable 1114//===----------------------------------------------------------------------===// 1115 1116func @variable(%arg0: f32) -> () { 1117 // CHECK: spv.Variable : !spv.ptr<f32, Function> 1118 %0 = spv.Variable : !spv.ptr<f32, Function> 1119 return 1120} 1121 1122// ----- 1123 1124func @variable_init_normal_constant() -> () { 1125 %0 = spv.constant 4.0 : f32 1126 // CHECK: spv.Variable init(%0) : !spv.ptr<f32, Function> 1127 %1 = spv.Variable init(%0) : !spv.ptr<f32, Function> 1128 return 1129} 1130 1131// ----- 1132 1133spv.module "Logical" "GLSL450" { 1134 spv.globalVariable @global : !spv.ptr<f32, Workgroup> 1135 func @variable_init_global_variable() -> () { 1136 %0 = spv._address_of @global : !spv.ptr<f32, Workgroup> 1137 // CHECK: spv.Variable init({{.*}}) : !spv.ptr<!spv.ptr<f32, Workgroup>, Function> 1138 %1 = spv.Variable init(%0) : !spv.ptr<!spv.ptr<f32, Workgroup>, Function> 1139 spv.Return 1140 } 1141} attributes { 1142 capability = ["VariablePointers"], 1143 extension = ["SPV_KHR_variable_pointers"] 1144} 1145 1146// ----- 1147 1148spv.module "Logical" "GLSL450" { 1149 spv.specConstant @sc = 42 : i32 1150 // CHECK-LABEL: @variable_init_spec_constant 1151 func @variable_init_spec_constant() -> () { 1152 %0 = spv._reference_of @sc : i32 1153 // CHECK: spv.Variable init(%0) : !spv.ptr<i32, Function> 1154 %1 = spv.Variable init(%0) : !spv.ptr<i32, Function> 1155 spv.Return 1156 } 1157} 1158 1159// ----- 1160 1161func @variable_bind() -> () { 1162 // expected-error @+1 {{cannot have 'descriptor_set' attribute (only allowed in spv.globalVariable)}} 1163 %0 = spv.Variable bind(1, 2) : !spv.ptr<f32, Function> 1164 return 1165} 1166 1167// ----- 1168 1169func @variable_init_bind() -> () { 1170 %0 = spv.constant 4.0 : f32 1171 // expected-error @+1 {{cannot have 'binding' attribute (only allowed in spv.globalVariable)}} 1172 %1 = spv.Variable init(%0) {binding = 5 : i32} : !spv.ptr<f32, Function> 1173 return 1174} 1175 1176// ----- 1177 1178func @variable_builtin() -> () { 1179 // expected-error @+1 {{cannot have 'built_in' attribute (only allowed in spv.globalVariable)}} 1180 %1 = spv.Variable built_in("GlobalInvocationID") : !spv.ptr<vector<3xi32>, Function> 1181 return 1182} 1183 1184// ----- 1185 1186func @expect_ptr_result_type(%arg0: f32) -> () { 1187 // expected-error @+1 {{expected spv.ptr type}} 1188 %0 = spv.Variable : f32 1189 return 1190} 1191 1192// ----- 1193 1194func @variable_init(%arg0: f32) -> () { 1195 // expected-error @+1 {{op initializer must be the result of a constant or spv.globalVariable op}} 1196 %0 = spv.Variable init(%arg0) : !spv.ptr<f32, Function> 1197 return 1198} 1199 1200// ----- 1201 1202func @cannot_be_generic_storage_class(%arg0: f32) -> () { 1203 // expected-error @+1 {{op can only be used to model function-level variables. Use spv.globalVariable for module-level variables}} 1204 %0 = spv.Variable : !spv.ptr<f32, Generic> 1205 return 1206} 1207