12#include "llvm/Config/config.h"
13#if defined(LLVM_HAVE_TFLITE)
25#include "tensorflow/lite/interpreter.h"
26#include "tensorflow/lite/kernels/register.h"
27#include "tensorflow/lite/model.h"
28#include "tensorflow/lite/model_builder.h"
29#include "tensorflow/lite/op_resolver.h"
30#include "tensorflow/lite/logger.h"
38class EvaluationResultImpl {
40 EvaluationResultImpl(
const std::vector<const TfLiteTensor *> &Outputs)
43 const TfLiteTensor *getOutput(
size_t I) {
return Outputs[
I]; }
45 EvaluationResultImpl(
const EvaluationResultImpl &) =
delete;
46 EvaluationResultImpl(EvaluationResultImpl &&Other) =
delete;
49 const std::vector<const TfLiteTensor *> Outputs;
52class TFModelEvaluatorImpl {
54 TFModelEvaluatorImpl(StringRef SavedModelPath,
55 const std::vector<TensorSpec> &InputSpecs,
56 const std::vector<TensorSpec> &OutputSpecs,
59 bool isValid()
const {
return IsValid; }
60 size_t outputSize()
const {
return Output.size(); }
62 std::unique_ptr<EvaluationResultImpl>
evaluate() {
64 return std::make_unique<EvaluationResultImpl>(Output);
67 const std::vector<TfLiteTensor *> &getInput()
const {
return Input; }
69 ~TFModelEvaluatorImpl();
72 std::unique_ptr<tflite::FlatBufferModel>
Model;
82 std::vector<TfLiteTensor *> Input;
85 std::vector<const TfLiteTensor *> Output;
87 void invalidate() { IsValid =
false; }
93 bool checkReportAndInvalidate(
const TfLiteTensor *Tensor,
94 const TensorSpec &Spec);
99TFModelEvaluatorImpl::TFModelEvaluatorImpl(
100 StringRef SavedModelPath,
const std::vector<TensorSpec> &InputSpecs,
101 const std::vector<TensorSpec> &OutputSpecs,
const char *Tags =
"serve")
104 tflite::LoggerOptions::SetMinimumLogSeverity(tflite::TFLITE_LOG_WARNING);
108 tflite::StderrReporter ErrorReporter;
112 Model = tflite::FlatBufferModel::BuildFromFile(TFLitePath.str().c_str(),
119 tflite::ops::builtin::BuiltinOpResolver
Resolver;
120 tflite::InterpreterBuilder Builder(*Model,
Resolver);
135 TfLiteAllocationType::kTfLiteArenaRwPersistent;
137 if (
Interpreter->AllocateTensors() != TfLiteStatus::kTfLiteOk) {
149 size_t NumberFeaturesPassed = 0;
150 for (
size_t I = 0;
I < InputSpecs.size(); ++
I) {
151 auto &InputSpec = InputSpecs[
I];
152 auto MapI = InputsMap.
find(InputSpec.name() +
":" +
153 std::to_string(InputSpec.port()));
154 if (MapI == InputsMap.
end()) {
159 if (!checkReportAndInvalidate(
Input[
I], InputSpec))
162 InputSpecs[
I].getTotalTensorBufferSize());
163 ++NumberFeaturesPassed;
166 if (NumberFeaturesPassed < Interpreter->inputs().
size()) {
168 errs() <<
"Required feature(s) have not been passed to the ML model";
173 for (
size_t I = 0;
I < OutputSpecs.size(); ++
I) {
174 const auto &OutputSpec = OutputSpecs[
I];
176 OutputsMap[OutputSpec.name() +
":" +
177 std::to_string(OutputSpec.port())]);
178 if (!checkReportAndInvalidate(Output[
I], OutputSpec))
183TFModelEvaluator::TFModelEvaluator(
StringRef SavedModelPath,
184 const std::vector<TensorSpec> &InputSpecs,
185 const std::vector<TensorSpec> &OutputSpecs,
187 : Impl(new TFModelEvaluatorImpl(SavedModelPath, InputSpecs, OutputSpecs,
189 if (!Impl->isValid())
193TFModelEvaluatorImpl::~TFModelEvaluatorImpl() {}
195bool TFModelEvaluatorImpl::checkReportAndInvalidate(
const TfLiteTensor *Tensor,
198 errs() <<
"Could not find TF_Output named: " +
Spec.name();
201 if (
Spec.getTotalTensorBufferSize() != Tensor->bytes)
210std::optional<TFModelEvaluator::EvaluationResult> TFModelEvaluator::evaluate() {
213 return EvaluationResult(Impl->evaluate());
216void *TFModelEvaluator::getUntypedInput(
size_t Index) {
217 TfLiteTensor *
T = Impl->getInput()[Index];
223TFModelEvaluator::EvaluationResult::EvaluationResult(
224 std::unique_ptr<EvaluationResultImpl> Impl)
227TFModelEvaluator::EvaluationResult::EvaluationResult(EvaluationResult &&
Other)
230TFModelEvaluator::EvaluationResult &
231TFModelEvaluator::EvaluationResult::operator=(EvaluationResult &&
Other) {
232 Impl = std::move(
Other.Impl);
236void *TFModelEvaluator::EvaluationResult::getUntypedTensorValue(
size_t Index) {
237 return Impl->getOutput(Index)->data.data;
241TFModelEvaluator::EvaluationResult::getUntypedTensorValue(
size_t Index)
const {
242 return Impl->getOutput(Index)->data.data;
245TFModelEvaluator::EvaluationResult::~EvaluationResult() {}
246TFModelEvaluator::~TFModelEvaluator() {}
static bool evaluate(const MCSpecifierExpr &Expr, MCValue &Res, const MCAssembler *Asm)
This file supports working with JSON data.
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
iterator find(StringRef Key)
StringRef - Represent a constant reference to a string, i.e.
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.