1// RUN: mlir-opt %s -split-input-file -pass-pipeline='builtin.module(func.func(canonicalize{test-convergence region-simplify=aggressive}))' | FileCheck %s 2 3//===----------------------------------------------------------------------===// 4// spirv.AccessChain 5//===----------------------------------------------------------------------===// 6 7func.func @combine_full_access_chain() -> f32 { 8 // CHECK: %[[INDEX:.*]] = spirv.Constant 0 9 // CHECK-NEXT: %[[VAR:.*]] = spirv.Variable 10 // CHECK-NEXT: %[[PTR:.*]] = spirv.AccessChain %[[VAR]][%[[INDEX]], %[[INDEX]], %[[INDEX]]] 11 // CHECK-NEXT: spirv.Load "Function" %[[PTR]] 12 %c0 = spirv.Constant 0: i32 13 %0 = spirv.Variable : !spirv.ptr<!spirv.struct<(!spirv.array<4x!spirv.array<4xf32>>, !spirv.array<4xi32>)>, Function> 14 %1 = spirv.AccessChain %0[%c0] : !spirv.ptr<!spirv.struct<(!spirv.array<4x!spirv.array<4xf32>>, !spirv.array<4xi32>)>, Function>, i32 -> !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function> 15 %2 = spirv.AccessChain %1[%c0, %c0] : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function>, i32, i32 -> !spirv.ptr<f32, Function> 16 %3 = spirv.Load "Function" %2 : f32 17 spirv.ReturnValue %3 : f32 18} 19 20// ----- 21 22func.func @combine_access_chain_multi_use() -> !spirv.array<4xf32> { 23 // CHECK: %[[INDEX:.*]] = spirv.Constant 0 24 // CHECK-NEXT: %[[VAR:.*]] = spirv.Variable 25 // CHECK-NEXT: %[[PTR_0:.*]] = spirv.AccessChain %[[VAR]][%[[INDEX]], %[[INDEX]]] 26 // CHECK-NEXT: %[[PTR_1:.*]] = spirv.AccessChain %[[VAR]][%[[INDEX]], %[[INDEX]], %[[INDEX]]] 27 // CHECK-NEXT: spirv.Load "Function" %[[PTR_0]] 28 // CHECK-NEXT: spirv.Load "Function" %[[PTR_1]] 29 %c0 = spirv.Constant 0: i32 30 %0 = spirv.Variable : !spirv.ptr<!spirv.struct<(!spirv.array<4x!spirv.array<4xf32>>, !spirv.array<4xi32>)>, Function> 31 %1 = spirv.AccessChain %0[%c0] : !spirv.ptr<!spirv.struct<(!spirv.array<4x!spirv.array<4xf32>>, !spirv.array<4xi32>)>, Function>, i32 -> !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function> 32 %2 = spirv.AccessChain %1[%c0] : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function>, i32 -> !spirv.ptr<!spirv.array<4xf32>, Function> 33 %3 = spirv.AccessChain %2[%c0] : !spirv.ptr<!spirv.array<4xf32>, Function>, i32 -> !spirv.ptr<f32, Function> 34 %4 = spirv.Load "Function" %2 : !spirv.array<4xf32> 35 %5 = spirv.Load "Function" %3 : f32 36 spirv.ReturnValue %4: !spirv.array<4xf32> 37} 38 39// ----- 40 41func.func @dont_combine_access_chain_without_common_base() -> !spirv.array<4xi32> { 42 // CHECK: %[[INDEX:.*]] = spirv.Constant 1 43 // CHECK-NEXT: %[[VAR_0:.*]] = spirv.Variable 44 // CHECK-NEXT: %[[VAR_1:.*]] = spirv.Variable 45 // CHECK-NEXT: %[[VAR_0_PTR:.*]] = spirv.AccessChain %[[VAR_0]][%[[INDEX]]] 46 // CHECK-NEXT: %[[VAR_1_PTR:.*]] = spirv.AccessChain %[[VAR_1]][%[[INDEX]]] 47 // CHECK-NEXT: spirv.Load "Function" %[[VAR_0_PTR]] 48 // CHECK-NEXT: spirv.Load "Function" %[[VAR_1_PTR]] 49 %c1 = spirv.Constant 1: i32 50 %0 = spirv.Variable : !spirv.ptr<!spirv.struct<(!spirv.array<4x!spirv.array<4xf32>>, !spirv.array<4xi32>)>, Function> 51 %1 = spirv.Variable : !spirv.ptr<!spirv.struct<(!spirv.array<4x!spirv.array<4xf32>>, !spirv.array<4xi32>)>, Function> 52 %2 = spirv.AccessChain %0[%c1] : !spirv.ptr<!spirv.struct<(!spirv.array<4x!spirv.array<4xf32>>, !spirv.array<4xi32>)>, Function>, i32 -> !spirv.ptr<!spirv.array<4xi32>, Function> 53 %3 = spirv.AccessChain %1[%c1] : !spirv.ptr<!spirv.struct<(!spirv.array<4x!spirv.array<4xf32>>, !spirv.array<4xi32>)>, Function>, i32 -> !spirv.ptr<!spirv.array<4xi32>, Function> 54 %4 = spirv.Load "Function" %2 : !spirv.array<4xi32> 55 %5 = spirv.Load "Function" %3 : !spirv.array<4xi32> 56 spirv.ReturnValue %4 : !spirv.array<4xi32> 57} 58 59// ----- 60 61//===----------------------------------------------------------------------===// 62// spirv.Bitcast 63//===----------------------------------------------------------------------===// 64 65func.func @convert_bitcast_full(%arg0 : vector<2xf32>) -> f64 { 66 // CHECK: %[[RESULT:.*]] = spirv.Bitcast {{%.*}} : vector<2xf32> to f64 67 // CHECK-NEXT: spirv.ReturnValue %[[RESULT]] 68 %0 = spirv.Bitcast %arg0 : vector<2xf32> to vector<2xi32> 69 %1 = spirv.Bitcast %0 : vector<2xi32> to i64 70 %2 = spirv.Bitcast %1 : i64 to f64 71 spirv.ReturnValue %2 : f64 72} 73 74// ----- 75 76func.func @convert_bitcast_multi_use(%arg0 : vector<2xf32>, %arg1 : !spirv.ptr<i64, Uniform>) -> f64 { 77 // CHECK: %[[RESULT_0:.*]] = spirv.Bitcast {{%.*}} : vector<2xf32> to i64 78 // CHECK-NEXT: %[[RESULT_1:.*]] = spirv.Bitcast {{%.*}} : vector<2xf32> to f64 79 // CHECK-NEXT: spirv.Store {{".*"}} {{%.*}}, %[[RESULT_0]] 80 // CHECK-NEXT: spirv.ReturnValue %[[RESULT_1]] 81 %0 = spirv.Bitcast %arg0 : vector<2xf32> to i64 82 %1 = spirv.Bitcast %0 : i64 to f64 83 spirv.Store "Uniform" %arg1, %0 : i64 84 spirv.ReturnValue %1 : f64 85} 86 87// ----- 88 89// CHECK-LABEL: @convert_bitcast_roundtip 90// CHECK-SAME: %[[ARG:.+]]: i64 91func.func @convert_bitcast_roundtip(%arg0 : i64) -> i64 { 92 // CHECK: spirv.ReturnValue %[[ARG]] 93 %0 = spirv.Bitcast %arg0 : i64 to f64 94 %1 = spirv.Bitcast %0 : f64 to i64 95 spirv.ReturnValue %1 : i64 96} 97 98// ----- 99 100// CHECK-LABEL: @convert_bitcast_chained_roundtip 101// CHECK-SAME: %[[ARG:.+]]: i64 102func.func @convert_bitcast_chained_roundtip(%arg0 : i64) -> i64 { 103 // CHECK: spirv.ReturnValue %[[ARG]] 104 %0 = spirv.Bitcast %arg0 : i64 to f64 105 %1 = spirv.Bitcast %0 : f64 to vector<2xi32> 106 %2 = spirv.Bitcast %1 : vector<2xi32> to vector<2xf32> 107 %3 = spirv.Bitcast %2 : vector<2xf32> to i64 108 spirv.ReturnValue %3 : i64 109} 110 111// ----- 112 113//===----------------------------------------------------------------------===// 114// spirv.CompositeExtract 115//===----------------------------------------------------------------------===// 116 117// CHECK-LABEL: extract_vector 118func.func @extract_vector() -> (i32, i32, i32) { 119 // CHECK-DAG: spirv.Constant 6 : i32 120 // CHECK-DAG: spirv.Constant -33 : i32 121 // CHECK-DAG: spirv.Constant 42 : i32 122 %0 = spirv.Constant dense<[42, -33, 6]> : vector<3xi32> 123 %1 = spirv.CompositeExtract %0[0 : i32] : vector<3xi32> 124 %2 = spirv.CompositeExtract %0[1 : i32] : vector<3xi32> 125 %3 = spirv.CompositeExtract %0[2 : i32] : vector<3xi32> 126 return %1, %2, %3 : i32, i32, i32 127} 128 129// ----- 130 131// CHECK-LABEL: extract_array_final 132func.func @extract_array_final() -> (i32, i32) { 133 // CHECK-DAG: spirv.Constant -5 : i32 134 // CHECK-DAG: spirv.Constant 4 : i32 135 %0 = spirv.Constant [dense<[4, -5]> : vector<2xi32>] : !spirv.array<1 x vector<2xi32>> 136 %1 = spirv.CompositeExtract %0[0 : i32, 0 : i32] : !spirv.array<1 x vector<2 x i32>> 137 %2 = spirv.CompositeExtract %0[0 : i32, 1 : i32] : !spirv.array<1 x vector<2 x i32>> 138 return %1, %2 : i32, i32 139} 140 141// ----- 142 143// CHECK-LABEL: extract_array_interm 144func.func @extract_array_interm() -> (vector<2xi32>) { 145 // CHECK: spirv.Constant dense<[4, -5]> : vector<2xi32> 146 %0 = spirv.Constant [dense<[4, -5]> : vector<2xi32>] : !spirv.array<1 x vector<2xi32>> 147 %1 = spirv.CompositeExtract %0[0 : i32] : !spirv.array<1 x vector<2 x i32>> 148 return %1 : vector<2xi32> 149} 150 151// ----- 152 153// CHECK-LABEL: extract_from_not_constant 154func.func @extract_from_not_constant() -> i32 { 155 %0 = spirv.Variable : !spirv.ptr<vector<3xi32>, Function> 156 %1 = spirv.Load "Function" %0 : vector<3xi32> 157 // CHECK: spirv.CompositeExtract 158 %2 = spirv.CompositeExtract %1[0 : i32] : vector<3xi32> 159 spirv.ReturnValue %2 : i32 160} 161 162// ----- 163 164// CHECK-LABEL: extract_insert 165// CHECK-SAME: (%[[COMP:.+]]: !spirv.array<1 x vector<2xf32>>, %[[VAL:.+]]: f32) 166func.func @extract_insert(%composite: !spirv.array<1xvector<2xf32>>, %val: f32) -> (f32, f32) { 167 // CHECK: %[[INSERT:.+]] = spirv.CompositeInsert %[[VAL]], %[[COMP]] 168 %insert = spirv.CompositeInsert %val, %composite[0 : i32, 1 : i32] : f32 into !spirv.array<1xvector<2xf32>> 169 %1 = spirv.CompositeExtract %insert[0 : i32, 0 : i32] : !spirv.array<1xvector<2xf32>> 170 // CHECK: %[[S:.+]] = spirv.CompositeExtract %[[INSERT]][0 : i32, 0 : i32] 171 %2 = spirv.CompositeExtract %insert[0 : i32, 1 : i32] : !spirv.array<1xvector<2xf32>> 172 // CHECK: return %[[S]], %[[VAL]] 173 return %1, %2 : f32, f32 174} 175 176// ----- 177 178// CHECK-LABEL: extract_construct 179// CHECK-SAME: (%[[VAL1:.+]]: vector<2xf32>, %[[VAL2:.+]]: vector<2xf32>) 180func.func @extract_construct(%val1: vector<2xf32>, %val2: vector<2xf32>) -> (vector<2xf32>, vector<2xf32>) { 181 %construct = spirv.CompositeConstruct %val1, %val2 : (vector<2xf32>, vector<2xf32>) -> !spirv.array<2xvector<2xf32>> 182 %1 = spirv.CompositeExtract %construct[0 : i32] : !spirv.array<2xvector<2xf32>> 183 %2 = spirv.CompositeExtract %construct[1 : i32] : !spirv.array<2xvector<2xf32>> 184 // CHECK: return %[[VAL1]], %[[VAL2]] 185 return %1, %2 : vector<2xf32>, vector<2xf32> 186} 187 188// ----- 189 190 // CHECK-LABEL: fold_composite_op 191 // CHECK-SAME: (%[[COMP:.+]]: !spirv.struct<(f32, f32)>, %[[VAL1:.+]]: f32, %[[VAL2:.+]]: f32) 192 func.func @fold_composite_op(%composite: !spirv.struct<(f32, f32)>, %val1: f32, %val2: f32) -> f32 { 193 %insert = spirv.CompositeInsert %val1, %composite[0 : i32] : f32 into !spirv.struct<(f32, f32)> 194 %1 = spirv.CompositeInsert %val2, %insert[1 : i32] : f32 into !spirv.struct<(f32, f32)> 195 %2 = spirv.CompositeExtract %1[0 : i32] : !spirv.struct<(f32, f32)> 196 // CHECK-NEXT: return %[[VAL1]] 197 return %2 : f32 198 } 199 200// ----- 201 202 // CHECK-LABEL: fold_composite_op 203 // CHECK-SAME: (%[[VAL1:.+]]: f32, %[[VAL2:.+]]: f32, %[[VAL3:.+]]: f32) 204 func.func @fold_composite_op(%val1: f32, %val2: f32, %val3: f32) -> f32 { 205 %composite = spirv.CompositeConstruct %val1, %val1, %val1 : (f32, f32, f32) -> !spirv.struct<(f32, f32, f32)> 206 %insert = spirv.CompositeInsert %val2, %composite[1 : i32] : f32 into !spirv.struct<(f32, f32, f32)> 207 %1 = spirv.CompositeInsert %val3, %insert[2 : i32] : f32 into !spirv.struct<(f32, f32, f32)> 208 %2 = spirv.CompositeExtract %1[0 : i32] : !spirv.struct<(f32, f32, f32)> 209 // CHECK-NEXT: return %[[VAL1]] 210 return %2 : f32 211 } 212 213// ----- 214 215// Not yet implemented case 216 217// CHECK-LABEL: extract_construct 218func.func @extract_construct(%val1: vector<3xf32>, %val2: f32) -> (f32, f32) { 219 // CHECK: spirv.CompositeConstruct 220 %construct = spirv.CompositeConstruct %val1, %val2 : (vector<3xf32>, f32) -> vector<4xf32> 221 // CHECK: spirv.CompositeExtract 222 %1 = spirv.CompositeExtract %construct[0 : i32] : vector<4xf32> 223 // CHECK: spirv.CompositeExtract 224 %2 = spirv.CompositeExtract %construct[1 : i32] : vector<4xf32> 225 return %1, %2 : f32, f32 226} 227 228// ----- 229 230//===----------------------------------------------------------------------===// 231// spirv.Constant 232//===----------------------------------------------------------------------===// 233 234// TODO: test constants in different blocks 235 236func.func @deduplicate_scalar_constant() -> (i32, i32) { 237 // CHECK: %[[CST:.*]] = spirv.Constant 42 : i32 238 %0 = spirv.Constant 42 : i32 239 %1 = spirv.Constant 42 : i32 240 // CHECK-NEXT: return %[[CST]], %[[CST]] 241 return %0, %1 : i32, i32 242} 243 244// ----- 245 246func.func @deduplicate_vector_constant() -> (vector<3xi32>, vector<3xi32>) { 247 // CHECK: %[[CST:.*]] = spirv.Constant dense<[1, 2, 3]> : vector<3xi32> 248 %0 = spirv.Constant dense<[1, 2, 3]> : vector<3xi32> 249 %1 = spirv.Constant dense<[1, 2, 3]> : vector<3xi32> 250 // CHECK-NEXT: return %[[CST]], %[[CST]] 251 return %0, %1 : vector<3xi32>, vector<3xi32> 252} 253 254// ----- 255 256func.func @deduplicate_composite_constant() -> (!spirv.array<1 x vector<2xi32>>, !spirv.array<1 x vector<2xi32>>) { 257 // CHECK: %[[CST:.*]] = spirv.Constant [dense<5> : vector<2xi32>] : !spirv.array<1 x vector<2xi32>> 258 %0 = spirv.Constant [dense<5> : vector<2xi32>] : !spirv.array<1 x vector<2xi32>> 259 %1 = spirv.Constant [dense<5> : vector<2xi32>] : !spirv.array<1 x vector<2xi32>> 260 // CHECK-NEXT: return %[[CST]], %[[CST]] 261 return %0, %1 : !spirv.array<1 x vector<2xi32>>, !spirv.array<1 x vector<2xi32>> 262} 263 264// ----- 265 266//===----------------------------------------------------------------------===// 267// spirv.IAdd 268//===----------------------------------------------------------------------===// 269 270// CHECK-LABEL: @iadd_zero 271// CHECK-SAME: (%[[ARG:.*]]: i32) 272func.func @iadd_zero(%arg0: i32) -> (i32, i32) { 273 %zero = spirv.Constant 0 : i32 274 %0 = spirv.IAdd %arg0, %zero : i32 275 %1 = spirv.IAdd %zero, %arg0 : i32 276 // CHECK: return %[[ARG]], %[[ARG]] 277 return %0, %1: i32, i32 278} 279 280// CHECK-LABEL: @const_fold_scalar_iadd_normal 281func.func @const_fold_scalar_iadd_normal() -> (i32, i32, i32) { 282 %c5 = spirv.Constant 5 : i32 283 %cn8 = spirv.Constant -8 : i32 284 285 // CHECK-DAG: spirv.Constant -3 286 // CHECK-DAG: spirv.Constant -16 287 // CHECK-DAG: spirv.Constant 10 288 %0 = spirv.IAdd %c5, %c5 : i32 289 %1 = spirv.IAdd %cn8, %cn8 : i32 290 %2 = spirv.IAdd %c5, %cn8 : i32 291 return %0, %1, %2: i32, i32, i32 292} 293 294// CHECK-LABEL: @const_fold_scalar_iadd_flow 295func.func @const_fold_scalar_iadd_flow() -> (i32, i32, i32, i32) { 296 %c1 = spirv.Constant 1 : i32 297 %c2 = spirv.Constant 2 : i32 298 %c3 = spirv.Constant 4294967295 : i32 // 2^32 - 1: 0xffff ffff 299 %c4 = spirv.Constant -2147483648 : i32 // -2^31 : 0x8000 0000 300 %c5 = spirv.Constant -1 : i32 // : 0xffff ffff 301 %c6 = spirv.Constant -2 : i32 // : 0xffff fffe 302 303 // 0x8000 0000 + 0xffff fffe = 0x1 7fff fffe -> 0x7fff fffe 304 // CHECK-DAG: spirv.Constant 2147483646 305 // 0x8000 0000 + 0xffff ffff = 0x1 7fff ffff -> 0x7fff ffff 306 // CHECK-DAG: spirv.Constant 2147483647 307 // 0x0000 0002 + 0xffff ffff = 0x1 0000 0001 -> 0x0000 0001 308 // CHECK-DAG: spirv.Constant 1 309 // 0x0000 0001 + 0xffff ffff = 0x1 0000 0000 -> 0x0000 0000 310 // CHECK-DAG: spirv.Constant 0 311 %0 = spirv.IAdd %c1, %c3 : i32 312 %1 = spirv.IAdd %c2, %c3 : i32 313 %2 = spirv.IAdd %c4, %c5 : i32 314 %3 = spirv.IAdd %c4, %c6 : i32 315 return %0, %1, %2, %3: i32, i32, i32, i32 316} 317 318// CHECK-LABEL: @const_fold_vector_iadd 319func.func @const_fold_vector_iadd() -> vector<3xi32> { 320 %vc1 = spirv.Constant dense<[42, -55, 127]> : vector<3xi32> 321 %vc2 = spirv.Constant dense<[-3, -15, 28]> : vector<3xi32> 322 323 // CHECK: spirv.Constant dense<[39, -70, 155]> 324 %0 = spirv.IAdd %vc1, %vc2 : vector<3xi32> 325 return %0: vector<3xi32> 326} 327 328// CHECK-LABEL: @iadd_poison 329// CHECK: %[[P:.*]] = ub.poison : i32 330// CHECK: return %[[P]] 331func.func @iadd_poison(%arg0: i32) -> i32 { 332 %0 = ub.poison : i32 333 %1 = spirv.IAdd %arg0, %0 : i32 334 return %1: i32 335} 336 337// ----- 338 339//===----------------------------------------------------------------------===// 340// spirv.IAddCarry 341//===----------------------------------------------------------------------===// 342 343// CHECK-LABEL: @iaddcarry_x_0 344func.func @iaddcarry_x_0(%arg0 : i32) -> !spirv.struct<(i32, i32)> { 345 // CHECK: %[[RET:.*]] = spirv.CompositeConstruct 346 %c0 = spirv.Constant 0 : i32 347 %0 = spirv.IAddCarry %arg0, %c0 : !spirv.struct<(i32, i32)> 348 349 // CHECK: return %[[RET]] 350 return %0 : !spirv.struct<(i32, i32)> 351} 352 353// CHECK-LABEL: @const_fold_scalar_iaddcarry 354func.func @const_fold_scalar_iaddcarry() -> (!spirv.struct<(i32, i32)>, !spirv.struct<(i32, i32)>) { 355 %c5 = spirv.Constant 5 : i32 356 %cn5 = spirv.Constant -5 : i32 357 %cn8 = spirv.Constant -8 : i32 358 359 // CHECK-DAG: %[[C0:.*]] = spirv.Constant 0 360 // CHECK-DAG: %[[CN3:.*]] = spirv.Constant -3 361 // CHECK-DAG: %[[UNDEF1:.*]] = spirv.Undef 362 // CHECK-DAG: %[[INTER1:.*]] = spirv.CompositeInsert %[[CN3]], %[[UNDEF1]][0 : i32] 363 // CHECK-DAG: %[[CC_CN3_C0:.*]] = spirv.CompositeInsert %[[C0]], %[[INTER1]][1 : i32] 364 // CHECK-DAG: %[[C1:.*]] = spirv.Constant 1 365 // CHECK-DAG: %[[CN13:.*]] = spirv.Constant -13 366 // CHECK-DAG: %[[UNDEF2:.*]] = spirv.Undef 367 // CHECK-DAG: %[[INTER2:.*]] = spirv.CompositeInsert %[[CN13]], %[[UNDEF2]][0 : i32] 368 // CHECK-DAG: %[[CC_CN13_C1:.*]] = spirv.CompositeInsert %[[C1]], %[[INTER2]][1 : i32] 369 %0 = spirv.IAddCarry %c5, %cn8 : !spirv.struct<(i32, i32)> 370 %1 = spirv.IAddCarry %cn5, %cn8 : !spirv.struct<(i32, i32)> 371 372 // CHECK: return %[[CC_CN3_C0]], %[[CC_CN13_C1]] 373 return %0, %1 : !spirv.struct<(i32, i32)>, !spirv.struct<(i32, i32)> 374} 375 376// CHECK-LABEL: @const_fold_vector_iaddcarry 377func.func @const_fold_vector_iaddcarry() -> !spirv.struct<(vector<3xi32>, vector<3xi32>)> { 378 %v0 = spirv.Constant dense<[5, -3, -1]> : vector<3xi32> 379 %v1 = spirv.Constant dense<[-8, -8, 1]> : vector<3xi32> 380 381 // CHECK-DAG: %[[CV1:.*]] = spirv.Constant dense<[-3, -11, 0]> 382 // CHECK-DAG: %[[CV2:.*]] = spirv.Constant dense<[0, 1, 1]> 383 // CHECK-DAG: %[[UNDEF:.*]] = spirv.Undef 384 // CHECK-DAG: %[[INTER:.*]] = spirv.CompositeInsert %[[CV1]], %[[UNDEF]][0 : i32] 385 // CHECK-DAG: %[[CC_CV1_CV2:.*]] = spirv.CompositeInsert %[[CV2]], %[[INTER]][1 : i32] 386 %0 = spirv.IAddCarry %v0, %v1 : !spirv.struct<(vector<3xi32>, vector<3xi32>)> 387 388 // CHECK: return %[[CC_CV1_CV2]] 389 return %0 : !spirv.struct<(vector<3xi32>, vector<3xi32>)> 390} 391 392// ----- 393 394//===----------------------------------------------------------------------===// 395// spirv.IMul 396//===----------------------------------------------------------------------===// 397 398// CHECK-LABEL: @imul_zero_one 399// CHECK-SAME: (%[[ARG:.*]]: i32) 400func.func @imul_zero_one(%arg0: i32) -> (i32, i32) { 401 // CHECK: %[[ZERO:.*]] = spirv.Constant 0 402 %zero = spirv.Constant 0 : i32 403 %one = spirv.Constant 1: i32 404 %0 = spirv.IMul %arg0, %zero : i32 405 %1 = spirv.IMul %one, %arg0 : i32 406 // CHECK: return %[[ZERO]], %[[ARG]] 407 return %0, %1: i32, i32 408} 409 410// CHECK-LABEL: @const_fold_scalar_imul_normal 411func.func @const_fold_scalar_imul_normal() -> (i32, i32, i32) { 412 %c5 = spirv.Constant 5 : i32 413 %cn8 = spirv.Constant -8 : i32 414 %c7 = spirv.Constant 7 : i32 415 416 // CHECK-DAG: spirv.Constant -56 417 // CHECK-DAG: spirv.Constant -40 418 // CHECK-DAG: spirv.Constant 35 419 %0 = spirv.IMul %c7, %c5 : i32 420 %1 = spirv.IMul %c5, %cn8 : i32 421 %2 = spirv.IMul %cn8, %c7 : i32 422 return %0, %1, %2: i32, i32, i32 423} 424 425// CHECK-LABEL: @const_fold_scalar_imul_flow 426func.func @const_fold_scalar_imul_flow() -> (i32, i32, i32) { 427 %c1 = spirv.Constant 2 : i32 428 %c2 = spirv.Constant 4 : i32 429 %c3 = spirv.Constant 4294967295 : i32 // 2^32 - 1 : 0xffff ffff 430 %c4 = spirv.Constant 2147483647 : i32 // 2^31 - 1 : 0x7fff ffff 431 432 // (0x7fff ffff << 2) = 0x1 ffff fffc -> 0xffff fffc 433 // CHECK-DAG: %[[CST4:.*]] = spirv.Constant -4 434 435 // (0xffff ffff << 1) = 0x1 ffff fffe -> 0xffff fffe 436 // CHECK-DAG: %[[CST2:.*]] = spirv.Constant -2 437 %0 = spirv.IMul %c1, %c3 : i32 438 // (0x7fff ffff << 1) = 0x0 ffff fffe -> 0xffff fffe 439 %1 = spirv.IMul %c1, %c4 : i32 440 %2 = spirv.IMul %c4, %c2 : i32 441 // CHECK: return %[[CST2]], %[[CST2]], %[[CST4]] 442 return %0, %1, %2: i32, i32, i32 443} 444 445 446// CHECK-LABEL: @const_fold_vector_imul 447func.func @const_fold_vector_imul() -> vector<3xi32> { 448 %vc1 = spirv.Constant dense<[42, -55, 127]> : vector<3xi32> 449 %vc2 = spirv.Constant dense<[-3, -15, 28]> : vector<3xi32> 450 451 // CHECK: spirv.Constant dense<[-126, 825, 3556]> 452 %0 = spirv.IMul %vc1, %vc2 : vector<3xi32> 453 return %0: vector<3xi32> 454} 455 456// ----- 457 458//===----------------------------------------------------------------------===// 459// spirv.SMulExtended 460//===----------------------------------------------------------------------===// 461 462// CHECK-LABEL: @smulextended_x_0 463func.func @smulextended_x_0(%arg0 : i32) -> !spirv.struct<(i32, i32)> { 464 // CHECK: %[[C0:.*]] = spirv.Constant 0 465 // CHECK: %[[RET:.*]] = spirv.CompositeConstruct %[[C0]], %[[C0]] 466 %c0 = spirv.Constant 0 : i32 467 %0 = spirv.SMulExtended %arg0, %c0 : !spirv.struct<(i32, i32)> 468 469 // CHECK: return %[[RET]] 470 return %0 : !spirv.struct<(i32, i32)> 471} 472 473// CHECK-LABEL: @const_fold_scalar_smulextended 474func.func @const_fold_scalar_smulextended() -> (!spirv.struct<(i32, i32)>, !spirv.struct<(i32, i32)>) { 475 %c5 = spirv.Constant 5 : i32 476 %cn5 = spirv.Constant -5 : i32 477 %cn8 = spirv.Constant -8 : i32 478 479 // CHECK-DAG: %[[CN40:.*]] = spirv.Constant -40 480 // CHECK-DAG: %[[CN1:.*]] = spirv.Constant -1 481 // CHECK-DAG: %[[UNDEF1:.*]] = spirv.Undef 482 // CHECK-DAG: %[[INTER1:.*]] = spirv.CompositeInsert %[[CN40]], %[[UNDEF1]][0 : i32] 483 // CHECK-DAG: %[[CC_CN40_CN1:.*]] = spirv.CompositeInsert %[[CN1]], %[[INTER1]] 484 // CHECK-DAG: %[[C40:.*]] = spirv.Constant 40 485 // CHECK-DAG: %[[C0:.*]] = spirv.Constant 0 486 // CHECK-DAG: %[[UNDEF2:.*]] = spirv.Undef 487 // CHECK-DAG: %[[INTER2:.*]] = spirv.CompositeInsert %[[C40]], %[[UNDEF2]][0 : i32] 488 // CHECK-DAG: %[[CC_C40_C0:.*]] = spirv.CompositeInsert %[[C0]], %[[INTER2]][1 : i32] 489 %0 = spirv.SMulExtended %c5, %cn8 : !spirv.struct<(i32, i32)> 490 %1 = spirv.SMulExtended %cn5, %cn8 : !spirv.struct<(i32, i32)> 491 492 // CHECK: return %[[CC_CN40_CN1]], %[[CC_C40_C0]] 493 return %0, %1 : !spirv.struct<(i32, i32)>, !spirv.struct<(i32, i32)> 494} 495 496// CHECK-LABEL: @const_fold_vector_smulextended 497func.func @const_fold_vector_smulextended() -> !spirv.struct<(vector<3xi32>, vector<3xi32>)> { 498 %v0 = spirv.Constant dense<[2147483647, -5, -1]> : vector<3xi32> 499 %v1 = spirv.Constant dense<[5, -8, 1]> : vector<3xi32> 500 501 // CHECK-DAG: %[[CV1:.*]] = spirv.Constant dense<[2147483643, 40, -1]> 502 // CHECK-DAG: %[[CV2:.*]] = spirv.Constant dense<[2, 0, -1]> 503 // CHECK-DAG: %[[UNDEF:.*]] = spirv.Undef 504 // CHECK-DAG: %[[INTER:.*]] = spirv.CompositeInsert %[[CV1]], %[[UNDEF]][0 : i32] 505 // CHECK-DAG: %[[CC_CV1_CV2:.*]] = spirv.CompositeInsert %[[CV2]], %[[INTER]][1 : i32] 506 %0 = spirv.SMulExtended %v0, %v1 : !spirv.struct<(vector<3xi32>, vector<3xi32>)> 507 508 // CHECK: return %[[CC_CV1_CV2]] 509 return %0 : !spirv.struct<(vector<3xi32>, vector<3xi32>)> 510 511} 512 513// ----- 514 515//===----------------------------------------------------------------------===// 516// spirv.UMulExtended 517//===----------------------------------------------------------------------===// 518 519// CHECK-LABEL: @umulextended_x_0 520func.func @umulextended_x_0(%arg0 : i32) -> !spirv.struct<(i32, i32)> { 521 // CHECK: %[[C0:.*]] = spirv.Constant 0 522 // CHECK: %[[RET:.*]] = spirv.CompositeConstruct %[[C0]], %[[C0]] 523 %c0 = spirv.Constant 0 : i32 524 %0 = spirv.UMulExtended %arg0, %c0 : !spirv.struct<(i32, i32)> 525 526 // CHECK: return %[[RET]] 527 return %0 : !spirv.struct<(i32, i32)> 528} 529 530// CHECK-LABEL: @umulextended_x_1 531// CHECK-SAME: (%[[ARG:.*]]: i32) 532func.func @umulextended_x_1(%arg0 : i32) -> !spirv.struct<(i32, i32)> { 533 // CHECK: %[[C0:.*]] = spirv.Constant 0 534 // CHECK: %[[RET:.*]] = spirv.CompositeConstruct %[[ARG]], %[[C0]] 535 %c0 = spirv.Constant 1 : i32 536 %0 = spirv.UMulExtended %arg0, %c0 : !spirv.struct<(i32, i32)> 537 538 // CHECK: return %[[RET]] 539 return %0 : !spirv.struct<(i32, i32)> 540} 541 542// CHECK-LABEL: @const_fold_scalar_umulextended 543func.func @const_fold_scalar_umulextended() -> (!spirv.struct<(i32, i32)>, !spirv.struct<(i32, i32)>) { 544 %c5 = spirv.Constant 5 : i32 545 %cn5 = spirv.Constant -5 : i32 546 %cn8 = spirv.Constant -8 : i32 547 548 549 // CHECK-DAG: %[[C40:.*]] = spirv.Constant 40 550 // CHECK-DAG: %[[CN13:.*]] = spirv.Constant -13 551 // CHECK-DAG: %[[CN40:.*]] = spirv.Constant -40 552 // CHECK-DAG: %[[C4:.*]] = spirv.Constant 4 553 // CHECK-DAG: %[[UNDEF1:.*]] = spirv.Undef 554 // CHECK-DAG: %[[INTER1:.*]] = spirv.CompositeInsert %[[CN40]], %[[UNDEF1]][0 : i32] 555 // CHECK-DAG: %[[CC_CN40_C4:.*]] = spirv.CompositeInsert %[[C4]], %[[INTER1]][1 : i32] 556 // CHECK-DAG: %[[UNDEF2:.*]] = spirv.Undef 557 // CHECK-DAG: %[[INTER2:.*]] = spirv.CompositeInsert %[[C40]], %[[UNDEF2]][0 : i32] 558 // CHECK-DAG: %[[CC_C40_CN13:.*]] = spirv.CompositeInsert %[[CN13]], %[[INTER2]][1 : i32] 559 %0 = spirv.UMulExtended %c5, %cn8 : !spirv.struct<(i32, i32)> 560 %1 = spirv.UMulExtended %cn5, %cn8 : !spirv.struct<(i32, i32)> 561 562 // CHECK: return %[[CC_CN40_C4]], %[[CC_C40_CN13]] 563 return %0, %1 : !spirv.struct<(i32, i32)>, !spirv.struct<(i32, i32)> 564} 565 566// CHECK-LABEL: @const_fold_vector_umulextended 567func.func @const_fold_vector_umulextended() -> !spirv.struct<(vector<3xi32>, vector<3xi32>)> { 568 %v0 = spirv.Constant dense<[2147483647, -5, -1]> : vector<3xi32> 569 %v1 = spirv.Constant dense<[5, -8, 1]> : vector<3xi32> 570 571 // CHECK-DAG: %[[CV1:.*]] = spirv.Constant dense<[2147483643, 40, -1]> 572 // CHECK-DAG: %[[CV2:.*]] = spirv.Constant dense<[2, -13, 0]> 573 // CHECK-DAG: %[[UNDEF:.*]] = spirv.Undef 574 // CHECK-DAG: %[[INTER:.*]] = spirv.CompositeInsert %[[CV1]], %[[UNDEF]] 575 // CHECK-DAG: %[[CC_CV1_CV2:.*]] = spirv.CompositeInsert %[[CV2]], %[[INTER]] 576 %0 = spirv.UMulExtended %v0, %v1 : !spirv.struct<(vector<3xi32>, vector<3xi32>)> 577 578 // CHECK: return %[[CC_CV1_CV2]] 579 return %0 : !spirv.struct<(vector<3xi32>, vector<3xi32>)> 580} 581 582// ----- 583 584 585//===----------------------------------------------------------------------===// 586// spirv.ISub 587//===----------------------------------------------------------------------===// 588 589// CHECK-LABEL: @isub_x_x 590func.func @isub_x_x(%arg0: i32) -> i32 { 591 // CHECK: spirv.Constant 0 592 %0 = spirv.ISub %arg0, %arg0: i32 593 return %0: i32 594} 595 596// CHECK-LABEL: @const_fold_scalar_isub_normal 597func.func @const_fold_scalar_isub_normal() -> (i32, i32, i32) { 598 %c5 = spirv.Constant 5 : i32 599 %cn8 = spirv.Constant -8 : i32 600 %c7 = spirv.Constant 7 : i32 601 602 // CHECK-DAG: spirv.Constant -15 603 // CHECK-DAG: spirv.Constant 13 604 // CHECK-DAG: spirv.Constant 2 605 %0 = spirv.ISub %c7, %c5 : i32 606 %1 = spirv.ISub %c5, %cn8 : i32 607 %2 = spirv.ISub %cn8, %c7 : i32 608 return %0, %1, %2: i32, i32, i32 609} 610 611// CHECK-LABEL: @const_fold_scalar_isub_flow 612func.func @const_fold_scalar_isub_flow() -> (i32, i32, i32, i32) { 613 %c1 = spirv.Constant 0 : i32 614 %c2 = spirv.Constant 1 : i32 615 %c3 = spirv.Constant 4294967295 : i32 // 2^32 - 1 : 0xffff ffff 616 %c4 = spirv.Constant 2147483647 : i32 // 2^31 : 0x7fff ffff 617 %c5 = spirv.Constant -1 : i32 // : 0xffff ffff 618 %c6 = spirv.Constant -2 : i32 // : 0xffff fffe 619 620 // 0xffff ffff - 0x7fff ffff -> 0xffff ffff + 0x8000 0001 = 0x1 8000 0000 621 // CHECK-DAG: spirv.Constant -2147483648 622 // 0x0000 0001 - 0xffff ffff -> 0x0000 0001 + 0x0000 0001 = 0x0000 0002 623 // CHECK-DAG: spirv.Constant 2 : 624 // 0x0000 0000 - 0xffff ffff -> 0x0000 0000 + 0x0000 0001 = 0x0000 0001 625 // CHECK-DAG: spirv.Constant 1 : 626 // 0xffff fffe - 0x7fff ffff -> 0xffff fffe + 0x8000 0001 = 0x1 7fff ffff 627 // CHECK-DAG: spirv.Constant 2147483647 628 %0 = spirv.ISub %c1, %c3 : i32 629 %1 = spirv.ISub %c2, %c3 : i32 630 %2 = spirv.ISub %c5, %c4 : i32 631 %3 = spirv.ISub %c6, %c4 : i32 632 return %0, %1, %2, %3: i32, i32, i32, i32 633} 634 635// CHECK-LABEL: @const_fold_vector_isub 636func.func @const_fold_vector_isub() -> vector<3xi32> { 637 %vc1 = spirv.Constant dense<[42, -55, 127]> : vector<3xi32> 638 %vc2 = spirv.Constant dense<[-3, -15, 28]> : vector<3xi32> 639 640 // CHECK: spirv.Constant dense<[45, -40, 99]> 641 %0 = spirv.ISub %vc1, %vc2 : vector<3xi32> 642 return %0: vector<3xi32> 643} 644 645// ----- 646 647//===----------------------------------------------------------------------===// 648// spirv.SDiv 649//===----------------------------------------------------------------------===// 650 651// CHECK-LABEL: @sdiv_x_1 652func.func @sdiv_x_1(%arg0 : i32) -> i32 { 653 // CHECK-NEXT: return %arg0 : i32 654 %c1 = spirv.Constant 1 : i32 655 %2 = spirv.SDiv %arg0, %c1: i32 656 return %2 : i32 657} 658 659// CHECK-LABEL: @sdiv_div_0_or_overflow 660func.func @sdiv_div_0_or_overflow() -> (i32, i32) { 661 // CHECK-DAG: %[[C0:.*]] = spirv.Constant 0 662 // CHECK-DAG: %[[CN1:.*]] = spirv.Constant -1 663 // CHECK-DAG: %[[CNMIN:.*]] = spirv.Constant -2147483648 664 665 %c0 = spirv.Constant 0 : i32 666 %cn1 = spirv.Constant -1 : i32 667 %min_i32 = spirv.Constant -2147483648 : i32 668 669 // CHECK: %0 = spirv.SDiv %[[CN1]], %[[C0]] 670 // CHECK: %1 = spirv.SDiv %[[CNMIN]], %[[CN1]] 671 %0 = spirv.SDiv %cn1, %c0 : i32 672 %1 = spirv.SDiv %min_i32, %cn1 : i32 673 return %0, %1 : i32, i32 674} 675 676// CHECK-LABEL: @const_fold_scalar_sdiv 677func.func @const_fold_scalar_sdiv() -> (i32, i32, i32, i32) { 678 %c56 = spirv.Constant 56 : i32 679 %c7 = spirv.Constant 7 : i32 680 %cn8 = spirv.Constant -8 : i32 681 %c3 = spirv.Constant 3 : i32 682 %cn3 = spirv.Constant -3 : i32 683 684 // CHECK-DAG: %[[CN18:.*]] = spirv.Constant -18 685 // CHECK-DAG: %[[CN2:.*]] = spirv.Constant -2 686 // CHECK-DAG: %[[CN7:.*]] = spirv.Constant -7 687 // CHECK-DAG: %[[C8:.*]] = spirv.Constant 8 688 %0 = spirv.SDiv %c56, %c7 : i32 689 %1 = spirv.SDiv %c56, %cn8 : i32 690 %2 = spirv.SDiv %cn8, %c3 : i32 691 %3 = spirv.SDiv %c56, %cn3 : i32 692 693 // CHECK: return %[[C8]], %[[CN7]], %[[CN2]], %[[CN18]] 694 return %0, %1, %2, %3: i32, i32, i32, i32 695} 696 697// CHECK-LABEL: @const_fold_vector_sdiv 698func.func @const_fold_vector_sdiv() -> vector<3xi32> { 699 // CHECK: %[[CVEC:.*]] = spirv.Constant dense<[0, -1, -3]> 700 701 %cv_num = spirv.Constant dense<[42, 24, -16]> : vector<3xi32> 702 %cv_denom = spirv.Constant dense<[76, -24, 5]> : vector<3xi32> 703 %0 = spirv.SDiv %cv_num, %cv_denom : vector<3xi32> 704 705 // CHECK: return %[[CVEC]] 706 return %0 : vector<3xi32> 707} 708 709// ----- 710 711//===----------------------------------------------------------------------===// 712// spirv.SMod 713//===----------------------------------------------------------------------===// 714 715// CHECK-LABEL: @smod_x_1 716func.func @smod_x_1(%arg0: i32, %arg1: vector<3xi32>) -> (i32, vector<3xi32>) { 717 // CHECK-DAG: %[[C0:.*]] = spirv.Constant 0 718 // CHECK-DAG: %[[CVEC0:.*]] = spirv.Constant dense<0> 719 %c1 = spirv.Constant 1 : i32 720 %cv1 = spirv.Constant dense<1> : vector<3xi32> 721 %0 = spirv.SMod %arg0, %c1: i32 722 %1 = spirv.SMod %arg1, %cv1: vector<3xi32> 723 724 // CHECK: return %[[C0]], %[[CVEC0]] 725 return %0, %1 : i32, vector<3xi32> 726} 727 728// CHECK-LABEL: @smod_div_0_or_overflow 729func.func @smod_div_0_or_overflow() -> (i32, i32) { 730 // CHECK-DAG: %[[C0:.*]] = spirv.Constant 0 731 // CHECK-DAG: %[[CN1:.*]] = spirv.Constant -1 732 // CHECK-DAG: %[[CNMIN:.*]] = spirv.Constant -2147483648 733 734 %c0 = spirv.Constant 0 : i32 735 %cn1 = spirv.Constant -1 : i32 736 %min_i32 = spirv.Constant -2147483648 : i32 737 738 // CHECK: %0 = spirv.SMod %[[CN1]], %[[C0]] 739 // CHECK: %1 = spirv.SMod %[[CNMIN]], %[[CN1]] 740 %0 = spirv.SMod %cn1, %c0 : i32 741 %1 = spirv.SMod %min_i32, %cn1 : i32 742 return %0, %1 : i32, i32 743} 744 745// CHECK-LABEL: @const_fold_scalar_smod 746func.func @const_fold_scalar_smod() -> (i32, i32, i32, i32, i32, i32, i32, i32) { 747 %c56 = spirv.Constant 56 : i32 748 %cn56 = spirv.Constant -56 : i32 749 %c59 = spirv.Constant 59 : i32 750 %cn59 = spirv.Constant -59 : i32 751 %c7 = spirv.Constant 7 : i32 752 %cn8 = spirv.Constant -8 : i32 753 %c3 = spirv.Constant 3 : i32 754 %cn3 = spirv.Constant -3 : i32 755 756 // CHECK-DAG: %[[ZERO:.*]] = spirv.Constant 0 : i32 757 // CHECK-DAG: %[[TWO:.*]] = spirv.Constant 2 : i32 758 // CHECK-DAG: %[[FIFTYTHREE:.*]] = spirv.Constant 53 : i32 759 // CHECK-DAG: %[[NFIFTYTHREE:.*]] = spirv.Constant -53 : i32 760 // CHECK-DAG: %[[THREE:.*]] = spirv.Constant 3 : i32 761 // CHECK-DAG: %[[NTHREE:.*]] = spirv.Constant -3 : i32 762 %0 = spirv.SMod %c56, %c7 : i32 763 %1 = spirv.SMod %c56, %cn8 : i32 764 %2 = spirv.SMod %c56, %c3 : i32 765 %3 = spirv.SMod %cn3, %c56 : i32 766 %4 = spirv.SMod %cn3, %cn56 : i32 767 %5 = spirv.SMod %c59, %c56 : i32 768 %6 = spirv.SMod %c59, %cn56 : i32 769 %7 = spirv.SMod %cn59, %cn56 : i32 770 771 // CHECK: return %[[ZERO]], %[[ZERO]], %[[TWO]], %[[FIFTYTHREE]], %[[NTHREE]], %[[THREE]], %[[NFIFTYTHREE]], %[[NTHREE]] 772 return %0, %1, %2, %3, %4, %5, %6, %7 : i32, i32, i32, i32, i32, i32, i32, i32 773} 774 775// CHECK-LABEL: @const_fold_vector_smod 776func.func @const_fold_vector_smod() -> vector<3xi32> { 777 // CHECK: %[[CVEC:.*]] = spirv.Constant dense<[42, -4, 4]> 778 779 %cv = spirv.Constant dense<[42, 24, -16]> : vector<3xi32> 780 %cv_mod = spirv.Constant dense<[76, -7, 5]> : vector<3xi32> 781 %0 = spirv.SMod %cv, %cv_mod : vector<3xi32> 782 783 // CHECK: return %[[CVEC]] 784 return %0 : vector<3xi32> 785} 786 787// ----- 788 789//===----------------------------------------------------------------------===// 790// spirv.SRem 791//===----------------------------------------------------------------------===// 792 793// CHECK-LABEL: @srem_x_1 794func.func @srem_x_1(%arg0: i32, %arg1: vector<3xi32>) -> (i32, vector<3xi32>) { 795 // CHECK-DAG: %[[C0:.*]] = spirv.Constant 0 796 // CHECK-DAG: %[[CVEC0:.*]] = spirv.Constant dense<0> 797 %c1 = spirv.Constant 1 : i32 798 %cv1 = spirv.Constant dense<1> : vector<3xi32> 799 %0 = spirv.SRem %arg0, %c1: i32 800 %1 = spirv.SRem %arg1, %cv1: vector<3xi32> 801 802 // CHECK: return %[[C0]], %[[CVEC0]] 803 return %0, %1 : i32, vector<3xi32> 804} 805 806// CHECK-LABEL: @srem_div_0_or_overflow 807func.func @srem_div_0_or_overflow() -> (i32, i32) { 808 // CHECK-DAG: %[[C0:.*]] = spirv.Constant 0 809 // CHECK-DAG: %[[CN1:.*]] = spirv.Constant -1 810 // CHECK-DAG: %[[CNMIN:.*]] = spirv.Constant -2147483648 811 %c0 = spirv.Constant 0 : i32 812 %cn1 = spirv.Constant -1 : i32 813 %min_i32 = spirv.Constant -2147483648 : i32 814 815 // CHECK: %0 = spirv.SRem %[[CN1]], %[[C0]] 816 // CHECK: %1 = spirv.SRem %[[CNMIN]], %[[CN1]] 817 %0 = spirv.SRem %cn1, %c0 : i32 818 %1 = spirv.SRem %min_i32, %cn1 : i32 819 return %0, %1 : i32, i32 820} 821 822// CHECK-LABEL: @const_fold_scalar_srem 823func.func @const_fold_scalar_srem() -> (i32, i32, i32, i32, i32) { 824 %c56 = spirv.Constant 56 : i32 825 %c7 = spirv.Constant 7 : i32 826 %cn8 = spirv.Constant -8 : i32 827 %c3 = spirv.Constant 3 : i32 828 %cn3 = spirv.Constant -3 : i32 829 830 // CHECK-DAG: %[[ONE:.*]] = spirv.Constant 1 : i32 831 // CHECK-DAG: %[[NTHREE:.*]] = spirv.Constant -3 : i32 832 // CHECK-DAG: %[[TWO:.*]] = spirv.Constant 2 : i32 833 // CHECK-DAG: %[[ZERO:.*]] = spirv.Constant 0 : i32 834 %0 = spirv.SRem %c56, %c7 : i32 835 %1 = spirv.SRem %c56, %cn8 : i32 836 %2 = spirv.SRem %c56, %c3 : i32 837 %3 = spirv.SRem %cn3, %c56 : i32 838 %4 = spirv.SRem %c7, %cn3 : i32 839 // CHECK: return %[[ZERO]], %[[ZERO]], %[[TWO]], %[[NTHREE]], %[[ONE]] 840 return %0, %1, %2, %3, %4 : i32, i32, i32, i32, i32 841} 842 843// ----- 844 845//===----------------------------------------------------------------------===// 846// spirv.UDiv 847//===----------------------------------------------------------------------===// 848 849// CHECK-LABEL: @udiv_x_1 850func.func @udiv_x_1(%arg0 : i32) -> i32 { 851 // CHECK-NEXT: return %arg0 : i32 852 %c1 = spirv.Constant 1 : i32 853 %2 = spirv.UDiv %arg0, %c1: i32 854 return %2 : i32 855} 856 857// CHECK-LABEL: @udiv_div_0 858func.func @udiv_div_0() -> i32 { 859 // CHECK-DAG: %[[C0:.*]] = spirv.Constant 0 860 // CHECK-DAG: %[[CN1:.*]] = spirv.Constant -1 861 %c0 = spirv.Constant 0 : i32 862 %cn1 = spirv.Constant -1 : i32 863 864 // CHECK: %0 = spirv.UDiv %[[CN1]], %[[C0]] 865 %0 = spirv.UDiv %cn1, %c0 : i32 866 return %0 : i32 867} 868 869// CHECK-LABEL: @const_fold_scalar_udiv 870func.func @const_fold_scalar_udiv() -> (i32, i32, i32) { 871 %c56 = spirv.Constant 56 : i32 872 %c7 = spirv.Constant 7 : i32 873 %cn8 = spirv.Constant -8 : i32 874 %c3 = spirv.Constant 3 : i32 875 876 // CHECK-DAG: %[[C0:.*]] = spirv.Constant 0 877 // CHECK-DAG: %[[CBIG:.*]] = spirv.Constant 1431655762 878 // CHECK-DAG: %[[C8:.*]] = spirv.Constant 8 879 %0 = spirv.UDiv %c56, %c7 : i32 880 %1 = spirv.UDiv %cn8, %c3 : i32 881 %2 = spirv.UDiv %c56, %cn8 : i32 882 883 // CHECK: return %[[C8]], %[[CBIG]], %[[C0]] 884 return %0, %1, %2 : i32, i32, i32 885} 886 887// ----- 888 889//===----------------------------------------------------------------------===// 890// spirv.UMod 891//===----------------------------------------------------------------------===// 892 893// CHECK-LABEL: @umod_x_1 894func.func @umod_x_1(%arg0: i32, %arg1: vector<3xi32>) -> (i32, vector<3xi32>) { 895 // CHECK-DAG: %[[C0:.*]] = spirv.Constant 0 896 // CHECK-DAG: %[[CVEC0:.*]] = spirv.Constant dense<0> 897 %c1 = spirv.Constant 1 : i32 898 %cv1 = spirv.Constant dense<1> : vector<3xi32> 899 %0 = spirv.UMod %arg0, %c1: i32 900 %1 = spirv.UMod %arg1, %cv1: vector<3xi32> 901 902 // CHECK: return %[[C0]], %[[CVEC0]] 903 return %0, %1 : i32, vector<3xi32> 904} 905 906// CHECK-LABEL: @umod_div_0 907func.func @umod_div_0() -> i32 { 908 // CHECK-DAG: %[[C0:.*]] = spirv.Constant 0 909 // CHECK-DAG: %[[CN1:.*]] = spirv.Constant -1 910 %c0 = spirv.Constant 0 : i32 911 %cn1 = spirv.Constant -1 : i32 912 913 // CHECK: %0 = spirv.UMod %[[CN1]], %[[C0]] 914 %0 = spirv.UMod %cn1, %c0 : i32 915 return %0 : i32 916} 917 918// CHECK-LABEL: @const_fold_scalar_umod 919func.func @const_fold_scalar_umod() -> (i32, i32, i32) { 920 %c56 = spirv.Constant 56 : i32 921 %c7 = spirv.Constant 7 : i32 922 %cn8 = spirv.Constant -8 : i32 923 %c3 = spirv.Constant 3 : i32 924 925 // CHECK-DAG: %[[C0:.*]] = spirv.Constant 0 926 // CHECK-DAG: %[[C2:.*]] = spirv.Constant 2 927 // CHECK-DAG: %[[C56:.*]] = spirv.Constant 56 928 %0 = spirv.UMod %c56, %c7 : i32 929 %1 = spirv.UMod %cn8, %c3 : i32 930 %2 = spirv.UMod %c56, %cn8 : i32 931 932 // CHECK: return %[[C0]], %[[C2]], %[[C56]] 933 return %0, %1, %2 : i32, i32, i32 934} 935 936// CHECK-LABEL: @const_fold_vector_umod 937func.func @const_fold_vector_umod() -> vector<3xi32> { 938 // CHECK: %[[CVEC:.*]] = spirv.Constant dense<[42, 24, 0]> 939 940 %cv = spirv.Constant dense<[42, 24, -16]> : vector<3xi32> 941 %cv_mod = spirv.Constant dense<[76, -7, 5]> : vector<3xi32> 942 %0 = spirv.UMod %cv, %cv_mod : vector<3xi32> 943 944 // CHECK: return %[[CVEC]] 945 return %0 : vector<3xi32> 946} 947 948// CHECK-LABEL: @umod_fold 949// CHECK-SAME: (%[[ARG:.*]]: i32) 950func.func @umod_fold(%arg0: i32) -> (i32, i32) { 951 // CHECK: %[[CONST4:.*]] = spirv.Constant 4 952 // CHECK: %[[CONST32:.*]] = spirv.Constant 32 953 %const1 = spirv.Constant 32 : i32 954 %0 = spirv.UMod %arg0, %const1 : i32 955 %const2 = spirv.Constant 4 : i32 956 %1 = spirv.UMod %0, %const2 : i32 957 // CHECK: %[[UMOD0:.*]] = spirv.UMod %[[ARG]], %[[CONST32]] 958 // CHECK: %[[UMOD1:.*]] = spirv.UMod %[[ARG]], %[[CONST4]] 959 // CHECK: return %[[UMOD0]], %[[UMOD1]] 960 return %0, %1: i32, i32 961} 962 963// CHECK-LABEL: @umod_fail_vector_fold 964// CHECK-SAME: (%[[ARG:.*]]: vector<4xi32>) 965func.func @umod_fail_vector_fold(%arg0: vector<4xi32>) -> (vector<4xi32>, vector<4xi32>) { 966 // CHECK: %[[CONST4:.*]] = spirv.Constant dense<4> : vector<4xi32> 967 // CHECK: %[[CONST32:.*]] = spirv.Constant dense<32> : vector<4xi32> 968 %const1 = spirv.Constant dense<32> : vector<4xi32> 969 %0 = spirv.UMod %arg0, %const1 : vector<4xi32> 970 // CHECK: %[[UMOD0:.*]] = spirv.UMod %[[ARG]], %[[CONST32]] 971 %const2 = spirv.Constant dense<4> : vector<4xi32> 972 %1 = spirv.UMod %0, %const2 : vector<4xi32> 973 // CHECK: %[[UMOD1:.*]] = spirv.UMod %[[UMOD0]], %[[CONST4]] 974 // CHECK: return %[[UMOD0]], %[[UMOD1]] 975 return %0, %1: vector<4xi32>, vector<4xi32> 976} 977 978// CHECK-LABEL: @umod_fold_same_divisor 979// CHECK-SAME: (%[[ARG:.*]]: i32) 980func.func @umod_fold_same_divisor(%arg0: i32) -> (i32, i32) { 981 // CHECK: %[[CONST1:.*]] = spirv.Constant 32 982 %const1 = spirv.Constant 32 : i32 983 %0 = spirv.UMod %arg0, %const1 : i32 984 %const2 = spirv.Constant 32 : i32 985 %1 = spirv.UMod %0, %const2 : i32 986 // CHECK: %[[UMOD0:.*]] = spirv.UMod %[[ARG]], %[[CONST1]] 987 // CHECK: %[[UMOD1:.*]] = spirv.UMod %[[ARG]], %[[CONST1]] 988 // CHECK: return %[[UMOD0]], %[[UMOD1]] 989 return %0, %1: i32, i32 990} 991 992// CHECK-LABEL: @umod_fail_fold 993// CHECK-SAME: (%[[ARG:.*]]: i32) 994func.func @umod_fail_fold(%arg0: i32) -> (i32, i32) { 995 // CHECK: %[[CONST5:.*]] = spirv.Constant 5 996 // CHECK: %[[CONST32:.*]] = spirv.Constant 32 997 %const1 = spirv.Constant 32 : i32 998 %0 = spirv.UMod %arg0, %const1 : i32 999 // CHECK: %[[UMOD0:.*]] = spirv.UMod %[[ARG]], %[[CONST32]] 1000 %const2 = spirv.Constant 5 : i32 1001 %1 = spirv.UMod %0, %const2 : i32 1002 // CHECK: %[[UMOD1:.*]] = spirv.UMod %[[UMOD0]], %[[CONST5]] 1003 // CHECK: return %[[UMOD0]], %[[UMOD1]] 1004 return %0, %1: i32, i32 1005} 1006 1007// ----- 1008 1009//===----------------------------------------------------------------------===// 1010// spirv.SNegate 1011//===----------------------------------------------------------------------===// 1012 1013// CHECK-LABEL: @snegate_twice 1014// CHECK-SAME: (%[[ARG:.*]]: i32) 1015func.func @snegate_twice(%arg0 : i32) -> i32 { 1016 %0 = spirv.SNegate %arg0 : i32 1017 %1 = spirv.SNegate %0 : i32 1018 1019 // CHECK: return %[[ARG]] : i32 1020 return %1 : i32 1021} 1022 1023// CHECK-LABEL: @snegate_min 1024func.func @snegate_min() -> (i8, i8) { 1025 // CHECK: %[[MIN:.*]] = spirv.Constant -128 : i8 1026 %cmin = spirv.Constant -128 : i8 1027 1028 %0 = spirv.SNegate %cmin : i8 1029 %1 = spirv.SNegate %0 : i8 1030 1031 // CHECK: return %[[MIN]], %[[MIN]] 1032 return %0, %1 : i8, i8 1033} 1034 1035// CHECK-LABEL: @const_fold_scalar_snegate 1036func.func @const_fold_scalar_snegate() -> (i32, i32, i32) { 1037 %c0 = spirv.Constant 0 : i32 1038 %c3 = spirv.Constant 3 : i32 1039 %cn3 = spirv.Constant -3 : i32 1040 1041 // CHECK-DAG: %[[THREE:.*]] = spirv.Constant 3 : i32 1042 // CHECK-DAG: %[[NTHREE:.*]] = spirv.Constant -3 : i32 1043 // CHECK-DAG: %[[ZERO:.*]] = spirv.Constant 0 : i32 1044 %0 = spirv.SNegate %c0 : i32 1045 %1 = spirv.SNegate %c3 : i32 1046 %2 = spirv.SNegate %cn3 : i32 1047 1048 // CHECK: return %[[ZERO]], %[[NTHREE]], %[[THREE]] 1049 return %0, %1, %2 : i32, i32, i32 1050} 1051 1052// CHECK-LABEL: @const_fold_vector_snegate 1053func.func @const_fold_vector_snegate() -> vector<3xi32> { 1054 // CHECK: spirv.Constant dense<[0, 3, -3]> 1055 %cv = spirv.Constant dense<[0, -3, 3]> : vector<3xi32> 1056 %0 = spirv.SNegate %cv : vector<3xi32> 1057 return %0 : vector<3xi32> 1058} 1059 1060// ----- 1061 1062//===----------------------------------------------------------------------===// 1063// spirv.Not 1064//===----------------------------------------------------------------------===// 1065 1066// CHECK-LABEL: @not_twice 1067// CHECK-SAME: (%[[ARG:.*]]: i32) 1068func.func @not_twice(%arg0 : i32) -> i32 { 1069 %0 = spirv.Not %arg0 : i32 1070 %1 = spirv.Not %0 : i32 1071 1072 // CHECK: return %[[ARG]] : i32 1073 return %1 : i32 1074} 1075 1076// CHECK-LABEL: @const_fold_scalar_not 1077func.func @const_fold_scalar_not() -> (i32, i32, i32) { 1078 %c0 = spirv.Constant 0 : i32 1079 %c3 = spirv.Constant 3 : i32 1080 %cn3 = spirv.Constant -3 : i32 1081 1082 // CHECK-DAG: %[[TWO:.*]] = spirv.Constant 2 : i32 1083 // CHECK-DAG: %[[NFOUR:.*]] = spirv.Constant -4 : i32 1084 // CHECK-DAG: %[[NONE:.*]] = spirv.Constant -1 : i32 1085 %0 = spirv.Not %c0 : i32 1086 %1 = spirv.Not %c3 : i32 1087 %2 = spirv.Not %cn3 : i32 1088 1089 // CHECK: return %[[NONE]], %[[NFOUR]], %[[TWO]] 1090 return %0, %1, %2 : i32, i32, i32 1091} 1092 1093// CHECK-LABEL: @const_fold_vector_not 1094func.func @const_fold_vector_not() -> vector<3xi32> { 1095 %cv = spirv.Constant dense<[-1, -4, 2]> : vector<3xi32> 1096 1097 // CHECK: spirv.Constant dense<[0, 3, -3]> 1098 %0 = spirv.Not %cv : vector<3xi32> 1099 1100 return %0 : vector<3xi32> 1101} 1102 1103// ----- 1104 1105//===----------------------------------------------------------------------===// 1106// spirv.LogicalAnd 1107//===----------------------------------------------------------------------===// 1108 1109// CHECK-LABEL: @convert_logical_and_true_false_scalar 1110// CHECK-SAME: %[[ARG:.+]]: i1 1111func.func @convert_logical_and_true_false_scalar(%arg: i1) -> (i1, i1) { 1112 %true = spirv.Constant true 1113 // CHECK: %[[FALSE:.+]] = spirv.Constant false 1114 %false = spirv.Constant false 1115 %0 = spirv.LogicalAnd %true, %arg: i1 1116 %1 = spirv.LogicalAnd %arg, %false: i1 1117 // CHECK: return %[[ARG]], %[[FALSE]] 1118 return %0, %1: i1, i1 1119} 1120 1121// CHECK-LABEL: @convert_logical_and_true_false_vector 1122// CHECK-SAME: %[[ARG:.+]]: vector<3xi1> 1123func.func @convert_logical_and_true_false_vector(%arg: vector<3xi1>) -> (vector<3xi1>, vector<3xi1>) { 1124 %true = spirv.Constant dense<true> : vector<3xi1> 1125 // CHECK: %[[FALSE:.+]] = spirv.Constant dense<false> 1126 %false = spirv.Constant dense<false> : vector<3xi1> 1127 %0 = spirv.LogicalAnd %true, %arg: vector<3xi1> 1128 %1 = spirv.LogicalAnd %arg, %false: vector<3xi1> 1129 // CHECK: return %[[ARG]], %[[FALSE]] 1130 return %0, %1: vector<3xi1>, vector<3xi1> 1131} 1132 1133// ----- 1134 1135//===----------------------------------------------------------------------===// 1136// spirv.LogicalNot 1137//===----------------------------------------------------------------------===// 1138 1139// CHECK-LABEL: @logical_not_twice 1140// CHECK-SAME: (%[[ARG:.*]]: i1) 1141func.func @logical_not_twice(%arg0 : i1) -> i1 { 1142 %0 = spirv.LogicalNot %arg0 : i1 1143 %1 = spirv.LogicalNot %0 : i1 1144 1145 // CHECK: return %[[ARG]] : i1 1146 return %1 : i1 1147} 1148 1149// CHECK-LABEL: @const_fold_scalar_logical_not 1150func.func @const_fold_scalar_logical_not() -> i1 { 1151 %true = spirv.Constant true 1152 1153 // CHECK: spirv.Constant false 1154 %0 = spirv.LogicalNot %true : i1 1155 1156 return %0 : i1 1157} 1158 1159// CHECK-LABEL: @const_fold_vector_logical_not 1160func.func @const_fold_vector_logical_not() -> vector<2xi1> { 1161 %cv = spirv.Constant dense<[true, false]> : vector<2xi1> 1162 1163 // CHECK: spirv.Constant dense<[false, true]> 1164 %0 = spirv.LogicalNot %cv : vector<2xi1> 1165 1166 return %0 : vector<2xi1> 1167} 1168 1169// ----- 1170 1171func.func @convert_logical_not_to_not_equal(%arg0: vector<3xi64>, %arg1: vector<3xi64>) -> vector<3xi1> { 1172 // CHECK: %[[RESULT:.*]] = spirv.INotEqual {{%.*}}, {{%.*}} : vector<3xi64> 1173 // CHECK-NEXT: spirv.ReturnValue %[[RESULT]] : vector<3xi1> 1174 %2 = spirv.IEqual %arg0, %arg1 : vector<3xi64> 1175 %3 = spirv.LogicalNot %2 : vector<3xi1> 1176 spirv.ReturnValue %3 : vector<3xi1> 1177} 1178 1179// ----- 1180 1181//===----------------------------------------------------------------------===// 1182// spirv.LogicalEqual 1183//===----------------------------------------------------------------------===// 1184 1185// CHECK-LABEL: @logical_equal_same 1186func.func @logical_equal_same(%arg0 : i1, %arg1 : vector<3xi1>) -> (i1, vector<3xi1>) { 1187 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1188 // CHECK-DAG: %[[CVTRUE:.*]] = spirv.Constant dense<true> 1189 1190 %0 = spirv.LogicalEqual %arg0, %arg0 : i1 1191 %1 = spirv.LogicalEqual %arg1, %arg1 : vector<3xi1> 1192 // CHECK: return %[[CTRUE]], %[[CVTRUE]] 1193 return %0, %1 : i1, vector<3xi1> 1194} 1195 1196// CHECK-LABEL: @const_fold_scalar_logical_equal 1197func.func @const_fold_scalar_logical_equal() -> (i1, i1) { 1198 %true = spirv.Constant true 1199 %false = spirv.Constant false 1200 1201 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1202 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1203 %0 = spirv.LogicalEqual %true, %false : i1 1204 %1 = spirv.LogicalEqual %false, %false : i1 1205 1206 // CHECK: return %[[CFALSE]], %[[CTRUE]] 1207 return %0, %1 : i1, i1 1208} 1209 1210// CHECK-LABEL: @const_fold_vector_logical_equal 1211func.func @const_fold_vector_logical_equal() -> vector<3xi1> { 1212 %cv0 = spirv.Constant dense<[true, false, true]> : vector<3xi1> 1213 %cv1 = spirv.Constant dense<[true, false, false]> : vector<3xi1> 1214 1215 // CHECK: %[[RET:.*]] = spirv.Constant dense<[true, true, false]> 1216 %0 = spirv.LogicalEqual %cv0, %cv1 : vector<3xi1> 1217 1218 // CHECK: return %[[RET]] 1219 return %0 : vector<3xi1> 1220} 1221 1222// ----- 1223 1224//===----------------------------------------------------------------------===// 1225// spirv.LogicalNotEqual 1226//===----------------------------------------------------------------------===// 1227 1228// CHECK-LABEL: @convert_logical_not_equal_false 1229// CHECK-SAME: %[[ARG:.+]]: vector<4xi1> 1230func.func @convert_logical_not_equal_false(%arg: vector<4xi1>) -> vector<4xi1> { 1231 %cst = spirv.Constant dense<false> : vector<4xi1> 1232 // CHECK: spirv.ReturnValue %[[ARG]] : vector<4xi1> 1233 %0 = spirv.LogicalNotEqual %arg, %cst : vector<4xi1> 1234 spirv.ReturnValue %0 : vector<4xi1> 1235} 1236 1237// CHECK-LABEL: @logical_not_equal_same 1238func.func @logical_not_equal_same(%arg0 : i1, %arg1 : vector<3xi1>) -> (i1, vector<3xi1>) { 1239 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1240 // CHECK-DAG: %[[CVFALSE:.*]] = spirv.Constant dense<false> 1241 %0 = spirv.LogicalNotEqual %arg0, %arg0 : i1 1242 %1 = spirv.LogicalNotEqual %arg1, %arg1 : vector<3xi1> 1243 1244 // CHECK: return %[[CFALSE]], %[[CVFALSE]] 1245 return %0, %1 : i1, vector<3xi1> 1246} 1247 1248// CHECK-LABEL: @const_fold_scalar_logical_not_equal 1249func.func @const_fold_scalar_logical_not_equal() -> (i1, i1) { 1250 %true = spirv.Constant true 1251 %false = spirv.Constant false 1252 1253 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1254 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1255 %0 = spirv.LogicalNotEqual %true, %false : i1 1256 %1 = spirv.LogicalNotEqual %false, %false : i1 1257 1258 // CHECK: return %[[CTRUE]], %[[CFALSE]] 1259 return %0, %1 : i1, i1 1260} 1261 1262// CHECK-LABEL: @const_fold_vector_logical_not_equal 1263func.func @const_fold_vector_logical_not_equal() -> vector<3xi1> { 1264 %cv0 = spirv.Constant dense<[true, false, true]> : vector<3xi1> 1265 %cv1 = spirv.Constant dense<[true, false, false]> : vector<3xi1> 1266 1267 // CHECK: %[[RET:.*]] = spirv.Constant dense<[false, false, true]> 1268 %0 = spirv.LogicalNotEqual %cv0, %cv1 : vector<3xi1> 1269 1270 // CHECK: return %[[RET]] 1271 return %0 : vector<3xi1> 1272} 1273 1274// ----- 1275 1276func.func @convert_logical_not_to_equal(%arg0: vector<3xi64>, %arg1: vector<3xi64>) -> vector<3xi1> { 1277 // CHECK: %[[RESULT:.*]] = spirv.IEqual {{%.*}}, {{%.*}} : vector<3xi64> 1278 // CHECK-NEXT: spirv.ReturnValue %[[RESULT]] : vector<3xi1> 1279 %2 = spirv.INotEqual %arg0, %arg1 : vector<3xi64> 1280 %3 = spirv.LogicalNot %2 : vector<3xi1> 1281 spirv.ReturnValue %3 : vector<3xi1> 1282} 1283 1284// ----- 1285 1286func.func @convert_logical_not_parent_multi_use(%arg0: vector<3xi64>, %arg1: vector<3xi64>, %arg2: !spirv.ptr<vector<3xi1>, Uniform>) -> vector<3xi1> { 1287 // CHECK: %[[RESULT_0:.*]] = spirv.INotEqual {{%.*}}, {{%.*}} : vector<3xi64> 1288 // CHECK-NEXT: %[[RESULT_1:.*]] = spirv.IEqual {{%.*}}, {{%.*}} : vector<3xi64> 1289 // CHECK-NEXT: spirv.Store "Uniform" {{%.*}}, %[[RESULT_0]] 1290 // CHECK-NEXT: spirv.ReturnValue %[[RESULT_1]] 1291 %0 = spirv.INotEqual %arg0, %arg1 : vector<3xi64> 1292 %1 = spirv.LogicalNot %0 : vector<3xi1> 1293 spirv.Store "Uniform" %arg2, %0 : vector<3xi1> 1294 spirv.ReturnValue %1 : vector<3xi1> 1295} 1296 1297// ----- 1298 1299func.func @convert_logical_not_to_logical_not_equal(%arg0: vector<3xi1>, %arg1: vector<3xi1>) -> vector<3xi1> { 1300 // CHECK: %[[RESULT:.*]] = spirv.LogicalNotEqual {{%.*}}, {{%.*}} : vector<3xi1> 1301 // CHECK-NEXT: spirv.ReturnValue %[[RESULT]] : vector<3xi1> 1302 %2 = spirv.LogicalEqual %arg0, %arg1 : vector<3xi1> 1303 %3 = spirv.LogicalNot %2 : vector<3xi1> 1304 spirv.ReturnValue %3 : vector<3xi1> 1305} 1306 1307// ----- 1308 1309func.func @convert_logical_not_to_logical_equal(%arg0: vector<3xi1>, %arg1: vector<3xi1>) -> vector<3xi1> { 1310 // CHECK: %[[RESULT:.*]] = spirv.LogicalEqual {{%.*}}, {{%.*}} : vector<3xi1> 1311 // CHECK-NEXT: spirv.ReturnValue %[[RESULT]] : vector<3xi1> 1312 %2 = spirv.LogicalNotEqual %arg0, %arg1 : vector<3xi1> 1313 %3 = spirv.LogicalNot %2 : vector<3xi1> 1314 spirv.ReturnValue %3 : vector<3xi1> 1315} 1316 1317// ----- 1318 1319//===----------------------------------------------------------------------===// 1320// spirv.LogicalOr 1321//===----------------------------------------------------------------------===// 1322 1323// CHECK-LABEL: @convert_logical_or_true_false_scalar 1324// CHECK-SAME: %[[ARG:.+]]: i1 1325func.func @convert_logical_or_true_false_scalar(%arg: i1) -> (i1, i1) { 1326 // CHECK: %[[TRUE:.+]] = spirv.Constant true 1327 %true = spirv.Constant true 1328 %false = spirv.Constant false 1329 %0 = spirv.LogicalOr %true, %arg: i1 1330 %1 = spirv.LogicalOr %arg, %false: i1 1331 // CHECK: return %[[TRUE]], %[[ARG]] 1332 return %0, %1: i1, i1 1333} 1334 1335// CHECK-LABEL: @convert_logical_or_true_false_vector 1336// CHECK-SAME: %[[ARG:.+]]: vector<3xi1> 1337func.func @convert_logical_or_true_false_vector(%arg: vector<3xi1>) -> (vector<3xi1>, vector<3xi1>) { 1338 // CHECK: %[[TRUE:.+]] = spirv.Constant dense<true> 1339 %true = spirv.Constant dense<true> : vector<3xi1> 1340 %false = spirv.Constant dense<false> : vector<3xi1> 1341 %0 = spirv.LogicalOr %true, %arg: vector<3xi1> 1342 %1 = spirv.LogicalOr %arg, %false: vector<3xi1> 1343 // CHECK: return %[[TRUE]], %[[ARG]] 1344 return %0, %1: vector<3xi1>, vector<3xi1> 1345} 1346 1347// ----- 1348 1349//===----------------------------------------------------------------------===// 1350// spirv.Select 1351//===----------------------------------------------------------------------===// 1352 1353// CHECK-LABEL: @convert_select_scalar 1354// CHECK-SAME: %[[ARG1:.+]]: i32, %[[ARG2:.+]]: i32 1355func.func @convert_select_scalar(%arg1: i32, %arg2: i32) -> (i32, i32) { 1356 %true = spirv.Constant true 1357 %false = spirv.Constant false 1358 %0 = spirv.Select %true, %arg1, %arg2 : i1, i32 1359 %1 = spirv.Select %false, %arg1, %arg2 : i1, i32 1360 1361 // CHECK: return %[[ARG1]], %[[ARG2]] 1362 return %0, %1 : i32, i32 1363} 1364 1365// CHECK-LABEL: @convert_select_vector 1366// CHECK-SAME: %[[ARG1:.+]]: vector<3xi32>, %[[ARG2:.+]]: vector<3xi32> 1367func.func @convert_select_vector(%arg1: vector<3xi32>, %arg2: vector<3xi32>) -> (vector<3xi32>, vector<3xi32>) { 1368 %true = spirv.Constant dense<true> : vector<3xi1> 1369 %false = spirv.Constant dense<false> : vector<3xi1> 1370 %0 = spirv.Select %true, %arg1, %arg2 : vector<3xi1>, vector<3xi32> 1371 %1 = spirv.Select %false, %arg1, %arg2 : vector<3xi1>, vector<3xi32> 1372 1373 // CHECK: return %[[ARG1]], %[[ARG2]] 1374 return %0, %1: vector<3xi32>, vector<3xi32> 1375} 1376 1377// CHECK-LABEL: @convert_select_vector_extra 1378// CHECK-SAME: %[[CONDITIONS:.+]]: vector<2xi1>, %[[ARG1:.+]]: vector<2xi32> 1379func.func @convert_select_vector_extra(%conditions: vector<2xi1>, %arg1: vector<2xi32>) -> (vector<2xi32>, vector<2xi32>) { 1380 %true_false = spirv.Constant dense<[true, false]> : vector<2xi1> 1381 %cvec_1 = spirv.Constant dense<[42, -132]> : vector<2xi32> 1382 %cvec_2 = spirv.Constant dense<[0, 42]> : vector<2xi32> 1383 1384 // CHECK: %[[RES:.+]] = spirv.Constant dense<42> 1385 %0 = spirv.Select %true_false, %cvec_1, %cvec_2: vector<2xi1>, vector<2xi32> 1386 1387 %1 = spirv.Select %conditions, %arg1, %arg1 : vector<2xi1>, vector<2xi32> 1388 1389 // CHECK: return %[[RES]], %[[ARG1]] 1390 return %0, %1: vector<2xi32>, vector<2xi32> 1391} 1392 1393// ----- 1394 1395//===----------------------------------------------------------------------===// 1396// spirv.IEqual 1397//===----------------------------------------------------------------------===// 1398 1399// CHECK-LABEL: @iequal_same 1400func.func @iequal_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { 1401 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1402 // CHECK-DAG: %[[CVTRUE:.*]] = spirv.Constant dense<true> 1403 %0 = spirv.IEqual %arg0, %arg0 : i32 1404 %1 = spirv.IEqual %arg1, %arg1 : vector<3xi32> 1405 1406 // CHECK: return %[[CTRUE]], %[[CVTRUE]] 1407 return %0, %1 : i1, vector<3xi1> 1408} 1409 1410// CHECK-LABEL: @const_fold_scalar_iequal 1411func.func @const_fold_scalar_iequal() -> (i1, i1) { 1412 %c5 = spirv.Constant 5 : i32 1413 %c6 = spirv.Constant 6 : i32 1414 1415 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1416 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1417 %0 = spirv.IEqual %c5, %c6 : i32 1418 %1 = spirv.IEqual %c5, %c5 : i32 1419 1420 // CHECK: return %[[CFALSE]], %[[CTRUE]] 1421 return %0, %1 : i1, i1 1422} 1423 1424// CHECK-LABEL: @const_fold_vector_iequal 1425func.func @const_fold_vector_iequal() -> vector<3xi1> { 1426 %cv0 = spirv.Constant dense<[-1, -4, 2]> : vector<3xi32> 1427 %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> 1428 1429 // CHECK: %[[RET:.*]] = spirv.Constant dense<[true, false, true]> 1430 %0 = spirv.IEqual %cv0, %cv1 : vector<3xi32> 1431 1432 // CHECK: return %[[RET]] 1433 return %0 : vector<3xi1> 1434} 1435 1436// ----- 1437 1438//===----------------------------------------------------------------------===// 1439// spirv.INotEqual 1440//===----------------------------------------------------------------------===// 1441 1442// CHECK-LABEL: @inotequal_same 1443func.func @inotequal_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { 1444 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1445 // CHECK-DAG: %[[CVFALSE:.*]] = spirv.Constant dense<false> 1446 %0 = spirv.INotEqual %arg0, %arg0 : i32 1447 %1 = spirv.INotEqual %arg1, %arg1 : vector<3xi32> 1448 1449 // CHECK: return %[[CFALSE]], %[[CVFALSE]] 1450 return %0, %1 : i1, vector<3xi1> 1451} 1452 1453// CHECK-LABEL: @const_fold_scalar_inotequal 1454func.func @const_fold_scalar_inotequal() -> (i1, i1) { 1455 %c5 = spirv.Constant 5 : i32 1456 %c6 = spirv.Constant 6 : i32 1457 1458 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1459 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1460 %0 = spirv.INotEqual %c5, %c6 : i32 1461 %1 = spirv.INotEqual %c5, %c5 : i32 1462 1463 // CHECK: return %[[CTRUE]], %[[CFALSE]] 1464 return %0, %1 : i1, i1 1465} 1466 1467// CHECK-LABEL: @const_fold_vector_inotequal 1468func.func @const_fold_vector_inotequal() -> vector<3xi1> { 1469 %cv0 = spirv.Constant dense<[-1, -4, 2]> : vector<3xi32> 1470 %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> 1471 1472 // CHECK: %[[RET:.*]] = spirv.Constant dense<[false, true, false]> 1473 %0 = spirv.INotEqual %cv0, %cv1 : vector<3xi32> 1474 1475 // CHECK: return %[[RET]] 1476 return %0 : vector<3xi1> 1477} 1478 1479// ----- 1480 1481//===----------------------------------------------------------------------===// 1482// spirv.SGreaterThan 1483//===----------------------------------------------------------------------===// 1484 1485// CHECK-LABEL: @sgt_same 1486func.func @sgt_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { 1487 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1488 // CHECK-DAG: %[[CVFALSE:.*]] = spirv.Constant dense<false> 1489 %0 = spirv.SGreaterThan %arg0, %arg0 : i32 1490 %1 = spirv.SGreaterThan %arg1, %arg1 : vector<3xi32> 1491 1492 // CHECK: return %[[CFALSE]], %[[CVFALSE]] 1493 return %0, %1 : i1, vector<3xi1> 1494} 1495 1496// CHECK-LABEL: @const_fold_scalar_sgt 1497func.func @const_fold_scalar_sgt() -> (i1, i1) { 1498 %c4 = spirv.Constant 4 : i32 1499 %c5 = spirv.Constant 5 : i32 1500 %c6 = spirv.Constant 6 : i32 1501 1502 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1503 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1504 %0 = spirv.SGreaterThan %c5, %c6 : i32 1505 %1 = spirv.SGreaterThan %c5, %c4 : i32 1506 1507 // CHECK: return %[[CFALSE]], %[[CTRUE]] 1508 return %0, %1 : i1, i1 1509} 1510 1511// CHECK-LABEL: @const_fold_vector_sgt 1512func.func @const_fold_vector_sgt() -> vector<3xi1> { 1513 %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> 1514 %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> 1515 1516 // CHECK: %[[RET:.*]] = spirv.Constant dense<[false, false, true]> 1517 %0 = spirv.SGreaterThan %cv0, %cv1 : vector<3xi32> 1518 1519 // CHECK: return %[[RET]] 1520 return %0 : vector<3xi1> 1521} 1522 1523// ----- 1524 1525//===----------------------------------------------------------------------===// 1526// spirv.SGreaterThanEqual 1527//===----------------------------------------------------------------------===// 1528 1529// CHECK-LABEL: @sge_same 1530func.func @sge_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { 1531 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1532 // CHECK-DAG: %[[CVTRUE:.*]] = spirv.Constant dense<true> 1533 %0 = spirv.SGreaterThanEqual %arg0, %arg0 : i32 1534 %1 = spirv.SGreaterThanEqual %arg1, %arg1 : vector<3xi32> 1535 1536 // CHECK: return %[[CTRUE]], %[[CVTRUE]] 1537 return %0, %1 : i1, vector<3xi1> 1538} 1539 1540// CHECK-LABEL: @const_fold_scalar_sge 1541func.func @const_fold_scalar_sge() -> (i1, i1) { 1542 %c4 = spirv.Constant 4 : i32 1543 %c5 = spirv.Constant 5 : i32 1544 %c6 = spirv.Constant 6 : i32 1545 1546 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1547 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1548 %0 = spirv.SGreaterThanEqual %c5, %c6 : i32 1549 %1 = spirv.SGreaterThanEqual %c5, %c4 : i32 1550 1551 // CHECK: return %[[CFALSE]], %[[CTRUE]] 1552 return %0, %1 : i1, i1 1553} 1554 1555// CHECK-LABEL: @const_fold_vector_sge 1556func.func @const_fold_vector_sge() -> vector<3xi1> { 1557 %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> 1558 %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> 1559 1560 // CHECK: %[[RET:.*]] = spirv.Constant dense<[true, false, true]> 1561 %0 = spirv.SGreaterThanEqual %cv0, %cv1 : vector<3xi32> 1562 1563 // CHECK: return %[[RET]] 1564 return %0 : vector<3xi1> 1565} 1566 1567// ----- 1568 1569//===----------------------------------------------------------------------===// 1570// spirv.UGreaterThan 1571//===----------------------------------------------------------------------===// 1572 1573// CHECK-LABEL: @ugt_same 1574func.func @ugt_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { 1575 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1576 // CHECK-DAG: %[[CVFALSE:.*]] = spirv.Constant dense<false> 1577 %0 = spirv.UGreaterThan %arg0, %arg0 : i32 1578 %1 = spirv.UGreaterThan %arg1, %arg1 : vector<3xi32> 1579 1580 // CHECK: return %[[CFALSE]], %[[CVFALSE]] 1581 return %0, %1 : i1, vector<3xi1> 1582} 1583 1584// CHECK-LABEL: @const_fold_scalar_ugt 1585func.func @const_fold_scalar_ugt() -> (i1, i1) { 1586 %c4 = spirv.Constant 4 : i32 1587 %c5 = spirv.Constant 5 : i32 1588 %cn6 = spirv.Constant -6 : i32 1589 1590 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1591 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1592 %0 = spirv.UGreaterThan %c5, %cn6 : i32 1593 %1 = spirv.UGreaterThan %c5, %c4 : i32 1594 1595 // CHECK: return %[[CFALSE]], %[[CTRUE]] 1596 return %0, %1 : i1, i1 1597} 1598 1599// CHECK-LABEL: @const_fold_vector_ugt 1600func.func @const_fold_vector_ugt() -> vector<3xi1> { 1601 %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> 1602 %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> 1603 1604 // CHECK: %[[RET:.*]] = spirv.Constant dense<[false, false, true]> 1605 %0 = spirv.UGreaterThan %cv0, %cv1 : vector<3xi32> 1606 1607 // CHECK: return %[[RET]] 1608 return %0 : vector<3xi1> 1609} 1610 1611// ----- 1612 1613//===----------------------------------------------------------------------===// 1614// spirv.UGreaterThanEqual 1615//===----------------------------------------------------------------------===// 1616 1617// CHECK-LABEL: @uge_same 1618func.func @uge_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { 1619 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1620 // CHECK-DAG: %[[CVTRUE:.*]] = spirv.Constant dense<true> 1621 %0 = spirv.UGreaterThanEqual %arg0, %arg0 : i32 1622 %1 = spirv.UGreaterThanEqual %arg1, %arg1 : vector<3xi32> 1623 1624 // CHECK: return %[[CTRUE]], %[[CVTRUE]] 1625 return %0, %1 : i1, vector<3xi1> 1626} 1627 1628// CHECK-LABEL: @const_fold_scalar_uge 1629func.func @const_fold_scalar_uge() -> (i1, i1) { 1630 %c4 = spirv.Constant 4 : i32 1631 %c5 = spirv.Constant 5 : i32 1632 %cn6 = spirv.Constant -6 : i32 1633 1634 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1635 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1636 %0 = spirv.UGreaterThanEqual %c5, %cn6 : i32 1637 %1 = spirv.UGreaterThanEqual %c5, %c4 : i32 1638 1639 // CHECK: return %[[CFALSE]], %[[CTRUE]] 1640 return %0, %1 : i1, i1 1641} 1642 1643// CHECK-LABEL: @const_fold_vector_uge 1644func.func @const_fold_vector_uge() -> vector<3xi1> { 1645 %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> 1646 %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> 1647 1648 // CHECK: %[[RET:.*]] = spirv.Constant dense<[true, false, true]> 1649 %0 = spirv.UGreaterThanEqual %cv0, %cv1 : vector<3xi32> 1650 1651 // CHECK: return %[[RET]] 1652 return %0 : vector<3xi1> 1653} 1654 1655// ----- 1656 1657//===----------------------------------------------------------------------===// 1658// spirv.SLessThan 1659//===----------------------------------------------------------------------===// 1660 1661// CHECK-LABEL: @slt_same 1662func.func @slt_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { 1663 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1664 // CHECK-DAG: %[[CVFALSE:.*]] = spirv.Constant dense<false> 1665 %0 = spirv.SLessThan %arg0, %arg0 : i32 1666 %1 = spirv.SLessThan %arg1, %arg1 : vector<3xi32> 1667 1668 // CHECK: return %[[CFALSE]], %[[CVFALSE]] 1669 return %0, %1 : i1, vector<3xi1> 1670} 1671 1672// CHECK-LABEL: @const_fold_scalar_slt 1673func.func @const_fold_scalar_slt() -> (i1, i1) { 1674 %c4 = spirv.Constant 4 : i32 1675 %c5 = spirv.Constant 5 : i32 1676 %c6 = spirv.Constant 6 : i32 1677 1678 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1679 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1680 %0 = spirv.SLessThan %c5, %c6 : i32 1681 %1 = spirv.SLessThan %c5, %c4 : i32 1682 1683 // CHECK: return %[[CTRUE]], %[[CFALSE]] 1684 return %0, %1 : i1, i1 1685} 1686 1687// CHECK-LABEL: @const_fold_vector_slt 1688func.func @const_fold_vector_slt() -> vector<3xi1> { 1689 %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> 1690 %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> 1691 1692 // CHECK: %[[RET:.*]] = spirv.Constant dense<[false, true, false]> 1693 %0 = spirv.SLessThan %cv0, %cv1 : vector<3xi32> 1694 1695 // CHECK: return %[[RET]] 1696 return %0 : vector<3xi1> 1697} 1698 1699// ----- 1700 1701//===----------------------------------------------------------------------===// 1702// spirv.SLessThanEqual 1703//===----------------------------------------------------------------------===// 1704 1705// CHECK-LABEL: @sle_same 1706func.func @sle_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { 1707 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1708 // CHECK-DAG: %[[CVTRUE:.*]] = spirv.Constant dense<true> 1709 %0 = spirv.SLessThanEqual %arg0, %arg0 : i32 1710 %1 = spirv.SLessThanEqual %arg1, %arg1 : vector<3xi32> 1711 1712 // CHECK: return %[[CTRUE]], %[[CVTRUE]] 1713 return %0, %1 : i1, vector<3xi1> 1714} 1715 1716// CHECK-LABEL: @const_fold_scalar_sle 1717func.func @const_fold_scalar_sle() -> (i1, i1) { 1718 %c4 = spirv.Constant 4 : i32 1719 %c5 = spirv.Constant 5 : i32 1720 %c6 = spirv.Constant 6 : i32 1721 1722 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1723 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1724 %0 = spirv.SLessThanEqual %c5, %c6 : i32 1725 %1 = spirv.SLessThanEqual %c5, %c4 : i32 1726 1727 // CHECK: return %[[CTRUE]], %[[CFALSE]] 1728 return %0, %1 : i1, i1 1729} 1730 1731// CHECK-LABEL: @const_fold_vector_sle 1732func.func @const_fold_vector_sle() -> vector<3xi1> { 1733 %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> 1734 %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> 1735 1736 // CHECK: %[[RET:.*]] = spirv.Constant dense<[true, true, false]> 1737 %0 = spirv.SLessThanEqual %cv0, %cv1 : vector<3xi32> 1738 1739 // CHECK: return %[[RET]] 1740 return %0 : vector<3xi1> 1741} 1742 1743// ----- 1744 1745//===----------------------------------------------------------------------===// 1746// spirv.ULessThan 1747//===----------------------------------------------------------------------===// 1748 1749// CHECK-LABEL: @ult_same 1750func.func @ult_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { 1751 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1752 // CHECK-DAG: %[[CVFALSE:.*]] = spirv.Constant dense<false> 1753 %0 = spirv.ULessThan %arg0, %arg0 : i32 1754 %1 = spirv.ULessThan %arg1, %arg1 : vector<3xi32> 1755 1756 // CHECK: return %[[CFALSE]], %[[CVFALSE]] 1757 return %0, %1 : i1, vector<3xi1> 1758} 1759 1760// CHECK-LABEL: @const_fold_scalar_ult 1761func.func @const_fold_scalar_ult() -> (i1, i1) { 1762 %c4 = spirv.Constant 4 : i32 1763 %c5 = spirv.Constant 5 : i32 1764 %cn6 = spirv.Constant -6 : i32 1765 1766 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1767 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1768 %0 = spirv.ULessThan %c5, %cn6 : i32 1769 %1 = spirv.ULessThan %c5, %c4 : i32 1770 1771 // CHECK: return %[[CTRUE]], %[[CFALSE]] 1772 return %0, %1 : i1, i1 1773} 1774 1775// CHECK-LABEL: @const_fold_vector_ult 1776func.func @const_fold_vector_ult() -> vector<3xi1> { 1777 %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> 1778 %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> 1779 1780 // CHECK: %[[RET:.*]] = spirv.Constant dense<[false, true, false]> 1781 %0 = spirv.ULessThan %cv0, %cv1 : vector<3xi32> 1782 1783 // CHECK: return %[[RET]] 1784 return %0 : vector<3xi1> 1785} 1786 1787// ----- 1788 1789//===----------------------------------------------------------------------===// 1790// spirv.ULessThanEqual 1791//===----------------------------------------------------------------------===// 1792 1793// CHECK-LABEL: @ule_same 1794func.func @ule_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { 1795 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1796 // CHECK-DAG: %[[CVTRUE:.*]] = spirv.Constant dense<true> 1797 %0 = spirv.ULessThanEqual %arg0, %arg0 : i32 1798 %1 = spirv.ULessThanEqual %arg1, %arg1 : vector<3xi32> 1799 1800 // CHECK: return %[[CTRUE]], %[[CVTRUE]] 1801 return %0, %1 : i1, vector<3xi1> 1802} 1803 1804// CHECK-LABEL: @const_fold_scalar_ule 1805func.func @const_fold_scalar_ule() -> (i1, i1) { 1806 %c4 = spirv.Constant 4 : i32 1807 %c5 = spirv.Constant 5 : i32 1808 %cn6 = spirv.Constant -6 : i32 1809 1810 // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true 1811 // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false 1812 %0 = spirv.ULessThanEqual %c5, %cn6 : i32 1813 %1 = spirv.ULessThanEqual %c5, %c4 : i32 1814 1815 // CHECK: return %[[CTRUE]], %[[CFALSE]] 1816 return %0, %1 : i1, i1 1817} 1818 1819// CHECK-LABEL: @const_fold_vector_ule 1820func.func @const_fold_vector_ule() -> vector<3xi1> { 1821 %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> 1822 %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> 1823 1824 // CHECK: %[[RET:.*]] = spirv.Constant dense<[true, true, false]> 1825 %0 = spirv.ULessThanEqual %cv0, %cv1 : vector<3xi32> 1826 1827 // CHECK: return %[[RET]] 1828 return %0 : vector<3xi1> 1829} 1830 1831// ----- 1832 1833//===----------------------------------------------------------------------===// 1834// spirv.LeftShiftLogical 1835//===----------------------------------------------------------------------===// 1836 1837// CHECK-LABEL: @lsl_x_0 1838// CHECK-SAME: (%[[ARG0:.*]]: i32, %[[ARG1:.*]]: vector<3xi32>) 1839func.func @lsl_x_0(%arg0 : i32, %arg1: vector<3xi32>) -> (i32, vector<3xi32>) { 1840 %c0 = spirv.Constant 0 : i32 1841 %cv0 = spirv.Constant dense<0> : vector<3xi32> 1842 1843 %0 = spirv.ShiftLeftLogical %arg0, %c0 : i32, i32 1844 %1 = spirv.ShiftLeftLogical %arg1, %cv0 : vector<3xi32>, vector<3xi32> 1845 1846 // CHECK: return %[[ARG0]], %[[ARG1]] 1847 return %0, %1 : i32, vector<3xi32> 1848} 1849 1850// CHECK-LABEL: @lsl_shift_overflow 1851// CHECK-SAME: (%[[ARG0:.*]]: i32, %[[ARG1:.*]]: vector<3xi32>) 1852func.func @lsl_shift_overflow(%arg0: i32, %arg1: vector<3xi32>) -> (i32, vector<3xi32>) { 1853 // CHECK-DAG: %[[C32:.*]] = spirv.Constant 32 1854 // CHECK-DAG: %[[CV:.*]] = spirv.Constant dense<[6, 18, 128]> 1855 %c32 = spirv.Constant 32 : i32 1856 %cv = spirv.Constant dense<[6, 18, 128]> : vector<3xi32> 1857 1858 // CHECK: %0 = spirv.ShiftLeftLogical %[[ARG0]], %[[C32]] 1859 // CHECK: %1 = spirv.ShiftLeftLogical %[[ARG1]], %[[CV]] 1860 %0 = spirv.ShiftLeftLogical %arg0, %c32 : i32, i32 1861 %1 = spirv.ShiftLeftLogical %arg1, %cv : vector<3xi32>, vector<3xi32> 1862 1863 return %0, %1 : i32, vector<3xi32> 1864} 1865 1866// CHECK-LABEL: @const_fold_scalar_lsl 1867func.func @const_fold_scalar_lsl() -> i32 { 1868 %c1 = spirv.Constant 65535 : i32 // 0x0000 ffff 1869 %c2 = spirv.Constant 17 : i32 1870 1871 // CHECK: %[[RET:.*]] = spirv.Constant -131072 1872 // 0x0000 ffff << 17 -> 0xfffe 0000 1873 %0 = spirv.ShiftLeftLogical %c1, %c2 : i32, i32 1874 1875 // CHECK: return %[[RET]] 1876 return %0 : i32 1877} 1878 1879// CHECK-LABEL: @const_fold_vector_lsl 1880func.func @const_fold_vector_lsl() -> vector<3xi32> { 1881 %c1 = spirv.Constant dense<[1, -1, 127]> : vector<3xi32> 1882 %c2 = spirv.Constant dense<[31, 16, 13]> : vector<3xi32> 1883 1884 // CHECK: %[[RET:.*]] = spirv.Constant dense<[-2147483648, -65536, 1040384]> 1885 %0 = spirv.ShiftLeftLogical %c1, %c2 : vector<3xi32>, vector<3xi32> 1886 1887 // CHECK: return %[[RET]] 1888 return %0 : vector<3xi32> 1889} 1890 1891// ----- 1892 1893//===----------------------------------------------------------------------===// 1894// spirv.RightShiftArithmetic 1895//===----------------------------------------------------------------------===// 1896 1897// CHECK-LABEL: @asr_x_0 1898// CHECK-SAME: (%[[ARG0:.*]]: i32, %[[ARG1:.*]]: vector<3xi32>) 1899func.func @asr_x_0(%arg0 : i32, %arg1: vector<3xi32>) -> (i32, vector<3xi32>) { 1900 %c0 = spirv.Constant 0 : i32 1901 %cv0 = spirv.Constant dense<0> : vector<3xi32> 1902 1903 %0 = spirv.ShiftRightArithmetic %arg0, %c0 : i32, i32 1904 %1 = spirv.ShiftRightArithmetic %arg1, %cv0 : vector<3xi32>, vector<3xi32> 1905 1906 // CHECK: return %[[ARG0]], %[[ARG1]] 1907 return %0, %1 : i32, vector<3xi32> 1908} 1909 1910// CHECK-LABEL: @asr_shift_overflow 1911// CHECK-SAME: (%[[ARG0:.*]]: i32, %[[ARG1:.*]]: vector<3xi32>) 1912func.func @asr_shift_overflow(%arg0: i32, %arg1: vector<3xi32>) -> (i32, vector<3xi32>) { 1913 // CHECK-DAG: %[[C32:.*]] = spirv.Constant 32 1914 // CHECK-DAG: %[[CV:.*]] = spirv.Constant dense<[6, 18, 128]> 1915 %c32 = spirv.Constant 32 : i32 1916 %cv = spirv.Constant dense<[6, 18, 128]> : vector<3xi32> 1917 1918 // CHECK: %0 = spirv.ShiftRightArithmetic %[[ARG0]], %[[C32]] 1919 // CHECK: %1 = spirv.ShiftRightArithmetic %[[ARG1]], %[[CV]] 1920 %0 = spirv.ShiftRightArithmetic %arg0, %c32 : i32, i32 1921 %1 = spirv.ShiftRightArithmetic %arg1, %cv : vector<3xi32>, vector<3xi32> 1922 1923 return %0, %1 : i32, vector<3xi32> 1924} 1925 1926// CHECK-LABEL: @const_fold_scalar_asr 1927func.func @const_fold_scalar_asr() -> i32 { 1928 %c1 = spirv.Constant -131072 : i32 // 0xfffe 0000 1929 %c2 = spirv.Constant 17 : i32 1930 // 0x0000 ffff ashr 17 -> 0xffff ffff 1931 // CHECK: %[[RET:.*]] = spirv.Constant -1 1932 %0 = spirv.ShiftRightArithmetic %c1, %c2 : i32, i32 1933 1934 // CHECK: return %[[RET]] 1935 return %0 : i32 1936} 1937 1938// CHECK-LABEL: @const_fold_vector_asr 1939func.func @const_fold_vector_asr() -> vector<3xi32> { 1940 %c1 = spirv.Constant dense<[-2147483648, 239847, 127]> : vector<3xi32> 1941 %c2 = spirv.Constant dense<[31, 16, 13]> : vector<3xi32> 1942 1943 // CHECK: %[[RET:.*]] = spirv.Constant dense<[-1, 3, 0]> 1944 %0 = spirv.ShiftRightArithmetic %c1, %c2 : vector<3xi32>, vector<3xi32> 1945 1946 // CHECK: return %[[RET]] 1947 return %0 : vector<3xi32> 1948} 1949 1950// ----- 1951 1952//===----------------------------------------------------------------------===// 1953// spirv.RightShiftLogical 1954//===----------------------------------------------------------------------===// 1955 1956// CHECK-LABEL: @lsr_x_0 1957// CHECK-SAME: (%[[ARG0:.*]]: i32, %[[ARG1:.*]]: vector<3xi32>) 1958func.func @lsr_x_0(%arg0 : i32, %arg1: vector<3xi32>) -> (i32, vector<3xi32>) { 1959 %c0 = spirv.Constant 0 : i32 1960 %cv0 = spirv.Constant dense<0> : vector<3xi32> 1961 1962 %0 = spirv.ShiftRightLogical %arg0, %c0 : i32, i32 1963 %1 = spirv.ShiftRightLogical %arg1, %cv0 : vector<3xi32>, vector<3xi32> 1964 1965 // CHECK: return %[[ARG0]], %[[ARG1]] 1966 return %0, %1 : i32, vector<3xi32> 1967} 1968 1969// CHECK-LABEL: @lsr_shift_overflow 1970// CHECK-SAME: (%[[ARG0:.*]]: i32, %[[ARG1:.*]]: vector<3xi32>) 1971func.func @lsr_shift_overflow(%arg0: i32, %arg1: vector<3xi32>) -> (i32, vector<3xi32>) { 1972 // CHECK-DAG: %[[C32:.*]] = spirv.Constant 32 1973 // CHECK-DAG: %[[CV:.*]] = spirv.Constant dense<[6, 18, 128]> 1974 %c32 = spirv.Constant 32 : i32 1975 %cv = spirv.Constant dense<[6, 18, 128]> : vector<3xi32> 1976 1977 // CHECK: %0 = spirv.ShiftRightLogical %[[ARG0]], %[[C32]] 1978 // CHECK: %1 = spirv.ShiftRightLogical %[[ARG1]], %[[CV]] 1979 %0 = spirv.ShiftRightLogical %arg0, %c32 : i32, i32 1980 %1 = spirv.ShiftRightLogical %arg1, %cv : vector<3xi32>, vector<3xi32> 1981 return %0, %1 : i32, vector<3xi32> 1982} 1983 1984// CHECK-LABEL: @const_fold_scalar_lsr 1985func.func @const_fold_scalar_lsr() -> i32 { 1986 %c1 = spirv.Constant -131072 : i32 // 0xfffe 0000 1987 %c2 = spirv.Constant 17 : i32 1988 1989 // 0x0000 ffff << 17 -> 0x0000 7fff 1990 // CHECK: %[[RET:.*]] = spirv.Constant 32767 1991 %0 = spirv.ShiftRightLogical %c1, %c2 : i32, i32 1992 1993 // CHECK: return %[[RET]] 1994 return %0 : i32 1995} 1996 1997// CHECK-LABEL: @const_fold_vector_lsr 1998func.func @const_fold_vector_lsr() -> vector<3xi32> { 1999 %c1 = spirv.Constant dense<[-2147483648, -1, -127]> : vector<3xi32> 2000 %c2 = spirv.Constant dense<[31, 16, 13]> : vector<3xi32> 2001 2002 // CHECK: %[[RET:.*]] = spirv.Constant dense<[1, 65535, 524287]> 2003 %0 = spirv.ShiftRightLogical %c1, %c2 : vector<3xi32>, vector<3xi32> 2004 2005 // CHECK: return %[[RET]] 2006 return %0 : vector<3xi32> 2007} 2008 2009// ----- 2010 2011//===----------------------------------------------------------------------===// 2012// spirv.BitwiseAnd 2013//===----------------------------------------------------------------------===// 2014 2015// CHECK-LABEL: @bitwise_and_x_x 2016// CHECK-SAME: (%[[ARG0:.*]]: i32, %[[ARG1:.*]]: vector<3xi32>) 2017func.func @bitwise_and_x_x(%arg0: i32, %arg1: vector<3xi32>) -> (i32, vector<3xi32>) { 2018 %0 = spirv.BitwiseAnd %arg0, %arg0 : i32 2019 %1 = spirv.BitwiseAnd %arg1, %arg1 : vector<3xi32> 2020 2021 // CHECK: return %[[ARG0]], %[[ARG1]] 2022 return %0, %1 : i32, vector<3xi32> 2023} 2024 2025// CHECK-LABEL: @bitwise_and_x_0 2026func.func @bitwise_and_x_0(%arg0 : i32, %arg1 : vector<3xi32>) -> (i32, vector<3xi32>) { 2027 // CHECK-DAG: %[[C0:.*]] = spirv.Constant 0 : i32 2028 // CHECK-DAG: %[[CV0:.*]] = spirv.Constant dense<0> : vector<3xi32> 2029 %c0 = spirv.Constant 0 : i32 2030 %cv0 = spirv.Constant dense<0> : vector<3xi32> 2031 2032 %0 = spirv.BitwiseAnd %arg0, %c0 : i32 2033 %1 = spirv.BitwiseAnd %arg1, %cv0 : vector<3xi32> 2034 2035 // CHECK: return %[[C0]], %[[CV0]] 2036 return %0, %1 : i32, vector<3xi32> 2037} 2038 2039// CHECK-LABEL: @bitwise_and_x_n1 2040// CHECK-SAME: (%[[ARG0:.*]]: i32, %[[ARG1:.*]]: vector<3xi32>) 2041func.func @bitwise_and_x_n1(%arg0: i32, %arg1: vector<3xi32>) -> (i32, vector<3xi32>) { 2042 %cn1 = spirv.Constant -1 : i32 2043 %cvn1 = spirv.Constant dense<-1> : vector<3xi32> 2044 %0 = spirv.BitwiseAnd %arg0, %cn1 : i32 2045 %1 = spirv.BitwiseAnd %arg1, %cvn1 : vector<3xi32> 2046 2047 // CHECK: return %[[ARG0]], %[[ARG1]] 2048 return %0, %1 : i32, vector<3xi32> 2049} 2050 2051// CHECK-LABEL: @const_fold_scalar_band 2052func.func @const_fold_scalar_band() -> i32 { 2053 %c1 = spirv.Constant -268464129 : i32 // 0xefff 8fff 2054 %c2 = spirv.Constant 268464128: i32 // 0x1000 7000 2055 2056 // 0xefff 8fff | 0x1000 7000 = 0xffff ffff = -1 2057 // CHECK: %[[C0:.*]] = spirv.Constant 0 2058 %0 = spirv.BitwiseAnd %c1, %c2 : i32 2059 2060 // CHECK: return %[[C0]] 2061 return %0 : i32 2062} 2063 2064// CHECK-LABEL: @const_fold_vector_band 2065func.func @const_fold_vector_band() -> vector<3xi32> { 2066 %c1 = spirv.Constant dense<[42, -55, 127]> : vector<3xi32> 2067 %c2 = spirv.Constant dense<[-3, -15, 28]> : vector<3xi32> 2068 2069 // CHECK: %[[CV:.*]] = spirv.Constant dense<[40, -63, 28]> 2070 %0 = spirv.BitwiseAnd %c1, %c2 : vector<3xi32> 2071 2072 // CHECK: return %[[CV]] 2073 return %0 : vector<3xi32> 2074} 2075 2076// ----- 2077 2078//===----------------------------------------------------------------------===// 2079// spirv.BitwiseOr 2080//===----------------------------------------------------------------------===// 2081 2082// CHECK-LABEL: @bitwise_or_x_x 2083// CHECK-SAME: (%[[ARG0:.*]]: i32, %[[ARG1:.*]]: vector<3xi32>) 2084func.func @bitwise_or_x_x(%arg0: i32, %arg1: vector<3xi32>) -> (i32, vector<3xi32>) { 2085 %0 = spirv.BitwiseOr %arg0, %arg0 : i32 2086 %1 = spirv.BitwiseOr %arg1, %arg1 : vector<3xi32> 2087 2088 // CHECK: return %[[ARG0]], %[[ARG1]] 2089 return %0, %1 : i32, vector<3xi32> 2090} 2091 2092// CHECK-LABEL: @bitwise_or_x_0 2093// CHECK-SAME: (%[[ARG0:.*]]: i32, %[[ARG1:.*]]: vector<3xi32>) 2094func.func @bitwise_or_x_0(%arg0: i32, %arg1: vector<3xi32>) -> (i32, vector<3xi32>) { 2095 %c1 = spirv.Constant 0 : i32 2096 %cv1 = spirv.Constant dense<0> : vector<3xi32> 2097 %0 = spirv.BitwiseOr %arg0, %c1 : i32 2098 %1 = spirv.BitwiseOr %arg1, %cv1 : vector<3xi32> 2099 2100 // CHECK: return %[[ARG0]], %[[ARG1]] 2101 return %0, %1 : i32, vector<3xi32> 2102} 2103 2104// CHECK-LABEL: @bitwise_or_x_n1 2105func.func @bitwise_or_x_n1(%arg0 : i32, %arg1 : vector<3xi32>) -> (i32, vector<3xi32>) { 2106 // CHECK-DAG: %[[CN1:.*]] = spirv.Constant -1 : i32 2107 // CHECK-DAG: %[[CVN1:.*]] = spirv.Constant dense<-1> : vector<3xi32> 2108 %cn1 = spirv.Constant -1 : i32 2109 %cvn1 = spirv.Constant dense<-1> : vector<3xi32> 2110 %0 = spirv.BitwiseOr %arg0, %cn1 : i32 2111 %1 = spirv.BitwiseOr %arg1, %cvn1 : vector<3xi32> 2112 2113 // CHECK: return %[[CN1]], %[[CVN1]] 2114 return %0, %1 : i32, vector<3xi32> 2115} 2116 2117// CHECK-LABEL: @const_fold_scalar_bor 2118func.func @const_fold_scalar_bor() -> i32 { 2119 %c1 = spirv.Constant -268464129 : i32 // 0xefff 8fff 2120 %c2 = spirv.Constant 268464128: i32 // 0x1000 7000 2121 2122 // 0xefff 8fff | 0x1000 7000 = 0xffff ffff = -1 2123 // CHECK: %[[CN1:.*]] = spirv.Constant -1 2124 %0 = spirv.BitwiseOr %c1, %c2 : i32 2125 2126 // CHECK: return %[[CN1]] 2127 return %0 : i32 2128} 2129 2130// CHECK-LABEL: @const_fold_vector_bor 2131func.func @const_fold_vector_bor() -> vector<3xi32> { 2132 %c1 = spirv.Constant dense<[42, -55, 127]> : vector<3xi32> 2133 %c2 = spirv.Constant dense<[-3, -15, 28]> : vector<3xi32> 2134 2135 // CHECK: %[[CV:.*]] = spirv.Constant dense<[-1, -7, 127]> 2136 %0 = spirv.BitwiseOr %c1, %c2 : vector<3xi32> 2137 2138 // CHECK: return %[[CV]] 2139 return %0 : vector<3xi32> 2140} 2141 2142// ----- 2143 2144//===----------------------------------------------------------------------===// 2145// spirv.BitwiseXor 2146//===----------------------------------------------------------------------===// 2147 2148// CHECK-LABEL: @bitwise_xor_x_0 2149// CHECK-SAME: (%[[ARG0:.*]]: i32, %[[ARG1:.*]]: vector<3xi32>) 2150func.func @bitwise_xor_x_0(%arg0: i32, %arg1: vector<3xi32>) -> (i32, vector<3xi32>) { 2151 %c0 = spirv.Constant 0 : i32 2152 %cv0 = spirv.Constant dense<0> : vector<3xi32> 2153 2154 %0 = spirv.BitwiseXor %arg0, %c0 : i32 2155 %1 = spirv.BitwiseXor %arg1, %cv0 : vector<3xi32> 2156 2157 // CHECK: return %[[ARG0]], %[[ARG1]] 2158 return %0, %1 : i32, vector<3xi32> 2159} 2160 2161// CHECK-LABEL: @bitwise_xor_x_x 2162func.func @bitwise_xor_x_x(%arg0 : i32, %arg1 : vector<3xi32>) -> (i32, vector<3xi32>) { 2163 // CHECK-DAG: %[[C0:.*]] = spirv.Constant 0 2164 // CHECK-DAG: %[[CV0:.*]] = spirv.Constant dense<0> 2165 %0 = spirv.BitwiseXor %arg0, %arg0 : i32 2166 %1 = spirv.BitwiseXor %arg1, %arg1 : vector<3xi32> 2167 2168 // CHECK: return %[[C0]], %[[CV0]] 2169 return %0, %1 : i32, vector<3xi32> 2170} 2171 2172// CHECK-LABEL: @const_fold_scalar_bxor 2173func.func @const_fold_scalar_bxor() -> i32 { 2174 %c1 = spirv.Constant 4294967295 : i32 // 2^32 - 1: 0xffff ffff 2175 %c2 = spirv.Constant -2147483648 : i32 // -2^31 : 0x8000 0000 2176 2177 // 0x8000 0000 ^ 0xffff fffe = 0xefff ffff 2178 // CHECK: %[[CBIG:.*]] = spirv.Constant 2147483647 2179 %0 = spirv.BitwiseXor %c1, %c2 : i32 2180 2181 // CHECK: return %[[CBIG]] 2182 return %0 : i32 2183} 2184 2185// CHECK-LABEL: @const_fold_vector_bxor 2186func.func @const_fold_vector_bxor() -> vector<3xi32> { 2187 %c1 = spirv.Constant dense<[42, -55, 127]> : vector<3xi32> 2188 %c2 = spirv.Constant dense<[-3, -15, 28]> : vector<3xi32> 2189 2190 // CHECK: %[[CV:.*]] = spirv.Constant dense<[-41, 56, 99]> 2191 %0 = spirv.BitwiseXor %c1, %c2 : vector<3xi32> 2192 2193 // CHECK: return %[[CV]] 2194 return %0 : vector<3xi32> 2195} 2196 2197// ----- 2198 2199//===----------------------------------------------------------------------===// 2200// spirv.mlir.selection 2201//===----------------------------------------------------------------------===// 2202 2203func.func @canonicalize_selection_op_scalar_type(%cond: i1) -> () { 2204 %0 = spirv.Constant 0: i32 2205 // CHECK-DAG: %[[TRUE_VALUE:.*]] = spirv.Constant 1 : i32 2206 %1 = spirv.Constant 1: i32 2207 // CHECK-DAG: %[[FALSE_VALUE:.*]] = spirv.Constant 2 : i32 2208 %2 = spirv.Constant 2: i32 2209 // CHECK: %[[DST_VAR:.*]] = spirv.Variable init({{%.*}}) : !spirv.ptr<i32, Function> 2210 %3 = spirv.Variable init(%0) : !spirv.ptr<i32, Function> 2211 2212 // CHECK: %[[SRC_VALUE:.*]] = spirv.Select {{%.*}}, %[[TRUE_VALUE]], %[[FALSE_VALUE]] : i1, i32 2213 // CHECK-NEXT: spirv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE]] ["Aligned", 4] : i32 2214 // CHECK-NEXT: spirv.Return 2215 spirv.mlir.selection { 2216 spirv.BranchConditional %cond, ^then, ^else 2217 2218 ^else: 2219 spirv.Store "Function" %3, %2 ["Aligned", 4]: i32 2220 spirv.Branch ^merge 2221 2222 ^then: 2223 spirv.Store "Function" %3, %1 ["Aligned", 4]: i32 2224 spirv.Branch ^merge 2225 2226 ^merge: 2227 spirv.mlir.merge 2228 } 2229 spirv.Return 2230} 2231 2232// ----- 2233 2234func.func @canonicalize_selection_op_vector_type(%cond: i1) -> () { 2235 %0 = spirv.Constant dense<[0, 1, 2]> : vector<3xi32> 2236 // CHECK-DAG: %[[TRUE_VALUE:.*]] = spirv.Constant dense<[1, 2, 3]> : vector<3xi32> 2237 %1 = spirv.Constant dense<[1, 2, 3]> : vector<3xi32> 2238 // CHECK-DAG: %[[FALSE_VALUE:.*]] = spirv.Constant dense<[2, 3, 4]> : vector<3xi32> 2239 %2 = spirv.Constant dense<[2, 3, 4]> : vector<3xi32> 2240 // CHECK: %[[DST_VAR:.*]] = spirv.Variable init({{%.*}}) : !spirv.ptr<vector<3xi32>, Function> 2241 %3 = spirv.Variable init(%0) : !spirv.ptr<vector<3xi32>, Function> 2242 2243 // CHECK: %[[SRC_VALUE:.*]] = spirv.Select {{%.*}}, %[[TRUE_VALUE]], %[[FALSE_VALUE]] : i1, vector<3xi32> 2244 // CHECK-NEXT: spirv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE]] ["Aligned", 8] : vector<3xi32> 2245 // CHECK-NEXT: spirv.Return 2246 spirv.mlir.selection { 2247 spirv.BranchConditional %cond, ^then, ^else 2248 2249 ^then: 2250 spirv.Store "Function" %3, %1 ["Aligned", 8]: vector<3xi32> 2251 spirv.Branch ^merge 2252 2253 ^else: 2254 spirv.Store "Function" %3, %2 ["Aligned", 8] : vector<3xi32> 2255 spirv.Branch ^merge 2256 2257 ^merge: 2258 spirv.mlir.merge 2259 } 2260 spirv.Return 2261} 2262 2263// ----- 2264 2265// CHECK-LABEL: cannot_canonicalize_selection_op_0 2266 2267// Store to a different variables. 2268func.func @cannot_canonicalize_selection_op_0(%cond: i1) -> () { 2269 %0 = spirv.Constant dense<[0, 1, 2]> : vector<3xi32> 2270 // CHECK-DAG: %[[SRC_VALUE_1:.*]] = spirv.Constant dense<[2, 3, 4]> : vector<3xi32> 2271 // CHECK-DAG: %[[SRC_VALUE_0:.*]] = spirv.Constant dense<[1, 2, 3]> : vector<3xi32> 2272 %1 = spirv.Constant dense<[1, 2, 3]> : vector<3xi32> 2273 %2 = spirv.Constant dense<[2, 3, 4]> : vector<3xi32> 2274 // CHECK: %[[DST_VAR_0:.*]] = spirv.Variable init({{%.*}}) : !spirv.ptr<vector<3xi32>, Function> 2275 %3 = spirv.Variable init(%0) : !spirv.ptr<vector<3xi32>, Function> 2276 // CHECK: %[[DST_VAR_1:.*]] = spirv.Variable init({{%.*}}) : !spirv.ptr<vector<3xi32>, Function> 2277 %4 = spirv.Variable init(%0) : !spirv.ptr<vector<3xi32>, Function> 2278 2279 // CHECK: spirv.mlir.selection { 2280 spirv.mlir.selection { 2281 // CHECK: spirv.BranchConditional 2282 // CHECK-SAME: ^bb1(%[[DST_VAR_0]], %[[SRC_VALUE_0]] 2283 // CHECK-SAME: ^bb1(%[[DST_VAR_1]], %[[SRC_VALUE_1]] 2284 spirv.BranchConditional %cond, ^then, ^else 2285 2286 ^then: 2287 // CHECK: ^bb1(%[[ARG0:.*]]: !spirv.ptr<vector<3xi32>, Function>, %[[ARG1:.*]]: vector<3xi32>): 2288 // CHECK: spirv.Store "Function" %[[ARG0]], %[[ARG1]] ["Aligned", 8] : vector<3xi32> 2289 spirv.Store "Function" %3, %1 ["Aligned", 8]: vector<3xi32> 2290 spirv.Branch ^merge 2291 2292 ^else: 2293 spirv.Store "Function" %4, %2 ["Aligned", 8] : vector<3xi32> 2294 spirv.Branch ^merge 2295 2296 ^merge: 2297 spirv.mlir.merge 2298 } 2299 spirv.Return 2300} 2301 2302// ----- 2303 2304// CHECK-LABEL: cannot_canonicalize_selection_op_1 2305 2306// A conditional block consists of more than 2 operations. 2307func.func @cannot_canonicalize_selection_op_1(%cond: i1) -> () { 2308 %0 = spirv.Constant dense<[0, 1, 2]> : vector<3xi32> 2309 // CHECK-DAG: %[[SRC_VALUE_0:.*]] = spirv.Constant dense<[1, 2, 3]> : vector<3xi32> 2310 %1 = spirv.Constant dense<[1, 2, 3]> : vector<3xi32> 2311 // CHECK-DAG: %[[SRC_VALUE_1:.*]] = spirv.Constant dense<[2, 3, 4]> : vector<3xi32> 2312 %2 = spirv.Constant dense<[2, 3, 4]> : vector<3xi32> 2313 // CHECK: %[[DST_VAR_0:.*]] = spirv.Variable init({{%.*}}) : !spirv.ptr<vector<3xi32>, Function> 2314 %3 = spirv.Variable init(%0) : !spirv.ptr<vector<3xi32>, Function> 2315 // CHECK: %[[DST_VAR_1:.*]] = spirv.Variable init({{%.*}}) : !spirv.ptr<vector<3xi32>, Function> 2316 %4 = spirv.Variable init(%0) : !spirv.ptr<vector<3xi32>, Function> 2317 2318 // CHECK: spirv.mlir.selection { 2319 spirv.mlir.selection { 2320 spirv.BranchConditional %cond, ^then, ^else 2321 2322 ^then: 2323 // CHECK: spirv.Store "Function" %[[DST_VAR_0]], %[[SRC_VALUE_0]] ["Aligned", 8] : vector<3xi32> 2324 spirv.Store "Function" %3, %1 ["Aligned", 8] : vector<3xi32> 2325 // CHECK: spirv.Store "Function" %[[DST_VAR_1]], %[[SRC_VALUE_0]] ["Aligned", 8] : vector<3xi32> 2326 spirv.Store "Function" %4, %1 ["Aligned", 8]: vector<3xi32> 2327 spirv.Branch ^merge 2328 2329 ^else: 2330 // CHECK: spirv.Store "Function" %[[DST_VAR_1]], %[[SRC_VALUE_1]] ["Aligned", 8] : vector<3xi32> 2331 spirv.Store "Function" %4, %2 ["Aligned", 8] : vector<3xi32> 2332 spirv.Branch ^merge 2333 2334 ^merge: 2335 spirv.mlir.merge 2336 } 2337 spirv.Return 2338} 2339 2340// ----- 2341 2342// CHECK-LABEL: cannot_canonicalize_selection_op_2 2343 2344// A control-flow goes into `^then` block from `^else` block. 2345func.func @cannot_canonicalize_selection_op_2(%cond: i1) -> () { 2346 %0 = spirv.Constant dense<[0, 1, 2]> : vector<3xi32> 2347 // CHECK-DAG: %[[SRC_VALUE_0:.*]] = spirv.Constant dense<[1, 2, 3]> : vector<3xi32> 2348 %1 = spirv.Constant dense<[1, 2, 3]> : vector<3xi32> 2349 // CHECK-DAG: %[[SRC_VALUE_1:.*]] = spirv.Constant dense<[2, 3, 4]> : vector<3xi32> 2350 %2 = spirv.Constant dense<[2, 3, 4]> : vector<3xi32> 2351 // CHECK: %[[DST_VAR:.*]] = spirv.Variable init({{%.*}}) : !spirv.ptr<vector<3xi32>, Function> 2352 %3 = spirv.Variable init(%0) : !spirv.ptr<vector<3xi32>, Function> 2353 2354 // CHECK: spirv.mlir.selection { 2355 spirv.mlir.selection { 2356 spirv.BranchConditional %cond, ^then, ^else 2357 2358 ^then: 2359 // CHECK: spirv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE_0]] ["Aligned", 8] : vector<3xi32> 2360 spirv.Store "Function" %3, %1 ["Aligned", 8]: vector<3xi32> 2361 spirv.Branch ^merge 2362 2363 ^else: 2364 // CHECK: spirv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE_1]] ["Aligned", 8] : vector<3xi32> 2365 spirv.Store "Function" %3, %2 ["Aligned", 8] : vector<3xi32> 2366 spirv.Branch ^then 2367 2368 ^merge: 2369 spirv.mlir.merge 2370 } 2371 spirv.Return 2372} 2373 2374// ----- 2375 2376// CHECK-LABEL: cannot_canonicalize_selection_op_3 2377 2378// `spirv.Return` as a block terminator. 2379func.func @cannot_canonicalize_selection_op_3(%cond: i1) -> () { 2380 %0 = spirv.Constant dense<[0, 1, 2]> : vector<3xi32> 2381 %1 = spirv.Constant dense<[1, 2, 3]> : vector<3xi32> 2382 // CHECK-DAG: %[[SRC_VALUE_0:.*]] = spirv.Constant dense<[1, 2, 3]> : vector<3xi32> 2383 // CHECK-DAG: %[[SRC_VALUE_1:.*]] = spirv.Constant dense<[2, 3, 4]> : vector<3xi32> 2384 %2 = spirv.Constant dense<[2, 3, 4]> : vector<3xi32> 2385 // CHECK: %[[DST_VAR:.*]] = spirv.Variable init({{%.*}}) : !spirv.ptr<vector<3xi32>, Function> 2386 %3 = spirv.Variable init(%0) : !spirv.ptr<vector<3xi32>, Function> 2387 2388 // CHECK: spirv.mlir.selection { 2389 spirv.mlir.selection { 2390 spirv.BranchConditional %cond, ^then, ^else 2391 2392 ^then: 2393 // CHECK: spirv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE_0]] ["Aligned", 8] : vector<3xi32> 2394 spirv.Store "Function" %3, %1 ["Aligned", 8]: vector<3xi32> 2395 spirv.Return 2396 2397 ^else: 2398 // CHECK: spirv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE_1]] ["Aligned", 8] : vector<3xi32> 2399 spirv.Store "Function" %3, %2 ["Aligned", 8] : vector<3xi32> 2400 spirv.Branch ^merge 2401 2402 ^merge: 2403 spirv.mlir.merge 2404 } 2405 spirv.Return 2406} 2407 2408// ----- 2409 2410// CHECK-LABEL: cannot_canonicalize_selection_op_4 2411 2412// Different memory access attributes. 2413func.func @cannot_canonicalize_selection_op_4(%cond: i1) -> () { 2414 %0 = spirv.Constant dense<[0, 1, 2]> : vector<3xi32> 2415 // CHECK-DAG: %[[SRC_VALUE_0:.*]] = spirv.Constant dense<[1, 2, 3]> : vector<3xi32> 2416 %1 = spirv.Constant dense<[1, 2, 3]> : vector<3xi32> 2417 // CHECK-DAG: %[[SRC_VALUE_1:.*]] = spirv.Constant dense<[2, 3, 4]> : vector<3xi32> 2418 %2 = spirv.Constant dense<[2, 3, 4]> : vector<3xi32> 2419 // CHECK: %[[DST_VAR:.*]] = spirv.Variable init({{%.*}}) : !spirv.ptr<vector<3xi32>, Function> 2420 %3 = spirv.Variable init(%0) : !spirv.ptr<vector<3xi32>, Function> 2421 2422 // CHECK: spirv.mlir.selection { 2423 spirv.mlir.selection { 2424 spirv.BranchConditional %cond, ^then, ^else 2425 2426 ^then: 2427 // CHECK: spirv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE_0]] ["Aligned", 4] : vector<3xi32> 2428 spirv.Store "Function" %3, %1 ["Aligned", 4]: vector<3xi32> 2429 spirv.Branch ^merge 2430 2431 ^else: 2432 // CHECK: spirv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE_1]] ["Aligned", 8] : vector<3xi32> 2433 spirv.Store "Function" %3, %2 ["Aligned", 8] : vector<3xi32> 2434 spirv.Branch ^merge 2435 2436 ^merge: 2437 spirv.mlir.merge 2438 } 2439 spirv.Return 2440} 2441