Skip to content

Commit f5ca57f

Browse files
committed
[onert] Negative testcase added for BROADCAST_TO operation.
- Added OperationValidator and ShapeValidator for BROADCAST_TO - Added negative testcases for BROADCAST_TO ONE-DCO-1.0-Signed-off-by: Seockho Kim seockho.kim@samsung.com
1 parent 8158c3b commit f5ca57f

5 files changed

Lines changed: 118 additions & 0 deletions

File tree

runtime/onert/core/src/compiler/ShapeValidator.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,41 @@ void ShapeValidator::visit(const ir::operation::BCQGather &node)
158158
// more shape validation will be done inside kernel.
159159
}
160160

161+
void ShapeValidator::visit(const ir::operation::BroadcastTo &node)
162+
{
163+
const auto &operands = _graph.operands();
164+
const auto output_index{node.getOutputs().at(0)};
165+
if (operands.at(output_index).info().isDynamic())
166+
return;
167+
168+
const auto input_index{node.getInputs().at(ir::operation::BroadcastTo::Input::INPUT)};
169+
const auto shape_index{node.getInputs().at(ir::operation::BroadcastTo::Input::SHAPE)};
170+
171+
std::vector<int32_t> input_shape = operands.at(input_index).shape().dims();
172+
std::vector<int32_t> target_shape = operands.at(shape_index).asVector<int32_t>();
173+
174+
int in_len = input_shape.size();
175+
int tgt_len = target_shape.size();
176+
int max_len = std::max(in_len, tgt_len);
177+
178+
std::vector<int32_t> in_shape_padded(max_len, 1);
179+
std::vector<int32_t> tgt_shape_padded(max_len, 1);
180+
181+
for (int i = 0; i < in_len; i++)
182+
{
183+
in_shape_padded[max_len - in_len + i] = input_shape[i];
184+
}
185+
for (int i = 0; i < tgt_len; i++)
186+
{
187+
tgt_shape_padded[max_len - tgt_len + i] = target_shape[i];
188+
}
189+
190+
for (int i = max_len - 1; i >= 0; --i)
191+
{
192+
OP_REQUIRES((in_shape_padded[i] == tgt_shape_padded[i]) || (in_shape_padded[i] == 1));
193+
}
194+
}
195+
161196
void ShapeValidator::visit(const ir::operation::Conv2D &node)
162197
{
163198
const auto &operands = _graph.operands();

runtime/onert/core/src/compiler/ShapeValidator.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class ShapeValidator : public ir::OperationVisitor
4848
void visit(const ir::operation::BatchToSpaceND &node) override;
4949
void visit(const ir::operation::BCQFullyConnected &node) override;
5050
void visit(const ir::operation::BCQGather &node) override;
51+
void visit(const ir::operation::BroadcastTo &node) override;
5152
void visit(const ir::operation::Conv2D &node) override;
5253
void visit(const ir::operation::Comparison &node) override;
5354
void visit(const ir::operation::DepthwiseConv2D &node) override;

runtime/onert/core/src/ir/OperationValidator.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,14 @@ void OperationValidator::visit(const operation::BinaryArithmetic &node)
149149
OP_REQUIRES(isSameType(lhs_index, output_index));
150150
}
151151

