// Copyright (c) 2018 Google LLC.
//
// 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 SOURCE_OPT_COPY_PROP_ARRAYS_H_
#define SOURCE_OPT_COPY_PROP_ARRAYS_H_

#include <memory>
#include <vector>

#include "source/opt/mem_pass.h"

namespace spvtools {
namespace opt {

// This pass implements a simple array copy propagation.  It does not do a full
// array data flow.  It looks for simple cases that meet the following
// conditions:
//
// 1) The source must never be stored to.
// 2) The target must be stored to exactly once.
// 3) The store to the target must be a store to the entire array, and be a
// copy of the entire source.
// 4) All loads of the target must be dominated by the store.
//
// The hard part is keeping all of the types correct.  We do not want to
// have to do too large a search to update everything, which may not be
// possible, do we give up if we see any instruction that might be hard to
// update.

class CopyPropagateArrays : public MemPass {
 public:
  const char* name() const override { return "copy-propagate-arrays"; }
  Status Process() override;

  IRContext::Analysis GetPreservedAnalyses() override {
    return IRContext::kAnalysisDefUse | IRContext::kAnalysisCFG |
           IRContext::kAnalysisInstrToBlockMapping |
           IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisDecorations |
           IRContext::kAnalysisDominatorAnalysis | IRContext::kAnalysisNameMap;
  }

 private:
  // The class used to identify a particular memory object.  This memory object
  // will be owned by a particular variable, meaning that the memory is part of
  // that variable.  It could be the entire variable or a member of the
  // variable.
  class MemoryObject {
   public:
    // Construction a memory object that is owned by |var_inst|.  The iterator
    // |begin| and |end| traverse a container of integers that identify which
    // member of |var_inst| this memory object will represent.  These integers
    // are interpreted the same way they would be in an |OpAccessChain|
    // instruction.
    template <class iterator>
    MemoryObject(Instruction* var_inst, iterator begin, iterator end);

    // Change |this| to now point to the member identified by |access_chain|
    // (starting from the current member).  The elements in |access_chain| are
    // interpreted the same as the indices in the |OpAccessChain|
    // instruction.
    void GetMember(const std::vector<uint32_t>& access_chain);

    // Change |this| to now represent the first enclosing object to which it
    // belongs.  (Remove the last element off the access_chain). It is invalid
    // to call this function if |this| does not represent a member of its owner.
    void GetParent() {
      assert(IsMember());
      access_chain_.pop_back();
    }

    // Returns true if |this| represents a member of its owner, and not the
    // entire variable.
    bool IsMember() const { return !access_chain_.empty(); }

    // Returns the number of members in the object represented by |this|.  If
    // |this| does not represent a composite type, the return value will be 0.
    uint32_t GetNumberOfMembers();

    // Returns the owning variable that the memory object is contained in.
    Instruction* GetVariable() const { return variable_inst_; }

    // Returns a vector of integers that can be used to access the specific
    // member that |this| represents starting from the owning variable.  These
    // values are to be interpreted the same way the indices are in an
    // |OpAccessChain| instruction.
    const std::vector<uint32_t>& AccessChain() const { return access_chain_; }

    // Returns the type id of the pointer type that can be used to point to this
    // memory object.
    uint32_t GetPointerTypeId(const CopyPropagateArrays* pass) const {
      analysis::DefUseManager* def_use_mgr =
          GetVariable()->context()->get_def_use_mgr();
      analysis::TypeManager* type_mgr =
          GetVariable()->context()->get_type_mgr();

      Instruction* var_pointer_inst =
          def_use_mgr->GetDef(GetVariable()->type_id());

      uint32_t member_type_id = pass->GetMemberTypeId(
          var_pointer_inst->GetSingleWordInOperand(1), GetAccessIds());

      uint32_t member_pointer_type_id = type_mgr->FindPointerToType(
          member_type_id, static_cast<SpvStorageClass>(
                              var_pointer_inst->GetSingleWordInOperand(0)));
      return member_pointer_type_id;
    }

    // Returns the storage class of the memory object.
    SpvStorageClass GetStorageClass() const {
      analysis::TypeManager* type_mgr =
          GetVariable()->context()->get_type_mgr();
      const analysis::Pointer* pointer_type =
          type_mgr->GetType(GetVariable()->type_id())->AsPointer();
      return pointer_type->storage_class();
    }

    // Returns true if |other| represents memory that is contains inside of the
    // memory represented by |this|.
    bool Contains(MemoryObject* other);

   private:
    // The variable that owns this memory object.
    Instruction* variable_inst_;

    // The access chain to reach the particular member the memory object
    // represents.  It should be interpreted the same way the indices in an
    // |OpAccessChain| are interpreted.
    std::vector<uint32_t> access_chain_;
    std::vector<uint32_t> GetAccessIds() const;
  };

