A64: Introduce 'branch types' that extend the architectural conditions.
authoralexandre.rames@arm.com <alexandre.rames@arm.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 19 Feb 2014 16:13:09 +0000 (16:13 +0000)
committeralexandre.rames@arm.com <alexandre.rames@arm.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 19 Feb 2014 16:13:09 +0000 (16:13 +0000)
The branch types include 'always' and 'never', and types like reg_zero (CBZ) and
reg_bit_clear (TBZ).
This will be used by incoming improvements to the code generated for
deoptimization exit points.

R=ulan@chromium.org

Review URL: https://codereview.chromium.org/170783002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19497 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/a64/macro-assembler-a64.cc
src/a64/macro-assembler-a64.h
test/cctest/test-assembler-a64.cc

index cd6b60a..2d55294 100644 (file)
@@ -666,6 +666,26 @@ bool MacroAssembler::NeedExtraInstructionsOrRegisterBranch(
 }
 
 
+void MacroAssembler::B(Label* label, BranchType type, Register reg, int bit) {
+  ASSERT((reg.Is(NoReg) || type >= kBranchTypeFirstUsingReg) &&
+         (bit == -1 || type >= kBranchTypeFirstUsingBit));
+  if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) {
+    B(static_cast<Condition>(type), label);
+  } else {
+    switch (type) {
+      case always:        B(label);              break;
+      case never:         break;
+      case reg_zero:      Cbz(reg, label);       break;
+      case reg_not_zero:  Cbnz(reg, label);      break;
+      case reg_bit_clear: Tbz(reg, bit, label);  break;
+      case reg_bit_set:   Tbnz(reg, bit, label); break;
+      default:
+        UNREACHABLE();
+    }
+  }
+}
+
+
 void MacroAssembler::B(Label* label, Condition cond) {
   ASSERT(allow_macro_instructions_);
   ASSERT((cond != al) && (cond != nv));
index a7f5117..7aa08ee 100644 (file)
@@ -64,6 +64,53 @@ inline MemOperand UntagSmiMemOperand(Register object, int offset);
 // ----------------------------------------------------------------------------
 // MacroAssembler
 
+enum BranchType {
+  // Copies of architectural conditions.
+  // The associated conditions can be used in place of those, the code will
+  // take care of reinterpreting them with the correct type.
+  integer_eq = eq,
+  integer_ne = ne,
+  integer_hs = hs,
+  integer_lo = lo,
+  integer_mi = mi,
+  integer_pl = pl,
+  integer_vs = vs,
+  integer_vc = vc,
+  integer_hi = hi,
+  integer_ls = ls,
+  integer_ge = ge,
+  integer_lt = lt,
+  integer_gt = gt,
+  integer_le = le,
+  integer_al = al,
+  integer_nv = nv,
+
+  // These two are *different* from the architectural codes al and nv.
+  // 'always' is used to generate unconditional branches.
+  // 'never' is used to not generate a branch (generally as the inverse
+  // branch type of 'always).
+  always, never,
+  // cbz and cbnz
+  reg_zero, reg_not_zero,
+  // tbz and tbnz
+  reg_bit_clear, reg_bit_set,
+
+  // Aliases.
+  kBranchTypeFirstCondition = eq,
+  kBranchTypeLastCondition = nv,
+  kBranchTypeFirstUsingReg = reg_zero,
+  kBranchTypeFirstUsingBit = reg_bit_clear
+};
+
+inline BranchType InvertBranchType(BranchType type) {
+  if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) {
+    return static_cast<BranchType>(
+        InvertCondition(static_cast<Condition>(type)));
+  } else {
+    return static_cast<BranchType>(type ^ 1);
+  }
+}
+
 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
 enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved };
@@ -212,6 +259,14 @@ class MacroAssembler : public Assembler {
   inline void Adr(const Register& rd, Label* label);
   inline void Asr(const Register& rd, const Register& rn, unsigned shift);
   inline void Asr(const Register& rd, const Register& rn, const Register& rm);
+
+  // Branch type inversion relies on these relations.
+  STATIC_ASSERT((reg_zero      == (reg_not_zero ^ 1)) &&
+                (reg_bit_clear == (reg_bit_set ^ 1)) &&
+                (always        == (never ^ 1)));
+
+  void B(Label* label, BranchType type, Register reg = NoReg, int bit = -1);
+
   inline void B(Label* label);
   inline void B(Condition cond, Label* label);
   void B(Label* label, Condition cond);
index 3766721..cb5a0b2 100644 (file)
@@ -2276,6 +2276,63 @@ TEST(far_branch_veneer_broken_link_chain) {
 }
 
 
+TEST(branch_type) {
+  INIT_V8();
+
+  SETUP();
+
+  Label fail, done;
+
+  START();
+  __ Mov(x0, 0x0);
+  __ Mov(x10, 0x7);
+  __ Mov(x11, 0x0);
+
+  // Test non taken branches.
+  __ Cmp(x10, 0x7);
+  __ B(&fail, ne);
+  __ B(&fail, never);
+  __ B(&fail, reg_zero, x10);
+  __ B(&fail, reg_not_zero, x11);
+  __ B(&fail, reg_bit_clear, x10, 0);
+  __ B(&fail, reg_bit_set, x10, 3);
+
+  // Test taken branches.
+  Label l1, l2, l3, l4, l5;
+  __ Cmp(x10, 0x7);
+  __ B(&l1, eq);
+  __ B(&fail);
+  __ Bind(&l1);
+  __ B(&l2, always);
+  __ B(&fail);
+  __ Bind(&l2);
+  __ B(&l3, reg_not_zero, x10);
+  __ B(&fail);
+  __ Bind(&l3);
+  __ B(&l4, reg_bit_clear, x10, 15);
+  __ B(&fail);
+  __ Bind(&l4);
+  __ B(&l5, reg_bit_set, x10, 1);
+  __ B(&fail);
+  __ Bind(&l5);
+
+  __ B(&done);
+
+  __ Bind(&fail);
+  __ Mov(x0, 0x1);
+
+  __ Bind(&done);
+
+  END();
+
+  RUN();
+
+  ASSERT_EQUAL_64(0x0, x0);
+
+  TEARDOWN();
+}
+
+
 TEST(ldr_str_offset) {
   INIT_V8();
   SETUP();