Home | History | Annotate | Download | only in optimizing
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "instruction_simplifier_mips.h"
     18 
     19 #include "arch/mips/instruction_set_features_mips.h"
     20 #include "mirror/array-inl.h"
     21 
     22 namespace art {
     23 namespace mips {
     24 
     25 class InstructionSimplifierMipsVisitor : public HGraphVisitor {
     26  public:
     27   InstructionSimplifierMipsVisitor(HGraph* graph,
     28                                    CodeGenerator* codegen,
     29                                    OptimizingCompilerStats* stats)
     30       : HGraphVisitor(graph),
     31         stats_(stats),
     32         codegen_(down_cast<CodeGeneratorMIPS*>(codegen)) {}
     33 
     34  private:
     35   void RecordSimplification() {
     36     MaybeRecordStat(stats_, MethodCompilationStat::kInstructionSimplificationsArch);
     37   }
     38 
     39   bool TryExtractArrayAccessIndex(HInstruction* access,
     40                                   HInstruction* index,
     41                                   DataType::Type packed_type);
     42   void VisitArrayGet(HArrayGet* instruction) OVERRIDE;
     43   void VisitArraySet(HArraySet* instruction) OVERRIDE;
     44 
     45   OptimizingCompilerStats* stats_;
     46   CodeGeneratorMIPS* codegen_;
     47 };
     48 
     49 bool InstructionSimplifierMipsVisitor::TryExtractArrayAccessIndex(HInstruction* access,
     50                                                                   HInstruction* index,
     51                                                                   DataType::Type packed_type) {
     52   if (codegen_->GetInstructionSetFeatures().IsR6() ||
     53       codegen_->GetInstructionSetFeatures().HasMsa()) {
     54     return false;
     55   }
     56   if (index->IsConstant() ||
     57       (index->IsBoundsCheck() && index->AsBoundsCheck()->GetIndex()->IsConstant())) {
     58     // If index is constant the whole address calculation often can be done by load/store
     59     // instructions themselves.
     60     // TODO: Treat the case with non-embeddable constants.
     61     return false;
     62   }
     63 
     64   if (packed_type != DataType::Type::kInt16 && packed_type != DataType::Type::kUint16 &&
     65       packed_type != DataType::Type::kInt32 && packed_type != DataType::Type::kInt64 &&
     66       packed_type != DataType::Type::kFloat32 && packed_type != DataType::Type::kFloat64) {
     67     return false;
     68   }
     69 
     70   if (access->IsArrayGet() && access->AsArrayGet()->IsStringCharAt()) {
     71     return false;
     72   }
     73 
     74   HGraph* graph = access->GetBlock()->GetGraph();
     75   ArenaAllocator* allocator = graph->GetAllocator();
     76   size_t component_shift = DataType::SizeShift(packed_type);
     77 
     78   bool is_extracting_beneficial = false;
     79   // It is beneficial to extract index intermediate address only if there are at least 2 users.
     80   for (const HUseListNode<HInstruction*>& use : index->GetUses()) {
     81     HInstruction* user = use.GetUser();
     82     if (user->IsArrayGet() && user != access && !user->AsArrayGet()->IsStringCharAt()) {
     83       HArrayGet* another_access = user->AsArrayGet();
     84       DataType::Type another_packed_type = another_access->GetType();
     85       size_t another_component_shift = DataType::SizeShift(another_packed_type);
     86       if (another_component_shift == component_shift) {
     87         is_extracting_beneficial = true;
     88         break;
     89       }
     90     } else if (user->IsArraySet() && user != access) {
     91       HArraySet* another_access = user->AsArraySet();
     92       DataType::Type another_packed_type = another_access->GetType();
     93       size_t another_component_shift = DataType::SizeShift(another_packed_type);
     94       if (another_component_shift == component_shift) {
     95         is_extracting_beneficial = true;
     96         break;
     97       }
     98     } else if (user->IsIntermediateArrayAddressIndex()) {
     99       HIntermediateArrayAddressIndex* another_access = user->AsIntermediateArrayAddressIndex();
    100       size_t another_component_shift = another_access->GetShift()->AsIntConstant()->GetValue();
    101       if (another_component_shift == component_shift) {
    102         is_extracting_beneficial = true;
    103         break;
    104       }
    105     }
    106   }
    107 
    108   if (!is_extracting_beneficial) {
    109     return false;
    110   }
    111 
    112   HIntConstant* shift = graph->GetIntConstant(component_shift);
    113   HIntermediateArrayAddressIndex* address =
    114       new (allocator) HIntermediateArrayAddressIndex(index, shift, kNoDexPc);
    115   access->GetBlock()->InsertInstructionBefore(address, access);
    116   access->ReplaceInput(address, 1);
    117   return true;
    118 }
    119 
    120 void InstructionSimplifierMipsVisitor::VisitArrayGet(HArrayGet* instruction) {
    121   DataType::Type packed_type = instruction->GetType();
    122   if (TryExtractArrayAccessIndex(instruction, instruction->GetIndex(), packed_type)) {
    123     RecordSimplification();
    124   }
    125 }
    126 
    127 void InstructionSimplifierMipsVisitor::VisitArraySet(HArraySet* instruction) {
    128   DataType::Type packed_type = instruction->GetComponentType();
    129   if (TryExtractArrayAccessIndex(instruction, instruction->GetIndex(), packed_type)) {
    130     RecordSimplification();
    131   }
    132 }
    133 
    134 void InstructionSimplifierMips::Run() {
    135   InstructionSimplifierMipsVisitor visitor(graph_, codegen_, stats_);
    136   visitor.VisitReversePostOrder();
    137 }
    138 
    139 }  // namespace mips
    140 }  // namespace art
    141