/*
 * Copyright (C) 2014 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_SSA_BUILDER_H_
#define ART_COMPILER_OPTIMIZING_SSA_BUILDER_H_

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

namespace art {

/**
 * Transforms a graph into SSA form. The liveness guarantees of
 * this transformation are listed below. A DEX register
 * being killed means its value at a given position in the code
 * will not be available to its environment uses. A merge in the
 * following text is materialized as a `HPhi`.
 *
 * (a) Dex registers that do not require merging (that is, they do not
 *     have different values at a join block) are available to all their
 *     environment uses. Note that it does not imply the instruction will
 *     have a physical location after register allocation. See the
 *     SsaLivenessAnalysis phase.
 *
 * (b) Dex registers that require merging, and the merging gives
 *     incompatible types, will be killed for environment uses of that merge.
 *
 * (c) When the `debuggable` flag is passed to the compiler, Dex registers
 *     that require merging and have a proper type after the merge, are
 *     available to all their environment uses. If the `debuggable` flag
 *     is not set, values of Dex registers only used by environments
 *     are killed.
 */
class SsaBuilder : public ValueObject {
 public:
  SsaBuilder(HGraph* graph,
             Handle<mirror::ClassLoader> class_loader,
             Handle<mirror::DexCache> dex_cache,
             VariableSizedHandleScope* handles,
             ScopedArenaAllocator* local_allocator)
      : graph_(graph),
        class_loader_(class_loader),
        dex_cache_(dex_cache),
        handles_(handles),
        agets_fixed_(false),
        local_allocator_(local_allocator),
        ambiguous_agets_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
        ambiguous_asets_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
        uninitialized_strings_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
        uninitialized_string_phis_(local_allocator->Adapter(kArenaAllocGraphBuilder)) {
    graph_->InitializeInexactObjectRTI(handles);
  }

  GraphAnalysisResult BuildSsa();

  HInstruction* GetFloatOrDoubleEquivalent(HInstruction* instruction, DataType::Type type);
  HInstruction* GetReferenceTypeEquivalent(HInstruction* instruction);

  void MaybeAddAmbiguousArrayGet(HArrayGet* aget) {
    DataType::Type type = aget->GetType();
    DCHECK(!DataType::IsFloatingPointType(type));
    if (DataType::IsIntOrLongType(type)) {
      ambiguous_agets_.push_back(aget);
    }
  }

  void MaybeAddAmbiguousArraySet(HArraySet* aset) {
    DataType::Type type = aset->GetValue()->GetType();
    if (DataType::IsIntOrLongType(type)) {
      ambiguous_asets_.push_back(aset);
    }
  }

  void AddUninitializedString(HNewInstance* string) {
    // In some rare cases (b/27847265), the same NewInstance may be seen
    // multiple times. We should only consider it once for removal, so we
    // ensure it is not added more than once.
    // Note that we cannot check whether this really is a NewInstance of String
    // before RTP. We DCHECK that in RemoveRedundantUninitializedStrings.
    if (!ContainsElement(uninitialized_strings_, string)) {
      uninitialized_strings_.push_back(string);
    }
  }

  void AddUninitializedStringPhi(HPhi* phi, HInvoke* invoke) {
    uninitialized_string_phis_.push_back(std::make_pair(phi, invoke));
  }

 private:
  void SetLoopHeaderPhiInputs();
  void FixEnvironmentPhis();
  void FixNullConstantType();
  void EquivalentPhisCleanup();
  void RunPrimitiveTypePropagation();

  // Attempts to resolve types of aget(-wide) instructions and type values passed
  // to aput(-wide) instructions from reference type information on the array
  // input. Returns false if the type of an array is unknown.
  bool FixAmbiguousArrayOps();

  bool TypeInputsOfPhi(HPhi* phi, ScopedArenaVector<HPhi*>* worklist);
  bool UpdatePrimitiveType(HPhi* phi, ScopedArenaVector<HPhi*>* worklist);
  void ProcessPrimitiveTypePropagationWorklist(ScopedArenaVector<HPhi*>* worklist);

  HFloatConstant* GetFloatEquivalent(HIntConstant* constant);
  HDoubleConstant* GetDoubleEquivalent(HLongConstant* constant);
  HPhi* GetFloatDoubleOrReferenceEquivalentOfPhi(HPhi* phi, DataType::Type type);
  HArrayGet* GetFloatOrDoubleEquivalentOfArrayGet(HArrayGet* aget);

  void RemoveRedundantUninitializedStrings();
  void ReplaceUninitializedStringPhis();

  HGraph* const graph_;
  Handle<mirror::ClassLoader> class_loader_;
  Handle<mirror::DexCache> dex_cache_;
  VariableSizedHandleScope* const handles_;

  // True if types of ambiguous ArrayGets have been resolved.
  bool agets_fixed_;

  ScopedArenaAllocator* const local_allocator_;
  ScopedArenaVector<HArrayGet*> ambiguous_agets_;
  ScopedArenaVector<HArraySet*> ambiguous_asets_;
  ScopedArenaVector<HNewInstance*> uninitialized_strings_;
  ScopedArenaVector<std::pair<HPhi*, HInvoke*>> uninitialized_string_phis_;

  DISALLOW_COPY_AND_ASSIGN(SsaBuilder);
};

}  // namespace art

#endif  // ART_COMPILER_OPTIMIZING_SSA_BUILDER_H_