  // Returns the memory object being stored to |var_inst| in the store
  // instruction |store_inst|, if one exists, that can be used in place of
  // |var_inst| in all of the loads of |var_inst|.  This code is conservative
  // and only identifies very simple cases.  If no such memory object can be
  // found, the return value is |nullptr|.
  std::unique_ptr<CopyPropagateArrays::MemoryObject> FindSourceObjectIfPossible(
      Instruction* var_inst, Instruction* store_inst);

  // Replaces all loads of |var_inst| with a load from |source| instead.
  // |insertion_pos| is a position where it is possible to construct the
  // address of |source| and also dominates all of the loads of |var_inst|.
  void PropagateObject(Instruction* var_inst, MemoryObject* source,
                       Instruction* insertion_pos);

  // Returns true if all of the references to |ptr_inst| can be rewritten and
  // are dominated by |store_inst|.
  bool HasValidReferencesOnly(Instruction* ptr_inst, Instruction* store_inst);

  // Returns a memory object that at one time was equivalent to the value in
  // |result|.  If no such memory object exists, the return value is |nullptr|.
  std::unique_ptr<MemoryObject> GetSourceObjectIfAny(uint32_t result);

  // Returns the memory object that is loaded by |load_inst|.  If a memory
  // object cannot be identified, the return value is |nullptr|.  The opcode of
  // |load_inst| must be |OpLoad|.
  std::unique_ptr<MemoryObject> BuildMemoryObjectFromLoad(
      Instruction* load_inst);

  // Returns the memory object that at some point was equivalent to the result
  // of |extract_inst|.  If a memory object cannot be identified, the return
  // value is |nullptr|.  The opcode of |extract_inst| must be
  // |OpCompositeExtract|.
  std::unique_ptr<MemoryObject> BuildMemoryObjectFromExtract(
      Instruction* extract_inst);

  // Returns the memory object that at some point was equivalent to the result
  // of |construct_inst|.  If a memory object cannot be identified, the return
  // value is |nullptr|.  The opcode of |constuct_inst| must be
  // |OpCompositeConstruct|.
  std::unique_ptr<MemoryObject> BuildMemoryObjectFromCompositeConstruct(
      Instruction* conststruct_inst);

  // Returns the memory object that at some point was equivalent to the result
  // of |insert_inst|.  If a memory object cannot be identified, the return
  // value is |nullptr\.  The opcode of |insert_inst| must be
  // |OpCompositeInsert|.  This function looks for a series of
  // |OpCompositeInsert| instructions that insert the elements one at a time in
  // order from beginning to end.
  std::unique_ptr<MemoryObject> BuildMemoryObjectFromInsert(
      Instruction* insert_inst);

  // Return true if |type_id| is a pointer type whose pointee type is an array.
  bool IsPointerToArrayType(uint32_t type_id);

  // Returns true of there are not stores using |ptr_inst| or something derived
  // from it.
  bool HasNoStores(Instruction* ptr_inst);

  // Creates an |OpAccessChain| instruction whose result is a pointer the memory
  // represented by |source|.  The new instruction will be placed before
  // |insertion_point|.  |insertion_point| must be part of a function.  Returns
  // the new instruction.
  Instruction* BuildNewAccessChain(Instruction* insertion_point,
                                   MemoryObject* source) const;

  // Rewrites all uses of |original_ptr| to use |new_pointer_inst| updating
  // types of other instructions as needed.  This function should not be called
  // if |CanUpdateUses(original_ptr_inst, new_pointer_inst->type_id())| returns
  // false.
  void UpdateUses(Instruction* original_ptr_inst,
                  Instruction* new_pointer_inst);

  // Return true if |UpdateUses| is able to change all of the uses of
  // |original_ptr_inst| to |type_id| and still have valid code.
  bool CanUpdateUses(Instruction* original_ptr_inst, uint32_t type_id);

  // Returns the id whose value is the same as |object_to_copy| except its type
  // is |new_type_id|.  Any instructions need to generate this value will be
  // inserted before |insertion_position|.
  uint32_t GenerateCopy(Instruction* object_to_copy, uint32_t new_type_id,
                        Instruction* insertion_position);

  // Returns a store to |var_inst| that writes to the entire variable, and is
  // the only store that does so.  Note it does not look through OpAccessChain
  // instruction, so partial stores are not considered.
  Instruction* FindStoreInstruction(const Instruction* var_inst) const;

  // Return the type id of the member of the type |id| access using
  // |access_chain|. The elements of |access_chain| are to be interpreted the
  // same way the indexes are used in an |OpCompositeExtract| instruction.
  uint32_t GetMemberTypeId(uint32_t id,
                           const std::vector<uint32_t>& access_chain) const;
};

}  // namespace opt
}  // namespace spvtools

#endif  // SOURCE_OPT_COPY_PROP_ARRAYS_H_
