diff options
-rw-r--r-- | compiler/optimizing/builder.cc | 57 | ||||
-rw-r--r-- | compiler/optimizing/builder.h | 1 | ||||
-rw-r--r-- | compiler/optimizing/code_generator.cc | 23 | ||||
-rw-r--r-- | compiler/optimizing/code_generator.h | 1 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 13 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 13 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 13 | ||||
-rw-r--r-- | compiler/utils/x86/assembler_x86.cc | 4 | ||||
-rw-r--r-- | compiler/utils/x86/assembler_x86.h | 1 | ||||
-rw-r--r-- | test/402-optimizing-control-flow/expected.txt | 0 | ||||
-rw-r--r-- | test/402-optimizing-control-flow/info.txt | 1 | ||||
-rw-r--r-- | test/402-optimizing-control-flow/src/Main.java | 76 |
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; + } +} |