/*
 * Copyright (C) 2016 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.
 */

#include "linear_order.h"

#include "base/scoped_arena_allocator.h"
#include "base/scoped_arena_containers.h"

namespace art HIDDEN {

static bool InSameLoop(HLoopInformation* first_loop, HLoopInformation* second_loop) {
  return first_loop == second_loop;
}

static bool IsLoop(HLoopInformation* info) {
  return info != nullptr;
}

static bool IsInnerLoop(HLoopInformation* outer, HLoopInformation* inner) {
  return (inner != outer)
      && (inner != nullptr)
      && (outer != nullptr)
      && inner->IsIn(*outer);
}

// Helper method to update work list for linear order.
static void AddToListForLinearization(ScopedArenaVector<HBasicBlock*>* worklist,
                                      HBasicBlock* block) {
  HLoopInformation* block_loop = block->GetLoopInformation();
  auto insert_pos = worklist->rbegin();  // insert_pos.base() will be the actual position.
  for (auto end = worklist->rend(); insert_pos != end; ++insert_pos) {
    HBasicBlock* current = *insert_pos;
    HLoopInformation* current_loop = current->GetLoopInformation();
    if (InSameLoop(block_loop, current_loop)
        || !IsLoop(current_loop)
        || IsInnerLoop(current_loop, block_loop)) {
      // The block can be processed immediately.
      break;
    }
  }
  worklist->insert(insert_pos.base(), block);
}

// Helper method to validate linear order.
static bool IsLinearOrderWellFormed(const HGraph* graph, ArrayRef<HBasicBlock*> linear_order) {
  for (HBasicBlock* header : graph->GetBlocks()) {
    if (header == nullptr || !header->IsLoopHeader()) {
      continue;
    }
    HLoopInformation* loop = header->GetLoopInformation();
    size_t num_blocks = loop->GetBlocks().NumSetBits();
    size_t found_blocks = 0u;
    for (HBasicBlock* block : linear_order) {
      if (loop->Contains(*block)) {
        found_blocks++;
        if (found_blocks == 1u && block != header) {
          // First block is not the header.
          return false;
        } else if (found_blocks == num_blocks && !loop->IsBackEdge(*block)) {
          // Last block is not a back edge.
          return false;
        }
      } else if (found_blocks != 0u && found_blocks != num_blocks) {
        // Blocks are not adjacent.
        return false;
      }
    }
    DCHECK_EQ(found_blocks, num_blocks);
  }
  return true;
}

void LinearizeGraphInternal(const HGraph* graph, ArrayRef<HBasicBlock*> linear_order) {
  DCHECK_EQ(linear_order.size(), graph->GetReversePostOrder().size());
  // Create a reverse post ordering with the following properties:
  // - Blocks in a loop are consecutive,
  // - Back-edge is the last block before loop exits.
  //
  // (1): Record the number of forward predecessors for each block. This is to
  //      ensure the resulting order is reverse post order. We could use the
  //      current reverse post order in the graph, but it would require making
  //      order queries to a GrowableArray, which is not the best data structure
  //      for it.
  ScopedArenaAllocator allocator(graph->GetArenaStack());
  ScopedArenaVector<uint32_t> forward_predecessors(graph->GetBlocks().size(),
                                                   allocator.Adapter(kArenaAllocLinearOrder));
  for (HBasicBlock* block : graph->GetReversePostOrder()) {
    size_t number_of_forward_predecessors = block->GetPredecessors().size();
    if (block->IsLoopHeader()) {
      number_of_forward_predecessors -= block->GetLoopInformation()->NumberOfBackEdges();
    }
    forward_predecessors[block->GetBlockId()] = number_of_forward_predecessors;
  }
  // (2): Following a worklist approach, first start with the entry block, and
  //      iterate over the successors. When all non-back edge predecessors of a
  //      successor block are visited, the successor block is added in the worklist
  //      following an order that satisfies the requirements to build our linear graph.
  ScopedArenaVector<HBasicBlock*> worklist(allocator.Adapter(kArenaAllocLinearOrder));
  worklist.push_back(graph->GetEntryBlock());
  size_t num_added = 0u;
  do {
    HBasicBlock* current = worklist.back();
    worklist.pop_back();
    linear_order[num_added] = current;
    ++num_added;
    for (HBasicBlock* successor : current->GetSuccessors()) {
      int block_id = successor->GetBlockId();
      size_t number_of_remaining_predecessors = forward_predecessors[block_id];
      if (number_of_remaining_predecessors == 1) {
        AddToListForLinearization(&worklist, successor);
      }
      forward_predecessors[block_id] = number_of_remaining_predecessors - 1;
    }
  } while (!worklist.empty());
  DCHECK_EQ(num_added, linear_order.size());

  DCHECK(graph->HasIrreducibleLoops() || IsLinearOrderWellFormed(graph, linear_order));
}

}  // namespace art
