10b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
20b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle
30b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew SelleLicensed under the Apache License, Version 2.0 (the "License");
40b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selleyou may not use this file except in compliance with the License.
50b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew SelleYou may obtain a copy of the License at
60b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle
70b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    http://www.apache.org/licenses/LICENSE-2.0
80b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle
90b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew SelleUnless required by applicable law or agreed to in writing, software
100b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selledistributed under the License is distributed on an "AS IS" BASIS,
110b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew SelleWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew SelleSee the License for the specific language governing permissions and
130b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Sellelimitations under the License.
140b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle==============================================================================*/
150b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle
160b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle#include <string>
170b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle#include <vector>
180b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle
190b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle#include "absl/strings/numbers.h"
200b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle#include "absl/strings/str_join.h"
210b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle#include "absl/strings/str_split.h"
220b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle#include "absl/strings/strip.h"
230b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle#include "tensorflow/contrib/lite/toco/toco_cmdline_flags.h"
240b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle#include "tensorflow/contrib/lite/toco/toco_port.h"
250b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle#include "tensorflow/core/platform/logging.h"
260b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle#include "tensorflow/core/util/command_line_flags.h"
270b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle
280b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Sellenamespace toco {
290b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle
300b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Sellebool ParseTocoFlagsFromCommandLineFlags(
310b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    int* argc, char* argv[], string* msg,
320b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    ParsedTocoFlags* parsed_toco_flags_ptr) {
330b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  using tensorflow::Flag;
340b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  ParsedTocoFlags& parsed_flags = *parsed_toco_flags_ptr;
350b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  std::vector<tensorflow::Flag> flags = {
360b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      Flag("input_file", parsed_flags.input_file.bind(),
370b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           parsed_flags.input_file.default_value(),
380b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           "Input file (model of any supported format). For Protobuf "
390b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           "formats, both text and binary are supported regardless of file "
400b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           "extension."),
410b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      Flag("output_file", parsed_flags.output_file.bind(),
420b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           parsed_flags.output_file.default_value(),
430b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           "Output file. "
440b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           "For Protobuf formats, the binary format will be used."),
450b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      Flag("input_format", parsed_flags.input_format.bind(),
460b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           parsed_flags.input_format.default_value(),
47982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen           "Input file format. One of: TENSORFLOW_GRAPHDEF, TFLITE."),
480b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      Flag("output_format", parsed_flags.output_format.bind(),
49982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen           parsed_flags.output_format.default_value(),
50982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen           "Output file format. "
51982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen           "One of TENSORFLOW_GRAPHDEF, TFLITE, GRAPHVIZ_DOT."),
520b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      Flag("default_ranges_min", parsed_flags.default_ranges_min.bind(),
530b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           parsed_flags.default_ranges_min.default_value(),
540b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           "If defined, will be used as the default value for the min bound "
550b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           "of min/max ranges used for quantization."),
560b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      Flag("default_ranges_max", parsed_flags.default_ranges_max.bind(),
570b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           parsed_flags.default_ranges_max.default_value(),
580b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           "If defined, will be used as the default value for the max bound "
590b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           "of min/max ranges used for quantization."),
606040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower      Flag("inference_type", parsed_flags.inference_type.bind(),
616040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower           parsed_flags.inference_type.default_value(),
626040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower           "Target data type of arrays in the output file (for input_arrays, "
63982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen           "this may be overridden by inference_input_type). "
64982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen           "One of FLOAT, QUANTIZED_UINT8."),
656040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower      Flag("inference_input_type", parsed_flags.inference_input_type.bind(),
666040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower           parsed_flags.inference_input_type.default_value(),
67982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen           "Target data type of input arrays. "
68982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen           "If not specified, inference_type is used. "
69982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen           "One of FLOAT, QUANTIZED_UINT8."),
700b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      Flag("input_type", parsed_flags.input_type.bind(),
710b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           parsed_flags.input_type.default_value(),
728cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower           "Deprecated ambiguous flag that set both --input_data_types and "
738cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower           "--inference_input_type."),
740b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      Flag("input_types", parsed_flags.input_types.bind(),
750b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           parsed_flags.input_types.default_value(),
768cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower           "Deprecated ambiguous flag that set both --input_data_types and "
778cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower           "--inference_input_type. Was meant to be a "
786040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower           "comma-separated list, but this was deprecated before "
796040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower           "multiple-input-types was ever properly supported."),
806040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower
810b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      Flag("drop_fake_quant", parsed_flags.drop_fake_quant.bind(),
820b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           parsed_flags.drop_fake_quant.default_value(),
83982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen           "Ignore and discard FakeQuant nodes. For instance, to "
840b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           "generate plain float code without fake-quantization from a "
85982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen           "quantized graph."),
860b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      Flag(
870b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          "reorder_across_fake_quant",
880b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          parsed_flags.reorder_across_fake_quant.bind(),
890b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          parsed_flags.reorder_across_fake_quant.default_value(),
900b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          "Normally, FakeQuant nodes must be strict boundaries for graph "
910b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          "transformations, in order to ensure that quantized inference has "
92982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen          "the exact same arithmetic behavior as quantized training --- which "
93982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen          "is the whole point of quantized training and of FakeQuant nodes in "
94982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen          "the first place. "
95982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen          "However, that entails subtle requirements on where exactly "
960b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          "FakeQuant nodes must be placed in the graph. Some quantized graphs "
970b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          "have FakeQuant nodes at unexpected locations, that prevent graph "
980b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          "transformations that are necessary in order to generate inference "
990b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          "code for these graphs. Such graphs should be fixed, but as a "
1000b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          "temporary work-around, setting this reorder_across_fake_quant flag "
101982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen          "allows TOCO to perform necessary graph transformaitons on them, "
1020b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          "at the cost of no longer faithfully matching inference and training "
1030b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          "arithmetic."),
1040b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      Flag("allow_custom_ops", parsed_flags.allow_custom_ops.bind(),
1050b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle           parsed_flags.allow_custom_ops.default_value(),
106982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen           "If true, allow TOCO to create TF Lite Custom operators for all the "
107982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen           "unsupported TensorFlow ops."),
108b8406da50df94dc17114c10d472a2058ff75b2d2A. Unique TensorFlower      Flag(
109b8406da50df94dc17114c10d472a2058ff75b2d2A. Unique TensorFlower          "drop_control_dependency",
110b8406da50df94dc17114c10d472a2058ff75b2d2A. Unique TensorFlower          parsed_flags.drop_control_dependency.bind(),
111b8406da50df94dc17114c10d472a2058ff75b2d2A. Unique TensorFlower          parsed_flags.drop_control_dependency.default_value(),
112b8406da50df94dc17114c10d472a2058ff75b2d2A. Unique TensorFlower          "If true, ignore control dependency requirements in input TensorFlow "
113b8406da50df94dc17114c10d472a2058ff75b2d2A. Unique TensorFlower          "GraphDef. Otherwise an error will be raised upon control dependency "
114b8406da50df94dc17114c10d472a2058ff75b2d2A. Unique TensorFlower          "inputs."),
1150b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  };
1160b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  bool asked_for_help =
1170b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      *argc == 2 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-help"));
1180b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  if (asked_for_help) {
1190b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    *msg += tensorflow::Flags::Usage(argv[0], flags);
1200b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    return false;
1210b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  } else {
1220b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    return tensorflow::Flags::Parse(argc, argv, flags);
1230b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  }
1240b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle}
1250b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle
1260b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Sellevoid ReadTocoFlagsFromCommandLineFlags(const ParsedTocoFlags& parsed_toco_flags,
1270b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle                                       TocoFlags* toco_flags) {
1280b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  namespace port = toco::port;
1290b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  port::CheckInitGoogleIsDone("InitGoogle is not done yet");
1300b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle
1310b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  enum class FlagRequirement { kNone, kMustBeSpecified, kMustNotBeSpecified };
1320b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle
1330b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle#define ENFORCE_FLAG_REQUIREMENT(name, requirement)                          \
1340b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  do {                                                                       \
1350b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    if (requirement == FlagRequirement::kMustBeSpecified) {                  \
1360b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      QCHECK(parsed_toco_flags.name.specified())                             \
1370b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          << "Missing required flag: " << #name;                             \
1380b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    }                                                                        \
1390b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    if (requirement == FlagRequirement::kMustNotBeSpecified) {               \
1400b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      QCHECK(!parsed_toco_flags.name.specified())                            \
1410b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          << "Given other flags, this flag should not have been specified: " \
1420b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          << #name;                                                          \
1430b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    }                                                                        \
1440b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  } while (false)
1450b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle#define READ_TOCO_FLAG(name, requirement)                     \
1460b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  ENFORCE_FLAG_REQUIREMENT(name, requirement);                \
1470b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  do {                                                        \
1480b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    if (parsed_toco_flags.name.specified()) {                 \
1490b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      toco_flags->set_##name(parsed_toco_flags.name.value()); \
1500b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    }                                                         \
1510b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  } while (false)
1520b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle
1530b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle#define PARSE_TOCO_FLAG(Type, name, requirement)               \
1540b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  ENFORCE_FLAG_REQUIREMENT(name, requirement);                 \
1550b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  do {                                                         \
1560b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    if (parsed_toco_flags.name.specified()) {                  \
1570b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      Type x;                                                  \
1580b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      QCHECK(Type##_Parse(parsed_toco_flags.name.value(), &x)) \
1590b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          << "Unrecognized " << #Type << " value "             \
1600b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle          << parsed_toco_flags.name.value();                   \
1610b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle      toco_flags->set_##name(x);                               \
1620b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    }                                                          \
1630b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  } while (false)
1640b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle
1650b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  PARSE_TOCO_FLAG(FileFormat, input_format, FlagRequirement::kMustBeSpecified);
1660b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  PARSE_TOCO_FLAG(FileFormat, output_format, FlagRequirement::kMustBeSpecified);
1676040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower  PARSE_TOCO_FLAG(IODataType, inference_type, FlagRequirement::kNone);
1686040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower  PARSE_TOCO_FLAG(IODataType, inference_input_type, FlagRequirement::kNone);
1690b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  READ_TOCO_FLAG(default_ranges_min, FlagRequirement::kNone);
1700b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  READ_TOCO_FLAG(default_ranges_max, FlagRequirement::kNone);
1710b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  READ_TOCO_FLAG(drop_fake_quant, FlagRequirement::kNone);
1720b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  READ_TOCO_FLAG(reorder_across_fake_quant, FlagRequirement::kNone);
1730b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  READ_TOCO_FLAG(allow_custom_ops, FlagRequirement::kNone);
174b8406da50df94dc17114c10d472a2058ff75b2d2A. Unique TensorFlower  READ_TOCO_FLAG(drop_control_dependency, FlagRequirement::kNone);
1750b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle
1766040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower  // Deprecated flag handling.
1776040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower  if (parsed_toco_flags.input_type.specified()) {
1788cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower    LOG(WARNING)
1798cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower        << "--input_type is deprecated. It was an ambiguous flag that set both "
1808cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower           "--input_data_types and --inference_input_type. If you are trying "
1818cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower           "to complement the input file with information about the type of "
1828cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower           "input arrays, use --input_data_type. If you are trying to control "
1838cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower           "the quantization/dequantization of real-numbers input arrays in "
1848cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower           "the output file, use --inference_input_type.";
1856040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower    toco::IODataType input_type;
1866040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower    QCHECK(toco::IODataType_Parse(parsed_toco_flags.input_type.value(),
1876040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower                                  &input_type));
1886040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower    toco_flags->set_inference_input_type(input_type);
1890b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  }
1906040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower  if (parsed_toco_flags.input_types.specified()) {
1918cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower    LOG(WARNING)
1928cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower        << "--input_types is deprecated. It was an ambiguous flag that set "
1938cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower           "both --input_data_types and --inference_input_type. If you are "
1948cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower           "trying to complement the input file with information about the "
1958cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower           "type of input arrays, use --input_data_type. If you are trying to "
1968cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower           "control the quantization/dequantization of real-numbers input "
1978cb4a0f69a631e9f405b724940bc978b3784b19aA. Unique TensorFlower           "arrays in the output file, use --inference_input_type.";
1980b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    std::vector<string> input_types =
1990b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle        absl::StrSplit(parsed_toco_flags.input_types.value(), ',');
2006040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower    QCHECK(!input_types.empty());
2016040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower    for (int i = 1; i < input_types.size(); i++) {
2026040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower      QCHECK_EQ(input_types[i], input_types[0]);
2030b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle    }
2046040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower    toco::IODataType input_type;
2056040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower    QCHECK(toco::IODataType_Parse(input_types[0], &input_type));
2066040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower    toco_flags->set_inference_input_type(input_type);
2070b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle  }
2086040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower
2096040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower#undef READ_TOCO_FLAG
2106040ed631ba8e95b97c0e3edb1dd31e04569b521A. Unique TensorFlower#undef PARSE_TOCO_FLAG
2110b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle}
2120b15439f8f0f2d4755587f4096c3ea04cb199d23Andrew Selle}  // namespace toco
213