152+
void OperationValidator::visit(const operation::BroadcastTo &node)
153+
{
154+
const auto input_index(node.getInputs().at(operation::BroadcastTo::Input::INPUT));
155+
const auto output_index(node.getOutputs().at(0));
156+
157+
OP_REQUIRES(isSameType(input_index, output_index));
158+
}
159+
152160
void OperationValidator::visit(const operation::Comparison &node)
153161
{
154162
const auto output_index{node.getOutputs().at(0)};

runtime/onert/core/src/ir/OperationValidator.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class OperationValidator : public OperationVisitor
4545
void visit(const operation::BatchMatMul &node) override;
4646
void visit(const operation::BatchToSpaceND &node) override;
4747
void visit(const operation::BinaryArithmetic &node) override;
48+
void visit(const operation::BroadcastTo &node) override;
4849
void visit(const operation::Comparison &node) override;
4950
void visit(const operation::Concat &node) override;
5051
void visit(const operation::Conv2D &node) override;

runtime/tests/nnfw_api/src/GenModelTests/one_op_tests/BroadcastTo.test.cc

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,76 @@ TEST_F(GenModelTest, OneOp_BroadcastTo_3D_to_3D)
6666

6767
SUCCEED();
6868
}
69+
70+
TEST_F(GenModelTest, OneOp_BroadcastTo_InputOutputDifferentType)
71+
{
72+
CircleGen cgen;
73+
const uint32_t shape_buf = cgen.addBuffer(std::vector<int32_t>{3, 3});
74+
int shape = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, shape_buf});
75+
int in = cgen.addTensor({{3}, circle::TensorType::TensorType_INT32});
76+
int out = cgen.addTensor({{3, 3}, circle::TensorType::TensorType_FLOAT32});
77+
cgen.addOperatorBroadcastTo({{in, shape}, {out}});
78+
cgen.setInputsAndOutputs({in}, {out});
79+
80+
_context = std::make_unique<GenModelTestContext>(cgen.finish());
81+
_context->addTestCase(uniformTCD<float>({{1, 2, 3}}, {{1, 2, 3, 1, 2, 3, 1, 2, 3}}));
82+
_context->setBackends({"cpu"});
83+
_context->expectFailModelLoad();
84+
85+
SUCCEED();
86+
}
87+
88+
TEST_F(GenModelTest, OneOp_BroadcastTo_1D_to_2D_InvalidShape)
89+
{
90+
CircleGen cgen;
91+
const uint32_t shape_buf = cgen.addBuffer(std::vector<int32_t>{3, 2});
92+
int shape = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, shape_buf});
93+
int in = cgen.addTensor({{3}, circle::TensorType::TensorType_FLOAT32});
94+
int out = cgen.addTensor({{3, 2}, circle::TensorType::TensorType_FLOAT32});
95+
cgen.addOperatorBroadcastTo({{in, shape}, {out}});
96+
cgen.setInputsAndOutputs({in}, {out});
97+
98+
_context = std::make_unique<GenModelTestContext>(cgen.finish());
99+
_context->addTestCase(uniformTCD<float>({{1, 2, 3}}, {{1, 2, 3, 1, 2, 3}}));
100+
_context->setBackends({"cpu"});
101+
_context->expectFailCompile();
102+
103+
SUCCEED();
104+
}
105+
106+
TEST_F(GenModelTest, OneOp_BroadcastTo_2D_to_3D_InvalidShape)
107+
{
108+
CircleGen cgen;
109+
const uint32_t shape_buf = cgen.addBuffer(std::vector<int32_t>{2, 1, 3});
110+
int shape = cgen.addTensor({{3}, circle::TensorType::TensorType_INT32, shape_buf});
111+
int in = cgen.addTensor({{2, 3}, circle::TensorType::TensorType_FLOAT32});
112+
int out = cgen.addTensor({{2, 1, 3}, circle::TensorType::TensorType_FLOAT32});
113+
cgen.addOperatorBroadcastTo({{in, shape}, {out}});
114+
cgen.setInputsAndOutputs({in}, {out});
115+
116+
_context = std::make_unique<GenModelTestContext>(cgen.finish());
117+
_context->addTestCase(uniformTCD<float>({{1, 2, 3, 1, 2, 3}}, {{1, 2, 3, 1, 2, 3}}));
118+
_context->setBackends({"cpu"});
119+
_context->expectFailCompile();
120+
121+
SUCCEED();
122+
}
123+
124+
TEST_F(GenModelTest, OneOp_BroadcastTo_3D_to_3D_InvalidShape)
125+
{
126+
CircleGen cgen;
127+
const uint32_t shape_buf = cgen.addBuffer(std::vector<int32_t>{2, 3, 2});
128+
int shape = cgen.addTensor({{3}, circle::TensorType::TensorType_INT32, shape_buf});
129+
int in = cgen.addTensor({{2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
130+
int out = cgen.addTensor({{2, 3, 2}, circle::TensorType::TensorType_FLOAT32});
131+
cgen.addOperatorBroadcastTo({{in, shape}, {out}});
132+
cgen.setInputsAndOutputs({in}, {out});
133+
134+
_context = std::make_unique<GenModelTestContext>(cgen.finish());
135+
_context->addTestCase(
136+
uniformTCD<float>({{1, 2, 1, 2, 1, 2, 1, 2}}, {{1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2}}));
137+
_context->setBackends({"cpu"});
138+
_context->expectFailCompile();
139+
140+
SUCCEED();
141+
}

0 commit comments

Comments
 (0)