2 * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "luci/Pass/DecomposeHardSwishPass.h"
19 #include <luci/IR/CircleNodes.h>
21 #include <gtest/gtest.h>
40 luci::CircleInput *_input = nullptr;
41 luci::CircleHardSwish *_hardswish = nullptr;
42 luci::CircleOutput *_output = nullptr;
45 class DecomposeHardSwishPass : public ::testing::Test
55 // graph input and output
56 auto graph_input = _hardswish_g._g.inputs()->create();
57 auto graph_output = _hardswish_g._g.outputs()->create();
60 _hardswish_g._input = _hardswish_g._g.nodes()->create<luci::CircleInput>();
61 _hardswish_g._input->index(graph_input->index());
62 _hardswish_g._input->shape({N, H, W, C});
63 _hardswish_g._input->dtype(loco::DataType::FLOAT32);
64 _hardswish_g._input->name("input");
67 _hardswish_g._hardswish = _hardswish_g._g.nodes()->create<luci::CircleHardSwish>();
68 _hardswish_g._hardswish->features(_hardswish_g._input);
69 _hardswish_g._hardswish->shape({N, H, W, C});
70 _hardswish_g._hardswish->dtype(loco::DataType::FLOAT32);
71 _hardswish_g._hardswish->name("hardswish");
74 _hardswish_g._output = _hardswish_g._g.nodes()->create<luci::CircleOutput>();
75 _hardswish_g._output->index(graph_output->index());
76 _hardswish_g._output->from(_hardswish_g._hardswish);
77 _hardswish_g._output->shape({N, H, W, C});
78 _hardswish_g._output->dtype(loco::DataType::FLOAT32);
79 _hardswish_g._output->name("output");
89 // graph input and output
90 auto graph_input = _hardswish_int32_g._g.inputs()->create();
91 auto graph_output = _hardswish_int32_g._g.outputs()->create();
94 _hardswish_int32_g._input = _hardswish_int32_g._g.nodes()->create<luci::CircleInput>();
95 _hardswish_int32_g._input->index(graph_input->index());
96 _hardswish_int32_g._input->shape({N, H, W, C});
97 _hardswish_int32_g._input->dtype(loco::DataType::S32);
98 _hardswish_int32_g._input->name("input");
101 _hardswish_int32_g._hardswish = _hardswish_int32_g._g.nodes()->create<luci::CircleHardSwish>();
102 _hardswish_int32_g._hardswish->features(_hardswish_int32_g._input);
103 _hardswish_int32_g._hardswish->shape({N, H, W, C});
104 _hardswish_int32_g._hardswish->dtype(loco::DataType::S32);
105 _hardswish_int32_g._hardswish->name("hardswish");
108 _hardswish_int32_g._output = _hardswish_int32_g._g.nodes()->create<luci::CircleOutput>();
109 _hardswish_int32_g._output->index(graph_output->index());
110 _hardswish_int32_g._output->from(_hardswish_int32_g._hardswish);
111 _hardswish_int32_g._output->shape({N, H, W, C});
112 _hardswish_int32_g._output->dtype(loco::DataType::S32);
113 _hardswish_int32_g._output->name("output");
123 luci::DecomposeHardSwishPass _pass;
124 HardSwishGraph _hardswish_g;
125 HardSwishGraph _hardswish_int32_g;
130 TEST_F(DecomposeHardSwishPass, name)
132 auto const name = _pass.name();
133 ASSERT_NE(nullptr, name);
137 * Decomposed graph looks like below.
139 * [CircleInput] [CircleConst]
145 * \ [CircleRelu6] [CircleConst]
157 TEST_F(DecomposeHardSwishPass, simple_test)
159 auto ret = _pass.run(&_hardswish_g._g);
162 auto mul2 = dynamic_cast<luci::CircleMul *>(_hardswish_g._output->from());
163 EXPECT_NE(nullptr, mul2);
165 auto input2 = dynamic_cast<luci::CircleInput *>(mul2->x());
166 EXPECT_NE(nullptr, input2);
168 auto mul1 = dynamic_cast<luci::CircleMul *>(mul2->y());
169 EXPECT_NE(nullptr, mul1);
171 auto relu6 = dynamic_cast<luci::CircleRelu6 *>(mul1->x());
172 EXPECT_NE(nullptr, relu6);
174 auto mul_const = dynamic_cast<luci::CircleConst *>(mul1->y());
175 EXPECT_NE(nullptr, mul_const);
176 EXPECT_FLOAT_EQ(1. / 6., mul_const->at<loco::DataType::FLOAT32>(0));
178 auto add = dynamic_cast<luci::CircleAdd *>(relu6->features());
179 EXPECT_NE(nullptr, add);
181 auto input1 = dynamic_cast<luci::CircleInput *>(add->x());
182 EXPECT_NE(nullptr, input1);
184 auto add_const = dynamic_cast<luci::CircleConst *>(add->y());
185 EXPECT_NE(nullptr, add_const);
186 EXPECT_FLOAT_EQ(3., add_const->at<loco::DataType::FLOAT32>(0));
189 TEST_F(DecomposeHardSwishPass, check_last_node)
191 auto ret = _pass.run(&_hardswish_g._g);
194 auto hardswish = dynamic_cast<luci::CircleHardSwish *>(_hardswish_g._output->from());
195 EXPECT_EQ(nullptr, hardswish);
198 TEST_F(DecomposeHardSwishPass, wrong_condition_NEG)
200 auto ret = _pass.run(&_hardswish_int32_g._g);
203 auto hardswish = dynamic_cast<luci::CircleHardSwish *>(_hardswish_g._output->from());
204 EXPECT_NE(nullptr, hardswish);