Revert "Revert "ARM: VIXL32: Use DontCare for SetFlags + fix for GenerateFrameEntry.""

Override Add in ArmVIXLMacroAssembler to improve 16-bit encodings.

This reverts commit 2f34995469e20a1ac342975856155f69995997ce.

Test: m test-art-host

Change-Id: Ief9f7576cd805104fd517a76b96d8a92f2208dfd
diff --git a/compiler/utils/arm/assembler_arm_vixl.h b/compiler/utils/arm/assembler_arm_vixl.h
index b4a4abc..17cf106 100644
--- a/compiler/utils/arm/assembler_arm_vixl.h
+++ b/compiler/utils/arm/assembler_arm_vixl.h
@@ -54,6 +54,77 @@
   void CompareAndBranchIfNonZero(vixl32::Register rn,
                                  vixl32::Label* label,
                                  bool is_far_target = true);
+
+  // In T32 some of the instructions (add, mov, etc) outside an IT block
+  // have only 32-bit encodings. But there are 16-bit flag setting
+  // versions of these instructions (adds, movs, etc). In most of the
+  // cases in ART we don't care if the instructions keep flags or not;
+  // thus we can benefit from smaller code size.
+  // VIXL will never generate flag setting versions (for example, adds
+  // for Add macro instruction) unless vixl32::DontCare option is
+  // explicitly specified. That's why we introduce wrappers to use
+  // DontCare option by default.
+#define WITH_FLAGS_DONT_CARE_RD_RN_OP(func_name) \
+  void (func_name)(vixl32::Register rd, vixl32::Register rn, const vixl32::Operand& operand) { \
+    MacroAssembler::func_name(vixl32::DontCare, rd, rn, operand); \
+  } \
+  using MacroAssembler::func_name
+
+  WITH_FLAGS_DONT_CARE_RD_RN_OP(Adc);
+  WITH_FLAGS_DONT_CARE_RD_RN_OP(Sub);
+  WITH_FLAGS_DONT_CARE_RD_RN_OP(Sbc);
+  WITH_FLAGS_DONT_CARE_RD_RN_OP(Rsb);
+  WITH_FLAGS_DONT_CARE_RD_RN_OP(Rsc);
+
+  WITH_FLAGS_DONT_CARE_RD_RN_OP(Eor);
+  WITH_FLAGS_DONT_CARE_RD_RN_OP(Orr);
+  WITH_FLAGS_DONT_CARE_RD_RN_OP(Orn);
+  WITH_FLAGS_DONT_CARE_RD_RN_OP(And);
+  WITH_FLAGS_DONT_CARE_RD_RN_OP(Bic);
+
+  WITH_FLAGS_DONT_CARE_RD_RN_OP(Asr);
+  WITH_FLAGS_DONT_CARE_RD_RN_OP(Lsr);
+  WITH_FLAGS_DONT_CARE_RD_RN_OP(Lsl);
+  WITH_FLAGS_DONT_CARE_RD_RN_OP(Ror);
+
+#undef WITH_FLAGS_DONT_CARE_RD_RN_OP
+
+#define WITH_FLAGS_DONT_CARE_RD_OP(func_name) \
+  void (func_name)(vixl32::Register rd, const vixl32::Operand& operand) { \
+    MacroAssembler::func_name(vixl32::DontCare, rd, operand); \
+  } \
+  using MacroAssembler::func_name
+
+  WITH_FLAGS_DONT_CARE_RD_OP(Mvn);
+  WITH_FLAGS_DONT_CARE_RD_OP(Mov);
+
+#undef WITH_FLAGS_DONT_CARE_RD_OP
+
+  // The following two functions don't fall into above categories. Overload them separately.
+  void Rrx(vixl32::Register rd, vixl32::Register rn) {
+    MacroAssembler::Rrx(vixl32::DontCare, rd, rn);
+  }
+  using MacroAssembler::Rrx;
+
+  void Mul(vixl32::Register rd, vixl32::Register rn, vixl32::Register rm) {
+    MacroAssembler::Mul(vixl32::DontCare, rd, rn, rm);
+  }
+  using MacroAssembler::Mul;
+
+  // TODO: Remove when MacroAssembler::Add(FlagsUpdate, Condition, Register, Register, Operand)
+  // makes the right decision about 16-bit encodings.
+  void Add(vixl32::Register rd, vixl32::Register rn, const vixl32::Operand& operand) {
+    if (rd.Is(rn)) {
+      MacroAssembler::Add(rd, rn, operand);
+    } else {
+      MacroAssembler::Add(vixl32::DontCare, rd, rn, operand);
+    }
+  }
+  using MacroAssembler::Add;
+
+  // These interfaces try to use 16-bit T2 encoding of B instruction.
+  void B(vixl32::Label* label);
+  void B(vixl32::Condition cond, vixl32::Label* label);
 };
 
 class ArmVIXLAssembler FINAL : public Assembler {