/*
 * Copyright (C) 2017 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_SUPERBLOCK_CLONER_H_
#define ART_COMPILER_OPTIMIZING_SUPERBLOCK_CLONER_H_

#include "base/arena_bit_vector.h"
#include "base/arena_containers.h"
#include "base/bit_vector-inl.h"
#include "nodes.h"

namespace art {

class InductionVarRange;

static const bool kSuperblockClonerLogging = false;
static const bool kSuperblockClonerVerify = false;

// Represents an edge between two HBasicBlocks.
//
// Note: objects of this class are small - pass them by value.
class HEdge : public ArenaObject<kArenaAllocSuperblockCloner> {
 public:
  HEdge(HBasicBlock* from, HBasicBlock* to) : from_(from->GetBlockId()), to_(to->GetBlockId()) {
    DCHECK_NE(to_, kInvalidBlockId);
    DCHECK_NE(from_, kInvalidBlockId);
  }
  HEdge(uint32_t from, uint32_t to) : from_(from), to_(to) {
    DCHECK_NE(to_, kInvalidBlockId);
    DCHECK_NE(from_, kInvalidBlockId);
  }
  HEdge() : from_(kInvalidBlockId), to_(kInvalidBlockId) {}

  uint32_t GetFrom() const { return from_; }
  uint32_t GetTo() const { return to_; }

  bool operator==(const HEdge& other) const {
    return this->from_ == other.from_ && this->to_ == other.to_;
  }

  bool operator!=(const HEdge& other) const { return !operator==(other); }
  void Dump(std::ostream& stream) const;

  // Returns whether an edge represents a valid edge in CF graph: whether the from_ block
  // has to_ block as a successor.
  bool IsValid() const { return from_ != kInvalidBlockId && to_ != kInvalidBlockId; }

 private:
  // Predecessor block id.
  uint32_t from_;
  // Successor block id.
  uint32_t to_;
};

// Returns whether a HEdge edge corresponds to an existing edge in the graph.
inline bool IsEdgeValid(HEdge edge, HGraph* graph) {
  if (!edge.IsValid()) {
    return false;
  }
  uint32_t from = edge.GetFrom();
  uint32_t to = edge.GetTo();
  if (from >= graph->GetBlocks().size() || to >= graph->GetBlocks().size()) {
    return false;
  }

  HBasicBlock* block_from = graph->GetBlocks()[from];
  HBasicBlock* block_to = graph->GetBlocks()[to];
  if (block_from == nullptr || block_to == nullptr) {
    return false;
  }

  return block_from->HasSuccessor(block_to, 0);
}

// SuperblockCloner provides a feature of cloning subgraphs in a smart, high level way without
// fine grain manipulation with IR; data flow and graph properties are resolved/adjusted
// automatically. The clone transformation is defined by specifying a set of basic blocks to copy
// and a set of rules how to treat edges, remap their successors. By using this approach such
// optimizations as Branch Target Expansion, Loop Peeling, Loop Unrolling, Loop Versioning can be
// implemented.
//
// The idea of the transformation is based on "Superblock cloning" technique described in the book
// "Engineering a Compiler. Second Edition", Keith D. Cooper, Linda Torczon, Rice University
// Houston, Texas. 2nd edition, Morgan Kaufmann. The original paper is "The Superblock: An Efective
// Technique for VLIW and Superscalar Compilation" by Hwu, W.M.W., Mahlke, S.A., Chen, W.Y. et al.
// J Supercomput (1993) 7: 229. doi:10.1007/BF01205185.
//
// There are two states of the IR graph: original graph (before the transformation) and
// copy graph (after).
//
// Before the transformation:
// Defining a set of basic block to copy (orig_bb_set) partitions all of the edges in the original
// graph into 4 categories/sets (use the following notation for edges: "(pred, succ)",
// where pred, succ - basic blocks):
//  - internal - pred, succ are members of ‘orig_bb_set’.
//  - outside  - pred, succ are not members of ‘orig_bb_set’.
//  - incoming - pred is not a member of ‘orig_bb_set’, succ is.
//  - outgoing - pred is a member of ‘orig_bb_set’, succ is not.
//
// Transformation:
//
// 1. Initial cloning:
//   1.1. For each ‘orig_block’ in orig_bb_set create a copy ‘copy_block’; these new blocks
//        form ‘copy_bb_set’.
//   1.2. For each edge (X, Y) from internal set create an edge (X_1, Y_1) where X_1, Y_1 are the
//        copies of X, Y basic blocks correspondingly; these new edges form ‘copy_internal’ edge
//        set.
//   1.3. For each edge (X, Y) from outgoing set create an edge (X_1, Y_1) where X_1, Y_1 are the
//        copies of X, Y basic blocks correspondingly; these new edges form ‘copy_outgoing’ edge
//        set.
// 2. Successors remapping.
//   2.1. 'remap_orig_internal’ - set of edges (X, Y) from ‘orig_bb_set’ whose successors should
//        be remapped to copy nodes: ((X, Y) will be transformed into (X, Y_1)).
//   2.2. ‘remap_copy_internal’ - set of edges (X_1, Y_1) from ‘copy_bb_set’ whose successors
//        should be remapped to copy nodes: (X_1, Y_1) will be transformed into (X_1, Y)).
//   2.3. 'remap_incoming’ - set of edges (X, Y) from the ‘incoming’ edge set in the original graph
//        whose successors should be remapped to copies nodes: ((X, Y) will be transformed into
//        (X, Y_1)).
// 3. Adjust control flow structures and relations (dominance, reverse post order, loops, etc).
// 4. Fix/resolve data flow.
// 5. Do cleanups (DCE, critical edges splitting, etc).
//
class SuperblockCloner : public ValueObject {
 public:
  // TODO: Investigate optimal types for the containers.
  using HBasicBlockMap = ArenaSafeMap<HBasicBlock*, HBasicBlock*>;
  using HInstructionMap = ArenaSafeMap<HInstruction*, HInstruction*>;
  using HBasicBlockSet = ArenaBitVector;
  using HEdgeSet = ArenaHashSet<HEdge>;

  SuperblockCloner(HGraph* graph,
                   const HBasicBlockSet* orig_bb_set,
                   HBasicBlockMap* bb_map,
                   HInstructionMap* hir_map,
                   InductionVarRange* induction_range);

  // Sets edge successor remapping info specified by corresponding edge sets.
  void SetSuccessorRemappingInfo(const HEdgeSet* remap_orig_internal,
                                 const HEdgeSet* remap_copy_internal,
                                 const HEdgeSet* remap_incoming);

  // Returns whether the specified subgraph is copyable.
  // TODO: Start from small range of graph patterns then extend it.
  bool IsSubgraphClonable() const;

  // Returns whether selected subgraph satisfies the criteria for fast data flow resolution
  // when iterative DF algorithm is not required and dominators/instructions inputs can be
  // trivially adjusted.
  //
  // TODO: formally describe the criteria.
  //
  // Loop peeling, unrolling and versioning satisfy the criteria.
  bool IsFastCase() const;

  // Runs the copy algorithm according to the description.
  void Run();

  // Cleans up the graph after transformation: splits critical edges, recalculates control flow
  // information (back-edges, dominators, loop info, etc), eliminates redundant phis.
  void CleanUp();

  // Returns a clone of a basic block (orig_block).
  //
  //  - The copy block will have no successors/predecessors; they should be set up manually.
  //  - For each instruction in the orig_block a copy is created and inserted into the copy block;
  //    this correspondence is recorded in the map (old instruction, new instruction).
  //  - Graph HIR is not valid after this transformation: all of the HIRs have their inputs the
  //    same, as in the original block, PHIs do not reflect a correct correspondence between the
  //    value and predecessors (as the copy block has no predecessors by now), etc.
  HBasicBlock* CloneBasicBlock(const HBasicBlock* orig_block);

  // Creates a clone for each basic blocks in orig_bb_set adding corresponding entries into bb_map_
  // and hir_map_.
  void CloneBasicBlocks();

  HInstruction* GetInstrCopy(HInstruction* orig_instr) const {
    auto copy_input_iter = hir_map_->find(orig_instr);
    DCHECK(copy_input_iter != hir_map_->end());
    return copy_input_iter->second;
  }

  HBasicBlock* GetBlockCopy(HBasicBlock* orig_block) const {
    HBasicBlock* block = bb_map_->Get(orig_block);
    DCHECK(block != nullptr);
    return block;
  }

  HInstruction* GetInstrOrig(HInstruction* copy_instr) const {
    for (auto it : *hir_map_) {
      if (it.second == copy_instr) {
        return it.first;
      }
    }
    return nullptr;
  }

  bool IsInOrigBBSet(uint32_t block_id) const {
    return orig_bb_set_.IsBitSet(block_id);
  }

  bool IsInOrigBBSet(const HBasicBlock* block) const {
    return IsInOrigBBSet(block->GetBlockId());
  }

  // Returns the area (the most outer loop) in the graph for which control flow (back edges, loops,
  // dominators) needs to be adjusted.
  HLoopInformation* GetRegionToBeAdjusted() const {
    return outer_loop_;
  }

 private:
  // Fills the 'exits' vector with the subgraph exits.
  void SearchForSubgraphExits(ArenaVector<HBasicBlock*>* exits) const;

  // Finds and records information about the area in the graph for which control flow (back edges,
  // loops, dominators) needs to be adjusted.
  void FindAndSetLocalAreaForAdjustments();

  // Remaps edges' successors according to the info specified in the edges sets.
  //
  // Only edge successors/predecessors and phis' input records (to have a correspondence between
  // a phi input record (not value) and a block's predecessor) are adjusted at this stage: neither
  // phis' nor instructions' inputs values are resolved.
  void RemapEdgesSuccessors();

  // Adjusts control flow (back edges, loops, dominators) for the local area defined by
  // FindAndSetLocalAreaForAdjustments.
  void AdjustControlFlowInfo();

  // Resolves Data Flow - adjusts phis' and instructions' inputs in order to have a valid graph in
  // the SSA form.
  void ResolveDataFlow();

  //
  // Helpers for live-outs processing and Subgraph-closed SSA.
  //
  //  - live-outs - values which are defined inside the subgraph and have uses outside.
  //  - Subgraph-closed SSA - SSA form for which all the values defined inside the subgraph
  //    have no outside uses except for the phi-nodes in the subgraph exits.
  //
  // Note: now if the subgraph has live-outs it is only clonable if it has a single exit; this
  // makes the subgraph-closed SSA form construction much easier.
  //
  // TODO: Support subgraphs with live-outs and multiple exits.
  //

  // For each live-out value 'val' in the region puts a record <val, val> into the map.
  // Returns whether all of the instructions in the subgraph are clonable.
  bool CollectLiveOutsAndCheckClonable(HInstructionMap* live_outs_) const;

  // Constructs Subgraph-closed SSA; precondition - a subgraph has a single exit.
  //
  // For each live-out 'val' in 'live_outs_' map inserts a HPhi 'phi' into the exit node, updates
  // the record in the map to <val, phi> and replaces all outside uses with this phi.
  void ConstructSubgraphClosedSSA();

  // Fixes the data flow for the live-out 'val' by adding a 'copy_val' input to the corresponding
  // (<val, phi>) phi after the cloning is done.
  void FixSubgraphClosedSSAAfterCloning();

  //
  // Helpers for CloneBasicBlock.
  //

  // Adjusts copy instruction's inputs: if the input of the original instruction is defined in the
  // orig_bb_set, replaces it with a corresponding copy otherwise leaves it the same as original.
  void ReplaceInputsWithCopies(HInstruction* copy_instr);

  // Recursively clones the environment for the copy instruction. If the input of the original
  // environment is defined in the orig_bb_set, replaces it with a corresponding copy otherwise
  // leaves it the same as original.
  void DeepCloneEnvironmentWithRemapping(HInstruction* copy_instr, const HEnvironment* orig_env);

  //
  // Helpers for RemapEdgesSuccessors.
  //

  // Remaps incoming or original internal edge to its copy, adjusts the phi inputs in orig_succ and
  // copy_succ.
  void RemapOrigInternalOrIncomingEdge(HBasicBlock* orig_block, HBasicBlock* orig_succ);

  // Adds copy internal edge (from copy_block to copy_succ), updates phis in the copy_succ.
  void AddCopyInternalEdge(HBasicBlock* orig_block, HBasicBlock* orig_succ);

  // Remaps copy internal edge to its origin, adjusts the phi inputs in orig_succ.
  void RemapCopyInternalEdge(HBasicBlock* orig_block, HBasicBlock* orig_succ);

  // Checks whether the edges remapping info corresponds to the subgraph versioning case:
  //  - none of the incoming edges are to be remapped (they are being duplicated).
  //  - none of the internal edges are to be remapped.
  bool IsRemapInfoForVersioning() const;

  // Processes incoming edges for subgraph versioning case: for each incoming edge (X, Y) adds
  // an edge (X, Y_1) where Y_1 = Copy(Y) and add corresponding phi input to copy phi.
  //
  // Note: such node X will now have two successors, its unconditional branch instruction
  // will be invalid and should be adjusted to some conditional branch by the client code.
  void CopyIncomingEdgesForVersioning();

  //
  // Local versions of control flow calculation/adjustment routines.
  //

  void FindBackEdgesLocal(HBasicBlock* entry_block, ArenaBitVector* local_set);
  void RecalculateBackEdgesInfo(ArenaBitVector* outer_loop_bb_set);
  GraphAnalysisResult AnalyzeLoopsLocally(ArenaBitVector* outer_loop_bb_set);
  void CleanUpControlFlow();

  //
  // Helpers for ResolveDataFlow
  //

  // Resolves the inputs of the phi.
  void ResolvePhi(HPhi* phi);

  // Update induction range after when fixing SSA.
  void UpdateInductionRangeInfoOf(
      HInstruction* user, HInstruction* old_instruction, HInstruction* replacement);

  //
  // Debug and logging methods.
  //
  void CheckInstructionInputsRemapping(HInstruction* orig_instr);
  bool CheckRemappingInfoIsValid();
  void VerifyGraph();
  void DumpInputSets();

  HBasicBlock* GetBlockById(uint32_t block_id) const {
    DCHECK(block_id < graph_->GetBlocks().size());
    HBasicBlock* block = graph_->GetBlocks()[block_id];
    DCHECK(block != nullptr);
    return block;
  }

  HGraph* const graph_;
  ArenaAllocator* const arena_;

  // Set of basic block in the original graph to be copied.
  HBasicBlockSet orig_bb_set_;

  // Sets of edges which require successors remapping.
  const HEdgeSet* remap_orig_internal_;
  const HEdgeSet* remap_copy_internal_;
  const HEdgeSet* remap_incoming_;

  // Correspondence map for blocks: (original block, copy block).
  HBasicBlockMap* bb_map_;
  // Correspondence map for instructions: (original HInstruction, copy HInstruction).
  HInstructionMap* hir_map_;
  // As a result of cloning, the induction range analysis information can be invalidated
  // and must be updated. If not null, the cloner updates it for changed instructions.
  InductionVarRange* induction_range_;
  // Area in the graph for which control flow (back edges, loops, dominators) needs to be adjusted.
  HLoopInformation* outer_loop_;
  HBasicBlockSet outer_loop_bb_set_;

  HInstructionMap live_outs_;

  ART_FRIEND_TEST(SuperblockClonerTest, AdjustControlFlowInfo);
  ART_FRIEND_TEST(SuperblockClonerTest, IsGraphConnected);

  DISALLOW_COPY_AND_ASSIGN(SuperblockCloner);
};

// Helper class to perform loop peeling/unrolling/versioning.
//
// This helper should be used when correspondence map between original and copied
// basic blocks/instructions are demanded.
class LoopClonerHelper : public ValueObject {
 public:
  LoopClonerHelper(HLoopInformation* info,
                   SuperblockCloner::HBasicBlockMap* bb_map,
                   SuperblockCloner::HInstructionMap* hir_map,
                   InductionVarRange* induction_range) :
      loop_info_(info),
      cloner_(info->GetHeader()->GetGraph(), &info->GetBlocks(), bb_map, hir_map, induction_range) {
    // For now do transformations only for natural loops.
    DCHECK(!info->IsIrreducible());
  }

  // Returns whether the loop can be peeled/unrolled (static function).
  static bool IsLoopClonable(HLoopInformation* loop_info);

  // Returns whether the loop can be peeled/unrolled.
  bool IsLoopClonable() const { return cloner_.IsSubgraphClonable(); }

  // Perform loop peeling.
  //
  // Control flow of an example (ignoring critical edges splitting).
  //
  //       Before                    After
  //
  //         |B|                      |B|
  //          |                        |
  //          v                        v
  //         |1|                      |1|
  //          |                        |
  //          v                        v
  //         |2|<-\                  |2A|
  //         / \  /                   / \
  //        v   v/                   /   v
  //       |4|  |3|                 /   |3A|
  //        |                      /     /
  //        v                     |     v
  //       |E|                     \   |2|<-\
  //                                \ / \   /
  //                                 v   v /
  //                                |4|  |3|
  //                                 |
  //                                 v
  //                                |E|
  HBasicBlock* DoPeeling() {
    return DoLoopTransformationImpl(TransformationKind::kPeeling);
  }

  // Perform loop unrolling.
  //
  // Control flow of an example (ignoring critical edges splitting).
  //
  //       Before                    After
  //
  //         |B|                      |B|
  //          |                        |
  //          v                        v
  //         |1|                      |1|
  //          |                        |
  //          v                        v
  //         |2|<-\                   |2A|<-\
  //         / \  /                   / \    \
  //        v   v/                   /   v    \
  //       |4|  |3|                 /   |3A|   |
  //        |                      /     /    /
  //        v                     |     v    /
  //       |E|                     \   |2|  /
  //                                \ / \  /
  //                                 v   v/
  //                                |4| |3|
  //                                 |
  //                                 v
  //                                |E|
  HBasicBlock* DoUnrolling() {
    return DoLoopTransformationImpl(TransformationKind::kUnrolling);
  }

  // Perform loop versioning.
  //
  // Control flow of an example (ignoring critical edges splitting).
  //
  //       Before                    After
  //
  //         |B|                      |B|
  //          |                        |
  //          v                        v
  //         |1|                      |1|_________
  //          |                        |          |
  //          v                        v          v
  //         |2|<-\                   |2|<-\     |2A|<-\
  //         / \  /                   / \  /     /  \  /
  //        v   v/                   |   v/      |   v/
  //        |   |3|                  |  |3|      | |3A|
  //        |                        | __________|
  //        |                        ||
  //        v                        vv
  //       |4|                       |4|
  //        |                         |
  //        v                         v
  //       |E|                       |E|
  HBasicBlock* DoVersioning() {
    return DoLoopTransformationImpl(TransformationKind::kVersioning);
  }

  HLoopInformation* GetRegionToBeAdjusted() const { return cloner_.GetRegionToBeAdjusted(); }

 protected:
  enum class TransformationKind {
    kPeeling,
    kUnrolling,
    kVersioning,
  };

  // Applies a specific loop transformation to the loop.
  HBasicBlock* DoLoopTransformationImpl(TransformationKind transformation);

 private:
  HLoopInformation* loop_info_;
  SuperblockCloner cloner_;

  DISALLOW_COPY_AND_ASSIGN(LoopClonerHelper);
};

// Helper class to perform loop peeling/unrolling/versioning.
//
// This helper should be used when there is no need to get correspondence information between
// original and copied basic blocks/instructions.
class LoopClonerSimpleHelper : public ValueObject {
 public:
  LoopClonerSimpleHelper(HLoopInformation* info, InductionVarRange* induction_range);
  bool IsLoopClonable() const { return helper_.IsLoopClonable(); }
  HBasicBlock* DoPeeling() { return helper_.DoPeeling(); }
  HBasicBlock* DoUnrolling() { return helper_.DoUnrolling(); }
  HBasicBlock* DoVersioning() { return helper_.DoVersioning(); }
  HLoopInformation* GetRegionToBeAdjusted() const { return helper_.GetRegionToBeAdjusted(); }

  const SuperblockCloner::HBasicBlockMap* GetBasicBlockMap() const { return &bb_map_; }
  const SuperblockCloner::HInstructionMap* GetInstructionMap() const { return &hir_map_; }

 private:
  SuperblockCloner::HBasicBlockMap bb_map_;
  SuperblockCloner::HInstructionMap hir_map_;
  LoopClonerHelper helper_;

  DISALLOW_COPY_AND_ASSIGN(LoopClonerSimpleHelper);
};

// Collects edge remapping info for loop peeling/unrolling for the loop specified by loop info.
void CollectRemappingInfoForPeelUnroll(bool to_unroll,
                                       HLoopInformation* loop_info,
                                       SuperblockCloner::HEdgeSet* remap_orig_internal,
                                       SuperblockCloner::HEdgeSet* remap_copy_internal,
                                       SuperblockCloner::HEdgeSet* remap_incoming);

// Returns whether blocks from 'work_set' are reachable from the rest of the graph.
//
// Returns whether such a set 'outer_entries' of basic blocks exists that:
// - each block from 'outer_entries' is not from 'work_set'.
// - each block from 'work_set' is reachable from at least one block from 'outer_entries'.
//
// After the function returns work_set contains only blocks from the original 'work_set'
// which are unreachable from the rest of the graph.
bool IsSubgraphConnected(SuperblockCloner::HBasicBlockSet* work_set, HGraph* graph);

// Returns a common predecessor of loop1 and loop2 in the loop tree or nullptr if it is the whole
// graph.
HLoopInformation* FindCommonLoop(HLoopInformation* loop1, HLoopInformation* loop2);
}  // namespace art

namespace std {

template <>
struct hash<art::HEdge> {
  size_t operator()(art::HEdge const& x) const noexcept  {
    // Use Cantor pairing function as the hash function.
    size_t a = x.GetFrom();
    size_t b = x.GetTo();
    return (a + b) * (a + b + 1) / 2 + b;
  }
};
ostream& operator<<(ostream& os, const art::HEdge& e);

}  // namespace std

#endif  // ART_COMPILER_OPTIMIZING_SUPERBLOCK_CLONER_H_
