From 7d64aab1a1148dbdb919a20e8c10b8e1ae24f794 Mon Sep 17 00:00:00 2001 From: "alexandre.rames@arm.com" Date: Wed, 19 Feb 2014 16:13:09 +0000 Subject: [PATCH] A64: Introduce 'branch types' that extend the architectural conditions. 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 | 20 ++++++++++++++ src/a64/macro-assembler-a64.h | 55 +++++++++++++++++++++++++++++++++++++ test/cctest/test-assembler-a64.cc | 57 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+) diff --git a/src/a64/macro-assembler-a64.cc b/src/a64/macro-assembler-a64.cc index cd6b60a..2d55294 100644 --- a/src/a64/macro-assembler-a64.cc +++ b/src/a64/macro-assembler-a64.cc @@ -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(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)); diff --git a/src/a64/macro-assembler-a64.h b/src/a64/macro-assembler-a64.h index a7f5117..7aa08ee 100644 --- a/src/a64/macro-assembler-a64.h +++ b/src/a64/macro-assembler-a64.h @@ -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( + InvertCondition(static_cast(type))); + } else { + return static_cast(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); diff --git a/test/cctest/test-assembler-a64.cc b/test/cctest/test-assembler-a64.cc index 3766721..cb5a0b2 100644 --- a/test/cctest/test-assembler-a64.cc +++ b/test/cctest/test-assembler-a64.cc @@ -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(); -- 2.7.4