<commit_before>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/service/hlo_verifier.h"
#include "tensorflow/compiler/xla/service/shape_inference.h"
#include "tensorflow/compiler/xla/status_macros.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/gtl/flatmap.h"

namespace xla {

namespace {

// Visitor which verifies that the output shape is correctly set. Verifies
// against the inferred shape for the instruction.
// TODO(b/26024837): Check output shape for all instruction types.
class ShapeVerifier : public DfsHloVisitor {
 public:
  explicit ShapeVerifier(
      const std::function<int64(const Shape&)>& shape_size_fn)
      : shape_size_fn_(shape_size_fn) {}

  Status HandleElementwiseUnary(HloInstruction* hlo) override {
    return CheckUnaryShape(hlo);
  }

  Status HandleElementwiseBinary(HloInstruction* hlo) override {
    return CheckBinaryShape(hlo);
  }

  Status HandleClamp(HloInstruction* clamp) override {
    return CheckTernaryShape(clamp);
  }

  Status HandleSelect(HloInstruction* select) override {
    return CheckTernaryShape(select);
  }

  Status HandleConcatenate(HloInstruction* concatenate) override {
    std::vector<const Shape*> operand_shapes;
    for (const HloInstruction* operand : concatenate->operands()) {
      operand_shapes.push_back(&operand->shape());
    }
    return CheckShape(
        concatenate, ShapeInference::InferConcatOpShape(
                         operand_shapes, concatenate->concatenate_dimension()));
  }

  Status HandleConvert(HloInstruction* convert) override {
    return CheckShape(convert, ShapeInference::InferConvertShape(
                                   convert->operand(0)->shape(),
                                   convert->shape().element_type()));
  }

  Status HandleBitcastConvert(HloInstruction* convert) override {
    return CheckShape(convert, ShapeInference::InferBitcastConvertShape(
                                   convert->operand(0)->shape(),
                                   convert->shape().element_type()));
  }

  Status HandleCopy(HloInstruction* copy) override {
    return CheckUnaryShape(copy);
  }

  Status HandleDot(HloInstruction* dot) override {
    return CheckBinaryShape(dot);
  }

  Status HandleConvolution(HloInstruction* convolution) override {
    TF_ASSIGN_OR_RETURN(
        const Shape expected,
        ShapeInference::InferConvolveShape(
            convolution->operand(0)->shape(), convolution->operand(1)->shape(),
            convolution->window(),
            convolution->convolution_dimension_numbers()));
    return CheckShape(convolution, expected);
  }

  Status HandleCrossReplicaSum(HloInstruction* crs) override {
    return CheckShape(crs, ShapeInference::InferCrossReplicaSumShape(
                               crs->operand(0)->shape()));
  }

  Status HandleReducePrecision(HloInstruction* reduce_precision) override {
    return CheckShape(reduce_precision,
                      ShapeInference::InferReducePrecisionShape(
                          reduce_precision->operand(0)->shape(),
                          reduce_precision->exponent_bits(),
                          reduce_precision->mantissa_bits()));
  }

  Status HandleInfeed(HloInstruction*) override {
    return tensorflow::Status::OK();
  }

  Status HandleOutfeed(HloInstruction*) override {
    return tensorflow::Status::OK();
  }

  Status HandleRng(HloInstruction*) override {
    return tensorflow::Status::OK();
  }

  Status HandleReverse(HloInstruction* reverse) override {
    return CheckShape(
        reverse, ShapeInference::InferReverseShape(reverse->operand(0)->shape(),
                                                   reverse->dimensions()));
  }

  Status HandleSort(HloInstruction* sort) override {
    return CheckUnaryShape(sort);
  }

  Status HandleConstant(HloInstruction* constant) override {
    return CheckShape(constant, constant->literal().shape());
  }

  Status HandleGetTupleElement(HloInstruction* get_tuple_element) override {
    return CheckShape(get_tuple_element,
                      ShapeInference::InferGetTupleElementShape(
                          get_tuple_element->operand(0)->shape(),
                          get_tuple_element->tuple_index()));
  }

  Status HandleReduce(HloInstruction* reduce) override {
    return CheckShape(
        reduce,
        ShapeInference::InferReduceShape(
            reduce->operand(0)->shape(), reduce->operand(1)->shape(),
            reduce->dimensions(), reduce->to_apply()->ComputeProgramShape()));
  }

  Status HandleBitcast(HloInstruction* bitcast) override {
    // Bitcasts can be any shape, as long as the size matches the operand size.
    TF_RET_CHECK(shape_size_fn_(bitcast->shape()) ==
                 shape_size_fn_(bitcast->operand(0)->shape()));
    return tensorflow::Status::OK();
  }

