Skip to content

Commit 294b277

Browse files
committed
Synced
1 parent 9bfaead commit 294b277

27 files changed

Lines changed: 680 additions & 401 deletions

ci/tflite_files.txt

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,17 @@ tensorflow/lite/core/c/common.h
3030
tensorflow/lite/core/macros.h
3131
tensorflow/lite/kernels/internal/common.h
3232
tensorflow/lite/kernels/internal/compatibility.h
33-
tensorflow/lite/kernels/internal/portable_tensor_utils.h
3433
tensorflow/lite/kernels/internal/portable_tensor_utils.cc
34+
tensorflow/lite/kernels/internal/portable_tensor_utils.h
3535
tensorflow/lite/kernels/internal/quantization_util.h
36-
tensorflow/lite/kernels/internal/reference/add.h
3736
tensorflow/lite/kernels/internal/reference/add_n.h
37+
tensorflow/lite/kernels/internal/reference/add.h
3838
tensorflow/lite/kernels/internal/reference/arg_min_max.h
39-
tensorflow/lite/kernels/internal/reference/batch_to_space_nd.h
4039
tensorflow/lite/kernels/internal/reference/batch_matmul.h
40+
tensorflow/lite/kernels/internal/reference/batch_to_space_nd.h
4141
tensorflow/lite/kernels/internal/reference/binary_function.h
4242
tensorflow/lite/kernels/internal/reference/broadcast_args.h
43+
tensorflow/lite/kernels/internal/reference/broadcast_loop.h
4344
tensorflow/lite/kernels/internal/reference/broadcast_to.h
4445
tensorflow/lite/kernels/internal/reference/ceil.h
4546
tensorflow/lite/kernels/internal/reference/comparisons.h
@@ -54,17 +55,17 @@ tensorflow/lite/kernels/internal/reference/div.h
5455
tensorflow/lite/kernels/internal/reference/elu.h
5556
tensorflow/lite/kernels/internal/reference/exp.h
5657
tensorflow/lite/kernels/internal/reference/fill.h
57-
tensorflow/lite/kernels/internal/reference/floor.h
5858
tensorflow/lite/kernels/internal/reference/floor_div.h
5959
tensorflow/lite/kernels/internal/reference/floor_mod.h
60+
tensorflow/lite/kernels/internal/reference/floor.h
6061
tensorflow/lite/kernels/internal/reference/fully_connected.h
6162
tensorflow/lite/kernels/internal/reference/hard_swish.h
6263
tensorflow/lite/kernels/internal/reference/integer_ops/add.h
6364
tensorflow/lite/kernels/internal/reference/integer_ops/conv.h
6465
tensorflow/lite/kernels/internal/reference/integer_ops/depthwise_conv.h
6566
tensorflow/lite/kernels/internal/reference/integer_ops/fully_connected.h
66-
tensorflow/lite/kernels/internal/reference/integer_ops/logistic.h
6767
tensorflow/lite/kernels/internal/reference/integer_ops/l2normalization.h
68+
tensorflow/lite/kernels/internal/reference/integer_ops/logistic.h
6869
tensorflow/lite/kernels/internal/reference/integer_ops/mean.h
6970
tensorflow/lite/kernels/internal/reference/integer_ops/mul.h
7071
tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h
@@ -73,14 +74,16 @@ tensorflow/lite/kernels/internal/reference/integer_ops/transpose_conv.h
7374
tensorflow/lite/kernels/internal/reference/l2normalization.h
7475
tensorflow/lite/kernels/internal/reference/leaky_relu.h
7576
tensorflow/lite/kernels/internal/reference/log_softmax.h
77+
tensorflow/lite/kernels/internal/reference/logistic.h
78+
tensorflow/lite/kernels/internal/reference/lstm_cell.h
7679
tensorflow/lite/kernels/internal/reference/maximum_minimum.h
7780
tensorflow/lite/kernels/internal/reference/mul.h
7881
tensorflow/lite/kernels/internal/reference/neg.h
7982
tensorflow/lite/kernels/internal/reference/pad.h
8083
tensorflow/lite/kernels/internal/reference/pooling.h
84+
tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h
8185
tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cc
8286
tensorflow/lite/kernels/internal/reference/portable_tensor_utils.h
83-
tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h
8487
tensorflow/lite/kernels/internal/reference/prelu.h
8588
tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h
8689
tensorflow/lite/kernels/internal/reference/quantize.h
@@ -90,18 +93,16 @@ tensorflow/lite/kernels/internal/reference/resize_bilinear.h
9093
tensorflow/lite/kernels/internal/reference/resize_nearest_neighbor.h
9194
tensorflow/lite/kernels/internal/reference/reverse.h
9295
tensorflow/lite/kernels/internal/reference/round.h
96+
tensorflow/lite/kernels/internal/reference/select.h
97+
tensorflow/lite/kernels/internal/reference/slice.h
9398
tensorflow/lite/kernels/internal/reference/softmax.h
9499
tensorflow/lite/kernels/internal/reference/space_to_batch_nd.h
95100
tensorflow/lite/kernels/internal/reference/space_to_depth.h
96-
tensorflow/lite/kernels/internal/reference/sub.h
97-
tensorflow/lite/kernels/internal/reference/logistic.h
98-
tensorflow/lite/kernels/internal/reference/lstm_cell.h
99-
tensorflow/lite/kernels/internal/reference/select.h
100-
tensorflow/lite/kernels/internal/reference/slice.h
101101
tensorflow/lite/kernels/internal/reference/strided_slice.h
102+
tensorflow/lite/kernels/internal/reference/sub.h
102103
tensorflow/lite/kernels/internal/reference/tanh.h
103-
tensorflow/lite/kernels/internal/reference/transpose.h
104104
tensorflow/lite/kernels/internal/reference/transpose_conv.h
105+
tensorflow/lite/kernels/internal/reference/transpose.h
105106
tensorflow/lite/kernels/internal/cppmath.h
106107
tensorflow/lite/kernels/internal/max.h
107108
tensorflow/lite/kernels/internal/min.h

