diff options
Diffstat (limited to 'compiler/optimizing')
| -rw-r--r-- | compiler/optimizing/code_generator.cc | 4 | ||||
| -rw-r--r-- | compiler/optimizing/constant_folding.h | 6 | ||||
| -rw-r--r-- | compiler/optimizing/constant_folding_test.cc | 5 | ||||
| -rw-r--r-- | compiler/optimizing/dead_code_elimination.h | 6 | ||||
| -rw-r--r-- | compiler/optimizing/dead_code_elimination_test.cc | 3 | ||||
| -rw-r--r-- | compiler/optimizing/gvn.h | 10 | ||||
| -rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 19 | ||||
| -rw-r--r-- | compiler/optimizing/instruction_simplifier.h | 13 | ||||
| -rw-r--r-- | compiler/optimizing/locations.h | 8 | ||||
| -rw-r--r-- | compiler/optimizing/optimization.cc | 6 | ||||
| -rw-r--r-- | compiler/optimizing/optimization.h | 13 | ||||
| -rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 29 | ||||
| -rw-r--r-- | compiler/optimizing/register_allocator.cc | 34 | ||||
| -rw-r--r-- | compiler/optimizing/ssa_phi_elimination.h | 17 | 
14 files changed, 100 insertions, 73 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 4d71cb780a..0b593275c7 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -589,12 +589,14 @@ void CodeGenerator::SaveLiveRegisters(LocationSummary* locations) {        if (locations->RegisterContainsObject(i)) {          locations->SetStackBit(stack_offset / kVRegSize);        } +      DCHECK_LT(stack_offset, GetFrameSize() - FrameEntrySpillSize());        stack_offset += SaveCoreRegister(stack_offset, i);      }    }    for (size_t i = 0, e = GetNumberOfFloatingPointRegisters(); i < e; ++i) {      if (register_set->ContainsFloatingPointRegister(i)) { +      DCHECK_LT(stack_offset, GetFrameSize() - FrameEntrySpillSize());        stack_offset += SaveFloatingPointRegister(stack_offset, i);      }    } @@ -605,12 +607,14 @@ void CodeGenerator::RestoreLiveRegisters(LocationSummary* locations) {    size_t stack_offset = first_register_slot_in_slow_path_;    for (size_t i = 0, e = GetNumberOfCoreRegisters(); i < e; ++i) {      if (register_set->ContainsCoreRegister(i)) { +      DCHECK_LT(stack_offset, GetFrameSize() - FrameEntrySpillSize());        stack_offset += RestoreCoreRegister(stack_offset, i);      }    }    for (size_t i = 0, e = GetNumberOfFloatingPointRegisters(); i < e; ++i) {      if (register_set->ContainsFloatingPointRegister(i)) { +      DCHECK_LT(stack_offset, GetFrameSize() - FrameEntrySpillSize());        stack_offset += RestoreFloatingPointRegister(stack_offset, i);      }    } diff --git a/compiler/optimizing/constant_folding.h b/compiler/optimizing/constant_folding.h index d2acfa6973..ac00824e33 100644 --- a/compiler/optimizing/constant_folding.h +++ b/compiler/optimizing/constant_folding.h @@ -32,10 +32,10 @@ namespace art {   */  class HConstantFolding : public HOptimization {   public: -  HConstantFolding(HGraph* graph, const HGraphVisualizer& visualizer) -      : HOptimization(graph, true, kConstantFoldingPassName, visualizer) {} +  explicit HConstantFolding(HGraph* graph) +      : HOptimization(graph, true, kConstantFoldingPassName) {} -  virtual void Run() OVERRIDE; +  void Run() OVERRIDE;    static constexpr const char* kConstantFoldingPassName = "constant_folding"; diff --git a/compiler/optimizing/constant_folding_test.cc b/compiler/optimizing/constant_folding_test.cc index 856c5165a3..a56b9d9a12 100644 --- a/compiler/optimizing/constant_folding_test.cc +++ b/compiler/optimizing/constant_folding_test.cc @@ -47,8 +47,7 @@ static void TestCode(const uint16_t* data,    ASSERT_EQ(expected_before, actual_before);    x86::CodeGeneratorX86 codegen(graph); -  HGraphVisualizer visualizer(nullptr, graph, codegen, ""); -  HConstantFolding(graph, visualizer).Run(); +  HConstantFolding(graph).Run();    SSAChecker ssa_checker(&allocator, graph);    ssa_checker.Run();    ASSERT_TRUE(ssa_checker.IsValid()); @@ -60,7 +59,7 @@ static void TestCode(const uint16_t* data,    check_after_cf(graph); -  HDeadCodeElimination(graph, visualizer).Run(); +  HDeadCodeElimination(graph).Run();    ssa_checker.Run();    ASSERT_TRUE(ssa_checker.IsValid()); diff --git a/compiler/optimizing/dead_code_elimination.h b/compiler/optimizing/dead_code_elimination.h index a4446ae04d..3db2c3ff3f 100644 --- a/compiler/optimizing/dead_code_elimination.h +++ b/compiler/optimizing/dead_code_elimination.h @@ -28,10 +28,10 @@ namespace art {   */  class HDeadCodeElimination : public HOptimization {   public: -  HDeadCodeElimination(HGraph* graph, const HGraphVisualizer& visualizer) -      : HOptimization(graph, true, kDeadCodeEliminationPassName, visualizer) {} +  explicit HDeadCodeElimination(HGraph* graph) +      : HOptimization(graph, true, kDeadCodeEliminationPassName) {} -  virtual void Run() OVERRIDE; +  void Run() OVERRIDE;    static constexpr const char* kDeadCodeEliminationPassName =      "dead_code_elimination"; diff --git a/compiler/optimizing/dead_code_elimination_test.cc b/compiler/optimizing/dead_code_elimination_test.cc index 0c6807482a..5d4b9cb024 100644 --- a/compiler/optimizing/dead_code_elimination_test.cc +++ b/compiler/optimizing/dead_code_elimination_test.cc @@ -41,8 +41,7 @@ static void TestCode(const uint16_t* data,    ASSERT_EQ(actual_before, expected_before);    x86::CodeGeneratorX86 codegen(graph); -  HGraphVisualizer visualizer(nullptr, graph, codegen, ""); -  HDeadCodeElimination(graph, visualizer).Run(); +  HDeadCodeElimination(graph).Run();    SSAChecker ssa_checker(&allocator, graph);    ssa_checker.Run();    ASSERT_TRUE(ssa_checker.IsValid()); diff --git a/compiler/optimizing/gvn.h b/compiler/optimizing/gvn.h index 8d2c77475c..a841d5f65a 100644 --- a/compiler/optimizing/gvn.h +++ b/compiler/optimizing/gvn.h @@ -18,6 +18,7 @@  #define ART_COMPILER_OPTIMIZING_GVN_H_  #include "nodes.h" +#include "optimization.h"  namespace art { @@ -165,11 +166,11 @@ class ValueSet : public ArenaObject<kArenaAllocMisc> {  /**   * Optimization phase that removes redundant instruction.   */ -class GlobalValueNumberer : public ValueObject { +class GlobalValueNumberer : public HOptimization {   public:    GlobalValueNumberer(ArenaAllocator* allocator, HGraph* graph) -      : allocator_(allocator), -        graph_(graph), +      : HOptimization(graph, true, "GVN"), +        allocator_(allocator),          block_effects_(allocator, graph->GetBlocks().Size()),          loop_effects_(allocator, graph->GetBlocks().Size()),          sets_(allocator, graph->GetBlocks().Size()), @@ -186,7 +187,7 @@ class GlobalValueNumberer : public ValueObject {      }    } -  void Run(); +  void Run() OVERRIDE;   private:    // Per-block GVN. Will also update the ValueSet of the dominated and @@ -202,7 +203,6 @@ class GlobalValueNumberer : public ValueObject {    SideEffects GetBlockEffects(HBasicBlock* block) const;    ArenaAllocator* const allocator_; -  HGraph* const graph_;    // Side effects of individual blocks, that is the union of the side effects    // of the instructions in the block. diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 3e8361eca1..3d65e9a0a4 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -18,11 +18,22 @@  namespace art { +class InstructionSimplifierVisitor : public HGraphVisitor { + public: +  explicit InstructionSimplifierVisitor(HGraph* graph) : HGraphVisitor(graph) {} + + private: +  void VisitSuspendCheck(HSuspendCheck* check) OVERRIDE; +  void VisitEqual(HEqual* equal) OVERRIDE; +  void VisitArraySet(HArraySet* equal) OVERRIDE; +}; +  void InstructionSimplifier::Run() { -  VisitInsertionOrder(); +  InstructionSimplifierVisitor visitor(graph_); +  visitor.VisitInsertionOrder();  } -void InstructionSimplifier::VisitSuspendCheck(HSuspendCheck* check) { +void InstructionSimplifierVisitor::VisitSuspendCheck(HSuspendCheck* check) {    HBasicBlock* block = check->GetBlock();    // Currently always keep the suspend check at entry.    if (block->IsEntryBlock()) return; @@ -38,7 +49,7 @@ void InstructionSimplifier::VisitSuspendCheck(HSuspendCheck* check) {    block->RemoveInstruction(check);  } -void InstructionSimplifier::VisitEqual(HEqual* equal) { +void InstructionSimplifierVisitor::VisitEqual(HEqual* equal) {    HInstruction* input1 = equal->InputAt(0);    HInstruction* input2 = equal->InputAt(1);    if (input1->GetType() == Primitive::kPrimBoolean && input2->IsIntConstant()) { @@ -55,7 +66,7 @@ void InstructionSimplifier::VisitEqual(HEqual* equal) {    }  } -void InstructionSimplifier::VisitArraySet(HArraySet* instruction) { +void InstructionSimplifierVisitor::VisitArraySet(HArraySet* instruction) {    HInstruction* value = instruction->GetValue();    if (value->GetType() != Primitive::kPrimNot) return; diff --git a/compiler/optimizing/instruction_simplifier.h b/compiler/optimizing/instruction_simplifier.h index 3844d57439..7068c7fc10 100644 --- a/compiler/optimizing/instruction_simplifier.h +++ b/compiler/optimizing/instruction_simplifier.h @@ -18,22 +18,19 @@  #define ART_COMPILER_OPTIMIZING_INSTRUCTION_SIMPLIFIER_H_  #include "nodes.h" +#include "optimization.h"  namespace art {  /**   * Implements optimizations specific to each instruction.   */ -class InstructionSimplifier : public HGraphVisitor { +class InstructionSimplifier : public HOptimization {   public: -  explicit InstructionSimplifier(HGraph* graph) : HGraphVisitor(graph) {} +  explicit InstructionSimplifier(HGraph* graph) +    : HOptimization(graph, true, "instruction_simplifier") {} -  void Run(); - - private: -  virtual void VisitSuspendCheck(HSuspendCheck* check) OVERRIDE; -  virtual void VisitEqual(HEqual* equal) OVERRIDE; -  virtual void VisitArraySet(HArraySet* equal) OVERRIDE; +  void Run() OVERRIDE;  };  }  // namespace art diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h index d1555d4e11..e1c8e8ed6e 100644 --- a/compiler/optimizing/locations.h +++ b/compiler/optimizing/locations.h @@ -391,6 +391,10 @@ class RegisterSet : public ValueObject {      return (register_set & (1 << reg)) != 0;    } +  size_t GetNumberOfRegisters() const { +    return __builtin_popcount(core_registers_) + __builtin_popcount(floating_point_registers_); +  } +   private:    uint32_t core_registers_;    uint32_t floating_point_registers_; @@ -503,6 +507,10 @@ class LocationSummary : public ArenaObject<kArenaAllocMisc> {      return &live_registers_;    } +  size_t GetNumberOfLiveRegisters() const { +    return live_registers_.GetNumberOfRegisters(); +  } +    bool InputOverlapsWithOutputOrTemp(uint32_t input_index, bool is_environment) const {      if (is_environment) return true;      if ((input_index == 0) diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc index ea98186d11..d1178d5798 100644 --- a/compiler/optimizing/optimization.cc +++ b/compiler/optimizing/optimization.cc @@ -21,12 +21,6 @@  namespace art { -void HOptimization::Execute() { -  Run(); -  visualizer_.DumpGraph(pass_name_); -  Check(); -} -  void HOptimization::Check() {    if (kIsDebugBuild) {      if (is_in_ssa_form_) { diff --git a/compiler/optimizing/optimization.h b/compiler/optimizing/optimization.h index 59683e2075..d281248f4a 100644 --- a/compiler/optimizing/optimization.h +++ b/compiler/optimizing/optimization.h @@ -29,25 +29,19 @@ class HOptimization : public ValueObject {   public:    HOptimization(HGraph* graph,                  bool is_in_ssa_form, -                const char* pass_name, -                const HGraphVisualizer& visualizer) +                const char* pass_name)        : graph_(graph),          is_in_ssa_form_(is_in_ssa_form), -        pass_name_(pass_name), -        visualizer_(visualizer) {} +        pass_name_(pass_name) {}    virtual ~HOptimization() {} -  // Execute the optimization pass. -  void Execute(); -    // Return the name of the pass.    const char* GetPassName() const { return pass_name_; }    // Peform the analysis itself.    virtual void Run() = 0; - private:    // Verify the graph; abort if it is not valid.    void Check(); @@ -59,9 +53,6 @@ class HOptimization : public ValueObject {    const bool is_in_ssa_form_;    // Optimization pass name.    const char* pass_name_; -  // A graph visualiser invoked after the execution of the optimization -  // pass if enabled. -  const HGraphVisualizer& visualizer_;    DISALLOW_COPY_AND_ASSIGN(HOptimization);  }; diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 53273a4568..42ac77d1d8 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -190,6 +190,25 @@ static bool CanOptimize(const DexFile::CodeItem& code_item) {    return code_item.tries_size_ == 0;  } +static void RunOptimizations(HGraph* graph, const HGraphVisualizer& visualizer) { +  HDeadCodeElimination opt1(graph); +  HConstantFolding opt2(graph); +  SsaRedundantPhiElimination opt3(graph); +  SsaDeadPhiElimination opt4(graph); +  InstructionSimplifier opt5(graph); +  GlobalValueNumberer opt6(graph->GetArena(), graph); +  InstructionSimplifier opt7(graph); + +  HOptimization* optimizations[] = { &opt1, &opt2, &opt3, &opt4, &opt5, &opt6, &opt7 }; + +  for (size_t i = 0; i < arraysize(optimizations); ++i) { +    HOptimization* optimization = optimizations[i]; +    optimization->Run(); +    optimization->Check(); +    visualizer.DumpGraph(optimization->GetPassName()); +  } +} +  CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,                                              uint32_t access_flags,                                              InvokeType invoke_type, @@ -257,17 +276,9 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,      visualizer.DumpGraph("ssa");      graph->FindNaturalLoops(); -    HDeadCodeElimination(graph, visualizer).Execute(); -    HConstantFolding(graph, visualizer).Execute(); +    RunOptimizations(graph, visualizer); -    SsaRedundantPhiElimination(graph).Run(); -    SsaDeadPhiElimination(graph).Run(); -    InstructionSimplifier(graph).Run(); -    GlobalValueNumberer(graph->GetArena(), graph).Run(); -    visualizer.DumpGraph(kGVNPassName); -    InstructionSimplifier(graph).Run();      PrepareForRegisterAllocation(graph).Run(); -      SsaLivenessAnalysis liveness(*graph, codegen);      liveness.Analyze();      visualizer.DumpGraph(kLivenessPassName); diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc index 4d6e66413d..2948496e15 100644 --- a/compiler/optimizing/register_allocator.cc +++ b/compiler/optimizing/register_allocator.cc @@ -215,9 +215,16 @@ void RegisterAllocator::ProcessInstruction(HInstruction* instruction) {        // By adding the following interval in the algorithm, we can compute this        // maximum before updating locations.        LiveInterval* interval = LiveInterval::MakeSlowPathInterval(allocator_, instruction); -      interval->AddRange(position, position + 1); -      unhandled_core_intervals_.Add(interval); -      unhandled_fp_intervals_.Add(interval); +      // The start of the interval must be after the position of the safepoint, so that +      // we can just check the number of active registers at that position. Note that this +      // will include the current interval in the computation of +      // `maximum_number_of_live_registers`, so we need a better strategy if this becomes +      // a problem. +      // TODO: We could put the logic in AddSorted, to ensure the safepoint range is +      // after all other intervals starting at that same position. +      interval->AddRange(position + 1, position + 2); +      AddSorted(&unhandled_core_intervals_, interval); +      AddSorted(&unhandled_fp_intervals_, interval);      }    } @@ -250,6 +257,7 @@ void RegisterAllocator::ProcessInstruction(HInstruction* instruction) {        : unhandled_fp_intervals_;    DCHECK(unhandled.IsEmpty() || current->StartsBeforeOrAt(unhandled.Peek())); +    // Some instructions define their output in fixed register/stack slot. We need    // to ensure we know these locations before doing register allocation. For a    // given register, we create an interval that covers these locations. The register @@ -475,6 +483,17 @@ void RegisterAllocator::LinearScan() {      LiveInterval* current = unhandled_->Pop();      DCHECK(!current->IsFixed() && !current->HasSpillSlot());      DCHECK(unhandled_->IsEmpty() || unhandled_->Peek()->GetStart() >= current->GetStart()); + +    if (current->IsSlowPathSafepoint()) { +      // Synthesized interval to record the maximum number of live registers +      // at safepoints. No need to allocate a register for it. +      // We know that current actives are all live at the safepoint (modulo +      // the one created by the safepoint). +      maximum_number_of_live_registers_ = +          std::max(maximum_number_of_live_registers_, active_.Size()); +      continue; +    } +      size_t position = current->GetStart();      // Remember the inactive_ size here since the ones moved to inactive_ from @@ -515,14 +534,6 @@ void RegisterAllocator::LinearScan() {        }      } -    if (current->IsSlowPathSafepoint()) { -      // Synthesized interval to record the maximum number of live registers -      // at safepoints. No need to allocate a register for it. -      maximum_number_of_live_registers_ = -          std::max(maximum_number_of_live_registers_, active_.Size()); -      continue; -    } -      // (4) Try to find an available register.      bool success = TryAllocateFreeReg(current); @@ -1062,6 +1073,7 @@ void RegisterAllocator::ConnectSiblings(LiveInterval* interval) {        switch (source.GetKind()) {          case Location::kRegister: {            locations->AddLiveRegister(source); +          DCHECK_LE(locations->GetNumberOfLiveRegisters(), maximum_number_of_live_registers_);            if (current->GetType() == Primitive::kPrimNot) {              locations->SetRegisterBit(source.reg());            } diff --git a/compiler/optimizing/ssa_phi_elimination.h b/compiler/optimizing/ssa_phi_elimination.h index 5274f09f3f..b7899712d6 100644 --- a/compiler/optimizing/ssa_phi_elimination.h +++ b/compiler/optimizing/ssa_phi_elimination.h @@ -18,6 +18,7 @@  #define ART_COMPILER_OPTIMIZING_SSA_PHI_ELIMINATION_H_  #include "nodes.h" +#include "optimization.h"  namespace art { @@ -25,15 +26,15 @@ namespace art {   * Optimization phase that removes dead phis from the graph. Dead phis are unused   * phis, or phis only used by other phis.   */ -class SsaDeadPhiElimination : public ValueObject { +class SsaDeadPhiElimination : public HOptimization {   public:    explicit SsaDeadPhiElimination(HGraph* graph) -      : graph_(graph), worklist_(graph->GetArena(), kDefaultWorklistSize) {} +      : HOptimization(graph, true, "dead_phi_elimination"), +        worklist_(graph->GetArena(), kDefaultWorklistSize) {} -  void Run(); +  void Run() OVERRIDE;   private: -  HGraph* const graph_;    GrowableArray<HPhi*> worklist_;    static constexpr size_t kDefaultWorklistSize = 8; @@ -47,15 +48,15 @@ class SsaDeadPhiElimination : public ValueObject {   * registers might be updated with the same value, or not updated at all. We can just   * replace the phi with the value when entering the loop.   */ -class SsaRedundantPhiElimination : public ValueObject { +class SsaRedundantPhiElimination : public HOptimization {   public:    explicit SsaRedundantPhiElimination(HGraph* graph) -      : graph_(graph), worklist_(graph->GetArena(), kDefaultWorklistSize) {} +      : HOptimization(graph, true, "redundant_phi_elimination"), +        worklist_(graph->GetArena(), kDefaultWorklistSize) {} -  void Run(); +  void Run() OVERRIDE;   private: -  HGraph* const graph_;    GrowableArray<HPhi*> worklist_;    static constexpr size_t kDefaultWorklistSize = 8;  |