1// RUN: mlir-opt -split-input-file -verify-diagnostics %s | FileCheck %s 2 3//===----------------------------------------------------------------------===// 4// spirv.AccessChain 5//===----------------------------------------------------------------------===// 6 7func.func @access_chain_struct() -> () { 8 %0 = spirv.Constant 1: i32 9 %1 = spirv.Variable : !spirv.ptr<!spirv.struct<(f32, !spirv.array<4xf32>)>, Function> 10 // CHECK: spirv.AccessChain {{.*}}[{{.*}}, {{.*}}] : !spirv.ptr<!spirv.struct<(f32, !spirv.array<4 x f32>)>, Function> 11 %2 = spirv.AccessChain %1[%0, %0] : !spirv.ptr<!spirv.struct<(f32, !spirv.array<4xf32>)>, Function>, i32, i32 -> !spirv.ptr<f32, Function> 12 return 13} 14 15func.func @access_chain_1D_array(%arg0 : i32) -> () { 16 %0 = spirv.Variable : !spirv.ptr<!spirv.array<4xf32>, Function> 17 // CHECK: spirv.AccessChain {{.*}}[{{.*}}] : !spirv.ptr<!spirv.array<4 x f32>, Function> 18 %1 = spirv.AccessChain %0[%arg0] : !spirv.ptr<!spirv.array<4xf32>, Function>, i32 -> !spirv.ptr<f32, Function> 19 return 20} 21 22func.func @access_chain_2D_array_1(%arg0 : i32) -> () { 23 %0 = spirv.Variable : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function> 24 // CHECK: spirv.AccessChain {{.*}}[{{.*}}, {{.*}}] : !spirv.ptr<!spirv.array<4 x !spirv.array<4 x f32>>, Function> 25 %1 = spirv.AccessChain %0[%arg0, %arg0] : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function>, i32, i32 -> !spirv.ptr<f32, Function> 26 %2 = spirv.Load "Function" %1 ["Volatile"] : f32 27 return 28} 29 30func.func @access_chain_2D_array_2(%arg0 : i32) -> () { 31 %0 = spirv.Variable : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function> 32 // CHECK: spirv.AccessChain {{.*}}[{{.*}}] : !spirv.ptr<!spirv.array<4 x !spirv.array<4 x f32>>, Function> 33 %1 = spirv.AccessChain %0[%arg0] : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function>, i32 -> !spirv.ptr<!spirv.array<4xf32>, Function> 34 %2 = spirv.Load "Function" %1 ["Volatile"] : !spirv.array<4xf32> 35 return 36} 37 38func.func @access_chain_rtarray(%arg0 : i32) -> () { 39 %0 = spirv.Variable : !spirv.ptr<!spirv.rtarray<f32>, Function> 40 // CHECK: spirv.AccessChain {{.*}}[{{.*}}] : !spirv.ptr<!spirv.rtarray<f32>, Function> 41 %1 = spirv.AccessChain %0[%arg0] : !spirv.ptr<!spirv.rtarray<f32>, Function>, i32 -> !spirv.ptr<f32, Function> 42 %2 = spirv.Load "Function" %1 ["Volatile"] : f32 43 return 44} 45 46// ----- 47 48func.func @access_chain_non_composite() -> () { 49 %0 = spirv.Constant 1: i32 50 %1 = spirv.Variable : !spirv.ptr<f32, Function> 51 // expected-error @+1 {{cannot extract from non-composite type 'f32' with index 0}} 52 %2 = spirv.AccessChain %1[%0] : !spirv.ptr<f32, Function>, i32 -> !spirv.ptr<f32, Function> 53 return 54} 55 56// ----- 57 58func.func @access_chain_no_indices(%index0 : i32) -> () { 59 %0 = spirv.Variable : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function> 60 // expected-error @+1 {{custom op 'spirv.AccessChain' number of operands and types do not match: got 0 operands and 1 types}} 61 %1 = spirv.AccessChain %0[] : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function>, i32 -> !spirv.ptr<f32, Function> 62 return 63} 64 65// ----- 66 67func.func @access_chain_missing_comma(%index0 : i32) -> () { 68 %0 = spirv.Variable : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function> 69 // expected-error @+1 {{expected ','}} 70 %1 = spirv.AccessChain %0[%index0] : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function> i32 71 return 72} 73 74// ----- 75 76func.func @access_chain_invalid_indices_types_count(%index0 : i32) -> () { 77 %0 = spirv.Variable : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function> 78 // expected-error @+1 {{custom op 'spirv.AccessChain' number of operands and types do not match: got 1 operands and 2 types}} 79 %1 = spirv.AccessChain %0[%index0] : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function>, i32, i32 -> !spirv.ptr<!spirv.array<4xf32>, Function> 80 return 81} 82 83// ----- 84 85func.func @access_chain_missing_indices_type(%index0 : i32) -> () { 86 %0 = spirv.Variable : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function> 87 // expected-error @+1 {{custom op 'spirv.AccessChain' number of operands and types do not match: got 2 operands and 1 types}} 88 %1 = spirv.AccessChain %0[%index0, %index0] : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function>, i32 -> !spirv.ptr<f32, Function> 89 return 90} 91 92// ----- 93 94func.func @access_chain_invalid_type(%index0 : i32) -> () { 95 %0 = spirv.Variable : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function> 96 %1 = spirv.Load "Function" %0 ["Volatile"] : !spirv.array<4x!spirv.array<4xf32>> 97 // expected-error @+1 {{'spirv.AccessChain' op operand #0 must be any SPIR-V pointer type, but got '!spirv.array<4 x !spirv.array<4 x f32>>'}} 98 %2 = spirv.AccessChain %1[%index0] : !spirv.array<4x!spirv.array<4xf32>>, i32 -> f32 99 return 100} 101 102// ----- 103 104func.func @access_chain_invalid_index_1(%index0 : i32) -> () { 105 %0 = spirv.Variable : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function> 106 // expected-error @+1 {{expected SSA operand}} 107 %1 = spirv.AccessChain %0[%index, 4] : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function>, i32, i32 108 return 109} 110 111// ----- 112 113func.func @access_chain_invalid_index_2(%index0 : i32) -> () { 114 %0 = spirv.Variable : !spirv.ptr<!spirv.struct<(f32, !spirv.array<4xf32>)>, Function> 115 // expected-error @+1 {{index must be an integer spirv.Constant to access element of spirv.struct}} 116 %1 = spirv.AccessChain %0[%index0, %index0] : !spirv.ptr<!spirv.struct<(f32, !spirv.array<4xf32>)>, Function>, i32, i32 -> !spirv.ptr<f32, Function> 117 return 118} 119 120// ----- 121 122func.func @access_chain_invalid_constant_type_1() -> () { 123 %0 = arith.constant 1: i32 124 %1 = spirv.Variable : !spirv.ptr<!spirv.struct<(f32, !spirv.array<4xf32>)>, Function> 125 // expected-error @+1 {{index must be an integer spirv.Constant to access element of spirv.struct, but provided arith.constant}} 126 %2 = spirv.AccessChain %1[%0, %0] : !spirv.ptr<!spirv.struct<(f32, !spirv.array<4xf32>)>, Function>, i32, i32 -> !spirv.ptr<f32, Function> 127 return 128} 129 130// ----- 131 132func.func @access_chain_out_of_bounds() -> () { 133 %index0 = "spirv.Constant"() { value = 12: i32} : () -> i32 134 %0 = spirv.Variable : !spirv.ptr<!spirv.struct<(f32, !spirv.array<4xf32>)>, Function> 135 // expected-error @+1 {{'spirv.AccessChain' op index 12 out of bounds for '!spirv.struct<(f32, !spirv.array<4 x f32>)>'}} 136 %1 = spirv.AccessChain %0[%index0, %index0] : !spirv.ptr<!spirv.struct<(f32, !spirv.array<4xf32>)>, Function>, i32, i32 -> !spirv.ptr<f32, Function> 137 return 138} 139 140// ----- 141 142func.func @access_chain_invalid_accessing_type(%index0 : i32) -> () { 143 %0 = spirv.Variable : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function> 144 // expected-error @+1 {{cannot extract from non-composite type 'f32' with index 0}} 145 %1 = spirv.AccessChain %0[%index0, %index0, %index0] : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function>, i32, i32, i32 -> !spirv.ptr<f32, Function> 146 return 147} 148// ----- 149 150//===----------------------------------------------------------------------===// 151// spirv.LoadOp 152//===----------------------------------------------------------------------===// 153 154// CHECK-LABEL: @simple_load 155func.func @simple_load() -> () { 156 %0 = spirv.Variable : !spirv.ptr<f32, Function> 157 // CHECK: spirv.Load "Function" %{{.*}} : f32 158 %1 = spirv.Load "Function" %0 : f32 159 return 160} 161 162// CHECK-LABEL: @load_none_access 163func.func @load_none_access() -> () { 164 %0 = spirv.Variable : !spirv.ptr<f32, Function> 165 // CHECK: spirv.Load "Function" %{{.*}} ["None"] : f32 166 %1 = spirv.Load "Function" %0 ["None"] : f32 167 return 168} 169 170// CHECK-LABEL: @volatile_load 171func.func @volatile_load() -> () { 172 %0 = spirv.Variable : !spirv.ptr<f32, Function> 173 // CHECK: spirv.Load "Function" %{{.*}} ["Volatile"] : f32 174 %1 = spirv.Load "Function" %0 ["Volatile"] : f32 175 return 176} 177 178// CHECK-LABEL: @aligned_load 179func.func @aligned_load() -> () { 180 %0 = spirv.Variable : !spirv.ptr<f32, Function> 181 // CHECK: spirv.Load "Function" %{{.*}} ["Aligned", 4] : f32 182 %1 = spirv.Load "Function" %0 ["Aligned", 4] : f32 183 return 184} 185 186// CHECK-LABEL: @volatile_aligned_load 187func.func @volatile_aligned_load() -> () { 188 %0 = spirv.Variable : !spirv.ptr<f32, Function> 189 // CHECK: spirv.Load "Function" %{{.*}} ["Volatile|Aligned", 4] : f32 190 %1 = spirv.Load "Function" %0 ["Volatile|Aligned", 4] : f32 191 return 192} 193 194// ----- 195 196// CHECK-LABEL: load_none_access 197func.func @load_none_access() -> () { 198 %0 = spirv.Variable : !spirv.ptr<f32, Function> 199 // CHECK: spirv.Load 200 // CHECK-SAME: ["None"] 201 %1 = "spirv.Load"(%0) {memory_access = #spirv.memory_access<None>} : (!spirv.ptr<f32, Function>) -> (f32) 202 return 203} 204 205// CHECK-LABEL: volatile_load 206func.func @volatile_load() -> () { 207 %0 = spirv.Variable : !spirv.ptr<f32, Function> 208 // CHECK: spirv.Load 209 // CHECK-SAME: ["Volatile"] 210 %1 = "spirv.Load"(%0) {memory_access = #spirv.memory_access<Volatile>} : (!spirv.ptr<f32, Function>) -> (f32) 211 return 212} 213 214// CHECK-LABEL: aligned_load 215func.func @aligned_load() -> () { 216 %0 = spirv.Variable : !spirv.ptr<f32, Function> 217 // CHECK: spirv.Load 218 // CHECK-SAME: ["Aligned", 4] 219 %1 = "spirv.Load"(%0) {memory_access = #spirv.memory_access<Aligned>, alignment = 4 : i32} : (!spirv.ptr<f32, Function>) -> (f32) 220 return 221} 222 223// CHECK-LABEL: volatile_aligned_load 224func.func @volatile_aligned_load() -> () { 225 %0 = spirv.Variable : !spirv.ptr<f32, Function> 226 // CHECK: spirv.Load 227 // CHECK-SAME: ["Volatile|Aligned", 4] 228 %1 = "spirv.Load"(%0) {memory_access = #spirv.memory_access<Volatile|Aligned>, alignment = 4 : i32} : (!spirv.ptr<f32, Function>) -> (f32) 229 return 230} 231 232// ----- 233 234func.func @simple_load_missing_storageclass() -> () { 235 %0 = spirv.Variable : !spirv.ptr<f32, Function> 236 // expected-error @+1 {{expected attribute value}} 237 %1 = spirv.Load %0 : f32 238 return 239} 240 241// ----- 242 243func.func @simple_load_missing_operand() -> () { 244 %0 = spirv.Variable : !spirv.ptr<f32, Function> 245 // expected-error @+1 {{expected SSA operand}} 246 %1 = spirv.Load "Function" : f32 247 return 248} 249 250// ----- 251 252func.func @simple_load_missing_rettype() -> () { 253 %0 = spirv.Variable : !spirv.ptr<f32, Function> 254 // expected-error @+1 {{expected ':'}} 255 %1 = spirv.Load "Function" %0 256 return 257} 258 259// ----- 260 261func.func @volatile_load_missing_lbrace() -> () { 262 %0 = spirv.Variable : !spirv.ptr<f32, Function> 263 // expected-error @+1 {{expected ':'}} 264 %1 = spirv.Load "Function" %0 "Volatile"] : f32 265 return 266} 267 268// ----- 269 270func.func @volatile_load_missing_rbrace() -> () { 271 %0 = spirv.Variable : !spirv.ptr<f32, Function> 272 // expected-error @+1 {{expected ']'}} 273 %1 = spirv.Load "Function" %0 ["Volatile"} : f32 274 return 275} 276 277// ----- 278 279func.func @aligned_load_missing_alignment() -> () { 280 %0 = spirv.Variable : !spirv.ptr<f32, Function> 281 // expected-error @+1 {{expected ','}} 282 %1 = spirv.Load "Function" %0 ["Aligned"] : f32 283 return 284} 285 286// ----- 287 288func.func @aligned_load_missing_comma() -> () { 289 %0 = spirv.Variable : !spirv.ptr<f32, Function> 290 // expected-error @+1 {{expected ','}} 291 %1 = spirv.Load "Function" %0 ["Aligned" 4] : f32 292 return 293} 294 295// ----- 296 297func.func @load_incorrect_attributes() -> () { 298 %0 = spirv.Variable : !spirv.ptr<f32, Function> 299 // expected-error @+1 {{expected ']'}} 300 %1 = spirv.Load "Function" %0 ["Volatile", 4] : f32 301 return 302} 303 304// ----- 305 306func.func @load_unknown_memory_access() -> () { 307 %0 = spirv.Variable : !spirv.ptr<f32, Function> 308 // expected-error @+1 {{custom op 'spirv.Load' invalid memory_access attribute specification: "Something"}} 309 %1 = spirv.Load "Function" %0 ["Something"] : f32 310 return 311} 312 313// ----- 314 315func.func @load_unknown_memory_access() -> () { 316 %0 = spirv.Variable : !spirv.ptr<f32, Function> 317 // expected-error @+1 {{custom op 'spirv.Load' invalid memory_access attribute specification: "Volatile|Something"}} 318 %1 = spirv.Load "Function" %0 ["Volatile|Something"] : f32 319 return 320} 321 322// ----- 323 324func.func @load_unknown_memory_access() -> () { 325 %0 = spirv.Variable : !spirv.ptr<f32, Function> 326 // expected-error @+1 {{failed to satisfy constraint: valid SPIR-V MemoryAccess}} 327 %1 = "spirv.Load"(%0) {memory_access = 0x80000000 : i32} : (!spirv.ptr<f32, Function>) -> (f32) 328 return 329} 330 331// ----- 332 333func.func @aligned_load_incorrect_attributes() -> () { 334 %0 = spirv.Variable : !spirv.ptr<f32, Function> 335 // expected-error @+1 {{expected ']'}} 336 %1 = spirv.Load "Function" %0 ["Aligned", 4, 23] : f32 337 return 338} 339 340// ----- 341 342spirv.module Logical GLSL450 { 343 spirv.GlobalVariable @var0 : !spirv.ptr<f32, Input> 344 spirv.GlobalVariable @var1 : !spirv.ptr<!spirv.sampled_image<!spirv.image<f32, Dim2D, IsDepth, Arrayed, SingleSampled, NeedSampler, Unknown>>, UniformConstant> 345 // CHECK-LABEL: @simple_load 346 spirv.func @simple_load() -> () "None" { 347 // CHECK: spirv.Load "Input" {{%.*}} : f32 348 %0 = spirv.mlir.addressof @var0 : !spirv.ptr<f32, Input> 349 %1 = spirv.Load "Input" %0 : f32 350 %2 = spirv.mlir.addressof @var1 : !spirv.ptr<!spirv.sampled_image<!spirv.image<f32, Dim2D, IsDepth, Arrayed, SingleSampled, NeedSampler, Unknown>>, UniformConstant> 351 // CHECK: spirv.Load "UniformConstant" {{%.*}} : !spirv.sampled_image 352 %3 = spirv.Load "UniformConstant" %2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, IsDepth, Arrayed, SingleSampled, NeedSampler, Unknown>> 353 spirv.Return 354 } 355} 356 357// ----- 358 359//===----------------------------------------------------------------------===// 360// spirv.StoreOp 361//===----------------------------------------------------------------------===// 362 363func.func @simple_store(%arg0 : f32) -> () { 364 %0 = spirv.Variable : !spirv.ptr<f32, Function> 365 // CHECK: spirv.Store "Function" %0, %arg0 : f32 366 spirv.Store "Function" %0, %arg0 : f32 367 return 368} 369 370// CHECK-LABEL: @volatile_store 371func.func @volatile_store(%arg0 : f32) -> () { 372 %0 = spirv.Variable : !spirv.ptr<f32, Function> 373 // CHECK: spirv.Store "Function" %0, %arg0 ["Volatile"] : f32 374 spirv.Store "Function" %0, %arg0 ["Volatile"] : f32 375 return 376} 377 378// CHECK-LABEL: @aligned_store 379func.func @aligned_store(%arg0 : f32) -> () { 380 %0 = spirv.Variable : !spirv.ptr<f32, Function> 381 // CHECK: spirv.Store "Function" %0, %arg0 ["Aligned", 4] : f32 382 spirv.Store "Function" %0, %arg0 ["Aligned", 4] : f32 383 return 384} 385 386// ----- 387 388func.func @simple_store_missing_ptr_type(%arg0 : f32) -> () { 389 %0 = spirv.Variable : !spirv.ptr<f32, Function> 390 // expected-error @+1 {{expected attribute value}} 391 spirv.Store %0, %arg0 : f32 392 return 393} 394 395// ----- 396 397func.func @simple_store_missing_operand(%arg0 : f32) -> () { 398 %0 = spirv.Variable : !spirv.ptr<f32, Function> 399 // expected-error @+1 {{expected operand}} 400 spirv.Store "Function" , %arg0 : f32 401 return 402} 403 404// ----- 405 406func.func @simple_store_missing_operand(%arg0 : f32) -> () { 407 %0 = spirv.Variable : !spirv.ptr<f32, Function> 408 // expected-error @+1 {{custom op 'spirv.Store' expected 2 operands}} 409 spirv.Store "Function" %0 : f32 410 return 411} 412 413// ----- 414 415func.func @volatile_store_missing_lbrace(%arg0 : f32) -> () { 416 %0 = spirv.Variable : !spirv.ptr<f32, Function> 417 // expected-error @+1 {{expected ':'}} 418 spirv.Store "Function" %0, %arg0 "Volatile"] : f32 419 return 420} 421 422// ----- 423 424func.func @volatile_store_missing_rbrace(%arg0 : f32) -> () { 425 %0 = spirv.Variable : !spirv.ptr<f32, Function> 426 // expected-error @+1 {{expected ']'}} 427 spirv.Store "Function" %0, %arg0 ["Volatile"} : f32 428 return 429} 430 431// ----- 432 433func.func @aligned_store_missing_alignment(%arg0 : f32) -> () { 434 %0 = spirv.Variable : !spirv.ptr<f32, Function> 435 // expected-error @+1 {{expected ','}} 436 spirv.Store "Function" %0, %arg0 ["Aligned"] : f32 437 return 438} 439 440// ----- 441 442func.func @aligned_store_missing_comma(%arg0 : f32) -> () { 443 %0 = spirv.Variable : !spirv.ptr<f32, Function> 444 // expected-error @+1 {{expected ','}} 445 spirv.Store "Function" %0, %arg0 ["Aligned" 4] : f32 446 return 447} 448 449// ----- 450 451func.func @load_incorrect_attributes(%arg0 : f32) -> () { 452 %0 = spirv.Variable : !spirv.ptr<f32, Function> 453 // expected-error @+1 {{expected ']'}} 454 spirv.Store "Function" %0, %arg0 ["Volatile", 4] : f32 455 return 456} 457 458// ----- 459 460func.func @aligned_store_incorrect_attributes(%arg0 : f32) -> () { 461 %0 = spirv.Variable : !spirv.ptr<f32, Function> 462 // expected-error @+1 {{expected ']'}} 463 spirv.Store "Function" %0, %arg0 ["Aligned", 4, 23] : f32 464 return 465} 466 467// ----- 468 469spirv.module Logical GLSL450 { 470 spirv.GlobalVariable @var0 : !spirv.ptr<f32, Input> 471 spirv.func @simple_store(%arg0 : f32) -> () "None" { 472 %0 = spirv.mlir.addressof @var0 : !spirv.ptr<f32, Input> 473 // CHECK: spirv.Store "Input" {{%.*}}, {{%.*}} : f32 474 spirv.Store "Input" %0, %arg0 : f32 475 spirv.Return 476 } 477} 478 479// ----- 480 481//===----------------------------------------------------------------------===// 482// spirv.Variable 483//===----------------------------------------------------------------------===// 484 485func.func @variable(%arg0: f32) -> () { 486 // CHECK: spirv.Variable : !spirv.ptr<f32, Function> 487 %0 = spirv.Variable : !spirv.ptr<f32, Function> 488 return 489} 490 491// ----- 492 493func.func @variable_init_normal_constant() -> () { 494 // CHECK: %[[cst:.*]] = spirv.Constant 495 %0 = spirv.Constant 4.0 : f32 496 // CHECK: spirv.Variable init(%[[cst]]) : !spirv.ptr<f32, Function> 497 %1 = spirv.Variable init(%0) : !spirv.ptr<f32, Function> 498 return 499} 500 501// ----- 502 503spirv.module Logical GLSL450 { 504 spirv.GlobalVariable @global : !spirv.ptr<f32, Workgroup> 505 spirv.func @variable_init_global_variable() -> () "None" { 506 %0 = spirv.mlir.addressof @global : !spirv.ptr<f32, Workgroup> 507 // CHECK: spirv.Variable init({{.*}}) : !spirv.ptr<!spirv.ptr<f32, Workgroup>, Function> 508 %1 = spirv.Variable init(%0) : !spirv.ptr<!spirv.ptr<f32, Workgroup>, Function> 509 spirv.Return 510 } 511} 512 513// ----- 514 515spirv.module Logical GLSL450 { 516 spirv.SpecConstant @sc = 42 : i32 517 // CHECK-LABEL: @variable_init_spec_constant 518 spirv.func @variable_init_spec_constant() -> () "None" { 519 %0 = spirv.mlir.referenceof @sc : i32 520 // CHECK: spirv.Variable init(%0) : !spirv.ptr<i32, Function> 521 %1 = spirv.Variable init(%0) : !spirv.ptr<i32, Function> 522 spirv.Return 523 } 524} 525 526// ----- 527 528func.func @variable_ptr_physical_buffer() -> () { 529 %0 = spirv.Variable {aliased_pointer} : 530 !spirv.ptr<!spirv.ptr<f32, PhysicalStorageBuffer>, Function> 531 %1 = spirv.Variable {restrict_pointer} : 532 !spirv.ptr<!spirv.ptr<f32, PhysicalStorageBuffer>, Function> 533 return 534} 535 536// ----- 537 538func.func @variable_ptr_physical_buffer_no_decoration() -> () { 539 // expected-error @+1 {{must be decorated either 'AliasedPointer' or 'RestrictPointer'}} 540 %0 = spirv.Variable : !spirv.ptr<!spirv.ptr<f32, PhysicalStorageBuffer>, Function> 541 return 542} 543 544// ----- 545 546func.func @variable_ptr_physical_buffer_two_alias_decorations() -> () { 547 // expected-error @+1 {{must have exactly one aliasing decoration}} 548 %0 = spirv.Variable {aliased_pointer, restrict_pointer} : 549 !spirv.ptr<!spirv.ptr<f32, PhysicalStorageBuffer>, Function> 550 return 551} 552 553// ----- 554 555func.func @variable_ptr_array_physical_buffer() -> () { 556 %0 = spirv.Variable {aliased_pointer} : 557 !spirv.ptr<!spirv.array<4x!spirv.ptr<f32, PhysicalStorageBuffer>>, Function> 558 %1 = spirv.Variable {restrict_pointer} : 559 !spirv.ptr<!spirv.array<4x!spirv.ptr<f32, PhysicalStorageBuffer>>, Function> 560 return 561} 562 563// ----- 564 565func.func @variable_ptr_array_physical_buffer_no_decoration() -> () { 566 // expected-error @+1 {{must be decorated either 'AliasedPointer' or 'RestrictPointer'}} 567 %0 = spirv.Variable : 568 !spirv.ptr<!spirv.array<4x!spirv.ptr<f32, PhysicalStorageBuffer>>, Function> 569 return 570} 571 572// ----- 573 574func.func @variable_ptr_array_physical_buffer_two_alias_decorations() -> () { 575 // expected-error @+1 {{must have exactly one aliasing decoration}} 576 %0 = spirv.Variable {aliased_pointer, restrict_pointer} : 577 !spirv.ptr<!spirv.array<4x!spirv.ptr<f32, PhysicalStorageBuffer>>, Function> 578 return 579} 580 581// ----- 582 583func.func @variable_bind() -> () { 584 // expected-error @+1 {{cannot have 'descriptor_set' attribute (only allowed in spirv.GlobalVariable)}} 585 %0 = spirv.Variable bind(1, 2) : !spirv.ptr<f32, Function> 586 return 587} 588 589// ----- 590 591func.func @variable_init_bind() -> () { 592 %0 = spirv.Constant 4.0 : f32 593 // expected-error @+1 {{cannot have 'binding' attribute (only allowed in spirv.GlobalVariable)}} 594 %1 = spirv.Variable init(%0) {binding = 5 : i32} : !spirv.ptr<f32, Function> 595 return 596} 597 598// ----- 599 600func.func @variable_builtin() -> () { 601 // expected-error @+1 {{cannot have 'built_in' attribute (only allowed in spirv.GlobalVariable)}} 602 %1 = spirv.Variable built_in("GlobalInvocationID") : !spirv.ptr<vector<3xi32>, Function> 603 return 604} 605 606// ----- 607 608func.func @expect_ptr_result_type(%arg0: f32) -> () { 609 // expected-error @+1 {{expected spirv.ptr type}} 610 %0 = spirv.Variable : f32 611 return 612} 613 614// ----- 615 616func.func @variable_init(%arg0: f32) -> () { 617 // expected-error @+1 {{op initializer must be the result of a constant or spirv.GlobalVariable op}} 618 %0 = spirv.Variable init(%arg0) : !spirv.ptr<f32, Function> 619 return 620} 621 622// ----- 623 624func.func @cannot_be_generic_storage_class(%arg0: f32) -> () { 625 // expected-error @+1 {{op can only be used to model function-level variables. Use spirv.GlobalVariable for module-level variables}} 626 %0 = spirv.Variable : !spirv.ptr<f32, Generic> 627 return 628} 629 630// ----- 631 632func.func @copy_memory_incompatible_ptrs() { 633 %0 = spirv.Variable : !spirv.ptr<f32, Function> 634 %1 = spirv.Variable : !spirv.ptr<i32, Function> 635 // expected-error @+1 {{both operands must be pointers to the same type}} 636 "spirv.CopyMemory"(%0, %1) {} : (!spirv.ptr<f32, Function>, !spirv.ptr<i32, Function>) -> () 637 spirv.Return 638} 639 640// ----- 641 642func.func @copy_memory_invalid_maa() { 643 %0 = spirv.Variable : !spirv.ptr<f32, Function> 644 %1 = spirv.Variable : !spirv.ptr<f32, Function> 645 // expected-error @+1 {{missing alignment value}} 646 "spirv.CopyMemory"(%0, %1) {memory_access=#spirv.memory_access<Aligned>} : (!spirv.ptr<f32, Function>, !spirv.ptr<f32, Function>) -> () 647 spirv.Return 648} 649 650// ----- 651 652func.func @copy_memory_invalid_source_maa() { 653 %0 = spirv.Variable : !spirv.ptr<f32, Function> 654 %1 = spirv.Variable : !spirv.ptr<f32, Function> 655 // expected-error @+1 {{invalid alignment specification with non-aligned memory access specification}} 656 "spirv.CopyMemory"(%0, %1) {source_memory_access=#spirv.memory_access<Volatile>, memory_access=#spirv.memory_access<Aligned>, source_alignment=8 : i32, alignment=4 : i32} : (!spirv.ptr<f32, Function>, !spirv.ptr<f32, Function>) -> () 657 spirv.Return 658} 659 660// ----- 661 662func.func @copy_memory_invalid_source_maa2() { 663 %0 = spirv.Variable : !spirv.ptr<f32, Function> 664 %1 = spirv.Variable : !spirv.ptr<f32, Function> 665 // expected-error @+1 {{missing alignment value}} 666 "spirv.CopyMemory"(%0, %1) {source_memory_access=#spirv.memory_access<Aligned>, memory_access=#spirv.memory_access<Aligned>, alignment=4 : i32} : (!spirv.ptr<f32, Function>, !spirv.ptr<f32, Function>) -> () 667 spirv.Return 668} 669 670// ----- 671 672func.func @copy_memory_print_maa() { 673 %0 = spirv.Variable : !spirv.ptr<f32, Function> 674 %1 = spirv.Variable : !spirv.ptr<f32, Function> 675 676 // CHECK: spirv.CopyMemory "Function" %{{.*}}, "Function" %{{.*}} ["Volatile"] : f32 677 "spirv.CopyMemory"(%0, %1) {memory_access=#spirv.memory_access<Volatile>} : (!spirv.ptr<f32, Function>, !spirv.ptr<f32, Function>) -> () 678 679 // CHECK: spirv.CopyMemory "Function" %{{.*}}, "Function" %{{.*}} ["Aligned", 4] : f32 680 "spirv.CopyMemory"(%0, %1) {memory_access=#spirv.memory_access<Aligned>, alignment=4 : i32} : (!spirv.ptr<f32, Function>, !spirv.ptr<f32, Function>) -> () 681 682 // CHECK: spirv.CopyMemory "Function" %{{.*}}, "Function" %{{.*}} ["Aligned", 4], ["Volatile"] : f32 683 "spirv.CopyMemory"(%0, %1) {source_memory_access=#spirv.memory_access<Volatile>, memory_access=#spirv.memory_access<Aligned>, alignment=4 : i32} : (!spirv.ptr<f32, Function>, !spirv.ptr<f32, Function>) -> () 684 685 // CHECK: spirv.CopyMemory "Function" %{{.*}}, "Function" %{{.*}} ["Aligned", 4], ["Aligned", 8] : f32 686 "spirv.CopyMemory"(%0, %1) {source_memory_access=#spirv.memory_access<Aligned>, memory_access=#spirv.memory_access<Aligned>, source_alignment=8 : i32, alignment=4 : i32} : (!spirv.ptr<f32, Function>, !spirv.ptr<f32, Function>) -> () 687 688 spirv.Return 689} 690 691// ----- 692 693//===----------------------------------------------------------------------===// 694// spirv.PtrAccessChain 695//===----------------------------------------------------------------------===// 696 697// CHECK-LABEL: func @ptr_access_chain1( 698// CHECK-SAME: %[[ARG0:.*]]: !spirv.ptr<f32, CrossWorkgroup>, 699// CHECK-SAME: %[[ARG1:.*]]: i64) 700// CHECK: spirv.PtrAccessChain %[[ARG0]][%[[ARG1]]] : !spirv.ptr<f32, CrossWorkgroup>, i64 701func.func @ptr_access_chain1(%arg0: !spirv.ptr<f32, CrossWorkgroup>, %arg1 : i64) -> () { 702 %0 = spirv.PtrAccessChain %arg0[%arg1] : !spirv.ptr<f32, CrossWorkgroup>, i64 -> !spirv.ptr<f32, CrossWorkgroup> 703 return 704} 705 706// ----- 707 708//===----------------------------------------------------------------------===// 709// spirv.InBoundsPtrAccessChain 710//===----------------------------------------------------------------------===// 711 712// CHECK-LABEL: func @inbounds_ptr_access_chain1( 713// CHECK-SAME: %[[ARG0:.*]]: !spirv.ptr<f32, CrossWorkgroup>, 714// CHECK-SAME: %[[ARG1:.*]]: i64) 715// CHECK: spirv.InBoundsPtrAccessChain %[[ARG0]][%[[ARG1]]] : !spirv.ptr<f32, CrossWorkgroup>, i64 716func.func @inbounds_ptr_access_chain1(%arg0: !spirv.ptr<f32, CrossWorkgroup>, %arg1 : i64) -> () { 717 %0 = spirv.InBoundsPtrAccessChain %arg0[%arg1] : !spirv.ptr<f32, CrossWorkgroup>, i64 -> !spirv.ptr<f32, CrossWorkgroup> 718 return 719} 720