2020-02-05 09:58:10 +08:00
|
|
|
// RUN: mlir-opt -split-input-file -convert-gpu-to-spirv %s -o - | FileCheck %s
|
2019-08-28 01:49:53 +08:00
|
|
|
|
2019-10-08 19:29:58 +08:00
|
|
|
module attributes {gpu.container_module} {
|
|
|
|
func @builtin() {
|
2021-10-13 07:14:57 +08:00
|
|
|
%c0 = arith.constant 1 : index
|
2020-10-22 13:43:34 +08:00
|
|
|
gpu.launch_func @kernels::@builtin_workgroup_id_x
|
|
|
|
blocks in (%c0, %c0, %c0) threads in (%c0, %c0, %c0)
|
2019-10-08 19:29:58 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-27 13:50:57 +08:00
|
|
|
// CHECK-LABEL: spv.module @{{.*}} Logical GLSL450
|
2021-03-05 05:17:12 +08:00
|
|
|
// CHECK: spv.GlobalVariable [[WORKGROUPID:@.*]] built_in("WorkgroupId")
|
Create a gpu.module operation for the GPU Dialect.
Summary:
This is based on the use of code constantly checking for an attribute on
a model and instead represents the distinct operaion with a different
op. Instead, this op can be used to provide better filtering.
Reverts "Revert "[mlir] Create a gpu.module operation for the GPU Dialect.""
This reverts commit ac446302ca4145cdc89f377c0c364c29ee303be5 after
fixing internal Google issues.
This additionally updates ROCDL lowering to use the new gpu.module.
Reviewers: herhut, mravishankar, antiagainst, nicolasvasilache
Subscribers: jholewinski, mgorny, mehdi_amini, jpienaar, burmako, shauheen, csigg, arpith-jacob, mgester, lucyrfox, aartbik, liufengdb, llvm-commits, mravishankar, rriddle, antiagainst, bkramer
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D72921
2020-01-17 22:18:23 +08:00
|
|
|
gpu.module @kernels {
|
2020-04-21 15:11:10 +08:00
|
|
|
gpu.func @builtin_workgroup_id_x() kernel
|
|
|
|
attributes {spv.entry_point_abi = {local_size = dense<[16, 1, 1]>: vector<3xi32>}} {
|
2020-11-18 00:45:32 +08:00
|
|
|
// CHECK: [[ADDRESS:%.*]] = spv.mlir.addressof [[WORKGROUPID]]
|
2019-10-08 19:29:58 +08:00
|
|
|
// CHECK-NEXT: [[VEC:%.*]] = spv.Load "Input" [[ADDRESS]]
|
|
|
|
// CHECK-NEXT: {{%.*}} = spv.CompositeExtract [[VEC]]{{\[}}0 : i32{{\]}}
|
2022-01-19 00:53:55 +08:00
|
|
|
%0 = gpu.block_id x
|
2019-12-17 04:12:20 +08:00
|
|
|
gpu.return
|
2019-10-08 19:29:58 +08:00
|
|
|
}
|
|
|
|
}
|
2019-08-28 01:49:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-10-08 19:29:58 +08:00
|
|
|
module attributes {gpu.container_module} {
|
|
|
|
func @builtin() {
|
2021-10-13 07:14:57 +08:00
|
|
|
%c0 = arith.constant 1 : index
|
|
|
|
%c256 = arith.constant 256 : i32
|
2020-10-22 13:43:34 +08:00
|
|
|
gpu.launch_func @kernels::@builtin_workgroup_id_y
|
|
|
|
blocks in (%c0, %c0, %c0) threads in (%c0, %c0, %c0)
|
2021-09-14 16:43:21 +08:00
|
|
|
dynamic_shared_memory_size %c256
|
2019-10-08 19:29:58 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-27 13:50:57 +08:00
|
|
|
// CHECK-LABEL: spv.module @{{.*}} Logical GLSL450
|
2021-03-05 05:17:12 +08:00
|
|
|
// CHECK: spv.GlobalVariable [[WORKGROUPID:@.*]] built_in("WorkgroupId")
|
Create a gpu.module operation for the GPU Dialect.
Summary:
This is based on the use of code constantly checking for an attribute on
a model and instead represents the distinct operaion with a different
op. Instead, this op can be used to provide better filtering.
Reverts "Revert "[mlir] Create a gpu.module operation for the GPU Dialect.""
This reverts commit ac446302ca4145cdc89f377c0c364c29ee303be5 after
fixing internal Google issues.
This additionally updates ROCDL lowering to use the new gpu.module.
Reviewers: herhut, mravishankar, antiagainst, nicolasvasilache
Subscribers: jholewinski, mgorny, mehdi_amini, jpienaar, burmako, shauheen, csigg, arpith-jacob, mgester, lucyrfox, aartbik, liufengdb, llvm-commits, mravishankar, rriddle, antiagainst, bkramer
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D72921
2020-01-17 22:18:23 +08:00
|
|
|
gpu.module @kernels {
|
2020-04-21 15:11:10 +08:00
|
|
|
gpu.func @builtin_workgroup_id_y() kernel
|
|
|
|
attributes {spv.entry_point_abi = {local_size = dense<[16, 1, 1]>: vector<3xi32>}} {
|
2020-11-18 00:45:32 +08:00
|
|
|
// CHECK: [[ADDRESS:%.*]] = spv.mlir.addressof [[WORKGROUPID]]
|
2019-10-08 19:29:58 +08:00
|
|
|
// CHECK-NEXT: [[VEC:%.*]] = spv.Load "Input" [[ADDRESS]]
|
|
|
|
// CHECK-NEXT: {{%.*}} = spv.CompositeExtract [[VEC]]{{\[}}1 : i32{{\]}}
|
2022-01-19 00:53:55 +08:00
|
|
|
%0 = gpu.block_id y
|
2019-12-17 04:12:20 +08:00
|
|
|
gpu.return
|
2019-10-08 19:29:58 +08:00
|
|
|
}
|
|
|
|
}
|
2019-08-28 01:49:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-10-08 19:29:58 +08:00
|
|
|
module attributes {gpu.container_module} {
|
|
|
|
func @builtin() {
|
2021-10-13 07:14:57 +08:00
|
|
|
%c0 = arith.constant 1 : index
|
2020-10-22 13:43:34 +08:00
|
|
|
gpu.launch_func @kernels::@builtin_workgroup_id_z
|
|
|
|
blocks in (%c0, %c0, %c0) threads in (%c0, %c0, %c0)
|
2019-10-08 19:29:58 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-27 13:50:57 +08:00
|
|
|
// CHECK-LABEL: spv.module @{{.*}} Logical GLSL450
|
2021-03-05 05:17:12 +08:00
|
|
|
// CHECK: spv.GlobalVariable [[WORKGROUPID:@.*]] built_in("WorkgroupId")
|
Create a gpu.module operation for the GPU Dialect.
Summary:
This is based on the use of code constantly checking for an attribute on
a model and instead represents the distinct operaion with a different
op. Instead, this op can be used to provide better filtering.
Reverts "Revert "[mlir] Create a gpu.module operation for the GPU Dialect.""
This reverts commit ac446302ca4145cdc89f377c0c364c29ee303be5 after
fixing internal Google issues.
This additionally updates ROCDL lowering to use the new gpu.module.
Reviewers: herhut, mravishankar, antiagainst, nicolasvasilache
Subscribers: jholewinski, mgorny, mehdi_amini, jpienaar, burmako, shauheen, csigg, arpith-jacob, mgester, lucyrfox, aartbik, liufengdb, llvm-commits, mravishankar, rriddle, antiagainst, bkramer
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D72921
2020-01-17 22:18:23 +08:00
|
|
|
gpu.module @kernels {
|
2020-04-21 15:11:10 +08:00
|
|
|
gpu.func @builtin_workgroup_id_z() kernel
|
|
|
|
attributes {spv.entry_point_abi = {local_size = dense<[16, 1, 1]>: vector<3xi32>}} {
|
2020-11-18 00:45:32 +08:00
|
|
|
// CHECK: [[ADDRESS:%.*]] = spv.mlir.addressof [[WORKGROUPID]]
|
2019-10-08 19:29:58 +08:00
|
|
|
// CHECK-NEXT: [[VEC:%.*]] = spv.Load "Input" [[ADDRESS]]
|
|
|
|
// CHECK-NEXT: {{%.*}} = spv.CompositeExtract [[VEC]]{{\[}}2 : i32{{\]}}
|
2022-01-19 00:53:55 +08:00
|
|
|
%0 = gpu.block_id z
|
2019-12-17 04:12:20 +08:00
|
|
|
gpu.return
|
2019-10-08 19:29:58 +08:00
|
|
|
}
|
|
|
|
}
|
2019-08-28 01:49:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-10-08 19:29:58 +08:00
|
|
|
module attributes {gpu.container_module} {
|
|
|
|
func @builtin() {
|
2021-10-13 07:14:57 +08:00
|
|
|
%c0 = arith.constant 1 : index
|
2020-10-22 13:43:34 +08:00
|
|
|
gpu.launch_func @kernels::@builtin_workgroup_size_x
|
|
|
|
blocks in (%c0, %c0, %c0) threads in (%c0, %c0, %c0)
|
2019-10-08 19:29:58 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-27 13:50:57 +08:00
|
|
|
// CHECK-LABEL: spv.module @{{.*}} Logical GLSL450
|
Create a gpu.module operation for the GPU Dialect.
Summary:
This is based on the use of code constantly checking for an attribute on
a model and instead represents the distinct operaion with a different
op. Instead, this op can be used to provide better filtering.
Reverts "Revert "[mlir] Create a gpu.module operation for the GPU Dialect.""
This reverts commit ac446302ca4145cdc89f377c0c364c29ee303be5 after
fixing internal Google issues.
This additionally updates ROCDL lowering to use the new gpu.module.
Reviewers: herhut, mravishankar, antiagainst, nicolasvasilache
Subscribers: jholewinski, mgorny, mehdi_amini, jpienaar, burmako, shauheen, csigg, arpith-jacob, mgester, lucyrfox, aartbik, liufengdb, llvm-commits, mravishankar, rriddle, antiagainst, bkramer
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D72921
2020-01-17 22:18:23 +08:00
|
|
|
gpu.module @kernels {
|
2020-04-21 15:11:10 +08:00
|
|
|
gpu.func @builtin_workgroup_size_x() kernel
|
|
|
|
attributes {spv.entry_point_abi = {local_size = dense<[32, 1, 1]>: vector<3xi32>}} {
|
2020-02-05 09:58:10 +08:00
|
|
|
// The constant value is obtained from the spv.entry_point_abi.
|
|
|
|
// Note that this ignores the workgroup size specification in gpu.launch.
|
|
|
|
// We may want to define gpu.workgroup_size and convert it to the entry
|
|
|
|
// point ABI we want here.
|
2021-03-05 05:15:46 +08:00
|
|
|
// CHECK: spv.Constant 32 : i32
|
2022-01-19 00:53:55 +08:00
|
|
|
%0 = gpu.block_dim x
|
2019-12-17 04:12:20 +08:00
|
|
|
gpu.return
|
2019-10-08 19:29:58 +08:00
|
|
|
}
|
|
|
|
}
|
2019-08-28 01:49:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2020-02-09 10:23:09 +08:00
|
|
|
module attributes {gpu.container_module} {
|
|
|
|
func @builtin() {
|
2021-10-13 07:14:57 +08:00
|
|
|
%c0 = arith.constant 1 : index
|
2020-10-22 13:43:34 +08:00
|
|
|
gpu.launch_func @kernels::@builtin_workgroup_size_y
|
|
|
|
blocks in (%c0, %c0, %c0) threads in (%c0, %c0, %c0)
|
2020-02-09 10:23:09 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-27 13:50:57 +08:00
|
|
|
// CHECK-LABEL: spv.module @{{.*}} Logical GLSL450
|
2020-02-09 10:23:09 +08:00
|
|
|
gpu.module @kernels {
|
2020-04-21 15:11:10 +08:00
|
|
|
gpu.func @builtin_workgroup_size_y() kernel
|
|
|
|
attributes {spv.entry_point_abi = {local_size = dense<[32, 4, 1]>: vector<3xi32>}} {
|
2020-02-05 09:58:10 +08:00
|
|
|
// The constant value is obtained from the spv.entry_point_abi.
|
2021-03-05 05:15:46 +08:00
|
|
|
// CHECK: spv.Constant 4 : i32
|
2022-01-19 00:53:55 +08:00
|
|
|
%0 = gpu.block_dim y
|
2020-02-09 10:23:09 +08:00
|
|
|
gpu.return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
module attributes {gpu.container_module} {
|
|
|
|
func @builtin() {
|
2021-10-13 07:14:57 +08:00
|
|
|
%c0 = arith.constant 1 : index
|
2020-10-22 13:43:34 +08:00
|
|
|
gpu.launch_func @kernels::@builtin_workgroup_size_z
|
|
|
|
blocks in (%c0, %c0, %c0) threads in (%c0, %c0, %c0)
|
2020-02-09 10:23:09 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-27 13:50:57 +08:00
|
|
|
// CHECK-LABEL: spv.module @{{.*}} Logical GLSL450
|
2020-02-09 10:23:09 +08:00
|
|
|
gpu.module @kernels {
|
2020-04-21 15:11:10 +08:00
|
|
|
gpu.func @builtin_workgroup_size_z() kernel
|
|
|
|
attributes {spv.entry_point_abi = {local_size = dense<[32, 4, 1]>: vector<3xi32>}} {
|
2020-02-05 09:58:10 +08:00
|
|
|
// The constant value is obtained from the spv.entry_point_abi.
|
2021-03-05 05:15:46 +08:00
|
|
|
// CHECK: spv.Constant 1 : i32
|
2022-01-19 00:53:55 +08:00
|
|
|
%0 = gpu.block_dim z
|
2020-02-09 10:23:09 +08:00
|
|
|
gpu.return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-10-08 19:29:58 +08:00
|
|
|
module attributes {gpu.container_module} {
|
|
|
|
func @builtin() {
|
2021-10-13 07:14:57 +08:00
|
|
|
%c0 = arith.constant 1 : index
|
2020-10-22 13:43:34 +08:00
|
|
|
gpu.launch_func @kernels::@builtin_local_id_x
|
|
|
|
blocks in (%c0, %c0, %c0) threads in (%c0, %c0, %c0)
|
2019-10-08 19:29:58 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-27 13:50:57 +08:00
|
|
|
// CHECK-LABEL: spv.module @{{.*}} Logical GLSL450
|
2021-03-05 05:17:12 +08:00
|
|
|
// CHECK: spv.GlobalVariable [[LOCALINVOCATIONID:@.*]] built_in("LocalInvocationId")
|
Create a gpu.module operation for the GPU Dialect.
Summary:
This is based on the use of code constantly checking for an attribute on
a model and instead represents the distinct operaion with a different
op. Instead, this op can be used to provide better filtering.
Reverts "Revert "[mlir] Create a gpu.module operation for the GPU Dialect.""
This reverts commit ac446302ca4145cdc89f377c0c364c29ee303be5 after
fixing internal Google issues.
This additionally updates ROCDL lowering to use the new gpu.module.
Reviewers: herhut, mravishankar, antiagainst, nicolasvasilache
Subscribers: jholewinski, mgorny, mehdi_amini, jpienaar, burmako, shauheen, csigg, arpith-jacob, mgester, lucyrfox, aartbik, liufengdb, llvm-commits, mravishankar, rriddle, antiagainst, bkramer
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D72921
2020-01-17 22:18:23 +08:00
|
|
|
gpu.module @kernels {
|
2020-04-21 15:11:10 +08:00
|
|
|
gpu.func @builtin_local_id_x() kernel
|
|
|
|
attributes {spv.entry_point_abi = {local_size = dense<[16, 1, 1]>: vector<3xi32>}} {
|
2020-11-18 00:45:32 +08:00
|
|
|
// CHECK: [[ADDRESS:%.*]] = spv.mlir.addressof [[LOCALINVOCATIONID]]
|
2019-10-08 19:29:58 +08:00
|
|
|
// CHECK-NEXT: [[VEC:%.*]] = spv.Load "Input" [[ADDRESS]]
|
|
|
|
// CHECK-NEXT: {{%.*}} = spv.CompositeExtract [[VEC]]{{\[}}0 : i32{{\]}}
|
2022-01-19 00:53:55 +08:00
|
|
|
%0 = gpu.thread_id x
|
2019-12-17 04:12:20 +08:00
|
|
|
gpu.return
|
2019-10-08 19:29:58 +08:00
|
|
|
}
|
|
|
|
}
|
2019-08-28 01:49:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-10-08 19:29:58 +08:00
|
|
|
module attributes {gpu.container_module} {
|
|
|
|
func @builtin() {
|
2021-10-13 07:14:57 +08:00
|
|
|
%c0 = arith.constant 1 : index
|
2020-10-22 13:43:34 +08:00
|
|
|
gpu.launch_func @kernels::@builtin_num_workgroups_x
|
|
|
|
blocks in (%c0, %c0, %c0) threads in (%c0, %c0, %c0)
|
2019-10-08 19:29:58 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-27 13:50:57 +08:00
|
|
|
// CHECK-LABEL: spv.module @{{.*}} Logical GLSL450
|
2021-03-05 05:17:12 +08:00
|
|
|
// CHECK: spv.GlobalVariable [[NUMWORKGROUPS:@.*]] built_in("NumWorkgroups")
|
Create a gpu.module operation for the GPU Dialect.
Summary:
This is based on the use of code constantly checking for an attribute on
a model and instead represents the distinct operaion with a different
op. Instead, this op can be used to provide better filtering.
Reverts "Revert "[mlir] Create a gpu.module operation for the GPU Dialect.""
This reverts commit ac446302ca4145cdc89f377c0c364c29ee303be5 after
fixing internal Google issues.
This additionally updates ROCDL lowering to use the new gpu.module.
Reviewers: herhut, mravishankar, antiagainst, nicolasvasilache
Subscribers: jholewinski, mgorny, mehdi_amini, jpienaar, burmako, shauheen, csigg, arpith-jacob, mgester, lucyrfox, aartbik, liufengdb, llvm-commits, mravishankar, rriddle, antiagainst, bkramer
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D72921
2020-01-17 22:18:23 +08:00
|
|
|
gpu.module @kernels {
|
2020-04-21 15:11:10 +08:00
|
|
|
gpu.func @builtin_num_workgroups_x() kernel
|
|
|
|
attributes {spv.entry_point_abi = {local_size = dense<[16, 1, 1]>: vector<3xi32>}} {
|
2020-11-18 00:45:32 +08:00
|
|
|
// CHECK: [[ADDRESS:%.*]] = spv.mlir.addressof [[NUMWORKGROUPS]]
|
2019-10-08 19:29:58 +08:00
|
|
|
// CHECK-NEXT: [[VEC:%.*]] = spv.Load "Input" [[ADDRESS]]
|
|
|
|
// CHECK-NEXT: {{%.*}} = spv.CompositeExtract [[VEC]]{{\[}}0 : i32{{\]}}
|
2022-01-19 00:53:55 +08:00
|
|
|
%0 = gpu.grid_dim x
|
2019-12-17 04:12:20 +08:00
|
|
|
gpu.return
|
2019-10-08 19:29:58 +08:00
|
|
|
}
|
|
|
|
}
|
2019-08-28 01:49:53 +08:00
|
|
|
}
|
2020-06-05 01:45:53 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
module attributes {gpu.container_module} {
|
2020-08-27 13:50:57 +08:00
|
|
|
// CHECK-LABEL: spv.module @{{.*}} Logical GLSL450
|
2021-03-05 05:17:12 +08:00
|
|
|
// CHECK: spv.GlobalVariable [[SUBGROUPID:@.*]] built_in("SubgroupId")
|
2020-06-05 01:45:53 +08:00
|
|
|
gpu.module @kernels {
|
|
|
|
gpu.func @builtin_subgroup_id() kernel
|
|
|
|
attributes {spv.entry_point_abi = {local_size = dense<[16, 1, 1]>: vector<3xi32>}} {
|
2020-11-18 00:45:32 +08:00
|
|
|
// CHECK: [[ADDRESS:%.*]] = spv.mlir.addressof [[SUBGROUPID]]
|
2020-06-05 01:45:53 +08:00
|
|
|
// CHECK-NEXT: {{%.*}} = spv.Load "Input" [[ADDRESS]]
|
|
|
|
%0 = gpu.subgroup_id : index
|
|
|
|
gpu.return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
module attributes {gpu.container_module} {
|
2020-08-27 13:50:57 +08:00
|
|
|
// CHECK-LABEL: spv.module @{{.*}} Logical GLSL450
|
2021-03-05 05:17:12 +08:00
|
|
|
// CHECK: spv.GlobalVariable [[NUMSUBGROUPS:@.*]] built_in("NumSubgroups")
|
2020-06-05 01:45:53 +08:00
|
|
|
gpu.module @kernels {
|
|
|
|
gpu.func @builtin_num_subgroups() kernel
|
|
|
|
attributes {spv.entry_point_abi = {local_size = dense<[16, 1, 1]>: vector<3xi32>}} {
|
2020-11-18 00:45:32 +08:00
|
|
|
// CHECK: [[ADDRESS:%.*]] = spv.mlir.addressof [[NUMSUBGROUPS]]
|
2020-06-05 01:45:53 +08:00
|
|
|
// CHECK-NEXT: {{%.*}} = spv.Load "Input" [[ADDRESS]]
|
|
|
|
%0 = gpu.num_subgroups : index
|
|
|
|
gpu.return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
module attributes {gpu.container_module} {
|
2020-08-27 13:50:57 +08:00
|
|
|
// CHECK-LABEL: spv.module @{{.*}} Logical GLSL450
|
2021-03-05 05:17:12 +08:00
|
|
|
// CHECK: spv.GlobalVariable [[SUBGROUPSIZE:@.*]] built_in("SubgroupSize")
|
2020-06-05 01:45:53 +08:00
|
|
|
gpu.module @kernels {
|
|
|
|
gpu.func @builtin_subgroup_size() kernel
|
|
|
|
attributes {spv.entry_point_abi = {local_size = dense<[16, 1, 1]>: vector<3xi32>}} {
|
2020-11-18 00:45:32 +08:00
|
|
|
// CHECK: [[ADDRESS:%.*]] = spv.mlir.addressof [[SUBGROUPSIZE]]
|
2020-06-05 01:45:53 +08:00
|
|
|
// CHECK-NEXT: {{%.*}} = spv.Load "Input" [[ADDRESS]]
|
|
|
|
%0 = gpu.subgroup_size : index
|
|
|
|
gpu.return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|