tensorflow/lite/core/c/common.cc

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ limitations under the License.
2020
#endif // TF_LITE_STATIC_MEMORY
2121

2222
#include <cstring>
23+
#include <new>
2324
#include <type_traits>
2425
#include <utility>
2526

@@ -111,6 +112,7 @@ TfLiteSparsity TfLiteSparsityClone(const TfLiteSparsity& src) {
111112
if (src.dim_metadata) {
112113
dst.dim_metadata = reinterpret_cast<TfLiteDimensionMetadata*>(
113114
calloc(1, sizeof(TfLiteDimensionMetadata) * src.dim_metadata_size));
115+
if (src.dim_metadata_size > 0 && !dst.dim_metadata) return TfLiteSparsity();
114116
for (int i = 0; i < src.dim_metadata_size; ++i) {
115117
dst.dim_metadata[i] = src.dim_metadata[i];
116118
dst.dim_metadata[i].array_segments =
@@ -129,6 +131,7 @@ TfLiteSparsity* TfLiteSparsityClone(const TfLiteSparsity* const src) {
129131
}
130132
TfLiteSparsity* dst =
131133
reinterpret_cast<TfLiteSparsity*>(calloc(1, sizeof(TfLiteSparsity)));
134+
if (!dst) return nullptr;
132135
*dst = TfLiteSparsityClone(*src);
133136
return dst;
134137
}
@@ -147,6 +150,7 @@ TfLiteQuantization TfLiteQuantizationClone(const TfLiteQuantization& src) {
147150
break;
148151
case kTfLiteAffineQuantization: {
149152
dst.params = calloc(1, sizeof(TfLiteAffineQuantization));
153+
if (!dst.params) return TfLiteQuantization();
150154
const TfLiteAffineQuantization* const src_params =
151155
reinterpret_cast<TfLiteAffineQuantization*>(src.params);
152156
TfLiteAffineQuantization* const dst_params =
@@ -158,6 +162,7 @@ TfLiteQuantization TfLiteQuantizationClone(const TfLiteQuantization& src) {
158162
}
159163
case kTfLiteBlockwiseQuantization: {
160164
dst.params = calloc(1, sizeof(TfLiteBlockwiseQuantization));
165+
if (!dst.params) return TfLiteQuantization();
161166
const TfLiteBlockwiseQuantization* const src_params =
162167
(TfLiteBlockwiseQuantization*)(src.params);
163168
TfLiteBlockwiseQuantization* const dst_params =
@@ -219,6 +224,9 @@ TfLiteFloatArray* TfLiteFloatArrayCopy(const TfLiteFloatArray* src) {
219224
void TfLiteFloatArrayFree(TfLiteFloatArray* a) { TfLiteVarArrayFree(a); }
220225

221226
void TfLiteTensorDataFree(TfLiteTensor* t) {
227+
if (t == nullptr) {
228+
return;
229+
}
222230
if (t->allocation_type == kTfLiteVariantObject && t->data.data) {
223231
delete static_cast<VariantData*>(t->data.data);
224232
} else if (t->allocation_type == kTfLiteDynamic ||
@@ -238,6 +246,9 @@ void TfLiteTensorDataFree(TfLiteTensor* t) {
238246
}
239247

240248
void TfLiteQuantizationFree(TfLiteQuantization* quantization) {
249+
if (quantization == nullptr) {
250+
return;
251+
}
241252
if (quantization->type == kTfLiteAffineQuantization) {
242253
TfLiteAffineQuantization* q_params =
243254
reinterpret_cast<TfLiteAffineQuantization*>(quantization->params);
@@ -294,6 +305,9 @@ void TfLiteSparsityFree(TfLiteSparsity* sparsity) {
294305
}
295306

296307
void TfLiteTensorFree(TfLiteTensor* t) {
308+
if (t == nullptr) {
309+
return;
310+
}
297311
TfLiteTensorDataFree(t);
298312
if (t->dims) TfLiteIntArrayFree(t->dims);
299313
t->dims = nullptr;
@@ -308,7 +322,7 @@ void TfLiteTensorFree(TfLiteTensor* t) {
308322
t->sparsity = nullptr;
309323
}
310324

311-
TfLiteTensor TfLiteTensorClone(const TfLiteTensor src) {
325+
TfLiteTensor TfLiteTensorClone(TfLiteTensor src) {
312326
// We copy all of the source data first, then we clone the fields that can't
313327
// be shared between two tensor instances.
314328
TfLiteTensor dst = src;
@@ -335,16 +349,18 @@ TfLiteTensor TfLiteTensorClone(const TfLiteTensor src) {
335349
break;
336350
case kTfLiteAllocationStrategyMalloc:
337351
dst.data.data = malloc(src.bytes);
352+
if (src.bytes > 0 && !dst.data.data) return TfLiteTensor();
338353
std::memcpy(dst.data.data, src.data.data, src.bytes);
339354
break;
340355
case kTfLiteAllocationStrategyNew:
341356
// Special case for variant objects. They are allocated using new/delete
342357
// but require using the `CloneTo` function.
343358
if (src.allocation_type == kTfLiteVariantObject) {
344-
dst.data.data = reinterpret_cast<const VariantData*>(src.data.data)
345-
->CloneTo(nullptr);
359+
dst.data.data =
360+
static_cast<const VariantData*>(src.data.data)->CloneTo(nullptr);
346361
} else {
347-
dst.data.data = new char[src.bytes];
362+
dst.data.data = new (std::nothrow) char[src.bytes];
363+
if (src.bytes > 0 && !dst.data.data) return TfLiteTensor();
348364
std::memcpy(dst.data.data, src.data.data, src.bytes);
349365
}
350366
break;
@@ -394,13 +410,21 @@ TfLiteStatus TfLiteTensorCopy(const TfLiteTensor* src, TfLiteTensor* dst) {
394410
}
395411
auto* dst_vd = static_cast<VariantData*>(dst->data.data);
396412
auto* src_vd = static_cast<VariantData*>(src->data.data);
413+
if (!src_vd) return kTfLiteError;
397414

398415
// `CloneTo` will handle the case when `dst_vd` is nullptr, so it is safe
399416
// to `CloneTo` something which was "freed". Also, returning from `CloneTo`
400417
// will implicitly cast to `VariantData`; don't need static cast here.
401418
dst->data.data = src_vd->CloneTo(dst_vd);
402419
} else {
403-
memcpy(dst->data.raw, src->data.raw, src->bytes);
420+
if (dst->allocation_type == kTfLiteVariantObject) {
421+
TfLiteTensorDataFree(dst);
422+
dst->allocation_type = src->allocation_type;
423+
}
424+
if (src->bytes > 0) {
425+
if (!dst->data.raw || !src->data.raw) return kTfLiteError;
426+
memcpy(dst->data.raw, src->data.raw, src->bytes);
427+
}
404428
}
405429
dst->buffer_handle = src->buffer_handle;
406430
dst->data_is_stale = src->data_is_stale;

tensorflow/lite/core/c/common.h

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ limitations under the License.
5656
#include <stdbool.h>
5757
#include <stddef.h>
5858
#include <stdint.h>
59+
#include <stdio.h>
5960

6061
#include "tensorflow/lite/core/c/c_api_types.h" // IWYU pragma: export
6162

@@ -277,13 +278,34 @@ void TfLiteFloatArrayFree(TfLiteFloatArray* a);
277278
} \
278279
} while (0)
279280

280-
#define TF_LITE_ENSURE_OK(context, status) \
281-
do { \
282-
const TfLiteStatus s = (status); \
283-
if ((s) != kTfLiteOk) { \
284-
return s; \
285-
} \
281+
#ifndef TF_LITE_STRIP_ERROR_STRINGS
282+
#define TF_LITE_VAR_ARG_HEAD(FIRST, ...) FIRST
283+
#define TF_LITE_STRINGIFY_HELPER(x) #x
284+
#define TF_LITE_STRINGIFY(x) TF_LITE_STRINGIFY_HELPER(x)
285+
// Checks that `status` evaluates to `kTfLiteOk`.
286+
//
287+
// Can take a printf style log message and its parameters after the status. The
288+
// message will be printed using `TF_LITE_KERNEL_LOG` in case of error.
289+
#define TF_LITE_ENSURE_OK(context, status, ...) \
290+
do { \
291+
const TfLiteStatus s = (status); \
292+
if (s != kTfLiteOk) { \
293+
if (sizeof(TF_LITE_VAR_ARG_HEAD("" __VA_ARGS__)) > sizeof("")) { \
294+
TF_LITE_MAYBE_KERNEL_LOG((context), __FILE__ ":" TF_LITE_STRINGIFY( \
295+
__LINE__) ": " __VA_ARGS__); \
296+
} \
297+
return s; \
298+
} \
286299
} while (0)
300+
#else
301+
#define TF_LITE_ENSURE_OK(context, status, ...) \
302+
do { \
303+
const TfLiteStatus s = (status); \
304+
if ((s) != kTfLiteOk) { \
305+
return s; \
306+
} \
307+
} while (0)
308+
#endif
287309

288310
// `std::unreachable` not available until CC23.
289311
#ifdef __GNUC__ // GCC, Clang, ICC
@@ -1060,6 +1082,13 @@ typedef struct TfLiteContext {
10601082
/// WARNING: This is an experimental interface that is subject to change.
10611083
TfLiteStatus (*ReleaseSubgraphContext)(struct TfLiteContext* context,
10621084
int subgraph_index);
1085+
#if defined(_WIN32)
1086+
/// Create a array of a given `size` (uninitialized entries).
1087+
TfLiteIntArray* (*TfLiteIntArrayCreate)(int size); // NOLINT
1088+
1089+
/// Free memory of array `a`.
1090+
void (*TfLiteIntArrayFree)(TfLiteIntArray* a); // NOLINT
1091+
#endif // defined(_WIN32)
10631092
} TfLiteContext;
10641093

10651094
/// `TfLiteOperator` is an external version of `TfLiteRegistration`

tensorflow/lite/kernels/internal/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ cc_library(
146146
copts = tflite_copts(),
147147
deps = [
148148
":compatibility",
149+
"//tensorflow/lite/types:half",
149150
],
150151
)
151152

tensorflow/lite/kernels/internal/common.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,23 @@ bool ReduceDimensionsForBroadcast(const RuntimeShape& input1_shape,
7878
if (!broadcast_input1) {
7979
broadcast_input1 = true;
8080
broadcast_input2 = false;
81+
if (num_compressed_dims >= MAX_DIM) return false;
8182
num_compressed_dims++;
83+
if (num_compressed_dims > MAX_DIM) {
84+
return false;
85+
}
8286
}
8387
compressed_input2_shape[num_compressed_dims - 1] *= input2_dim;
8488
compressed_output_shape[num_compressed_dims - 1] *= input2_dim;
8589
} else if (input2_dim == 1) {
8690
if (!broadcast_input2) {
8791
broadcast_input1 = false;
8892
broadcast_input2 = true;
93+
if (num_compressed_dims >= MAX_DIM) return false;
8994
num_compressed_dims++;
95+
if (num_compressed_dims > MAX_DIM) {
96+
return false;
97+
}
9098
}
9199
compressed_input1_shape[num_compressed_dims - 1] *= input1_dim;
92100
compressed_output_shape[num_compressed_dims - 1] *= input1_dim;
@@ -95,7 +103,11 @@ bool ReduceDimensionsForBroadcast(const RuntimeShape& input1_shape,
95103
if (broadcast_input1 || broadcast_input2 || first_nonunit) {
96104
broadcast_input1 = false;
97105
broadcast_input2 = false;
106+
if (num_compressed_dims >= MAX_DIM) return false;
98107
num_compressed_dims++;
108+
if (num_compressed_dims > MAX_DIM) {
109+
return false;
110+
}
99111
}
100112
compressed_input1_shape[num_compressed_dims - 1] *= input1_dim;
101113
compressed_input2_shape[num_compressed_dims - 1] *= input1_dim;
@@ -105,7 +117,11 @@ bool ReduceDimensionsForBroadcast(const RuntimeShape& input1_shape,
105117
}
106118
if (num_input1_dims > num_input2_dims) {
107119
if (!broadcast_input2) {
120+
if (num_compressed_dims >= MAX_DIM) return false;
108121
num_compressed_dims++;
122+
if (num_compressed_dims > MAX_DIM) {
123+
return false;
124+
}
109125
}
110126
for (size_t i = 0; i < num_input1_dims - num_input2_dims; i++) {
111127
const size_t input1_dim = input1_dims[i];
@@ -117,7 +133,11 @@ bool ReduceDimensionsForBroadcast(const RuntimeShape& input1_shape,
117133
}
118134
} else if (num_input2_dims > num_input1_dims) {
119135
if (!broadcast_input1) {
136+
if (num_compressed_dims >= MAX_DIM) return false;
120137
num_compressed_dims++;
138+
if (num_compressed_dims > MAX_DIM) {
139+
return false;
140+
}
121141
}
122142
for (size_t i = 0; i < num_input2_dims - num_input1_dims; i++) {
123143
const size_t input2_dim = input2_dims[i];

tensorflow/lite/kernels/internal/reference/add.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ limitations under the License.
2323
#include "fixedpoint/fixedpoint.h"
2424
#include "tensorflow/lite/kernels/internal/common.h"
2525
#include "tensorflow/lite/kernels/internal/compatibility.h"
26+
#include "tensorflow/lite/kernels/internal/reference/broadcast_loop.h"
2627

2728
namespace tflite {
2829

@@ -39,7 +40,7 @@ inline void Add(const ArithmeticParams& params,
3940
const int flat_size =
4041
MatchingElementsSize(input1_shape, input2_shape, output_shape);
4142
for (int i = 0; i < flat_size; ++i) {
42-
output_data[i] = ActivationFunctionWithMinMax(
43+
output_data[i] = ActivationFunctionWithMinMax<T>(
4344
input1_data[i] + input2_data[i], activation_min, activation_max);
4445
}
4546
}
@@ -328,6 +329,20 @@ BroadcastAdd6DSlow(const ArithmeticParams& params,
328329
constexpr int kMaxBroadcastDim = 6;
329330
T activation_min, activation_max;
330331
GetActivationParams(params, &activation_min, &activation_max);
332+
const int broadcast_rank = std::max(
333+
output_shape.DimensionsCount(),
334+
std::max(input1_shape.DimensionsCount(), input2_shape.DimensionsCount()));
335+
if (broadcast_rank > kMaxBroadcastDim) {
336+
ForEachBroadcastedElement(
337+
input1_shape, input2_shape, output_shape,
338+
[&](int output_index, int input1_index, int input2_index) {
339+
output_data[output_index] = ActivationFunctionWithMinMax(
340+
static_cast<T>(input1_data[input1_index] +
341+
input2_data[input2_index]),
342+
activation_min, activation_max);
343+
});
344+
return;
345+
}
331346

332347
// In Tensorflow, the dimensions are canonically named (batch_number, row,
333348
// col, channel), with extents (batches, height, width, depth), with the
@@ -421,6 +436,19 @@ BroadcastAdd6DSlow(const ArithmeticParams& params,
421436
const RuntimeShape& input2_shape, const T* input2_data,
422437
const RuntimeShape& output_shape, T* output_data) {
423438
constexpr int kMaxBroadcastDim = 6;
439+
const int broadcast_rank = std::max(
440+
output_shape.DimensionsCount(),
441+
std::max(input1_shape.DimensionsCount(), input2_shape.DimensionsCount()));
442+
if (broadcast_rank > kMaxBroadcastDim) {
443+
ForEachBroadcastedElement(
444+
input1_shape, input2_shape, output_shape,
445+
[&](int output_index, int input1_index, int input2_index) {
446+
AddElementwise(1, params, input1_data + input1_index,
447+
input2_data + input2_index,
448+
output_data + output_index);
449+
});
450+
return;
451+
}
424452

425453
// In Tensorflow, the dimensions are canonically named (batch_number, row,
426454
// col, channel), with extents (batches, height, width, depth), with the

0 commit comments

Comments
 (0)