  Status HandleBroadcast(HloInstruction* broadcast) override {
    // HLO broadcast has no exact analog at the proto level so there is no
    // ShapeInference method. Check the output shape explicitly.
    const Shape& operand_shape = broadcast->operand(0)->shape();
    TF_RET_CHECK(ShapeUtil::Rank(operand_shape) ==
                 broadcast->dimensions().size());
    for (int64 operand_dimension = 0;
         operand_dimension < ShapeUtil::Rank(operand_shape);
         ++operand_dimension) {
      int64 output_dimension = broadcast->dimensions()[operand_dimension];
      TF_RET_CHECK(broadcast->shape().dimensions(output_dimension) ==
                   operand_shape.dimensions(operand_dimension));
    }
    return tensorflow::Status::OK();<commit_msg>Change HLO verifier semantics for bitcasts to: Bitcasts that are not the root of a computation can be any shape byte size. Bitcasts that are the root of a computation must have the same shape byte size as their operand.<commit_after>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/service/hlo_verifier.h"
#include "tensorflow/compiler/xla/service/shape_inference.h"
#include "tensorflow/compiler/xla/status_macros.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/gtl/flatmap.h"

namespace xla {

namespace {

// Visitor which verifies that the output shape is correctly set. Verifies
// against the inferred shape for the instruction.
// TODO(b/26024837): Check output shape for all instruction types.
class ShapeVerifier : public DfsHloVisitor {
 public:
  explicit ShapeVerifier(
      const std::function<int64(const Shape&)>& shape_size_fn)
      : shape_size_fn_(shape_size_fn) {}

  Status HandleElementwiseUnary(HloInstruction* hlo) override {
    return CheckUnaryShape(hlo);
  }

  Status HandleElementwiseBinary(HloInstruction* hlo) override {
    return CheckBinaryShape(hlo);
  }

  Status HandleClamp(HloInstruction* clamp) override {
    return CheckTernaryShape(clamp);
  }

  Status HandleSelect(HloInstruction* select) override {
    return CheckTernaryShape(select);
  }

  Status HandleConcatenate(HloInstruction* concatenate) override {
    std::vector<const Shape*> operand_shapes;
    for (const HloInstruction* operand : concatenate->operands()) {
      operand_shapes.push_back(&operand->shape());
    }
    return CheckShape(
        concatenate, ShapeInference::InferConcatOpShape(
                         operand_shapes, concatenate->concatenate_dimension()));
  }

  Status HandleConvert(HloInstruction* convert) override {
    return CheckShape(convert, ShapeInference::InferConvertShape(
                                   convert->operand(0)->shape(),
                                   convert->shape().element_type()));
  }

  Status HandleBitcastConvert(HloInstruction* convert) override {
    return CheckShape(convert, ShapeInference::InferBitcastConvertShape(
                                   convert->operand(0)->shape(),
                                   convert->shape().element_type()));
  }

  Status HandleCopy(HloInstruction* copy) override {
    return CheckUnaryShape(copy);
  }

  Status HandleDot(HloInstruction* dot) override {
    return CheckBinaryShape(dot);
  }

  Status HandleConvolution(HloInstruction* convolution) override {
    TF_ASSIGN_OR_RETURN(
        const Shape expected,
        ShapeInference::InferConvolveShape(
            convolution->operand(0)->shape(), convolution->operand(1)->shape(),
            convolution->window(),
            convolution->convolution_dimension_numbers()));
    return CheckShape(convolution, expected);
  }

  Status HandleCrossReplicaSum(HloInstruction* crs) override {
    return CheckShape(crs, ShapeInference::InferCrossReplicaSumShape(
                               crs->operand(0)->shape()));
  }

  Status HandleReducePrecision(HloInstruction* reduce_precision) override {
    return CheckShape(reduce_precision,
                      ShapeInference::InferReducePrecisionShape(
                          reduce_precision->operand(0)->shape(),
                          reduce_precision->exponent_bits(),
                          reduce_precision->mantissa_bits()));
  }

  Status HandleInfeed(HloInstruction*) override {
    return tensorflow::Status::OK();
  }

  Status HandleOutfeed(HloInstruction*) override {
    return tensorflow::Status::OK();
  }

  Status HandleRng(HloInstruction*) override {
    return tensorflow::Status::OK();
  }

  Status HandleReverse(HloInstruction* reverse) override {
    return CheckShape(
        reverse, ShapeInference::InferReverseShape(reverse->operand(0)->shape(),
                                                   reverse->dimensions()));
  }

  Status HandleSort(HloInstruction* sort) override {
    return CheckUnaryShape(sort);
  }

  Status HandleConstant(HloInstruction* constant) override {
    return CheckShape(constant, constant->literal().shape());
  }

  Status HandleGetTupleElement(HloInstruction* get_tuple_element) override {
    return CheckShape(get_tuple_element,
                      ShapeInference::InferGetTupleElementShape(
                          get_tuple_element->operand(0)->shape(),
                          get_tuple_element->tuple_index()));
  }

  Status HandleReduce(HloInstruction* reduce) override {
    return CheckShape(
        reduce,
        ShapeInference::InferReduceShape(
            reduce->operand(0)->shape(), reduce->operand(1)->shape(),
            reduce->dimensions(), reduce->to_apply()->ComputeProgramShape()));
  }

  Status HandleBitcast(HloInstruction* bitcast) override {
    // Bitcasts that are not the root of a computation can be any shape.
    // Bitcasts that are the root of a computation must have the same shape
    // byte size as their operand.
    if (bitcast->parent()->root_instruction() == bitcast) {
      TF_RET_CHECK(shape_size_fn_(bitcast->shape()) ==
                   shape_size_fn_(bitcast->operand(0)->shape()));
    }
    return tensorflow::Status::OK();
  }

  Status HandleBroadcast(HloInstruction* broadcast) override {
    // HLO broadcast has no exact analog at the proto level so there is no
    // ShapeInference method. Check the output shape explicitly.
    const Shape& operand_shape = broadcast->operand(0)->shape();
    TF_RET_CHECK(ShapeUtil::Rank(operand_shape) ==
                 broadcast->dimensions().size());
    for (int64 operand_dimension = 0;
         operand_dimension < ShapeUtil::Rank(operand_shape);
         ++operand_dimension) {
      int64 output_dimension = broadcast->dimensions()[operand_dimension];
      TF_RET_CHECK(broadcast->shape().dimensions(output_dimension) ==
                   operand_shape.dimensions(operand_dimension));
    }
    return tensorflow::Status::OK();
{'fraction_non_alphanumeric': 0.11048224530935029, 'fraction_numerical': 0.0054271980151961545, 'mean_word_length': 3.3548278190411884, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 95, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5209491', 'n_tokens_mistral': 3548, 'n_tokens_neox': 3416, 'n_words': 798}