Lei Zhang 3148f10b17 [mlir][spirv] Use spv.vce in spv.module and wire up (de)serialization
This commits changes the definition of spv.module to use the #spv.vce
attribute for specifying (version, capabilities, extensions) triple
so that we can have better API and custom assembly form. Since now
we have proper modelling of the triple, (de)serialization is wired up
to use them.

With the new UpdateVCEPass, we don't need to manually specify the
required extensions and capabilities anymore when creating a spv.module.
One just need to call UpdateVCEPass before serialization to get the
needed version/extensions/capabilities.

Differential Revision: https://reviews.llvm.org/D75872
2020-03-12 19:37:45 -04:00

229 lines
6.3 KiB
MLIR

// RUN: mlir-opt %s -split-input-file -pass-pipeline='spv.module(inline)' -mlir-disable-inline-simplify | 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._address_of @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>
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._address_of
// 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.selection {
spv.BranchConditional %cond, ^then, ^merge
^then:
spv.Return
^merge:
spv._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.selection {
spv.BranchConditional %cond, ^then, ^merge
^then:
spv.Branch ^merge
^merge:
spv._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.selection
// CHECK-NEXT: spv.BranchConditional %[[TRUE]], ^bb1, ^bb2
// CHECK-NEXT: ^bb1:
// CHECK-NEXT: spv.Branch ^bb2
// CHECK-NEXT: ^bb2:
// CHECK-NEXT: spv._merge
spv.FunctionCall @callee(%0) : (i1) -> ()
spv.Return
}
}
// -----
spv.module Logical GLSL450 {
spv.func @callee(%cond : i1) -> () "None" {
spv.loop {
spv.Branch ^header
^header:
spv.BranchConditional %cond, ^body, ^merge
^body:
spv.Return
^continue:
spv.Branch ^header
^merge:
spv._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.loop {
spv.Branch ^header
^header:
spv.BranchConditional %cond, ^body, ^merge
^body:
spv.Branch ^continue
^continue:
spv.Branch ^header
^merge:
spv._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.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._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._address_of @arg_0
// CHECK-DAG: [[ADDRESS_ARG1:%.*]] = spv._address_of @arg_1
// CHECK-DAG: [[LOADPTR:%.*]] = spv.AccessChain [[ADDRESS_ARG0]]
// CHECK: [[VAL:%.*]] = spv.Load "StorageBuffer" [[LOADPTR]]
%2 = spv._address_of @arg_0 : !spv.ptr<!spv.struct<i32 [0]>, StorageBuffer>
%3 = spv._address_of @arg_1 : !spv.ptr<!spv.struct<i32 [0]>, StorageBuffer>
%4 = spv.AccessChain %2[%1] : !spv.ptr<!spv.struct<i32 [0]>, StorageBuffer>
%5 = spv.Load "StorageBuffer" %4 : i32
%6 = spv.SGreaterThan %5, %1 : i32
// CHECK: spv.selection
spv.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>
// 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._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.