From: Nicolas Geoffray Date: Wed, 20 May 2015 10:25:27 +0000 (+0100) Subject: [Optimizing] Thumb2 assembler: use 16bits branches when we can. X-Git-Tag: android-x86-7.1-r1~889^2~1218^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=d126ba19a2a3352fedbe43ed628ab60ccd401424;p=android-x86%2Fart.git [Optimizing] Thumb2 assembler: use 16bits branches when we can. We cannot relocate branches, but we can at least encode branches on 16bits when the target is known. Change-Id: Icb6116ed974fc97e03622ac80d914c2c06f4cba2 --- diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 7b37f7484..1c76630ef 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -391,7 +391,7 @@ CodeGeneratorARM::CodeGeneratorARM(HGraph* graph, location_builder_(graph, this), instruction_visitor_(graph, this), move_resolver_(graph->GetArena(), this), - assembler_(true), + assembler_(false /* can_relocate_branches */), isa_features_(isa_features) { // Save the PC register to mimic Quick. AddAllocatedRegister(Location::RegisterLocation(PC)); diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc index e7cf26eee..75f2b77c9 100644 --- a/compiler/utils/arm/assembler_thumb2.cc +++ b/compiler/utils/arm/assembler_thumb2.cc @@ -1638,7 +1638,6 @@ void Thumb2Assembler::EmitBranch(Condition cond, Label* label, bool link, bool x // branch the size may change if it so happens that other branches change size that change // the distance to the target and that distance puts this branch over the limit for 16 bits. if (size == Branch::k16Bit) { - DCHECK(!force_32bit_branches_); Emit16(0); // Space for a 16 bit branch. } else { Emit32(0); // Space for a 32 bit branch. @@ -1646,7 +1645,7 @@ void Thumb2Assembler::EmitBranch(Condition cond, Label* label, bool link, bool x } else { // Branch is to an unbound label. Emit space for it. uint16_t branch_id = AddBranch(branch_type, pc, cond); // Unresolved branch. - if (force_32bit_branches_ || force_32bit_) { + if (!CanRelocateBranches() || force_32bit_) { Emit16(static_cast(label->position_)); // Emit current label link. Emit16(0); // another 16 bits. } else { @@ -2282,7 +2281,7 @@ void Thumb2Assembler::Bind(Label* label) { uint32_t branch_location = branch->GetLocation(); uint16_t next = buffer_.Load(branch_location); // Get next in chain. if (changed) { - DCHECK(!force_32bit_branches_); + DCHECK(CanRelocateBranches()); MakeHoleForBranch(branch->GetLocation(), 2); if (branch->IsCompareAndBranch()) { // A cbz/cbnz instruction has changed size. There is no valid encoding for @@ -2742,21 +2741,21 @@ void Thumb2Assembler::dmb(DmbOptions flavor) { void Thumb2Assembler::CompareAndBranchIfZero(Register r, Label* label) { - if (force_32bit_branches_) { + if (CanRelocateBranches()) { + cbz(r, label); + } else { cmp(r, ShifterOperand(0)); b(label, EQ); - } else { - cbz(r, label); } } void Thumb2Assembler::CompareAndBranchIfNonZero(Register r, Label* label) { - if (force_32bit_branches_) { + if (CanRelocateBranches()) { + cbnz(r, label); + } else { cmp(r, ShifterOperand(0)); b(label, NE); - } else { - cbnz(r, label); } } } // namespace arm diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h index 17eae8be0..90d489fb0 100644 --- a/compiler/utils/arm/assembler_thumb2.h +++ b/compiler/utils/arm/assembler_thumb2.h @@ -31,8 +31,8 @@ namespace arm { class Thumb2Assembler FINAL : public ArmAssembler { public: - explicit Thumb2Assembler(bool force_32bit_branches = false) - : force_32bit_branches_(force_32bit_branches), + explicit Thumb2Assembler(bool can_relocate_branches = true) + : can_relocate_branches_(can_relocate_branches), force_32bit_(false), it_cond_index_(kNoItCondition), next_condition_(AL) { @@ -52,8 +52,8 @@ class Thumb2Assembler FINAL : public ArmAssembler { return force_32bit_; } - bool IsForced32BitBranches() const { - return force_32bit_branches_; + bool CanRelocateBranches() const { + return can_relocate_branches_; } void FinalizeInstructions(const MemoryRegion& region) OVERRIDE { @@ -439,8 +439,12 @@ class Thumb2Assembler FINAL : public ArmAssembler { void EmitShift(Register rd, Register rm, Shift shift, uint8_t amount, bool setcc = false); void EmitShift(Register rd, Register rn, Shift shift, Register rm, bool setcc = false); - bool force_32bit_branches_; // Force the assembler to use 32 bit branch instructions. - bool force_32bit_; // Force the assembler to use 32 bit thumb2 instructions. + // Whether the assembler can relocate branches. If false, unresolved branches will be + // emitted on 32bits. + bool can_relocate_branches_; + + // Force the assembler to use 32 bit thumb2 instructions. + bool force_32bit_; // IfThen conditions. Used to check that conditional instructions match the preceding IT. Condition it_conditions_[4]; @@ -556,12 +560,21 @@ class Thumb2Assembler FINAL : public ArmAssembler { // size of the branch to change return true. Otherwise return false. bool Resolve(uint32_t target) { target_ = target; - Size newsize = CalculateSize(); - if (size_ != newsize) { - size_ = newsize; - return true; + if (assembler_->CanRelocateBranches()) { + Size new_size = CalculateSize(); + if (size_ != new_size) { + size_ = new_size; + return true; + } + return false; + } else { + if (kIsDebugBuild) { + Size new_size = CalculateSize(); + // Check that the size has not increased. + DCHECK(!(new_size == k32Bit && size_ == k16Bit)); + } + return false; } - return false; } // Move a cbz/cbnz branch. This is always forward. @@ -577,6 +590,7 @@ class Thumb2Assembler FINAL : public ArmAssembler { // size of the branch instruction. It returns true if the branch // has changed size. bool Relocate(uint32_t oldlocation, int32_t delta) { + DCHECK(assembler_->CanRelocateBranches()); if (location_ > oldlocation) { location_ += delta; } @@ -589,9 +603,9 @@ class Thumb2Assembler FINAL : public ArmAssembler { } // Calculate the new size. - Size newsize = CalculateSize(); - if (size_ != newsize) { - size_ = newsize; + Size new_size = CalculateSize(); + if (size_ != new_size) { + size_ = new_size; return true; } return false; @@ -633,15 +647,13 @@ class Thumb2Assembler FINAL : public ArmAssembler { private: // Calculate the size of the branch instruction based on its type and offset. Size CalculateSize() const { - if (assembler_->IsForced32BitBranches()) { - return k32Bit; - } if (target_ == kUnresolved) { if (assembler_->IsForced32Bit() && (type_ == kUnconditional || type_ == kConditional)) { return k32Bit; } - return k16Bit; + return assembler_->CanRelocateBranches() ? k16Bit : k32Bit; } + // When the target is resolved, we know the best encoding for it. int32_t delta = target_ - location_ - 4; if (delta < 0) { delta = -delta;