diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2015-03-23 16:44:35 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2015-03-23 16:44:36 +0000 |
commit | 5af26bd446660bc5d13dd6ff9470e6920a51e26e (patch) | |
tree | a7a8ffcef09783b7ca91c70aa90e48efaf650b38 /compiler/optimizing | |
parent | af2bec33e5f124e37e9dbbe0fef1261411bd372d (diff) | |
parent | 2d35d9d7490ef3880ee366ccbf8f6e791f398c47 (diff) | |
download | art-5af26bd446660bc5d13dd6ff9470e6920a51e26e.tar.gz art-5af26bd446660bc5d13dd6ff9470e6920a51e26e.tar.bz2 art-5af26bd446660bc5d13dd6ff9470e6920a51e26e.zip |
Merge "Opt Compiler: Materialise constants that cannot be encoded"
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/code_generator_arm64.cc | 9 | ||||
-rw-r--r-- | compiler/optimizing/common_arm64.h | 34 |
2 files changed, 39 insertions, 4 deletions
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index aeec5dd1c4..99283a0056 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -63,6 +63,7 @@ using helpers::StackOperandFrom; using helpers::VIXLRegCodeFromART; using helpers::WRegisterFrom; using helpers::XRegisterFrom; +using helpers::ARM64EncodableConstantOrRegister; static constexpr size_t kHeapRefSize = sizeof(mirror::HeapReference<mirror::Object>); static constexpr int kCurrentMethodStackOffset = 0; @@ -1106,7 +1107,7 @@ void LocationsBuilderARM64::HandleBinaryOp(HBinaryOperation* instr) { case Primitive::kPrimInt: case Primitive::kPrimLong: locations->SetInAt(0, Location::RequiresRegister()); - locations->SetInAt(1, Location::RegisterOrConstant(instr->InputAt(1))); + locations->SetInAt(1, ARM64EncodableConstantOrRegister(instr->InputAt(1), instr)); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; @@ -1398,7 +1399,7 @@ void LocationsBuilderARM64::VisitCompare(HCompare* compare) { switch (in_type) { case Primitive::kPrimLong: { locations->SetInAt(0, Location::RequiresRegister()); - locations->SetInAt(1, Location::RegisterOrConstant(compare->InputAt(1))); + locations->SetInAt(1, ARM64EncodableConstantOrRegister(compare->InputAt(1), compare)); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } @@ -1468,7 +1469,7 @@ void InstructionCodeGeneratorARM64::VisitCompare(HCompare* compare) { void LocationsBuilderARM64::VisitCondition(HCondition* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); locations->SetInAt(0, Location::RequiresRegister()); - locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); + locations->SetInAt(1, ARM64EncodableConstantOrRegister(instruction->InputAt(1), instruction)); if (instruction->NeedsMaterialization()) { locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); } @@ -2116,7 +2117,7 @@ void LocationsBuilderARM64::VisitNeg(HNeg* neg) { switch (neg->GetResultType()) { case Primitive::kPrimInt: case Primitive::kPrimLong: - locations->SetInAt(0, Location::RegisterOrConstant(neg->InputAt(0))); + locations->SetInAt(0, ARM64EncodableConstantOrRegister(neg->InputAt(0), neg)); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; diff --git a/compiler/optimizing/common_arm64.h b/compiler/optimizing/common_arm64.h index 9447d3b816..fd8c0c6242 100644 --- a/compiler/optimizing/common_arm64.h +++ b/compiler/optimizing/common_arm64.h @@ -183,6 +183,40 @@ static inline vixl::Operand OperandFromMemOperand(const vixl::MemOperand& mem_op } } +static bool CanEncodeConstantAsImmediate(HConstant* constant, HInstruction* instr) { + DCHECK(constant->IsIntConstant() || constant->IsLongConstant() || constant->IsNullConstant()); + + // For single uses we let VIXL handle the constant generation since it will + // use registers that are not managed by the register allocator (wip0, wip1). + if (constant->GetUses().HasOnlyOneUse()) { + return true; + } + + int64_t value = CodeGenerator::GetInt64ValueOf(constant); + + if (instr->IsAdd() || instr->IsSub() || instr->IsCondition() || instr->IsCompare()) { + // Uses aliases of ADD/SUB instructions. + return vixl::Assembler::IsImmAddSub(value); + } else if (instr->IsAnd() || instr->IsOr() || instr->IsXor()) { + // Uses logical operations. + return vixl::Assembler::IsImmLogical(value, vixl::kXRegSize); + } else { + DCHECK(instr->IsNeg()); + // Uses mov -immediate. + return vixl::Assembler::IsImmMovn(value, vixl::kXRegSize); + } +} + +static inline Location ARM64EncodableConstantOrRegister(HInstruction* constant, + HInstruction* instr) { + if (constant->IsConstant() + && CanEncodeConstantAsImmediate(constant->AsConstant(), instr)) { + return Location::ConstantLocation(constant->AsConstant()); + } + + return Location::RequiresRegister(); +} + } // namespace helpers } // namespace arm64 } // namespace art |