summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/builder.cc57
-rw-r--r--compiler/optimizing/builder.h1
-rw-r--r--compiler/optimizing/code_generator.cc23
-rw-r--r--compiler/optimizing/code_generator.h1
-rw-r--r--compiler/optimizing/code_generator_arm.cc13
-rw-r--r--compiler/optimizing/code_generator_x86.cc13
-rw-r--r--compiler/optimizing/nodes.h13
-rw-r--r--compiler/utils/x86/assembler_x86.cc4
-rw-r--r--compiler/utils/x86/assembler_x86.h1
-rw-r--r--test/402-optimizing-control-flow/expected.txt0
-rw-r--r--test/402-optimizing-control-flow/info.txt1
-rw-r--r--test/402-optimizing-control-flow/src/Main.java76
12 files changed, 164 insertions, 39 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index f89583d..beccf01 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -44,15 +44,14 @@ bool HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) {
graph_->SetNumberOfInVRegs(number_of_parameters);
const char* shorty = dex_compilation_unit_->GetShorty();
int locals_index = locals_.Size() - number_of_parameters;
- HBasicBlock* first_block = entry_block_->GetSuccessors()->Get(0);
int parameter_index = 0;
if (!dex_compilation_unit_->IsStatic()) {
// Add the implicit 'this' argument, not expressed in the signature.
HParameterValue* parameter = new (arena_) HParameterValue(parameter_index++);
- first_block->AddInstruction(parameter);
+ entry_block_->AddInstruction(parameter);
HLocal* local = GetLocalAt(locals_index++);
- first_block->AddInstruction(new (arena_) HStoreLocal(local, parameter));
+ entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter));
number_of_parameters--;
}
@@ -68,11 +67,11 @@ bool HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) {
default: {
// integer and reference parameters.
HParameterValue* parameter = new (arena_) HParameterValue(parameter_index++);
- first_block->AddInstruction(parameter);
+ entry_block_->AddInstruction(parameter);
HLocal* local = GetLocalAt(locals_index++);
// Store the parameter value in the local that the dex code will use
// to reference that parameter.
- first_block->AddInstruction(new (arena_) HStoreLocal(local, parameter));
+ entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter));
break;
}
}
@@ -87,6 +86,24 @@ static bool CanHandleCodeItem(const DexFile::CodeItem& code_item) {
return true;
}
+template<typename T>
+void HGraphBuilder::If_22t(const Instruction& instruction, int32_t dex_offset, bool is_not) {
+ HInstruction* first = LoadLocal(instruction.VRegA());
+ HInstruction* second = LoadLocal(instruction.VRegB());
+ current_block_->AddInstruction(new (arena_) T(first, second));
+ if (is_not) {
+ current_block_->AddInstruction(new (arena_) HNot(current_block_->GetLastInstruction()));
+ }
+ current_block_->AddInstruction(new (arena_) HIf(current_block_->GetLastInstruction()));
+ HBasicBlock* target = FindBlockStartingAt(instruction.GetTargetOffset() + dex_offset);
+ DCHECK(target != nullptr);
+ current_block_->AddSuccessor(target);
+ target = FindBlockStartingAt(dex_offset + instruction.SizeInCodeUnits());
+ DCHECK(target != nullptr);
+ current_block_->AddSuccessor(target);
+ current_block_ = nullptr;
+}
+
HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
if (!CanHandleCodeItem(code_item)) {
return nullptr;
@@ -238,6 +255,19 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_
break;
}
+ case Instruction::CONST_16: {
+ int32_t register_index = instruction.VRegA();
+ HIntConstant* constant = GetConstant(instruction.VRegB_21s());
+ UpdateLocal(register_index, constant);
+ break;
+ }
+
+ case Instruction::MOVE: {
+ HInstruction* value = LoadLocal(instruction.VRegB());
+ UpdateLocal(instruction.VRegA(), value);
+ break;
+ }
+
case Instruction::RETURN_VOID: {
current_block_->AddInstruction(new (arena_) HReturnVoid());
current_block_->AddSuccessor(exit_block_);
@@ -246,17 +276,12 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_
}
case Instruction::IF_EQ: {
- HInstruction* first = LoadLocal(instruction.VRegA());
- HInstruction* second = LoadLocal(instruction.VRegB());
- current_block_->AddInstruction(new (arena_) HEqual(first, second));
- current_block_->AddInstruction(new (arena_) HIf(current_block_->GetLastInstruction()));
- HBasicBlock* target = FindBlockStartingAt(instruction.GetTargetOffset() + dex_offset);
- DCHECK(target != nullptr);
- current_block_->AddSuccessor(target);
- target = FindBlockStartingAt(dex_offset + instruction.SizeInCodeUnits());
- DCHECK(target != nullptr);
- current_block_->AddSuccessor(target);
- current_block_ = nullptr;
+ If_22t<HEqual>(instruction, dex_offset, false);
+ break;
+ }
+
+ case Instruction::IF_NE: {
+ If_22t<HEqual>(instruction, dex_offset, true);
break;
}
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h
index df64d71..60d9982 100644
--- a/compiler/optimizing/builder.h
+++ b/compiler/optimizing/builder.h
@@ -79,6 +79,7 @@ class HGraphBuilder : public ValueObject {
template<typename T> void Binop_12x(const Instruction& instruction);
template<typename T> void Binop_22b(const Instruction& instruction, bool reverse);
template<typename T> void Binop_22s(const Instruction& instruction, bool reverse);
+ template<typename T> void If_22t(const Instruction& instruction, int32_t dex_offset, bool is_not);
ArenaAllocator* const arena_;
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 40a7b6f..7e63c69 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -33,8 +33,8 @@ void CodeGenerator::Compile(CodeAllocator* allocator) {
const GrowableArray<HBasicBlock*>* blocks = GetGraph()->GetBlocks();
DCHECK(blocks->Get(0) == GetGraph()->GetEntryBlock());
DCHECK(GoesToNextBlock(GetGraph()->GetEntryBlock(), blocks->Get(1)));
- CompileEntryBlock();
- for (size_t i = 1; i < blocks->Size(); i++) {
+ GenerateFrameEntry();
+ for (size_t i = 0; i < blocks->Size(); i++) {
CompileBlock(blocks->Get(i));
}
size_t code_size = GetAssembler()->CodeSize();
@@ -43,30 +43,11 @@ void CodeGenerator::Compile(CodeAllocator* allocator) {
GetAssembler()->FinalizeInstructions(code);
}
-void CodeGenerator::CompileEntryBlock() {
- HGraphVisitor* location_builder = GetLocationBuilder();
- HGraphVisitor* instruction_visitor = GetInstructionVisitor();
- if (kIsDebugBuild) {
- for (HInstructionIterator it(GetGraph()->GetEntryBlock()); !it.Done(); it.Advance()) {
- HInstruction* current = it.Current();
- // Instructions in the entry block should not generate code.
- current->Accept(location_builder);
- DCHECK(current->GetLocations() == nullptr);
- current->Accept(instruction_visitor);
- }
- }
- GenerateFrameEntry();
-}
-
void CodeGenerator::CompileBlock(HBasicBlock* block) {
Bind(GetLabelOf(block));
HGraphVisitor* location_builder = GetLocationBuilder();
HGraphVisitor* instruction_visitor = GetInstructionVisitor();
for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
- // For each instruction, we emulate a stack-based machine, where the inputs are popped from
- // the runtime stack, and the result is pushed on the stack. We currently can do this because
- // we do not perform any code motion, and the Dex format does not reference individual
- // instructions but uses registers instead (our equivalent of HLocal).
HInstruction* current = it.Current();
current->Accept(location_builder);
InitLocations(current);
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index e144733..6648598 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -180,7 +180,6 @@ class CodeGenerator : public ArenaObject {
private:
void InitLocations(HInstruction* instruction);
void CompileBlock(HBasicBlock* block);
- void CompileEntryBlock();
HGraph* const graph_;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 2364bc8..4e88765 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -149,7 +149,6 @@ void LocationsBuilderARM::VisitLocal(HLocal* local) {
void InstructionCodeGeneratorARM::VisitLocal(HLocal* local) {
DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
- codegen_->SetFrameSize(codegen_->GetFrameSize() + kArmWordSize);
}
void LocationsBuilderARM::VisitLoadLocal(HLoadLocal* load) {
@@ -384,5 +383,17 @@ void InstructionCodeGeneratorARM::VisitParameterValue(HParameterValue* instructi
}
}
+void LocationsBuilderARM::VisitNot(HNot* instruction) {
+ LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ locations->SetInAt(0, Location(R0));
+ locations->SetOut(Location(R0));
+ instruction->SetLocations(locations);
+}
+
+void InstructionCodeGeneratorARM::VisitNot(HNot* instruction) {
+ LocationSummary* locations = instruction->GetLocations();
+ __ eor(locations->Out().reg<Register>(), locations->InAt(0).reg<Register>(), ShifterOperand(1));
+}
+
} // namespace arm
} // namespace art
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 540a72a..88198dc 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -379,5 +379,18 @@ void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instructi
}
}
+void LocationsBuilderX86::VisitNot(HNot* instruction) {
+ LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ locations->SetInAt(0, Location(EAX));
+ locations->SetOut(Location(EAX));
+ instruction->SetLocations(locations);
+}
+
+void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
+ LocationSummary* locations = instruction->GetLocations();
+ DCHECK_EQ(locations->InAt(0).reg<Register>(), locations->Out().reg<Register>());
+ __ xorl(locations->Out().reg<Register>(), Immediate(1));
+}
+
} // namespace x86
} // namespace art
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index d1f672f..adea0ba 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -227,6 +227,7 @@ class HBasicBlock : public ArenaObject {
M(LoadLocal) \
M(Local) \
M(NewInstance) \
+ M(Not) \
M(ParameterValue) \
M(PushArgument) \
M(Return) \
@@ -740,6 +741,18 @@ class HParameterValue : public HTemplateInstruction<0> {
DISALLOW_COPY_AND_ASSIGN(HParameterValue);
};
+class HNot : public HTemplateInstruction<1> {
+ public:
+ explicit HNot(HInstruction* input) {
+ SetRawInputAt(0, input);
+ }
+
+ DECLARE_INSTRUCTION(Not);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HNot);
+};
+
class HGraphVisitor : public ValueObject {
public:
explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index 6043c17..6a3efc5 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -863,6 +863,10 @@ void X86Assembler::xorl(Register dst, Register src) {
EmitOperand(dst, Operand(src));
}
+void X86Assembler::xorl(Register dst, const Immediate& imm) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitComplex(6, Operand(dst), imm);
+}
void X86Assembler::addl(Register reg, const Immediate& imm) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index f8fc4c0..057c80a 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -354,6 +354,7 @@ class X86Assembler FINAL : public Assembler {
void orl(Register dst, Register src);
void xorl(Register dst, Register src);
+ void xorl(Register dst, const Immediate& imm);
void addl(Register dst, Register src);
void addl(Register reg, const Immediate& imm);
diff --git a/test/402-optimizing-control-flow/expected.txt b/test/402-optimizing-control-flow/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/402-optimizing-control-flow/expected.txt
diff --git a/test/402-optimizing-control-flow/info.txt b/test/402-optimizing-control-flow/info.txt
new file mode 100644
index 0000000..37d9458
--- /dev/null
+++ b/test/402-optimizing-control-flow/info.txt
@@ -0,0 +1 @@
+A set of tests for testing control flow instructions on the optimizing compiler.
diff --git a/test/402-optimizing-control-flow/src/Main.java b/test/402-optimizing-control-flow/src/Main.java
new file mode 100644
index 0000000..3339ef4
--- /dev/null
+++ b/test/402-optimizing-control-flow/src/Main.java
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+// Note that $opt$ is a marker for the optimizing compiler to ensure
+// it does compile the method.
+
+public class Main {
+
+ public static void expectEquals(int expected, int value) {
+ if (expected != value) {
+ throw new Error("Expected: " + expected + ", found: " + value);
+ }
+ }
+
+ public static void main(String[] args) {
+ int result = $opt$testIfEq1(42);
+ expectEquals(42, result);
+
+ result = $opt$testIfEq2(42);
+ expectEquals(7, result);
+
+ result = $opt$testWhileLoop(42);
+ expectEquals(45, result);
+
+ result = $opt$testDoWhileLoop(42);
+ expectEquals(45, result);
+
+ result = $opt$testForLoop(42);
+ expectEquals(44, result);
+ }
+
+ static int $opt$testIfEq1(int a) {
+ if (a + 1 == 43) {
+ return 42;
+ } else {
+ return 7;
+ }
+ }
+
+ static int $opt$testIfEq2(int a) {
+ if (a + 1 == 41) {
+ return 42;
+ } else {
+ return 7;
+ }
+ }
+
+ static int $opt$testWhileLoop(int a) {
+ while (a++ != 44) {}
+ return a;
+ }
+
+ static int $opt$testDoWhileLoop(int a) {
+ do {
+ } while (a++ != 44);
+ return a;
+ }
+
+ static int $opt$testForLoop(int a) {
+ for (; a != 44; a++) {}
+ return a;
+ }
+}