blob: 3bdf90f652819e80d5de4b24783dac7913f4b161 [file] [log] [blame]
Lena Djokica2901602017-09-21 13:50:52 +02001/*
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
22namespace art {
23namespace mips {
24
25class 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() {
Vladimir Markocd09e1f2017-11-24 15:02:40 +000036 MaybeRecordStat(stats_, MethodCompilationStat::kInstructionSimplificationsArch);
Lena Djokica2901602017-09-21 13:50:52 +020037 }
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
49bool 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();
Vladimir Markoca6fff82017-10-03 14:49:14 +010075 ArenaAllocator* allocator = graph->GetAllocator();
Lena Djokica2901602017-09-21 13:50:52 +020076 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 =
Vladimir Markoca6fff82017-10-03 14:49:14 +0100114 new (allocator) HIntermediateArrayAddressIndex(index, shift, kNoDexPc);
Lena Djokica2901602017-09-21 13:50:52 +0200115 access->GetBlock()->InsertInstructionBefore(address, access);
116 access->ReplaceInput(address, 1);
117 return true;
118}
119
120void InstructionSimplifierMipsVisitor::VisitArrayGet(HArrayGet* instruction) {
121 DataType::Type packed_type = instruction->GetType();
122 if (TryExtractArrayAccessIndex(instruction, instruction->GetIndex(), packed_type)) {
123 RecordSimplification();
124 }
125}
126
127void InstructionSimplifierMipsVisitor::VisitArraySet(HArraySet* instruction) {
128 DataType::Type packed_type = instruction->GetComponentType();
129 if (TryExtractArrayAccessIndex(instruction, instruction->GetIndex(), packed_type)) {
130 RecordSimplification();
131 }
132}
133
Aart Bik24773202018-04-26 10:28:51 -0700134bool InstructionSimplifierMips::Run() {
Lena Djokica2901602017-09-21 13:50:52 +0200135 InstructionSimplifierMipsVisitor visitor(graph_, codegen_, stats_);
136 visitor.VisitReversePostOrder();
Aart Bik24773202018-04-26 10:28:51 -0700137 return true;
Lena Djokica2901602017-09-21 13:50:52 +0200138}
139
140} // namespace mips
141} // namespace art