/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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.
 */

#ifndef ART_COMPILER_OPTIMIZING_LOOP_ANALYSIS_H_
#define ART_COMPILER_OPTIMIZING_LOOP_ANALYSIS_H_

#include "base/macros.h"
#include "nodes.h"

namespace art HIDDEN {

class CodeGenerator;
class InductionVarRange;
class LoopAnalysis;

// Class to hold cached information on properties of the loop.
class LoopAnalysisInfo : public ValueObject {
 public:
  // No loop unrolling factor (just one copy of the loop-body).
  static constexpr uint32_t kNoUnrollingFactor = 1;
  // Used for unknown and non-constant trip counts (see InductionVarRange::HasKnownTripCount).
  static constexpr int64_t kUnknownTripCount = -1;

  explicit LoopAnalysisInfo(HLoopInformation* loop_info)
      : trip_count_(kUnknownTripCount),
        bb_num_(0),
        instr_num_(0),
        exits_num_(0),
        invariant_exits_num_(0),
        has_instructions_preventing_scalar_peeling_(false),
        has_instructions_preventing_scalar_unrolling_(false),
        has_long_type_instructions_(false),
        loop_info_(loop_info) {}

  int64_t GetTripCount() const { return trip_count_; }
  size_t GetNumberOfBasicBlocks() const { return bb_num_; }
  size_t GetNumberOfInstructions() const { return instr_num_; }
  size_t GetNumberOfExits() const { return exits_num_; }
  size_t GetNumberOfInvariantExits() const { return invariant_exits_num_; }

  bool HasInstructionsPreventingScalarPeeling() const {
    return has_instructions_preventing_scalar_peeling_;
  }

  bool HasInstructionsPreventingScalarUnrolling() const {
    return has_instructions_preventing_scalar_unrolling_;
  }

  bool HasInstructionsPreventingScalarOpts() const {
    return HasInstructionsPreventingScalarPeeling() || HasInstructionsPreventingScalarUnrolling();
  }

  bool HasLongTypeInstructions() const {
    return has_long_type_instructions_;
  }

  HLoopInformation* GetLoopInfo() const { return loop_info_; }

 private:
  // Trip count of the loop if known, kUnknownTripCount otherwise.
  int64_t trip_count_;
  // Number of basic blocks in the loop body.
  size_t bb_num_;
  // Number of instructions in the loop body.
  size_t instr_num_;
  // Number of loop's exits.
  size_t exits_num_;
  // Number of "if" loop exits (with HIf instruction) whose condition is loop-invariant.
  size_t invariant_exits_num_;
  // Whether the loop has instructions which make scalar loop peeling non-beneficial.
  bool has_instructions_preventing_scalar_peeling_;
  // Whether the loop has instructions which make scalar loop unrolling non-beneficial.
  bool has_instructions_preventing_scalar_unrolling_;
  // Whether the loop has instructions of primitive long type; unrolling these loop will
  // likely introduce spill/fills on 32-bit targets.
  bool has_long_type_instructions_;

  // Corresponding HLoopInformation.
  HLoopInformation* loop_info_;

  friend class LoopAnalysis;
};

// Placeholder class for methods and routines used to analyse loops, calculate loop properties
// and characteristics.
class LoopAnalysis : public ValueObject {
 public:
  // Calculates loops basic properties like body size, exits number, etc. and fills
  // 'analysis_results' with this information.
  static void CalculateLoopBasicProperties(HLoopInformation* loop_info,
                                           LoopAnalysisInfo* analysis_results,
                                           int64_t trip_count);

  // Returns the trip count of the loop if it is known and kUnknownTripCount otherwise.
  static int64_t GetLoopTripCount(HLoopInformation* loop_info,
                                  const InductionVarRange* induction_range);

 private:
  // Returns whether an instruction makes scalar loop peeling/unrolling non-beneficial.
  //
  // If in the loop body we have a dex/runtime call then its contribution to the whole
  // loop performance will probably prevail. So peeling/unrolling optimization will not bring
  // any noticeable performance improvement. It will increase the code size.
  static bool MakesScalarPeelingUnrollingNonBeneficial(HInstruction* instruction) {
    return (instruction->IsNewArray() ||
        instruction->IsNewInstance() ||
        instruction->IsUnresolvedInstanceFieldGet() ||
        instruction->IsUnresolvedInstanceFieldSet() ||
        instruction->IsUnresolvedStaticFieldGet() ||
        instruction->IsUnresolvedStaticFieldSet() ||
        // TODO: Support loops with intrinsified invokes.
        instruction->IsInvoke());
  }
};

//
// Helper class which holds target-dependent methods and constants needed for loop optimizations.
//
// To support peeling/unrolling for a new architecture one needs to create new helper class,
// inherit it from this and add implementation for the following methods.
//
class ArchNoOptsLoopHelper : public ArenaObject<kArenaAllocOptimization> {
 public:
  explicit ArchNoOptsLoopHelper(const CodeGenerator& codegen) : codegen_(codegen) {}
  virtual ~ArchNoOptsLoopHelper() {}

  // Creates an instance of specialised helper for the target or default helper if the target
  // doesn't support loop peeling and unrolling.
  static ArchNoOptsLoopHelper* Create(const CodeGenerator& codegen, ArenaAllocator* allocator);

  // Returns whether the loop is not beneficial for loop peeling/unrolling.
  //
  // For example, if the loop body has too many instructions then peeling/unrolling optimization
  // will not bring any noticeable performance improvement however will increase the code size.
  //
  // Returns 'true' by default, should be overridden by particular target loop helper.
  virtual bool IsLoopNonBeneficialForScalarOpts(
      [[maybe_unused]] LoopAnalysisInfo* loop_analysis_info) const {
    return true;
  }

  // Returns optimal scalar unrolling factor for the loop.
  //
  // Returns kNoUnrollingFactor by default, should be overridden by particular target loop helper.
  virtual uint32_t GetScalarUnrollingFactor(
      [[maybe_unused]] const LoopAnalysisInfo* analysis_info) const {
    return LoopAnalysisInfo::kNoUnrollingFactor;
  }

  // Returns whether scalar loop peeling is enabled,
  //
  // Returns 'false' by default, should be overridden by particular target loop helper.
  virtual bool IsLoopPeelingEnabled() const { return false; }

  // Returns whether it is beneficial to fully unroll the loop.
  //
  // Returns 'false' by default, should be overridden by particular target loop helper.
  virtual bool IsFullUnrollingBeneficial([[maybe_unused]] LoopAnalysisInfo* analysis_info) const {
    return false;
  }

  // Returns optimal SIMD unrolling factor for the loop.
  //
  // Returns kNoUnrollingFactor by default, should be overridden by particular target loop helper.
  virtual uint32_t GetSIMDUnrollingFactor([[maybe_unused]] HBasicBlock* block,
                                          [[maybe_unused]] int64_t trip_count,
                                          [[maybe_unused]] uint32_t max_peel,
                                          [[maybe_unused]] uint32_t vector_length) const {
    return LoopAnalysisInfo::kNoUnrollingFactor;
  }

 protected:
  const CodeGenerator& codegen_;
};

}  // namespace art

#endif  // ART_COMPILER_OPTIMIZING_LOOP_ANALYSIS_H_
