blob: 3a848c5c1d353bebaae5eafe357b39f96bc9c206 [file]
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// RUN: iree-opt -split-input-file -iree-index-computation -simplify-spirv-affine-exprs=false -convert-iree-to-spirv -verify-diagnostics -o - %s | IreeFileCheck %s
module {
// CHECK-DAG: spv.globalVariable [[GLOBALIDVAR:@.*]] built_in("GlobalInvocationId") : !spv.ptr<vector<3xi32>, Input>
// CHECK: func @pad_zero_interior
// CHECK-SAME: [[ARG0:%.*]]: !spv.ptr<!spv.struct<!spv.array<12 x !spv.array<4 x f32 [4]> [16]> [0]>, StorageBuffer>
// CHECK-SAME: [[ARG1:%.*]]: !spv.ptr<!spv.struct<!spv.array<18 x !spv.array<12 x f32 [4]> [48]> [0]>, StorageBuffer>
func @pad_zero_interior(%arg0 : memref<12x4xf32>, %arg1 : memref<18x12xf32>)
attributes {iree.executable.export, iree.executable.workload = dense<[12, 18, 1]> : tensor<3xi32>, iree.executable.workgroup_size = dense<[32, 1, 1]> : tensor<3xi32>, iree.ordinal = 0 : i32} {
// CHECK: [[GLOBALIDPTR:%.*]] = spv._address_of [[GLOBALIDVAR]]
// CHECK: [[GLOBALID:%.*]] = spv.Load "Input" [[GLOBALIDPTR]]
// CHECK: [[GLOBALIDX:%.*]] = spv.CompositeExtract [[GLOBALID]][0 : i32]
// CHECK: [[GLOBALIDY:%.*]] = spv.CompositeExtract [[GLOBALID]][1 : i32]
// CHECK: spv.selection
// CHECK: [[ZERO1:%.*]] = spv.constant 0 : i32
// CHECK: [[LOWER_PAD0:%.*]] = spv.constant -4 : i32
// CHECK: [[INDEX0:%.*]] = spv.IAdd [[GLOBALIDY]], [[LOWER_PAD0]] : i32
// CHECK: [[LOWER_PAD1:%.*]] = spv.constant -5 : i32
// CHECK: [[INDEX1:%.*]] = spv.IAdd [[GLOBALIDX]], [[LOWER_PAD1]] : i32
// CHECK: [[ARG0LOADPTR:%.*]] = spv.AccessChain [[ARG0]]{{\[}}[[ZERO1]], [[INDEX0]], [[INDEX1]]{{\]}}
// CHECK: [[INPUTVAL:%.*]] = spv.Load "StorageBuffer" [[ARG0LOADPTR]] : f32
%0 = iree.load_input(%arg0 : memref<12x4xf32>) : tensor<12x4xf32>
// CHECK: [[PADVAL:%.*]] = spv.constant 0.000000e+00 : f32
%1 = constant dense<0.0> : tensor<f32>
// CHECK: [[ZERO2:%.*]] = spv.constant 0 : i32
// CHECK: [[COND0:%.*]] = spv.constant true
// CHECK: [[LOWER_PAD0_2:%.*]] = spv.constant 4 : i32
// CHECK: [[STRIDE0:%.*]] = spv.constant 1 : i32
// CHECK: [[OPERAND_EXTENT0:%.*]] = spv.constant 12 : i32
// CHECK: [[TEMP1:%.*]] = spv.IMul [[STRIDE0]], [[OPERAND_EXTENT0]] : i32
// CHECK: [[BOUND0:%.*]] = spv.IAdd [[LOWER_PAD0_2]], [[TEMP1]] : i32
// CHECK: [[CHECK_UB0:%.*]] = spv.SLessThan [[GLOBALIDY]], [[BOUND0]] : i32
// CHECK: [[COND1:%.*]] = spv.LogicalAnd [[COND0]], [[CHECK_UB0]] : i1
// CHECK: [[CHECK_LB0:%.*]] = spv.SGreaterThanEqual [[GLOBALIDY]], [[LOWER_PAD0_2]] : i32
// CHECK: [[COND2:%.*]] = spv.LogicalAnd [[COND1]], [[CHECK_LB0]] : i1
// CHECK: [[LOWER_PAD1_2:%.*]] = spv.constant 5 : i32
// CHECK: [[STRIDE1:%.*]] = spv.constant 1 : i32
// CHECK: [[OPERAND_EXTENT1:%.*]] = spv.constant 4 : i32
// CHECK: [[TEMP2:%.*]] = spv.IMul [[STRIDE1]], [[OPERAND_EXTENT1]] : i32
// CHECK: [[BOUND1:%.*]] = spv.IAdd [[LOWER_PAD1_2]], [[TEMP2]] : i32
// CHECK: [[CHECK_UB1:%.*]] = spv.SLessThan [[GLOBALIDX]], [[BOUND1]] : i32
// CHECK: [[COND3:%.*]] = spv.LogicalAnd [[COND2]], [[CHECK_UB1]] : i1
// CHECK: [[CHECK_LB1:%.*]] = spv.SGreaterThanEqual [[GLOBALIDX]], [[LOWER_PAD1_2]] : i32
// CHECK: [[COND4:%.*]] = spv.LogicalAnd [[COND3]], [[CHECK_LB1]] : i1
// CHECK: [[VALUE:%.*]] = spv.Select [[COND4]], [[INPUTVAL]], [[PADVAL]] : i1, f32
%2 = "xla_hlo.pad"(%0, %1) {edge_padding_high = dense<[2, 3]> : tensor<2xi64>, edge_padding_low = dense<[4, 5]> : tensor<2xi64>, interior_padding = dense<0> : tensor<2xi64>} : (tensor<12x4xf32>, tensor<f32>) -> tensor<18x12xf32>
iree.store_output(%2 : tensor<18x12xf32>, %arg1 : memref<18x12xf32>)
iree.return
}
}
// -----
module {
// CHECK-DAG: spv.globalVariable [[GLOBALIDVAR:@.*]] built_in("GlobalInvocationId") : !spv.ptr<vector<3xi32>, Input>
// CHECK: func @pad_no_op
// CHECK-SAME: [[ARG0:%[a-zA-Z0-9]*]]: !spv.ptr<!spv.struct<!spv.array<12 x !spv.array<4 x f32 [4]> [16]> [0]>, StorageBuffer>
func @pad_no_op(%arg0 : memref<12x4xf32>, %arg1 : memref<12x4xf32>)
attributes {iree.executable.export, iree.executable.workload = dense<[4, 12, 1]> : tensor<3xi32>, iree.executable.workgroup_size = dense<[32, 1, 1]> : tensor<3xi32>, iree.ordinal = 0 : i32} {
// CHECK: [[GLOBALIDPTR:%.*]] = spv._address_of [[GLOBALIDVAR]]
// CHECK: [[GLOBALID:%.*]] = spv.Load "Input" [[GLOBALIDPTR]]
// CHECK: [[GLOBALIDX:%.*]] = spv.CompositeExtract [[GLOBALID]][0 : i32]
// CHECK: [[GLOBALIDY:%.*]] = spv.CompositeExtract [[GLOBALID]][1 : i32]
// CHECK: spv.selection
// CHECK: [[ZERO1:%.*]] = spv.constant 0 : i32
// CHECK: [[ARG0LOADPTR:%.*]] = spv.AccessChain [[ARG0]]{{\[}}[[ZERO1]], [[GLOBALIDY]], [[GLOBALIDX]]{{\]}}
// CHECK: [[INPUTVAL:%.*]] = spv.Load "StorageBuffer" [[ARG0LOADPTR]] : f32
%0 = iree.load_input(%arg0 : memref<12x4xf32>) : tensor<12x4xf32>
// CHECK: [[PADVAL:%.*]] = spv.constant 0.000000e+00 : f32
%1 = constant dense<0.0> : tensor<f32>
// CHECK: [[ZERO2:%.*]] = spv.constant 0 : i32
// CHECK: [[COND0:%.*]] = spv.constant true
// CHECK: {{%.*}} = spv.Select [[COND0]], [[INPUTVAL]], [[PADVAL]] : i1, f32
%2 = "xla_hlo.pad"(%0, %1) {edge_padding_high = dense<[0, 0]> : tensor<2xi64>, edge_padding_low = dense<[0, 0]> : tensor<2xi64>, interior_padding = dense<0> : tensor<2xi64>} : (tensor<12x4xf32>, tensor<f32>) -> tensor<12x4xf32>
iree.store_output(%2 : tensor<12x4xf32>, %arg1 : memref<12x4xf32>)
iree.return
}
}
// -----
module {
// CHECK-DAG: spv.globalVariable [[GLOBALIDVAR:@.*]] built_in("GlobalInvocationId") : !spv.ptr<vector<3xi32>, Input>
// CHECK: func @pad_zero_interior
// CHECK-SAME: [[ARG0:%.*]]: !spv.ptr<!spv.struct<!spv.array<12 x !spv.array<4 x f32 [4]> [16]> [0]>, StorageBuffer>
func @pad_zero_interior(%arg0 : memref<12x4xf32>, %arg1 : memref<29x18xf32>)
attributes {iree.executable.export, iree.executable.workload = dense<[18, 29, 1]> : tensor<3xi32>, iree.executable.workgroup_size = dense<[32, 1, 1]> : tensor<3xi32>, iree.ordinal = 0 : i32} {
// CHECK: [[GLOBALIDPTR:%.*]] = spv._address_of [[GLOBALIDVAR]]
// CHECK: [[GLOBALID:%.*]] = spv.Load "Input" [[GLOBALIDPTR]]
// CHECK: [[GLOBALIDX:%.*]] = spv.CompositeExtract [[GLOBALID]][0 : i32]
// CHECK: [[GLOBALIDY:%.*]] = spv.CompositeExtract [[GLOBALID]][1 : i32]
// CHECK: spv.selection
// CHECK: [[ZERO1:%.*]] = spv.constant 0 : i32
// CHECK: [[INTERIOR0:%.*]] = spv.constant 2 : i32
// CHECK: [[SUB_PAD0:%.*]] = spv.SDiv [[GLOBALIDY]], [[INTERIOR0]] : i32
// CHECK: [[LOWER_PAD0:%.*]] = spv.constant -2 : i32
// CHECK: [[INDEX0:%.*]] = spv.IAdd [[SUB_PAD0]], [[LOWER_PAD0]] : i32
// CHECK: [[LOWER_PAD1:%.*]] = spv.constant -5 : i32
// CHECK: [[SUB_PAD1:%.*]] = spv.IAdd [[GLOBALIDX]], [[LOWER_PAD1]] : i32
// CHECK: [[INTERIOR1:%.*]] = spv.constant 3 : i32
// CHECK: [[INDEX1:%.*]] = spv.SDiv [[SUB_PAD1]], [[INTERIOR1]] : i32
// CHECK: [[ARG0LOADPTR:%.*]] = spv.AccessChain [[ARG0]]{{\[}}[[ZERO1]], [[INDEX0]], [[INDEX1]]{{\]}}
// CHECK: [[INPUTVAL:%.*]] = spv.Load "StorageBuffer" [[ARG0LOADPTR]] : f32
%0 = iree.load_input(%arg0 : memref<12x4xf32>) : tensor<12x4xf32>
// CHECK: [[PADVAL:%.*]] = spv.constant 0.000000e+00 : f32
%1 = constant dense<0.0> : tensor<f32>
// CHECK: [[ZERO2:%.*]] = spv.constant 0 : i32
// CHECK: [[COND0:%.*]] = spv.constant true
// CHECK: [[LOWER_PAD0_2:%.*]] = spv.constant 4 : i32
// CHECK: [[STRIDE0:%.*]] = spv.constant 2 : i32
// CHECK: [[OPERAND_EXTENT0:%.*]] = spv.constant 12 : i32
// CHECK: [[TEMP1:%.*]] = spv.IMul [[STRIDE0]], [[OPERAND_EXTENT0]] : i32
// CHECK: [[BOUND0:%.*]] = spv.IAdd [[LOWER_PAD0_2]], [[TEMP1]] : i32
// CHECK: [[CHECK_UB0:%.*]] = spv.SLessThan [[GLOBALIDY]], [[BOUND0]] : i32
// CHECK: [[COND1:%.*]] = spv.LogicalAnd [[COND0]], [[CHECK_UB0]] : i1
// CHECK: [[CHECK_LB0:%.*]] = spv.SGreaterThanEqual [[GLOBALIDY]], [[LOWER_PAD0_2]] : i32
// CHECK: [[COND2:%.*]] = spv.LogicalAnd [[COND1]], [[CHECK_LB0]] : i1
// CHECK: [[TEMP1_1:%.*]] = spv.ISub [[GLOBALIDY]], [[LOWER_PAD0_2]] : i32
// CHECK: [[TEMP1_2:%.*]] = spv.SMod [[TEMP1_1]], [[STRIDE0]] : i32
// CHECK: [[CHECK_INTERIOR0:%.*]] = spv.IEqual [[TEMP1_2]], [[ZERO2]] : i32
// CHECK: [[COND3:%.*]] = spv.LogicalAnd [[COND2]], [[CHECK_INTERIOR0]] : i1
// CHECK: [[LOWER_PAD1_2:%.*]] = spv.constant 5 : i32
// CHECK: [[STRIDE1:%.*]] = spv.constant 3 : i32
// CHECK: [[OPERAND_EXTENT1:%.*]] = spv.constant 4 : i32
// CHECK: [[TEMP2:%.*]] = spv.IMul [[STRIDE1]], [[OPERAND_EXTENT1]] : i32
// CHECK: [[BOUND1:%.*]] = spv.IAdd [[LOWER_PAD1_2]], [[TEMP2]] : i32
// CHECK: [[CHECK_UB1:%.*]] = spv.SLessThan [[GLOBALIDX]], [[BOUND1]] : i32
// CHECK: [[COND4:%.*]] = spv.LogicalAnd [[COND3]], [[CHECK_UB1]] : i1
// CHECK: [[CHECK_LB1:%.*]] = spv.SGreaterThanEqual [[GLOBALIDX]], [[LOWER_PAD1_2]] : i32
// CHECK: [[COND5:%.*]] = spv.LogicalAnd [[COND4]], [[CHECK_LB1]] : i1
// CHECK: [[TEMP2_1:%.*]] = spv.ISub [[GLOBALIDX]], [[LOWER_PAD1_2]] : i32
// CHECK: [[TEMP2_2:%.*]] = spv.SMod [[TEMP2_1]], [[STRIDE1]] : i32
// CHECK: [[CHECK_INTERIOR1:%.*]] = spv.IEqual [[TEMP2_2]], [[ZERO2]] : i32
// CHECK: [[COND6:%.*]] = spv.LogicalAnd [[COND5]], [[CHECK_INTERIOR1]] : i1
// CHECK: [[VALUE:%.*]] = spv.Select [[COND6]], [[INPUTVAL]], [[PADVAL]] : i1, f32
%2 = "xla_hlo.pad"(%0, %1) {edge_padding_high = dense<[2, 3]> : tensor<2xi64>, edge_padding_low = dense<[4, 5]> : tensor<2xi64>, interior_padding = dense<[1, 2]> : tensor<2xi64>} : (tensor<12x4xf32>, tensor<f32>) -> tensor<29x18xf32>
iree.store_output(%2 : tensor<29x18xf32>, %arg1 : memref<29x18xf32>)
iree.return
}
}