mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 19:14:38 +02:00
8145438: Guarantee failures since 8144028: Use AArch64 bit-test instructions in C2
Implement short and long versions of bit test instructions. Reviewed-by: kvn
This commit is contained in:
parent
ae19a4b931
commit
dd5481cbbc
5 changed files with 127 additions and 30 deletions
|
@ -3484,10 +3484,14 @@ int Matcher::regnum_to_fpu_offset(int regnum)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Matcher::is_short_branch_offset(int rule, int br_size, int offset)
|
// Is this branch offset short enough that a short branch can be used?
|
||||||
{
|
//
|
||||||
Unimplemented();
|
// NOTE: If the platform does not provide any short branch variants, then
|
||||||
return false;
|
// this method should return false for offset 0.
|
||||||
|
bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
|
||||||
|
// The passed offset is relative to address of the branch.
|
||||||
|
|
||||||
|
return (-32768 <= offset && offset < 32768);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool Matcher::isSimpleConstant64(jlong value) {
|
const bool Matcher::isSimpleConstant64(jlong value) {
|
||||||
|
@ -13845,7 +13849,8 @@ instruct cmpP_narrowOop_imm0_branch(cmpOp cmp, iRegN oop, immP0 zero, label labl
|
||||||
|
|
||||||
// Test bit and Branch
|
// Test bit and Branch
|
||||||
|
|
||||||
instruct cmpL_branch_sign(cmpOp cmp, iRegL op1, immL0 op2, label labl, rFlagsReg cr) %{
|
// Patterns for short (< 32KiB) variants
|
||||||
|
instruct cmpL_branch_sign(cmpOp cmp, iRegL op1, immL0 op2, label labl) %{
|
||||||
match(If cmp (CmpL op1 op2));
|
match(If cmp (CmpL op1 op2));
|
||||||
predicate(n->in(1)->as_Bool()->_test._test == BoolTest::lt
|
predicate(n->in(1)->as_Bool()->_test._test == BoolTest::lt
|
||||||
|| n->in(1)->as_Bool()->_test._test == BoolTest::ge);
|
|| n->in(1)->as_Bool()->_test._test == BoolTest::ge);
|
||||||
|
@ -13855,16 +13860,15 @@ instruct cmpL_branch_sign(cmpOp cmp, iRegL op1, immL0 op2, label labl, rFlagsReg
|
||||||
format %{ "cb$cmp $op1, $labl # long" %}
|
format %{ "cb$cmp $op1, $labl # long" %}
|
||||||
ins_encode %{
|
ins_encode %{
|
||||||
Label* L = $labl$$label;
|
Label* L = $labl$$label;
|
||||||
Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
|
Assembler::Condition cond =
|
||||||
if (cond == Assembler::LT)
|
((Assembler::Condition)$cmp$$cmpcode == Assembler::LT) ? Assembler::NE : Assembler::EQ;
|
||||||
__ tbnz($op1$$Register, 63, *L);
|
__ tbr(cond, $op1$$Register, 63, *L);
|
||||||
else
|
|
||||||
__ tbz($op1$$Register, 63, *L);
|
|
||||||
%}
|
%}
|
||||||
ins_pipe(pipe_cmp_branch);
|
ins_pipe(pipe_cmp_branch);
|
||||||
|
ins_short_branch(1);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct cmpI_branch_sign(cmpOp cmp, iRegIorL2I op1, immI0 op2, label labl, rFlagsReg cr) %{
|
instruct cmpI_branch_sign(cmpOp cmp, iRegIorL2I op1, immI0 op2, label labl) %{
|
||||||
match(If cmp (CmpI op1 op2));
|
match(If cmp (CmpI op1 op2));
|
||||||
predicate(n->in(1)->as_Bool()->_test._test == BoolTest::lt
|
predicate(n->in(1)->as_Bool()->_test._test == BoolTest::lt
|
||||||
|| n->in(1)->as_Bool()->_test._test == BoolTest::ge);
|
|| n->in(1)->as_Bool()->_test._test == BoolTest::ge);
|
||||||
|
@ -13874,16 +13878,15 @@ instruct cmpI_branch_sign(cmpOp cmp, iRegIorL2I op1, immI0 op2, label labl, rFla
|
||||||
format %{ "cb$cmp $op1, $labl # int" %}
|
format %{ "cb$cmp $op1, $labl # int" %}
|
||||||
ins_encode %{
|
ins_encode %{
|
||||||
Label* L = $labl$$label;
|
Label* L = $labl$$label;
|
||||||
Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
|
Assembler::Condition cond =
|
||||||
if (cond == Assembler::LT)
|
((Assembler::Condition)$cmp$$cmpcode == Assembler::LT) ? Assembler::NE : Assembler::EQ;
|
||||||
__ tbnz($op1$$Register, 31, *L);
|
__ tbr(cond, $op1$$Register, 31, *L);
|
||||||
else
|
|
||||||
__ tbz($op1$$Register, 31, *L);
|
|
||||||
%}
|
%}
|
||||||
ins_pipe(pipe_cmp_branch);
|
ins_pipe(pipe_cmp_branch);
|
||||||
|
ins_short_branch(1);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct cmpL_branch_bit(cmpOp cmp, iRegL op1, immL op2, immL0 op3, label labl, rFlagsReg cr) %{
|
instruct cmpL_branch_bit(cmpOp cmp, iRegL op1, immL op2, immL0 op3, label labl) %{
|
||||||
match(If cmp (CmpL (AndL op1 op2) op3));
|
match(If cmp (CmpL (AndL op1 op2) op3));
|
||||||
predicate((n->in(1)->as_Bool()->_test._test == BoolTest::ne
|
predicate((n->in(1)->as_Bool()->_test._test == BoolTest::ne
|
||||||
|| n->in(1)->as_Bool()->_test._test == BoolTest::eq)
|
|| n->in(1)->as_Bool()->_test._test == BoolTest::eq)
|
||||||
|
@ -13896,15 +13899,13 @@ instruct cmpL_branch_bit(cmpOp cmp, iRegL op1, immL op2, immL0 op3, label labl,
|
||||||
Label* L = $labl$$label;
|
Label* L = $labl$$label;
|
||||||
Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
|
Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
|
||||||
int bit = exact_log2($op2$$constant);
|
int bit = exact_log2($op2$$constant);
|
||||||
if (cond == Assembler::EQ)
|
__ tbr(cond, $op1$$Register, bit, *L);
|
||||||
__ tbz($op1$$Register, bit, *L);
|
|
||||||
else
|
|
||||||
__ tbnz($op1$$Register, bit, *L);
|
|
||||||
%}
|
%}
|
||||||
ins_pipe(pipe_cmp_branch);
|
ins_pipe(pipe_cmp_branch);
|
||||||
|
ins_short_branch(1);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct cmpI_branch_bit(cmpOp cmp, iRegIorL2I op1, immI op2, immI0 op3, label labl, rFlagsReg cr) %{
|
instruct cmpI_branch_bit(cmpOp cmp, iRegIorL2I op1, immI op2, immI0 op3, label labl) %{
|
||||||
match(If cmp (CmpI (AndI op1 op2) op3));
|
match(If cmp (CmpI (AndI op1 op2) op3));
|
||||||
predicate((n->in(1)->as_Bool()->_test._test == BoolTest::ne
|
predicate((n->in(1)->as_Bool()->_test._test == BoolTest::ne
|
||||||
|| n->in(1)->as_Bool()->_test._test == BoolTest::eq)
|
|| n->in(1)->as_Bool()->_test._test == BoolTest::eq)
|
||||||
|
@ -13917,10 +13918,79 @@ instruct cmpI_branch_bit(cmpOp cmp, iRegIorL2I op1, immI op2, immI0 op3, label l
|
||||||
Label* L = $labl$$label;
|
Label* L = $labl$$label;
|
||||||
Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
|
Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
|
||||||
int bit = exact_log2($op2$$constant);
|
int bit = exact_log2($op2$$constant);
|
||||||
if (cond == Assembler::EQ)
|
__ tbr(cond, $op1$$Register, bit, *L);
|
||||||
__ tbz($op1$$Register, bit, *L);
|
%}
|
||||||
else
|
ins_pipe(pipe_cmp_branch);
|
||||||
__ tbnz($op1$$Register, bit, *L);
|
ins_short_branch(1);
|
||||||
|
%}
|
||||||
|
|
||||||
|
// And far variants
|
||||||
|
instruct far_cmpL_branch_sign(cmpOp cmp, iRegL op1, immL0 op2, label labl) %{
|
||||||
|
match(If cmp (CmpL op1 op2));
|
||||||
|
predicate(n->in(1)->as_Bool()->_test._test == BoolTest::lt
|
||||||
|
|| n->in(1)->as_Bool()->_test._test == BoolTest::ge);
|
||||||
|
effect(USE labl);
|
||||||
|
|
||||||
|
ins_cost(BRANCH_COST);
|
||||||
|
format %{ "cb$cmp $op1, $labl # long" %}
|
||||||
|
ins_encode %{
|
||||||
|
Label* L = $labl$$label;
|
||||||
|
Assembler::Condition cond =
|
||||||
|
((Assembler::Condition)$cmp$$cmpcode == Assembler::LT) ? Assembler::NE : Assembler::EQ;
|
||||||
|
__ tbr(cond, $op1$$Register, 63, *L, /*far*/true);
|
||||||
|
%}
|
||||||
|
ins_pipe(pipe_cmp_branch);
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct far_cmpI_branch_sign(cmpOp cmp, iRegIorL2I op1, immI0 op2, label labl) %{
|
||||||
|
match(If cmp (CmpI op1 op2));
|
||||||
|
predicate(n->in(1)->as_Bool()->_test._test == BoolTest::lt
|
||||||
|
|| n->in(1)->as_Bool()->_test._test == BoolTest::ge);
|
||||||
|
effect(USE labl);
|
||||||
|
|
||||||
|
ins_cost(BRANCH_COST);
|
||||||
|
format %{ "cb$cmp $op1, $labl # int" %}
|
||||||
|
ins_encode %{
|
||||||
|
Label* L = $labl$$label;
|
||||||
|
Assembler::Condition cond =
|
||||||
|
((Assembler::Condition)$cmp$$cmpcode == Assembler::LT) ? Assembler::NE : Assembler::EQ;
|
||||||
|
__ tbr(cond, $op1$$Register, 31, *L, /*far*/true);
|
||||||
|
%}
|
||||||
|
ins_pipe(pipe_cmp_branch);
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct far_cmpL_branch_bit(cmpOp cmp, iRegL op1, immL op2, immL0 op3, label labl) %{
|
||||||
|
match(If cmp (CmpL (AndL op1 op2) op3));
|
||||||
|
predicate((n->in(1)->as_Bool()->_test._test == BoolTest::ne
|
||||||
|
|| n->in(1)->as_Bool()->_test._test == BoolTest::eq)
|
||||||
|
&& is_power_of_2(n->in(2)->in(1)->in(2)->get_long()));
|
||||||
|
effect(USE labl);
|
||||||
|
|
||||||
|
ins_cost(BRANCH_COST);
|
||||||
|
format %{ "tb$cmp $op1, $op2, $labl" %}
|
||||||
|
ins_encode %{
|
||||||
|
Label* L = $labl$$label;
|
||||||
|
Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
|
||||||
|
int bit = exact_log2($op2$$constant);
|
||||||
|
__ tbr(cond, $op1$$Register, bit, *L, /*far*/true);
|
||||||
|
%}
|
||||||
|
ins_pipe(pipe_cmp_branch);
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct far_cmpI_branch_bit(cmpOp cmp, iRegIorL2I op1, immI op2, immI0 op3, label labl) %{
|
||||||
|
match(If cmp (CmpI (AndI op1 op2) op3));
|
||||||
|
predicate((n->in(1)->as_Bool()->_test._test == BoolTest::ne
|
||||||
|
|| n->in(1)->as_Bool()->_test._test == BoolTest::eq)
|
||||||
|
&& is_power_of_2(n->in(2)->in(1)->in(2)->get_int()));
|
||||||
|
effect(USE labl);
|
||||||
|
|
||||||
|
ins_cost(BRANCH_COST);
|
||||||
|
format %{ "tb$cmp $op1, $op2, $labl" %}
|
||||||
|
ins_encode %{
|
||||||
|
Label* L = $labl$$label;
|
||||||
|
Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
|
||||||
|
int bit = exact_log2($op2$$constant);
|
||||||
|
__ tbr(cond, $op1$$Register, bit, *L, /*far*/true);
|
||||||
%}
|
%}
|
||||||
ins_pipe(pipe_cmp_branch);
|
ins_pipe(pipe_cmp_branch);
|
||||||
%}
|
%}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#define CPU_AARCH64_VM_C1_MACROASSEMBLER_AARCH64_HPP
|
#define CPU_AARCH64_VM_C1_MACROASSEMBLER_AARCH64_HPP
|
||||||
|
|
||||||
using MacroAssembler::build_frame;
|
using MacroAssembler::build_frame;
|
||||||
|
using MacroAssembler::null_check;
|
||||||
|
|
||||||
// C1_MacroAssembler contains high-level macros for C1
|
// C1_MacroAssembler contains high-level macros for C1
|
||||||
|
|
||||||
|
|
|
@ -1354,9 +1354,8 @@ void InterpreterMacroAssembler::notify_method_entry() {
|
||||||
// the code to check if the event should be sent.
|
// the code to check if the event should be sent.
|
||||||
if (JvmtiExport::can_post_interpreter_events()) {
|
if (JvmtiExport::can_post_interpreter_events()) {
|
||||||
Label L;
|
Label L;
|
||||||
ldr(r3, Address(rthread, JavaThread::interp_only_mode_offset()));
|
ldrw(r3, Address(rthread, JavaThread::interp_only_mode_offset()));
|
||||||
tst(r3, ~0);
|
cbzw(r3, L);
|
||||||
br(Assembler::EQ, L);
|
|
||||||
call_VM(noreg, CAST_FROM_FN_PTR(address,
|
call_VM(noreg, CAST_FROM_FN_PTR(address,
|
||||||
InterpreterRuntime::post_method_entry));
|
InterpreterRuntime::post_method_entry));
|
||||||
bind(L);
|
bind(L);
|
||||||
|
|
|
@ -487,6 +487,32 @@ public:
|
||||||
orr(Vd, T, Vn, Vn);
|
orr(Vd, T, Vn, Vn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Generalized Test Bit And Branch, including a "far" variety which
|
||||||
|
// spans more than 32KiB.
|
||||||
|
void tbr(Condition cond, Register Rt, int bitpos, Label &dest, bool far = false) {
|
||||||
|
assert(cond == EQ || cond == NE, "must be");
|
||||||
|
|
||||||
|
if (far)
|
||||||
|
cond = ~cond;
|
||||||
|
|
||||||
|
void (Assembler::* branch)(Register Rt, int bitpos, Label &L);
|
||||||
|
if (cond == Assembler::EQ)
|
||||||
|
branch = &Assembler::tbz;
|
||||||
|
else
|
||||||
|
branch = &Assembler::tbnz;
|
||||||
|
|
||||||
|
if (far) {
|
||||||
|
Label L;
|
||||||
|
(this->*branch)(Rt, bitpos, L);
|
||||||
|
b(dest);
|
||||||
|
bind(L);
|
||||||
|
} else {
|
||||||
|
(this->*branch)(Rt, bitpos, dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// macro instructions for accessing and updating floating point
|
// macro instructions for accessing and updating floating point
|
||||||
// status register
|
// status register
|
||||||
//
|
//
|
||||||
|
|
|
@ -1246,7 +1246,8 @@ bool InstructForm::check_branch_variant(ArchDesc &AD, InstructForm *short_branch
|
||||||
!is_short_branch() && // Don't match another short branch variant
|
!is_short_branch() && // Don't match another short branch variant
|
||||||
reduce_result() != NULL &&
|
reduce_result() != NULL &&
|
||||||
strcmp(reduce_result(), short_branch->reduce_result()) == 0 &&
|
strcmp(reduce_result(), short_branch->reduce_result()) == 0 &&
|
||||||
_matrule->equivalent(AD.globalNames(), short_branch->_matrule)) {
|
_matrule->equivalent(AD.globalNames(), short_branch->_matrule) &&
|
||||||
|
equivalent_predicates(this, short_branch)) {
|
||||||
// The instructions are equivalent.
|
// The instructions are equivalent.
|
||||||
|
|
||||||
// Now verify that both instructions have the same parameters and
|
// Now verify that both instructions have the same parameters and
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue