blob: 63812eff81e88950a31f8cc1141e270298168f1d [file] [log] [blame]
// RUN: mlir-opt %s -split-input-file -pass-pipeline='spv.module(inline{default-pipeline=''})' | FileCheck %s
spv.module Logical GLSL450 {
spv.func @callee() "None" {
spv.Return
}
// CHECK-LABEL: @calling_single_block_ret_func
spv.func @calling_single_block_ret_func() "None" {
// CHECK-NEXT: spv.Return
spv.FunctionCall @callee() : () -> ()
spv.Return
}
}
// -----
spv.module Logical GLSL450 {
spv.func @callee() -> i32 "None" {
%0 = spv.Constant 42 : i32
spv.ReturnValue %0 : i32
}
// CHECK-LABEL: @calling_single_block_retval_func
spv.func @calling_single_block_retval_func() -> i32 "None" {
// CHECK-NEXT: %[[CST:.*]] = spv.Constant 42
%0 = spv.FunctionCall @callee() : () -> (i32)
// CHECK-NEXT: spv.ReturnValue %[[CST]]
spv.ReturnValue %0 : i32
}
}
// -----
spv.module Logical GLSL450 {
spv.GlobalVariable @data bind(0, 0) : !spv.ptr<!spv.struct<(!spv.rtarray<i32> [0])>, StorageBuffer>
spv.func @callee() "None" {
%0 = spv.mlir.addressof @data : !spv.ptr<!spv.struct<(!spv.rtarray<i32> [0])>, StorageBuffer>
%1 = spv.Constant 0: i32
%2 = spv.AccessChain %0[%1, %1] : !spv.ptr<!spv.struct<(!spv.rtarray<i32> [0])>, StorageBuffer>, i32, i32
spv.Branch ^next
^next:
%3 = spv.Constant 42: i32
spv.Store "StorageBuffer" %2, %3 : i32
spv.Return
}
// CHECK-LABEL: @calling_multi_block_ret_func
spv.func @calling_multi_block_ret_func() "None" {
// CHECK-NEXT: spv.mlir.addressof
// CHECK-NEXT: spv.Constant 0
// CHECK-NEXT: spv.AccessChain
// CHECK-NEXT: spv.Branch ^bb1
// CHECK-NEXT: ^bb1:
// CHECK-NEXT: spv.Constant
// CHECK-NEXT: spv.Store
// CHECK-NEXT: spv.Branch ^bb2
spv.FunctionCall @callee() : () -> ()
// CHECK-NEXT: ^bb2:
// CHECK-NEXT: spv.Return
spv.Return
}
}
// TODO: calling_multi_block_retval_func
// -----
spv.module Logical GLSL450 {
spv.func @callee(%cond : i1) -> () "None" {
spv.mlir.selection {
spv.BranchConditional %cond, ^then, ^merge
^then:
spv.Return
^merge:
spv.mlir.merge
}
spv.Return
}
// CHECK-LABEL: @calling_selection_ret_func
spv.func @calling_selection_ret_func() "None" {
%0 = spv.Constant true
// CHECK: spv.FunctionCall
spv.FunctionCall @callee(%0) : (i1) -> ()
spv.Return
}
}
// -----
spv.module Logical GLSL450 {
spv.func @callee(%cond : i1) -> () "None" {
spv.mlir.selection {
spv.BranchConditional %cond, ^then, ^merge
^then:
spv.Branch ^merge
^merge:
spv.mlir.merge
}
spv.Return
}
// CHECK-LABEL: @calling_selection_no_ret_func
spv.func @calling_selection_no_ret_func() "None" {
// CHECK-NEXT: %[[TRUE:.*]] = spv.Constant true
%0 = spv.Constant true
// CHECK-NEXT: spv.mlir.selection
// CHECK-NEXT: spv.BranchConditional %[[TRUE]], ^bb1, ^bb2
// CHECK-NEXT: ^bb1:
// CHECK-NEXT: spv.Branch ^bb2
// CHECK-NEXT: ^bb2:
// CHECK-NEXT: spv.mlir.merge
spv.FunctionCall @callee(%0) : (i1) -> ()
spv.Return
}
}
// -----
spv.module Logical GLSL450 {
spv.func @callee(%cond : i1) -> () "None" {
spv.mlir.loop {
spv.Branch ^header
^header:
spv.BranchConditional %cond, ^body, ^merge
^body:
spv.Return
^continue:
spv.Branch ^header
^merge:
spv.mlir.merge
}
spv.Return
}
// CHECK-LABEL: @calling_loop_ret_func
spv.func @calling_loop_ret_func() "None" {
%0 = spv.Constant true
// CHECK: spv.FunctionCall
spv.FunctionCall @callee(%0) : (i1) -> ()
spv.Return
}
}
// -----
spv.module Logical GLSL450 {
spv.func @callee(%cond : i1) -> () "None" {
spv.mlir.loop {
spv.Branch ^header
^header:
spv.BranchConditional %cond, ^body, ^merge
^body:
spv.Branch ^continue
^continue:
spv.Branch ^header
^merge:
spv.mlir.merge
}
spv.Return
}
// CHECK-LABEL: @calling_loop_no_ret_func
spv.func @calling_loop_no_ret_func() "None" {
// CHECK-NEXT: %[[TRUE:.*]] = spv.Constant true
%0 = spv.Constant true
// CHECK-NEXT: spv.mlir.loop
// CHECK-NEXT: spv.Branch ^bb1
// CHECK-NEXT: ^bb1:
// CHECK-NEXT: spv.BranchConditional %[[TRUE]], ^bb2, ^bb4
// CHECK-NEXT: ^bb2:
// CHECK-NEXT: spv.Branch ^bb3
// CHECK-NEXT: ^bb3:
// CHECK-NEXT: spv.Branch ^bb1
// CHECK-NEXT: ^bb4:
// CHECK-NEXT: spv.mlir.merge
spv.FunctionCall @callee(%0) : (i1) -> ()
spv.Return
}
}
// -----
spv.module Logical GLSL450 {
spv.GlobalVariable @arg_0 bind(0, 0) : !spv.ptr<!spv.struct<(i32 [0])>, StorageBuffer>
spv.GlobalVariable @arg_1 bind(0, 1) : !spv.ptr<!spv.struct<(i32 [0])>, StorageBuffer>
// CHECK: @inline_into_selection_region
spv.func @inline_into_selection_region() "None" {
%1 = spv.Constant 0 : i32
// CHECK-DAG: [[ADDRESS_ARG0:%.*]] = spv.mlir.addressof @arg_0
// CHECK-DAG: [[ADDRESS_ARG1:%.*]] = spv.mlir.addressof @arg_1
// CHECK-DAG: [[LOADPTR:%.*]] = spv.AccessChain [[ADDRESS_ARG0]]
// CHECK: [[VAL:%.*]] = spv.Load "StorageBuffer" [[LOADPTR]]
%2 = spv.mlir.addressof @arg_0 : !spv.ptr<!spv.struct<(i32 [0])>, StorageBuffer>
%3 = spv.mlir.addressof @arg_1 : !spv.ptr<!spv.struct<(i32 [0])>, StorageBuffer>
%4 = spv.AccessChain %2[%1] : !spv.ptr<!spv.struct<(i32 [0])>, StorageBuffer>, i32
%5 = spv.Load "StorageBuffer" %4 : i32
%6 = spv.SGreaterThan %5, %1 : i32
// CHECK: spv.mlir.selection
spv.mlir.selection {
spv.BranchConditional %6, ^bb1, ^bb2
^bb1: // pred: ^bb0
// CHECK: [[STOREPTR:%.*]] = spv.AccessChain [[ADDRESS_ARG1]]
%7 = spv.AccessChain %3[%1] : !spv.ptr<!spv.struct<(i32 [0])>, StorageBuffer>, i32
// CHECK-NOT: spv.FunctionCall
// CHECK: spv.AtomicIAdd "Device" "AcquireRelease" [[STOREPTR]], [[VAL]]
// CHECK: spv.Branch
spv.FunctionCall @atomic_add(%5, %7) : (i32, !spv.ptr<i32, StorageBuffer>) -> ()
spv.Branch ^bb2
^bb2 : // 2 preds: ^bb0, ^bb1
spv.mlir.merge
}
// CHECK: spv.Return
spv.Return
}
spv.func @atomic_add(%arg0: i32, %arg1: !spv.ptr<i32, StorageBuffer>) "None" {
%0 = spv.AtomicIAdd "Device" "AcquireRelease" %arg1, %arg0 : !spv.ptr<i32, StorageBuffer>
spv.Return
}
spv.EntryPoint "GLCompute" @inline_into_selection_region
spv.ExecutionMode @inline_into_selection_region "LocalSize", 32, 1, 1
}
// TODO: Add tests for inlining structured control flow into
// structured control flow.