1// RUN: mlir-opt %s -split-input-file -pass-pipeline='builtin.module(spirv.module(inline{default-pipeline=''}))' | FileCheck %s 2 3spirv.module Logical GLSL450 { 4 spirv.func @callee() "None" { 5 spirv.Return 6 } 7 8 // CHECK-LABEL: @calling_single_block_ret_func 9 spirv.func @calling_single_block_ret_func() "None" { 10 // CHECK-NEXT: spirv.Return 11 spirv.FunctionCall @callee() : () -> () 12 spirv.Return 13 } 14} 15 16// ----- 17 18spirv.module Logical GLSL450 { 19 spirv.func @callee() -> i32 "None" { 20 %0 = spirv.Constant 42 : i32 21 spirv.ReturnValue %0 : i32 22 } 23 24 // CHECK-LABEL: @calling_single_block_retval_func 25 spirv.func @calling_single_block_retval_func() -> i32 "None" { 26 // CHECK-NEXT: %[[CST:.*]] = spirv.Constant 42 27 %0 = spirv.FunctionCall @callee() : () -> (i32) 28 // CHECK-NEXT: spirv.ReturnValue %[[CST]] 29 spirv.ReturnValue %0 : i32 30 } 31} 32 33// ----- 34 35spirv.module Logical GLSL450 { 36 spirv.GlobalVariable @data bind(0, 0) : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i32> [0])>, StorageBuffer> 37 spirv.func @callee() "None" { 38 %0 = spirv.mlir.addressof @data : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i32> [0])>, StorageBuffer> 39 %1 = spirv.Constant 0: i32 40 %2 = spirv.AccessChain %0[%1, %1] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i32> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<i32, StorageBuffer> 41 spirv.Branch ^next 42 43 ^next: 44 %3 = spirv.Constant 42: i32 45 spirv.Store "StorageBuffer" %2, %3 : i32 46 spirv.Return 47 } 48 49 // CHECK-LABEL: @calling_multi_block_ret_func 50 spirv.func @calling_multi_block_ret_func() "None" { 51 // CHECK-NEXT: spirv.mlir.addressof 52 // CHECK-NEXT: spirv.Constant 0 53 // CHECK-NEXT: spirv.AccessChain 54 // CHECK-NEXT: spirv.Branch ^bb1 55 // CHECK-NEXT: ^bb1: 56 // CHECK-NEXT: spirv.Constant 57 // CHECK-NEXT: spirv.Store 58 // CHECK-NEXT: spirv.Branch ^bb2 59 spirv.FunctionCall @callee() : () -> () 60 // CHECK-NEXT: ^bb2: 61 // CHECK-NEXT: spirv.Return 62 spirv.Return 63 } 64} 65 66// TODO: calling_multi_block_retval_func 67 68// ----- 69 70spirv.module Logical GLSL450 { 71 spirv.func @callee(%cond : i1) -> () "None" { 72 spirv.mlir.selection { 73 spirv.BranchConditional %cond, ^then, ^merge 74 ^then: 75 spirv.Return 76 ^merge: 77 spirv.mlir.merge 78 } 79 spirv.Return 80 } 81 82 // CHECK-LABEL: @calling_selection_ret_func 83 spirv.func @calling_selection_ret_func() "None" { 84 %0 = spirv.Constant true 85 // CHECK: spirv.FunctionCall 86 spirv.FunctionCall @callee(%0) : (i1) -> () 87 spirv.Return 88 } 89} 90 91// ----- 92 93spirv.module Logical GLSL450 { 94 spirv.func @callee(%cond : i1) -> () "None" { 95 spirv.mlir.selection { 96 spirv.BranchConditional %cond, ^then, ^merge 97 ^then: 98 spirv.Branch ^merge 99 ^merge: 100 spirv.mlir.merge 101 } 102 spirv.Return 103 } 104 105 // CHECK-LABEL: @calling_selection_no_ret_func 106 spirv.func @calling_selection_no_ret_func() "None" { 107 // CHECK-NEXT: %[[TRUE:.*]] = spirv.Constant true 108 %0 = spirv.Constant true 109 // CHECK-NEXT: spirv.mlir.selection 110 // CHECK-NEXT: spirv.BranchConditional %[[TRUE]], ^bb1, ^bb2 111 // CHECK-NEXT: ^bb1: 112 // CHECK-NEXT: spirv.Branch ^bb2 113 // CHECK-NEXT: ^bb2: 114 // CHECK-NEXT: spirv.mlir.merge 115 spirv.FunctionCall @callee(%0) : (i1) -> () 116 spirv.Return 117 } 118} 119 120// ----- 121 122spirv.module Logical GLSL450 { 123 spirv.func @callee(%cond : i1) -> () "None" { 124 spirv.mlir.loop { 125 spirv.Branch ^header 126 ^header: 127 spirv.BranchConditional %cond, ^body, ^merge 128 ^body: 129 spirv.Return 130 ^continue: 131 spirv.Branch ^header 132 ^merge: 133 spirv.mlir.merge 134 } 135 spirv.Return 136 } 137 138 // CHECK-LABEL: @calling_loop_ret_func 139 spirv.func @calling_loop_ret_func() "None" { 140 %0 = spirv.Constant true 141 // CHECK: spirv.FunctionCall 142 spirv.FunctionCall @callee(%0) : (i1) -> () 143 spirv.Return 144 } 145} 146 147// ----- 148 149spirv.module Logical GLSL450 { 150 spirv.func @callee(%cond : i1) -> () "None" { 151 spirv.mlir.loop { 152 spirv.Branch ^header 153 ^header: 154 spirv.BranchConditional %cond, ^body, ^merge 155 ^body: 156 spirv.Branch ^continue 157 ^continue: 158 spirv.Branch ^header 159 ^merge: 160 spirv.mlir.merge 161 } 162 spirv.Return 163 } 164 165 // CHECK-LABEL: @calling_loop_no_ret_func 166 spirv.func @calling_loop_no_ret_func() "None" { 167 // CHECK-NEXT: %[[TRUE:.*]] = spirv.Constant true 168 %0 = spirv.Constant true 169 // CHECK-NEXT: spirv.mlir.loop 170 // CHECK-NEXT: spirv.Branch ^bb1 171 // CHECK-NEXT: ^bb1: 172 // CHECK-NEXT: spirv.BranchConditional %[[TRUE]], ^bb2, ^bb4 173 // CHECK-NEXT: ^bb2: 174 // CHECK-NEXT: spirv.Branch ^bb3 175 // CHECK-NEXT: ^bb3: 176 // CHECK-NEXT: spirv.Branch ^bb1 177 // CHECK-NEXT: ^bb4: 178 // CHECK-NEXT: spirv.mlir.merge 179 spirv.FunctionCall @callee(%0) : (i1) -> () 180 spirv.Return 181 } 182} 183 184// ----- 185 186spirv.module Logical GLSL450 { 187 spirv.GlobalVariable @arg_0 bind(0, 0) : !spirv.ptr<!spirv.struct<(i32 [0])>, StorageBuffer> 188 spirv.GlobalVariable @arg_1 bind(0, 1) : !spirv.ptr<!spirv.struct<(i32 [0])>, StorageBuffer> 189 190 // CHECK: @inline_into_selection_region 191 spirv.func @inline_into_selection_region() "None" { 192 %1 = spirv.Constant 0 : i32 193 // CHECK-DAG: [[ADDRESS_ARG0:%.*]] = spirv.mlir.addressof @arg_0 194 // CHECK-DAG: [[ADDRESS_ARG1:%.*]] = spirv.mlir.addressof @arg_1 195 // CHECK-DAG: [[LOADPTR:%.*]] = spirv.AccessChain [[ADDRESS_ARG0]] 196 // CHECK: [[VAL:%.*]] = spirv.Load "StorageBuffer" [[LOADPTR]] 197 %2 = spirv.mlir.addressof @arg_0 : !spirv.ptr<!spirv.struct<(i32 [0])>, StorageBuffer> 198 %3 = spirv.mlir.addressof @arg_1 : !spirv.ptr<!spirv.struct<(i32 [0])>, StorageBuffer> 199 %4 = spirv.AccessChain %2[%1] : !spirv.ptr<!spirv.struct<(i32 [0])>, StorageBuffer>, i32 -> !spirv.ptr<i32, StorageBuffer> 200 %5 = spirv.Load "StorageBuffer" %4 : i32 201 %6 = spirv.SGreaterThan %5, %1 : i32 202 // CHECK: spirv.mlir.selection 203 spirv.mlir.selection { 204 spirv.BranchConditional %6, ^bb1, ^bb2 205 ^bb1: // pred: ^bb0 206 // CHECK: [[STOREPTR:%.*]] = spirv.AccessChain [[ADDRESS_ARG1]] 207 %7 = spirv.AccessChain %3[%1] : !spirv.ptr<!spirv.struct<(i32 [0])>, StorageBuffer>, i32 -> !spirv.ptr<i32, StorageBuffer> 208 // CHECK-NOT: spirv.FunctionCall 209 // CHECK: spirv.AtomicIAdd <Device> <AcquireRelease> [[STOREPTR]], [[VAL]] 210 // CHECK: spirv.Branch 211 spirv.FunctionCall @atomic_add(%5, %7) : (i32, !spirv.ptr<i32, StorageBuffer>) -> () 212 spirv.Branch ^bb2 213 ^bb2 : // 2 preds: ^bb0, ^bb1 214 spirv.mlir.merge 215 } 216 // CHECK: spirv.Return 217 spirv.Return 218 } 219 spirv.func @atomic_add(%arg0: i32, %arg1: !spirv.ptr<i32, StorageBuffer>) "None" { 220 %0 = spirv.AtomicIAdd <Device> <AcquireRelease> %arg1, %arg0 : !spirv.ptr<i32, StorageBuffer> 221 spirv.Return 222 } 223 spirv.EntryPoint "GLCompute" @inline_into_selection_region 224 spirv.ExecutionMode @inline_into_selection_region "LocalSize", 32, 1, 1 225} 226 227// ----- 228 229spirv.module Logical GLSL450 { 230 // CHECK-LABEL: @foo 231 spirv.func @foo(%arg0: i32) -> i32 "None" { 232 // CHECK-NOT: spirv.FunctionCall 233 // CHECK-NEXT: spirv.Constant 1 234 %res = spirv.FunctionCall @bar(%arg0) : (i32) -> i32 235 spirv.ReturnValue %res : i32 236 } 237 238 spirv.func @bar(%arg1: i32) -> i32 "None" attributes {sym_visibility = "private"} { 239 %cst1_i32 = spirv.Constant 1 : i32 240 %0 = spirv.IEqual %arg1, %cst1_i32 : i32 241 spirv.BranchConditional %0, ^bb1(%cst1_i32 : i32), ^bb2 242 ^bb1(%1: i32): 243 spirv.ReturnValue %1 : i32 244 ^bb2: 245 spirv.ReturnValue %cst1_i32 : i32 246 } 247} 248 249// TODO: Add tests for inlining structured control flow into 250// structured control flow. 251