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

239 lines
7.1 KiB
MLIR

// RUN: mlir-translate -split-input-file -test-spirv-roundtrip %s | FileCheck %s
// Test branch with one block argument
spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
spv.func @foo() -> () "None" {
// CHECK: %[[CST:.*]] = spv.constant 0
%zero = spv.constant 0 : i32
// CHECK-NEXT: spv.Branch ^bb1(%[[CST]] : i32)
spv.Branch ^bb1(%zero : i32)
// CHECK-NEXT: ^bb1(%{{.*}}: i32):
^bb1(%arg0: i32):
spv.Return
}
spv.func @main() -> () "None" {
spv.Return
}
spv.EntryPoint "GLCompute" @main
}
// -----
// Test branch with multiple block arguments
spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
spv.func @foo() -> () "None" {
// CHECK: %[[ZERO:.*]] = spv.constant 0
%zero = spv.constant 0 : i32
// CHECK-NEXT: %[[ONE:.*]] = spv.constant 1
%one = spv.constant 1.0 : f32
// CHECK-NEXT: spv.Branch ^bb1(%[[ZERO]], %[[ONE]] : i32, f32)
spv.Branch ^bb1(%zero, %one : i32, f32)
// CHECK-NEXT: ^bb1(%{{.*}}: i32, %{{.*}}: f32): // pred: ^bb0
^bb1(%arg0: i32, %arg1: f32):
spv.Return
}
spv.func @main() -> () "None" {
spv.Return
}
spv.EntryPoint "GLCompute" @main
}
// -----
// Test using block arguments within branch
spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
spv.func @foo() -> () "None" {
// CHECK: %[[CST0:.*]] = spv.constant 0
%zero = spv.constant 0 : i32
// CHECK-NEXT: spv.Branch ^bb1(%[[CST0]] : i32)
spv.Branch ^bb1(%zero : i32)
// CHECK-NEXT: ^bb1(%[[ARG:.*]]: i32):
^bb1(%arg0: i32):
// CHECK-NEXT: %[[ADD:.*]] = spv.IAdd %[[ARG]], %[[ARG]] : i32
%0 = spv.IAdd %arg0, %arg0 : i32
// CHECK-NEXT: %[[CST1:.*]] = spv.constant 0
// CHECK-NEXT: spv.Branch ^bb2(%[[CST1]], %[[ADD]] : i32, i32)
spv.Branch ^bb2(%zero, %0 : i32, i32)
// CHECK-NEXT: ^bb2(%{{.*}}: i32, %{{.*}}: i32):
^bb2(%arg1: i32, %arg2: i32):
spv.Return
}
spv.func @main() -> () "None" {
spv.Return
}
spv.EntryPoint "GLCompute" @main
}
// -----
// Test block not following domination order
spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
spv.func @foo() -> () "None" {
// CHECK: spv.Branch ^bb1
spv.Branch ^bb1
// CHECK-NEXT: ^bb1:
// CHECK-NEXT: %[[ZERO:.*]] = spv.constant 0
// CHECK-NEXT: %[[ONE:.*]] = spv.constant 1
// CHECK-NEXT: spv.Branch ^bb2(%[[ZERO]], %[[ONE]] : i32, f32)
// CHECK-NEXT: ^bb2(%{{.*}}: i32, %{{.*}}: f32):
^bb2(%arg0: i32, %arg1: f32):
// CHECK-NEXT: spv.Return
spv.Return
// This block is reordered to follow domination order.
^bb1:
%zero = spv.constant 0 : i32
%one = spv.constant 1.0 : f32
spv.Branch ^bb2(%zero, %one : i32, f32)
}
spv.func @main() -> () "None" {
spv.Return
}
spv.EntryPoint "GLCompute" @main
}
// -----
// Test multiple predecessors
spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
spv.func @foo() -> () "None" {
%var = spv.Variable : !spv.ptr<i32, Function>
// CHECK: spv.selection
spv.selection {
%true = spv.constant true
// CHECK: spv.BranchConditional %{{.*}}, ^bb1, ^bb2
spv.BranchConditional %true, ^true, ^false
// CHECK-NEXT: ^bb1:
^true:
// CHECK-NEXT: %[[ZERO:.*]] = spv.constant 0
%zero = spv.constant 0 : i32
// CHECK-NEXT: spv.Branch ^bb3(%[[ZERO]] : i32)
spv.Branch ^phi(%zero: i32)
// CHECK-NEXT: ^bb2:
^false:
// CHECK-NEXT: %[[ONE:.*]] = spv.constant 1
%one = spv.constant 1 : i32
// CHECK-NEXT: spv.Branch ^bb3(%[[ONE]] : i32)
spv.Branch ^phi(%one: i32)
// CHECK-NEXT: ^bb3(%[[ARG:.*]]: i32):
^phi(%arg: i32):
// CHECK-NEXT: spv.Store "Function" %{{.*}}, %[[ARG]] : i32
spv.Store "Function" %var, %arg : i32
// CHECK-NEXT: spv.Return
spv.Return
// CHECK-NEXT: ^bb4:
^merge:
// CHECK-NEXT: spv._merge
spv._merge
}
spv.Return
}
spv.func @main() -> () "None" {
spv.Return
}
spv.EntryPoint "GLCompute" @main
}
// -----
// Test nested loops with block arguments
spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
spv.globalVariable @__builtin_var_NumWorkgroups__ built_in("NumWorkgroups") : !spv.ptr<vector<3xi32>, Input>
spv.globalVariable @__builtin_var_WorkgroupId__ built_in("WorkgroupId") : !spv.ptr<vector<3xi32>, Input>
spv.func @fmul_kernel() "None" {
%3 = spv.constant 12 : i32
%4 = spv.constant 32 : i32
%5 = spv.constant 4 : i32
%6 = spv._address_of @__builtin_var_WorkgroupId__ : !spv.ptr<vector<3xi32>, Input>
%7 = spv.Load "Input" %6 : vector<3xi32>
%8 = spv.CompositeExtract %7[0 : i32] : vector<3xi32>
%9 = spv._address_of @__builtin_var_WorkgroupId__ : !spv.ptr<vector<3xi32>, Input>
%10 = spv.Load "Input" %9 : vector<3xi32>
%11 = spv.CompositeExtract %10[1 : i32] : vector<3xi32>
%18 = spv._address_of @__builtin_var_NumWorkgroups__ : !spv.ptr<vector<3xi32>, Input>
%19 = spv.Load "Input" %18 : vector<3xi32>
%20 = spv.CompositeExtract %19[0 : i32] : vector<3xi32>
%21 = spv._address_of @__builtin_var_NumWorkgroups__ : !spv.ptr<vector<3xi32>, Input>
%22 = spv.Load "Input" %21 : vector<3xi32>
%23 = spv.CompositeExtract %22[1 : i32] : vector<3xi32>
%30 = spv.IMul %11, %4 : i32
%31 = spv.IMul %23, %4 : i32
// CHECK: spv.Branch ^[[FN_BB:.*]](%{{.*}} : i32)
// CHECK: ^[[FN_BB]](%[[FN_BB_ARG:.*]]: i32):
// CHECK: spv.loop {
spv.loop {
// CHECK: spv.Branch ^bb1(%[[FN_BB_ARG]] : i32)
spv.Branch ^bb1(%30 : i32)
// CHECK: ^[[LP1_HDR:.*]](%[[LP1_HDR_ARG:.*]]: i32):
^bb1(%32: i32):
// CHECK: spv.SLessThan
%33 = spv.SLessThan %32, %3 : i32
// CHECK: spv.BranchConditional %{{.*}}, ^[[LP1_BDY:.*]], ^[[LP1_MG:.*]]
spv.BranchConditional %33, ^bb2, ^bb3
// CHECK: ^[[LP1_BDY]]:
^bb2:
// CHECK: %[[MUL:.*]] = spv.IMul
%34 = spv.IMul %8, %5 : i32
// CHECK: spv.IMul
%35 = spv.IMul %20, %5 : i32
// CHECK: spv.Branch ^[[LP1_CNT:.*]](%[[MUL]] : i32)
// CHECK: ^[[LP1_CNT]](%[[LP1_CNT_ARG:.*]]: i32):
// CHECK: spv.loop {
spv.loop {
// CHECK: spv.Branch ^[[LP2_HDR:.*]](%[[LP1_CNT_ARG]] : i32)
spv.Branch ^bb1(%34 : i32)
// CHECK: ^[[LP2_HDR]](%[[LP2_HDR_ARG:.*]]: i32):
^bb1(%37: i32):
// CHECK: spv.SLessThan %[[LP2_HDR_ARG]]
%38 = spv.SLessThan %37, %5 : i32
// CHECK: spv.BranchConditional %{{.*}}, ^[[LP2_BDY:.*]], ^[[LP2_MG:.*]]
spv.BranchConditional %38, ^bb2, ^bb3
// CHECK: ^[[LP2_BDY]]:
^bb2:
// CHECK: %[[ADD1:.*]] = spv.IAdd
%48 = spv.IAdd %37, %35 : i32
// CHECK: spv.Branch ^[[LP2_HDR]](%[[ADD1]] : i32)
spv.Branch ^bb1(%48 : i32)
// CHECK: ^[[LP2_MG]]:
^bb3:
// CHECK: spv._merge
spv._merge
}
// CHECK: %[[ADD2:.*]] = spv.IAdd %[[LP1_HDR_ARG]]
%36 = spv.IAdd %32, %31 : i32
// CHECK: spv.Branch ^[[LP1_HDR]](%[[ADD2]] : i32)
spv.Branch ^bb1(%36 : i32)
// CHECK: ^[[LP1_MG]]:
^bb3:
// CHECK: spv._merge
spv._merge
}
spv.Return
}
spv.EntryPoint "GLCompute" @fmul_kernel, @__builtin_var_WorkgroupId__, @__builtin_var_NumWorkgroups__
spv.ExecutionMode @fmul_kernel "LocalSize", 32, 1, 1
}