[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/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h
index 17eae8b..90d489f 100644
--- a/compiler/utils/arm/assembler_thumb2.h
+++ b/compiler/utils/arm/assembler_thumb2.h
@@ -31,8 +31,8 @@
 
 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 @@
     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 @@
   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 @@
     // 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 @@
     // 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 @@
       }
 
       // 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 @@
    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;