summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2014-11-28 16:04:38 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2014-11-28 16:04:38 +0000
commit33c5aac7efcf82c86a907b321d700e673f95d648 (patch)
treee859c5878af17bf158b1f49d2c8d41151665d28a /compiler
parent6e2d377d42397b4d83ef210ba000237798911656 (diff)
parent3bcc8ea079d867f26622defd0611d134a3b4ae49 (diff)
Merge "Don't use CanHoldArm in the code generator."
Diffstat (limited to 'compiler')
-rw-r--r--compiler/optimizing/code_generator_arm.cc22
-rw-r--r--compiler/utils/arm/assembler_arm.cc30
-rw-r--r--compiler/utils/arm/assembler_arm.h41
-rw-r--r--compiler/utils/arm/assembler_arm32.cc51
-rw-r--r--compiler/utils/arm/assembler_arm32.h7
-rw-r--r--compiler/utils/arm/assembler_thumb2.cc55
-rw-r--r--compiler/utils/arm/assembler_thumb2.h6
7 files changed, 124 insertions, 88 deletions
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 7d6d827386..dc861144ca 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -949,20 +949,20 @@ void InstructionCodeGeneratorARM::VisitIf(HIf* if_instr) {
// Condition has not been materialized, use its inputs as the
// comparison and its condition as the branch condition.
LocationSummary* locations = cond->GetLocations();
+ Register left = locations->InAt(0).AsRegister<Register>();
if (locations->InAt(1).IsRegister()) {
- __ cmp(locations->InAt(0).AsRegister<Register>(),
- ShifterOperand(locations->InAt(1).AsRegister<Register>()));
+ __ cmp(left, ShifterOperand(locations->InAt(1).AsRegister<Register>()));
} else {
DCHECK(locations->InAt(1).IsConstant());
int32_t value =
locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
ShifterOperand operand;
- if (ShifterOperand::CanHoldArm(value, &operand)) {
- __ cmp(locations->InAt(0).AsRegister<Register>(), ShifterOperand(value));
+ if (GetAssembler()->ShifterOperandCanHold(R0, left, CMP, value, &operand)) {
+ __ cmp(left, operand);
} else {
Register temp = IP;
__ LoadImmediate(temp, value);
- __ cmp(locations->InAt(0).AsRegister<Register>(), ShifterOperand(temp));
+ __ cmp(left, ShifterOperand(temp));
}
}
__ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()),
@@ -988,21 +988,21 @@ void LocationsBuilderARM::VisitCondition(HCondition* comp) {
void InstructionCodeGeneratorARM::VisitCondition(HCondition* comp) {
if (!comp->NeedsMaterialization()) return;
-
LocationSummary* locations = comp->GetLocations();
+ Register left = locations->InAt(0).AsRegister<Register>();
+
if (locations->InAt(1).IsRegister()) {
- __ cmp(locations->InAt(0).AsRegister<Register>(),
- ShifterOperand(locations->InAt(1).AsRegister<Register>()));
+ __ cmp(left, ShifterOperand(locations->InAt(1).AsRegister<Register>()));
} else {
DCHECK(locations->InAt(1).IsConstant());
int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
ShifterOperand operand;
- if (ShifterOperand::CanHoldArm(value, &operand)) {
- __ cmp(locations->InAt(0).AsRegister<Register>(), ShifterOperand(value));
+ if (GetAssembler()->ShifterOperandCanHold(R0, left, CMP, value, &operand)) {
+ __ cmp(left, operand);
} else {
Register temp = IP;
__ LoadImmediate(temp, value);
- __ cmp(locations->InAt(0).AsRegister<Register>(), ShifterOperand(temp));
+ __ cmp(left, ShifterOperand(temp));
}
}
__ it(ARMCondition(comp->GetCondition()), kItElse);
diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc
index 0f28591775..05287732c5 100644
--- a/compiler/utils/arm/assembler_arm.cc
+++ b/compiler/utils/arm/assembler_arm.cc
@@ -165,36 +165,6 @@ uint32_t ShifterOperand::encodingThumb() const {
return 0;
}
-bool ShifterOperand::CanHoldThumb(Register rd, Register rn, Opcode opcode,
- uint32_t immediate, ShifterOperand* shifter_op) {
- shifter_op->type_ = kImmediate;
- shifter_op->immed_ = immediate;
- shifter_op->is_shift_ = false;
- shifter_op->is_rotate_ = false;
- switch (opcode) {
- case ADD:
- case SUB:
- if (rn == SP) {
- if (rd == SP) {
- return immediate < (1 << 9); // 9 bits allowed.
- } else {
- return immediate < (1 << 12); // 12 bits.
- }
- }
- if (immediate < (1 << 12)) { // Less than (or equal to) 12 bits can always be done.
- return true;
- }
- return ArmAssembler::ModifiedImmediate(immediate) != kInvalidModifiedImmediate;
-
- case MOV:
- // TODO: Support less than or equal to 12bits.
- return ArmAssembler::ModifiedImmediate(immediate) != kInvalidModifiedImmediate;
- case MVN:
- default:
- return ArmAssembler::ModifiedImmediate(immediate) != kInvalidModifiedImmediate;
- }
-}
-
uint32_t Address::encodingArm() const {
CHECK(IsAbsoluteUint(12, offset_));
uint32_t encoding;
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h
index d288b700ed..c86ec4b3d6 100644
--- a/compiler/utils/arm/assembler_arm.h
+++ b/compiler/utils/arm/assembler_arm.h
@@ -30,6 +30,9 @@
namespace art {
namespace arm {
+class Arm32Assembler;
+class Thumb2Assembler;
+
class ShifterOperand {
public:
ShifterOperand() : type_(kUnknown), rm_(kNoRegister), rs_(kNoRegister),
@@ -103,33 +106,6 @@ class ShifterOperand {
kImmediate
};
- static bool CanHoldArm(uint32_t immediate, ShifterOperand* shifter_op) {
- // Avoid the more expensive test for frequent small immediate values.
- if (immediate < (1 << kImmed8Bits)) {
- shifter_op->type_ = kImmediate;
- shifter_op->is_rotate_ = true;
- shifter_op->rotate_ = 0;
- shifter_op->immed_ = immediate;
- return true;
- }
- // Note that immediate must be unsigned for the test to work correctly.
- for (int rot = 0; rot < 16; rot++) {
- uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot));
- if (imm8 < (1 << kImmed8Bits)) {
- shifter_op->type_ = kImmediate;
- shifter_op->is_rotate_ = true;
- shifter_op->rotate_ = rot;
- shifter_op->immed_ = imm8;
- return true;
- }
- }
- return false;
- }
-
- static bool CanHoldThumb(Register rd, Register rn, Opcode opcode,
- uint32_t immediate, ShifterOperand* shifter_op);
-
-
private:
Type type_;
Register rm_;
@@ -140,6 +116,9 @@ class ShifterOperand {
uint32_t rotate_;
uint32_t immed_;
+ friend class Arm32Assembler;
+ friend class Thumb2Assembler;
+
#ifdef SOURCE_ASSEMBLER_SUPPORT
friend class BinaryAssembler;
#endif
@@ -611,6 +590,14 @@ class ArmAssembler : public Assembler {
virtual void Ror(Register rd, Register rm, Register rn, bool setcc = false,
Condition cond = AL) = 0;
+ // Returns whether the `immediate` can fit in a `ShifterOperand`. If yes,
+ // `shifter_op` contains the operand.
+ virtual bool ShifterOperandCanHold(Register rd,
+ Register rn,
+ Opcode opcode,
+ uint32_t immediate,
+ ShifterOperand* shifter_op) = 0;
+
static bool IsInstructionForExceptionHandling(uintptr_t pc);
virtual void Bind(Label* label) = 0;
diff --git a/compiler/utils/arm/assembler_arm32.cc b/compiler/utils/arm/assembler_arm32.cc
index a541763881..8f6d45ab53 100644
--- a/compiler/utils/arm/assembler_arm32.cc
+++ b/compiler/utils/arm/assembler_arm32.cc
@@ -25,6 +25,37 @@
namespace art {
namespace arm {
+bool Arm32Assembler::ShifterOperandCanHoldArm32(uint32_t immediate, ShifterOperand* shifter_op) {
+ // Avoid the more expensive test for frequent small immediate values.
+ if (immediate < (1 << kImmed8Bits)) {
+ shifter_op->type_ = ShifterOperand::kImmediate;
+ shifter_op->is_rotate_ = true;
+ shifter_op->rotate_ = 0;
+ shifter_op->immed_ = immediate;
+ return true;
+ }
+ // Note that immediate must be unsigned for the test to work correctly.
+ for (int rot = 0; rot < 16; rot++) {
+ uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot));
+ if (imm8 < (1 << kImmed8Bits)) {
+ shifter_op->type_ = ShifterOperand::kImmediate;
+ shifter_op->is_rotate_ = true;
+ shifter_op->rotate_ = rot;
+ shifter_op->immed_ = imm8;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Arm32Assembler::ShifterOperandCanHold(Register rd ATTRIBUTE_UNUSED,
+ Register rn ATTRIBUTE_UNUSED,
+ Opcode opcode ATTRIBUTE_UNUSED,
+ uint32_t immediate,
+ ShifterOperand* shifter_op) {
+ return ShifterOperandCanHoldArm32(immediate, shifter_op);
+}
+
void Arm32Assembler::and_(Register rd, Register rn, const ShifterOperand& so,
Condition cond) {
EmitType01(cond, so.type(), AND, 0, rn, rd, so);
@@ -1291,16 +1322,16 @@ void Arm32Assembler::AddConstant(Register rd, Register rn, int32_t value,
// positive values and sub for negatives ones, which would slightly improve
// the readability of generated code for some constants.
ShifterOperand shifter_op;
- if (ShifterOperand::CanHoldArm(value, &shifter_op)) {
+ if (ShifterOperandCanHoldArm32(value, &shifter_op)) {
add(rd, rn, shifter_op, cond);
- } else if (ShifterOperand::CanHoldArm(-value, &shifter_op)) {
+ } else if (ShifterOperandCanHoldArm32(-value, &shifter_op)) {
sub(rd, rn, shifter_op, cond);
} else {
CHECK(rn != IP);
- if (ShifterOperand::CanHoldArm(~value, &shifter_op)) {
+ if (ShifterOperandCanHoldArm32(~value, &shifter_op)) {
mvn(IP, shifter_op, cond);
add(rd, rn, ShifterOperand(IP), cond);
- } else if (ShifterOperand::CanHoldArm(~(-value), &shifter_op)) {
+ } else if (ShifterOperandCanHoldArm32(~(-value), &shifter_op)) {
mvn(IP, shifter_op, cond);
sub(rd, rn, ShifterOperand(IP), cond);
} else {
@@ -1318,16 +1349,16 @@ void Arm32Assembler::AddConstant(Register rd, Register rn, int32_t value,
void Arm32Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value,
Condition cond) {
ShifterOperand shifter_op;
- if (ShifterOperand::CanHoldArm(value, &shifter_op)) {
+ if (ShifterOperandCanHoldArm32(value, &shifter_op)) {
adds(rd, rn, shifter_op, cond);
- } else if (ShifterOperand::CanHoldArm(-value, &shifter_op)) {
+ } else if (ShifterOperandCanHoldArm32(-value, &shifter_op)) {
subs(rd, rn, shifter_op, cond);
} else {
CHECK(rn != IP);
- if (ShifterOperand::CanHoldArm(~value, &shifter_op)) {
+ if (ShifterOperandCanHoldArm32(~value, &shifter_op)) {
mvn(IP, shifter_op, cond);
adds(rd, rn, ShifterOperand(IP), cond);
- } else if (ShifterOperand::CanHoldArm(~(-value), &shifter_op)) {
+ } else if (ShifterOperandCanHoldArm32(~(-value), &shifter_op)) {
mvn(IP, shifter_op, cond);
subs(rd, rn, ShifterOperand(IP), cond);
} else {
@@ -1343,9 +1374,9 @@ void Arm32Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value
void Arm32Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) {
ShifterOperand shifter_op;
- if (ShifterOperand::CanHoldArm(value, &shifter_op)) {
+ if (ShifterOperandCanHoldArm32(value, &shifter_op)) {
mov(rd, shifter_op, cond);
- } else if (ShifterOperand::CanHoldArm(~value, &shifter_op)) {
+ } else if (ShifterOperandCanHoldArm32(~value, &shifter_op)) {
mvn(rd, shifter_op, cond);
} else {
movw(rd, Low16Bits(value), cond);
diff --git a/compiler/utils/arm/assembler_arm32.h b/compiler/utils/arm/assembler_arm32.h
index 0b009e16d9..6c8d41587b 100644
--- a/compiler/utils/arm/assembler_arm32.h
+++ b/compiler/utils/arm/assembler_arm32.h
@@ -273,6 +273,12 @@ class Arm32Assembler FINAL : public ArmAssembler {
int32_t offset,
Condition cond = AL) OVERRIDE;
+ bool ShifterOperandCanHold(Register rd,
+ Register rn,
+ Opcode opcode,
+ uint32_t immediate,
+ ShifterOperand* shifter_op) OVERRIDE;
+
static bool IsInstructionForExceptionHandling(uintptr_t pc);
@@ -359,6 +365,7 @@ class Arm32Assembler FINAL : public ArmAssembler {
static int DecodeBranchOffset(int32_t inst);
int32_t EncodeTstOffset(int offset, int32_t inst);
int DecodeTstOffset(int32_t inst);
+ bool ShifterOperandCanHoldArm32(uint32_t immediate, ShifterOperand* shifter_op);
};
} // namespace arm
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index dac2f2b315..479186c5d7 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -25,6 +25,39 @@
namespace art {
namespace arm {
+bool Thumb2Assembler::ShifterOperandCanHold(Register rd,
+ Register rn,
+ Opcode opcode,
+ uint32_t immediate,
+ ShifterOperand* shifter_op) {
+ shifter_op->type_ = ShifterOperand::kImmediate;
+ shifter_op->immed_ = immediate;
+ shifter_op->is_shift_ = false;
+ shifter_op->is_rotate_ = false;
+ switch (opcode) {
+ case ADD:
+ case SUB:
+ if (rn == SP) {
+ if (rd == SP) {
+ return immediate < (1 << 9); // 9 bits allowed.
+ } else {
+ return immediate < (1 << 12); // 12 bits.
+ }
+ }
+ if (immediate < (1 << 12)) { // Less than (or equal to) 12 bits can always be done.
+ return true;
+ }
+ return ArmAssembler::ModifiedImmediate(immediate) != kInvalidModifiedImmediate;
+
+ case MOV:
+ // TODO: Support less than or equal to 12bits.
+ return ArmAssembler::ModifiedImmediate(immediate) != kInvalidModifiedImmediate;
+ case MVN:
+ default:
+ return ArmAssembler::ModifiedImmediate(immediate) != kInvalidModifiedImmediate;
+ }
+}
+
void Thumb2Assembler::and_(Register rd, Register rn, const ShifterOperand& so,
Condition cond) {
EmitDataProcessing(cond, AND, 0, rn, rd, so);
@@ -2375,16 +2408,16 @@ void Thumb2Assembler::AddConstant(Register rd, Register rn, int32_t value,
// positive values and sub for negatives ones, which would slightly improve
// the readability of generated code for some constants.
ShifterOperand shifter_op;
- if (ShifterOperand::CanHoldThumb(rd, rn, ADD, value, &shifter_op)) {
+ if (ShifterOperandCanHold(rd, rn, ADD, value, &shifter_op)) {
add(rd, rn, shifter_op, cond);
- } else if (ShifterOperand::CanHoldThumb(rd, rn, SUB, -value, &shifter_op)) {
+ } else if (ShifterOperandCanHold(rd, rn, SUB, -value, &shifter_op)) {
sub(rd, rn, shifter_op, cond);
} else {
CHECK(rn != IP);
- if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~value, &shifter_op)) {
+ if (ShifterOperandCanHold(rd, rn, MVN, ~value, &shifter_op)) {
mvn(IP, shifter_op, cond);
add(rd, rn, ShifterOperand(IP), cond);
- } else if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~(-value), &shifter_op)) {
+ } else if (ShifterOperandCanHold(rd, rn, MVN, ~(-value), &shifter_op)) {
mvn(IP, shifter_op, cond);
sub(rd, rn, ShifterOperand(IP), cond);
} else {
@@ -2402,16 +2435,16 @@ void Thumb2Assembler::AddConstant(Register rd, Register rn, int32_t value,
void Thumb2Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value,
Condition cond) {
ShifterOperand shifter_op;
- if (ShifterOperand::CanHoldThumb(rd, rn, ADD, value, &shifter_op)) {
+ if (ShifterOperandCanHold(rd, rn, ADD, value, &shifter_op)) {
adds(rd, rn, shifter_op, cond);
- } else if (ShifterOperand::CanHoldThumb(rd, rn, ADD, -value, &shifter_op)) {
+ } else if (ShifterOperandCanHold(rd, rn, ADD, -value, &shifter_op)) {
subs(rd, rn, shifter_op, cond);
} else {
CHECK(rn != IP);
- if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~value, &shifter_op)) {
+ if (ShifterOperandCanHold(rd, rn, MVN, ~value, &shifter_op)) {
mvn(IP, shifter_op, cond);
adds(rd, rn, ShifterOperand(IP), cond);
- } else if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~(-value), &shifter_op)) {
+ } else if (ShifterOperandCanHold(rd, rn, MVN, ~(-value), &shifter_op)) {
mvn(IP, shifter_op, cond);
subs(rd, rn, ShifterOperand(IP), cond);
} else {
@@ -2425,11 +2458,12 @@ void Thumb2Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t valu
}
}
+
void Thumb2Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) {
ShifterOperand shifter_op;
- if (ShifterOperand::CanHoldThumb(rd, R0, MOV, value, &shifter_op)) {
+ if (ShifterOperandCanHold(rd, R0, MOV, value, &shifter_op)) {
mov(rd, shifter_op, cond);
- } else if (ShifterOperand::CanHoldThumb(rd, R0, MVN, ~value, &shifter_op)) {
+ } else if (ShifterOperandCanHold(rd, R0, MVN, ~value, &shifter_op)) {
mvn(rd, shifter_op, cond);
} else {
movw(rd, Low16Bits(value), cond);
@@ -2440,6 +2474,7 @@ void Thumb2Assembler::LoadImmediate(Register rd, int32_t value, Condition cond)
}
}
+
// Implementation note: this method must emit at most one instruction when
// Address::CanHoldLoadOffsetThumb.
void Thumb2Assembler::LoadFromOffset(LoadOperandType type,
diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h
index cfa251acf2..48a3a7eeb2 100644
--- a/compiler/utils/arm/assembler_thumb2.h
+++ b/compiler/utils/arm/assembler_thumb2.h
@@ -304,6 +304,12 @@ class Thumb2Assembler FINAL : public ArmAssembler {
int32_t offset,
Condition cond = AL) OVERRIDE;
+ bool ShifterOperandCanHold(Register rd,
+ Register rn,
+ Opcode opcode,
+ uint32_t immediate,
+ ShifterOperand* shifter_op) OVERRIDE;
+
static bool IsInstructionForExceptionHandling(uintptr_t pc);