tensorflow/lite/toco/graph_transformations/resolve_constant_concatenation.cc
// Resolves the concatenation operator if all its inputs are constant arrays.
Resolves the concatenation operator if all its inputs are constant arrays.
Resolves the concatenation operator if all its inputs are constant arrays .
::tensorflow::Status ResolveConstantConcatenation::Run(Model* model,
                                                       std::size_t op_index,
                                                       bool* modified) {
  *modified = false;
  const auto concat_it = model->operators.begin() + op_index;
  const auto* concat_base_op = concat_it->get();
  if (concat_base_op->type != OperatorType::kConcatenation) {
    return ::tensorflow::Status::OK();
  }
  const auto* concat_op =
      static_cast<const ConcatenationOperator*>(concat_base_op);
  for (const std::string& input_name : concat_op->inputs) {
    const Operator* input_op = GetOpWithOutput(*model, input_name);
    if (input_op) return ::tensorflow::Status::OK();
    if (!IsConstantParameterArray(*model, input_name))
      return ::tensorflow::Status::OK();
    if (!model->GetArray(input_name).has_shape())
      return ::tensorflow::Status::OK();
    if (model->GetArray(input_name).quantization_params)
      return ::tensorflow::Status::OK();
    if (!IsDiscardableArray(*model, input_name))
      return ::tensorflow::Status::OK();
  }
  const int concatenation_axis = concat_op->axis;
  CHECK_EQ(concat_op->outputs.size(), 1);
  std::string concatenated_array_name = concat_op->outputs[0];
  Array& concatenated_array = model->GetOrCreateArray(concatenated_array_name);
  std::vector<Array*> input_arrays;
  for (const std::string& input_name : concat_op->inputs) {
    input_arrays.push_back(&model->GetArray(input_name));
  }
  AddMessageF("Performing constant concat of %s into %s",
              absl::StrJoin(concat_op->inputs, ", "), concatenated_array_name);
  switch (concatenated_array.data_type) {
    case ArrayDataType::kFloat:
      ConcatenateTensorBuffers<ArrayDataType::kFloat>(
          input_arrays, concatenation_axis, &concatenated_array);
      SetMinMaxForConcatenedArray(this, input_arrays, &concatenated_array);
      break;
    case ArrayDataType::kUint8:
      ConcatenateTensorBuffers<ArrayDataType::kUint8>(
          input_arrays, concatenation_axis, &concatenated_array);
      break;
    case ArrayDataType::kInt32:
      ConcatenateTensorBuffers<ArrayDataType::kInt32>(
          input_arrays, concatenation_axis, &concatenated_array);
      break;
    case ArrayDataType::kInt64:
      ConcatenateTensorBuffers<ArrayDataType::kInt64>(
          input_arrays, concatenation_axis, &concatenated_array);
      break;
    case ArrayDataType::kString:
      ConcatenateTensorBuffers<ArrayDataType::kString>(
          input_arrays, concatenation_axis, &concatenated_array);
      break;
    case ArrayDataType::kComplex64:
      ConcatenateTensorBuffers<ArrayDataType::kComplex64>(
          input_arrays, concatenation_axis, &concatenated_array);
      break;
    default:
      LOG(FATAL) << "ArrayDataType not supported";
  }
  DeleteOpAndArrays(model, concat_op);
  *modified = true;
  return ::tensorflow::Status::OK();
}
:: tensorflow :: Status ResolveConstantConcatenation :: Run ( Model * model , std :: size_t op_index , bool * modified ) { * modified = false ; const auto concat_it = model -> operators . begin ( ) + op_index ; const auto * concat_base_op = concat_it -> get ( ) ; if ( concat_base_op -> type != OperatorType :: kConcatenation ) { return :: tensorflow :: Status :: OK ( ) ; } const auto * concat_op = static_cast < const ConcatenationOperator * > ( concat_base_op ) ; for ( const std :: string & input_name : concat_op -> inputs ) { const Operator * input_op = GetOpWithOutput ( * model , input_name ) ; if ( input_op ) return :: tensorflow :: Status :: OK ( ) ; if ( ! IsConstantParameterArray ( * model , input_name ) ) return :: tensorflow :: Status :: OK ( ) ; if ( ! model -> GetArray ( input_name ) . has_shape ( ) ) return :: tensorflow :: Status :: OK ( ) ; if ( model -> GetArray ( input_name ) . quantization_params ) return :: tensorflow :: Status :: OK ( ) ; if ( ! IsDiscardableArray ( * model , input_name ) ) return :: tensorflow :: Status :: OK ( ) ; } const int concatenation_axis = concat_op -> axis ; CHECK_EQ ( concat_op -> outputs . size ( ) , 1 ) ; std :: string concatenated_array_name = concat_op -> outputs [ 0 ] ; Array & concatenated_array = model -> GetOrCreateArray ( concatenated_array_name ) ; std :: vector < Array * > input_arrays ; for ( const std :: string & input_name : concat_op -> inputs ) { input_arrays . push_back ( & model -> GetArray ( input_name ) ) ; } AddMessageF ( " " , absl :: StrJoin ( concat_op -> inputs , " " ) , concatenated_array_name ) ; switch ( concatenated_array . data_type ) { case ArrayDataType :: kFloat : ConcatenateTensorBuffers < ArrayDataType :: kFloat > ( input_arrays , concatenation_axis , & concatenated_array ) ; SetMinMaxForConcatenedArray ( this , input_arrays , & concatenated_array ) ; break ; case ArrayDataType :: kUint8 : ConcatenateTensorBuffers < ArrayDataType :: kUint8 > ( input_arrays , concatenation_axis , & concatenated_array ) ; break ; case ArrayDataType :: kInt32 : ConcatenateTensorBuffers < ArrayDataType :: kInt32 > ( input_arrays , concatenation_axis , & concatenated_array ) ; break ; case ArrayDataType :: kInt64 : ConcatenateTensorBuffers < ArrayDataType :: kInt64 > ( input_arrays , concatenation_axis , & concatenated_array ) ; break ; case ArrayDataType :: kString : ConcatenateTensorBuffers < ArrayDataType :: kString > ( input_arrays , concatenation_axis , & concatenated_array ) ; break ; case ArrayDataType :: kComplex64 : ConcatenateTensorBuffers < ArrayDataType :: kComplex64 > ( input_arrays , concatenation_axis , & concatenated_array ) ; break ; default : LOG ( FATAL ) << " " ; } DeleteOpAndArrays ( model , concat_op ) ; * modified = true ; return :: tensorflow :: Status :: OK ( ) ; }
Resolves the concatenation operator if all its inputs are constant arrays.
Resolves the concatenation operator if all its inputs are constant arrays .
// We only expect constant unquantized arrays as input, otherwise we return. // We  also make sure the shapes of the input arrays are known and they are // all discardable.