summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing
diff options
context:
space:
mode:
authorNicolas Geoffray <ngeoffray@google.com>2015-03-23 16:44:35 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-03-23 16:44:36 +0000
commit5af26bd446660bc5d13dd6ff9470e6920a51e26e (patch)
treea7a8ffcef09783b7ca91c70aa90e48efaf650b38 /compiler/optimizing
parentaf2bec33e5f124e37e9dbbe0fef1261411bd372d (diff)
parent2d35d9d7490ef3880ee366ccbf8f6e791f398c47 (diff)
downloadart-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.cc9
-rw-r--r--compiler/optimizing/common_arm64.h34
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