提交 46aea118 编写于 作者: K kvn

7063629: use cbcond in C2 generated code on T4

Summary: Use new short branch instruction in C2 generated code.
Reviewed-by: never
上级 6becc0d2
...@@ -1192,6 +1192,8 @@ class Assembler : public AbstractAssembler { ...@@ -1192,6 +1192,8 @@ class Assembler : public AbstractAssembler {
assert(offset() == 0 || !cbcond_before(), "cbcond should not follow an other cbcond"); assert(offset() == 0 || !cbcond_before(), "cbcond should not follow an other cbcond");
} }
public:
bool use_cbcond(Label& L) { bool use_cbcond(Label& L) {
if (!UseCBCond || cbcond_before()) return false; if (!UseCBCond || cbcond_before()) return false;
intptr_t x = intptr_t(target_distance(L)) - intptr_t(pc()); intptr_t x = intptr_t(target_distance(L)) - intptr_t(pc());
...@@ -1199,7 +1201,6 @@ class Assembler : public AbstractAssembler { ...@@ -1199,7 +1201,6 @@ class Assembler : public AbstractAssembler {
return is_simm(x, 12); return is_simm(x, 12);
} }
public:
// Tells assembler you know that next instruction is delayed // Tells assembler you know that next instruction is delayed
Assembler* delayed() { Assembler* delayed() {
#ifdef CHECK_DELAY #ifdef CHECK_DELAY
...@@ -1248,6 +1249,10 @@ public: ...@@ -1248,6 +1249,10 @@ public:
inline void bpr(RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt = relocInfo::none); inline void bpr(RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt = relocInfo::none);
inline void bpr(RCondition c, bool a, Predict p, Register s1, Label& L); inline void bpr(RCondition c, bool a, Predict p, Register s1, Label& L);
// compare and branch
inline void cbcond(Condition c, CC cc, Register s1, Register s2, Label& L);
inline void cbcond(Condition c, CC cc, Register s1, int simm5, Label& L);
protected: // use MacroAssembler::br instead protected: // use MacroAssembler::br instead
// pp 138 // pp 138
...@@ -1275,10 +1280,6 @@ public: ...@@ -1275,10 +1280,6 @@ public:
inline void cb( Condition c, bool a, address d, relocInfo::relocType rt = relocInfo::none ); inline void cb( Condition c, bool a, address d, relocInfo::relocType rt = relocInfo::none );
inline void cb( Condition c, bool a, Label& L ); inline void cb( Condition c, bool a, Label& L );
// compare and branch
inline void cbcond(Condition c, CC cc, Register s1, Register s2, Label& L);
inline void cbcond(Condition c, CC cc, Register s1, int simm5, Label& L);
// pp 149 // pp 149
inline void call( address d, relocInfo::relocType rt = relocInfo::runtime_call_type ); inline void call( address d, relocInfo::relocType rt = relocInfo::runtime_call_type );
......
此差异已折叠。
...@@ -144,8 +144,13 @@ void VM_Version::initialize() { ...@@ -144,8 +144,13 @@ void VM_Version::initialize() {
// Currently not supported anywhere. // Currently not supported anywhere.
FLAG_SET_DEFAULT(UseFPUForSpilling, false); FLAG_SET_DEFAULT(UseFPUForSpilling, false);
assert((InteriorEntryAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size");
#endif #endif
assert((CodeEntryAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size");
assert((OptoLoopAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size");
char buf[512]; char buf[512];
jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
(has_v9() ? ", v9" : (has_v8() ? ", v8" : "")), (has_v9() ? ", v9" : (has_v8() ? ", v8" : "")),
......
...@@ -1339,9 +1339,8 @@ void Assembler::incl(Address dst) { ...@@ -1339,9 +1339,8 @@ void Assembler::incl(Address dst) {
emit_operand(rax, dst); emit_operand(rax, dst);
} }
void Assembler::jcc(Condition cc, Label& L, relocInfo::relocType rtype) { void Assembler::jcc(Condition cc, Label& L, bool maybe_short) {
InstructionMark im(this); InstructionMark im(this);
relocate(rtype);
assert((0 <= cc) && (cc < 16), "illegal cc"); assert((0 <= cc) && (cc < 16), "illegal cc");
if (L.is_bound()) { if (L.is_bound()) {
address dst = target(L); address dst = target(L);
...@@ -1350,7 +1349,7 @@ void Assembler::jcc(Condition cc, Label& L, relocInfo::relocType rtype) { ...@@ -1350,7 +1349,7 @@ void Assembler::jcc(Condition cc, Label& L, relocInfo::relocType rtype) {
const int short_size = 2; const int short_size = 2;
const int long_size = 6; const int long_size = 6;
intptr_t offs = (intptr_t)dst - (intptr_t)_code_pos; intptr_t offs = (intptr_t)dst - (intptr_t)_code_pos;
if (rtype == relocInfo::none && is8bit(offs - short_size)) { if (maybe_short && is8bit(offs - short_size)) {
// 0111 tttn #8-bit disp // 0111 tttn #8-bit disp
emit_byte(0x70 | cc); emit_byte(0x70 | cc);
emit_byte((offs - short_size) & 0xFF); emit_byte((offs - short_size) & 0xFF);
...@@ -1399,7 +1398,7 @@ void Assembler::jmp(Address adr) { ...@@ -1399,7 +1398,7 @@ void Assembler::jmp(Address adr) {
emit_operand(rsp, adr); emit_operand(rsp, adr);
} }
void Assembler::jmp(Label& L, relocInfo::relocType rtype) { void Assembler::jmp(Label& L, bool maybe_short) {
if (L.is_bound()) { if (L.is_bound()) {
address entry = target(L); address entry = target(L);
assert(entry != NULL, "jmp most probably wrong"); assert(entry != NULL, "jmp most probably wrong");
...@@ -1407,7 +1406,7 @@ void Assembler::jmp(Label& L, relocInfo::relocType rtype) { ...@@ -1407,7 +1406,7 @@ void Assembler::jmp(Label& L, relocInfo::relocType rtype) {
const int short_size = 2; const int short_size = 2;
const int long_size = 5; const int long_size = 5;
intptr_t offs = entry - _code_pos; intptr_t offs = entry - _code_pos;
if (rtype == relocInfo::none && is8bit(offs - short_size)) { if (maybe_short && is8bit(offs - short_size)) {
emit_byte(0xEB); emit_byte(0xEB);
emit_byte((offs - short_size) & 0xFF); emit_byte((offs - short_size) & 0xFF);
} else { } else {
...@@ -1420,7 +1419,6 @@ void Assembler::jmp(Label& L, relocInfo::relocType rtype) { ...@@ -1420,7 +1419,6 @@ void Assembler::jmp(Label& L, relocInfo::relocType rtype) {
// the forward jump will not run beyond 256 bytes, use jmpb to // the forward jump will not run beyond 256 bytes, use jmpb to
// force an 8-bit displacement. // force an 8-bit displacement.
InstructionMark im(this); InstructionMark im(this);
relocate(rtype);
L.add_patch_at(code(), locator()); L.add_patch_at(code(), locator());
emit_byte(0xE9); emit_byte(0xE9);
emit_long(0); emit_long(0);
......
...@@ -1065,8 +1065,7 @@ private: ...@@ -1065,8 +1065,7 @@ private:
// Note: The same Label can be used for forward and backward branches // Note: The same Label can be used for forward and backward branches
// but it may be bound only once. // but it may be bound only once.
void jcc(Condition cc, Label& L, void jcc(Condition cc, Label& L, bool maybe_short = true);
relocInfo::relocType rtype = relocInfo::none);
// Conditional jump to a 8-bit offset to L. // Conditional jump to a 8-bit offset to L.
// WARNING: be very careful using this for forward jumps. If the label is // WARNING: be very careful using this for forward jumps. If the label is
...@@ -1077,7 +1076,7 @@ private: ...@@ -1077,7 +1076,7 @@ private:
void jmp(Address entry); // pc <- entry void jmp(Address entry); // pc <- entry
// Label operations & relative jumps (PPUM Appendix D) // Label operations & relative jumps (PPUM Appendix D)
void jmp(Label& L, relocInfo::relocType rtype = relocInfo::none); // unconditional jump to L void jmp(Label& L, bool maybe_short = true); // unconditional jump to L
void jmp(Register entry); // pc <- entry void jmp(Register entry); // pc <- entry
......
...@@ -1369,7 +1369,12 @@ const uint Matcher::vector_ideal_reg(void) { ...@@ -1369,7 +1369,12 @@ const uint Matcher::vector_ideal_reg(void) {
// //
// NOTE: If the platform does not provide any short branch variants, then // NOTE: If the platform does not provide any short branch variants, then
// this method should return false for offset 0. // this method should return false for offset 0.
bool Matcher::is_short_branch_offset(int rule, int offset) { bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
// The passed offset is relative to address of the branch.
// On 86 a branch displacement is calculated relative to address
// of a next instruction.
offset -= br_size;
// the short version of jmpConUCF2 contains multiple branches, // the short version of jmpConUCF2 contains multiple branches,
// making the reach slightly less // making the reach slightly less
if (rule == jmpConUCF2_rule) if (rule == jmpConUCF2_rule)
...@@ -1713,18 +1718,6 @@ encode %{ ...@@ -1713,18 +1718,6 @@ encode %{
else emit_d32(cbuf,con); else emit_d32(cbuf,con);
%} %}
enc_class Lbl (label labl) %{ // GOTO
Label *l = $labl$$label;
emit_d32(cbuf, (l->loc_pos() - (cbuf.insts_size()+4)));
%}
enc_class LblShort (label labl) %{ // GOTO
Label *l = $labl$$label;
int disp = l->loc_pos() - (cbuf.insts_size()+1);
assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp");
emit_d8(cbuf, disp);
%}
enc_class OpcSReg (eRegI dst) %{ // BSWAP enc_class OpcSReg (eRegI dst) %{ // BSWAP
emit_cc(cbuf, $secondary, $dst$$reg ); emit_cc(cbuf, $secondary, $dst$$reg );
%} %}
...@@ -1747,21 +1740,6 @@ encode %{ ...@@ -1747,21 +1740,6 @@ encode %{
emit_rm(cbuf, 0x3, $secondary, $div$$reg ); emit_rm(cbuf, 0x3, $secondary, $div$$reg );
%} %}
enc_class Jcc (cmpOp cop, label labl) %{ // JCC
Label *l = $labl$$label;
$$$emit8$primary;
emit_cc(cbuf, $secondary, $cop$$cmpcode);
emit_d32(cbuf, (l->loc_pos() - (cbuf.insts_size()+4)));
%}
enc_class JccShort (cmpOp cop, label labl) %{ // JCC
Label *l = $labl$$label;
emit_cc(cbuf, $primary, $cop$$cmpcode);
int disp = l->loc_pos() - (cbuf.insts_size()+1);
assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp");
emit_d8(cbuf, disp);
%}
enc_class enc_cmov(cmpOp cop ) %{ // CMOV enc_class enc_cmov(cmpOp cop ) %{ // CMOV
$$$emit8$primary; $$$emit8$primary;
emit_cc(cbuf, $secondary, $cop$$cmpcode); emit_cc(cbuf, $secondary, $cop$$cmpcode);
...@@ -13055,8 +13033,10 @@ instruct jmpDir(label labl) %{ ...@@ -13055,8 +13033,10 @@ instruct jmpDir(label labl) %{
ins_cost(300); ins_cost(300);
format %{ "JMP $labl" %} format %{ "JMP $labl" %}
size(5); size(5);
opcode(0xE9); ins_encode %{
ins_encode( OpcP, Lbl( labl ) ); Label* L = $labl$$label;
__ jmp(*L, false); // Always long jump
%}
ins_pipe( pipe_jmp ); ins_pipe( pipe_jmp );
%} %}
...@@ -13068,8 +13048,10 @@ instruct jmpCon(cmpOp cop, eFlagsReg cr, label labl) %{ ...@@ -13068,8 +13048,10 @@ instruct jmpCon(cmpOp cop, eFlagsReg cr, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "J$cop $labl" %} format %{ "J$cop $labl" %}
size(6); size(6);
opcode(0x0F, 0x80); ins_encode %{
ins_encode( Jcc( cop, labl) ); Label* L = $labl$$label;
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
%}
ins_pipe( pipe_jcc ); ins_pipe( pipe_jcc );
%} %}
...@@ -13081,8 +13063,10 @@ instruct jmpLoopEnd(cmpOp cop, eFlagsReg cr, label labl) %{ ...@@ -13081,8 +13063,10 @@ instruct jmpLoopEnd(cmpOp cop, eFlagsReg cr, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "J$cop $labl\t# Loop end" %} format %{ "J$cop $labl\t# Loop end" %}
size(6); size(6);
opcode(0x0F, 0x80); ins_encode %{
ins_encode( Jcc( cop, labl) ); Label* L = $labl$$label;
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
%}
ins_pipe( pipe_jcc ); ins_pipe( pipe_jcc );
%} %}
...@@ -13094,8 +13078,10 @@ instruct jmpLoopEndU(cmpOpU cop, eFlagsRegU cmp, label labl) %{ ...@@ -13094,8 +13078,10 @@ instruct jmpLoopEndU(cmpOpU cop, eFlagsRegU cmp, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "J$cop,u $labl\t# Loop end" %} format %{ "J$cop,u $labl\t# Loop end" %}
size(6); size(6);
opcode(0x0F, 0x80); ins_encode %{
ins_encode( Jcc( cop, labl) ); Label* L = $labl$$label;
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
%}
ins_pipe( pipe_jcc ); ins_pipe( pipe_jcc );
%} %}
...@@ -13106,8 +13092,10 @@ instruct jmpLoopEndUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ ...@@ -13106,8 +13092,10 @@ instruct jmpLoopEndUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{
ins_cost(200); ins_cost(200);
format %{ "J$cop,u $labl\t# Loop end" %} format %{ "J$cop,u $labl\t# Loop end" %}
size(6); size(6);
opcode(0x0F, 0x80); ins_encode %{
ins_encode( Jcc( cop, labl) ); Label* L = $labl$$label;
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
%}
ins_pipe( pipe_jcc ); ins_pipe( pipe_jcc );
%} %}
...@@ -13119,8 +13107,10 @@ instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{ ...@@ -13119,8 +13107,10 @@ instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "J$cop,u $labl" %} format %{ "J$cop,u $labl" %}
size(6); size(6);
opcode(0x0F, 0x80); ins_encode %{
ins_encode(Jcc(cop, labl)); Label* L = $labl$$label;
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
%}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
%} %}
...@@ -13131,8 +13121,10 @@ instruct jmpConUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ ...@@ -13131,8 +13121,10 @@ instruct jmpConUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{
ins_cost(200); ins_cost(200);
format %{ "J$cop,u $labl" %} format %{ "J$cop,u $labl" %}
size(6); size(6);
opcode(0x0F, 0x80); ins_encode %{
ins_encode(Jcc(cop, labl)); Label* L = $labl$$label;
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
%}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
%} %}
...@@ -13151,28 +13143,19 @@ instruct jmpConUCF2(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{ ...@@ -13151,28 +13143,19 @@ instruct jmpConUCF2(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{
$$emit$$"done:" $$emit$$"done:"
} }
%} %}
size(12);
opcode(0x0F, 0x80);
ins_encode %{ ins_encode %{
Label* l = $labl$$label; Label* l = $labl$$label;
$$$emit8$primary;
emit_cc(cbuf, $secondary, Assembler::parity);
int parity_disp = -1;
bool ok = false;
if ($cop$$cmpcode == Assembler::notEqual) { if ($cop$$cmpcode == Assembler::notEqual) {
// the two jumps 6 bytes apart so the jump distances are too __ jcc(Assembler::parity, *l, false);
parity_disp = l->loc_pos() - (cbuf.insts_size() + 4); __ jcc(Assembler::notEqual, *l, false);
} else if ($cop$$cmpcode == Assembler::equal) { } else if ($cop$$cmpcode == Assembler::equal) {
parity_disp = 6; Label done;
ok = true; __ jccb(Assembler::parity, done);
__ jcc(Assembler::equal, *l, false);
__ bind(done);
} else { } else {
ShouldNotReachHere(); ShouldNotReachHere();
} }
emit_d32(cbuf, parity_disp);
$$$emit8$primary;
emit_cc(cbuf, $secondary, $cop$$cmpcode);
int disp = l->loc_pos() - (cbuf.insts_size() + 4);
emit_d32(cbuf, disp);
%} %}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
%} %}
...@@ -13239,8 +13222,10 @@ instruct jmpDir_short(label labl) %{ ...@@ -13239,8 +13222,10 @@ instruct jmpDir_short(label labl) %{
ins_cost(300); ins_cost(300);
format %{ "JMP,s $labl" %} format %{ "JMP,s $labl" %}
size(2); size(2);
opcode(0xEB); ins_encode %{
ins_encode( OpcP, LblShort( labl ) ); Label* L = $labl$$label;
__ jmpb(*L);
%}
ins_pipe( pipe_jmp ); ins_pipe( pipe_jmp );
ins_short_branch(1); ins_short_branch(1);
%} %}
...@@ -13253,8 +13238,10 @@ instruct jmpCon_short(cmpOp cop, eFlagsReg cr, label labl) %{ ...@@ -13253,8 +13238,10 @@ instruct jmpCon_short(cmpOp cop, eFlagsReg cr, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "J$cop,s $labl" %} format %{ "J$cop,s $labl" %}
size(2); size(2);
opcode(0x70); ins_encode %{
ins_encode( JccShort( cop, labl) ); Label* L = $labl$$label;
__ jccb((Assembler::Condition)($cop$$cmpcode), *L);
%}
ins_pipe( pipe_jcc ); ins_pipe( pipe_jcc );
ins_short_branch(1); ins_short_branch(1);
%} %}
...@@ -13267,8 +13254,10 @@ instruct jmpLoopEnd_short(cmpOp cop, eFlagsReg cr, label labl) %{ ...@@ -13267,8 +13254,10 @@ instruct jmpLoopEnd_short(cmpOp cop, eFlagsReg cr, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "J$cop,s $labl\t# Loop end" %} format %{ "J$cop,s $labl\t# Loop end" %}
size(2); size(2);
opcode(0x70); ins_encode %{
ins_encode( JccShort( cop, labl) ); Label* L = $labl$$label;
__ jccb((Assembler::Condition)($cop$$cmpcode), *L);
%}
ins_pipe( pipe_jcc ); ins_pipe( pipe_jcc );
ins_short_branch(1); ins_short_branch(1);
%} %}
...@@ -13281,8 +13270,10 @@ instruct jmpLoopEndU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{ ...@@ -13281,8 +13270,10 @@ instruct jmpLoopEndU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "J$cop,us $labl\t# Loop end" %} format %{ "J$cop,us $labl\t# Loop end" %}
size(2); size(2);
opcode(0x70); ins_encode %{
ins_encode( JccShort( cop, labl) ); Label* L = $labl$$label;
__ jccb((Assembler::Condition)($cop$$cmpcode), *L);
%}
ins_pipe( pipe_jcc ); ins_pipe( pipe_jcc );
ins_short_branch(1); ins_short_branch(1);
%} %}
...@@ -13294,8 +13285,10 @@ instruct jmpLoopEndUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ ...@@ -13294,8 +13285,10 @@ instruct jmpLoopEndUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "J$cop,us $labl\t# Loop end" %} format %{ "J$cop,us $labl\t# Loop end" %}
size(2); size(2);
opcode(0x70); ins_encode %{
ins_encode( JccShort( cop, labl) ); Label* L = $labl$$label;
__ jccb((Assembler::Condition)($cop$$cmpcode), *L);
%}
ins_pipe( pipe_jcc ); ins_pipe( pipe_jcc );
ins_short_branch(1); ins_short_branch(1);
%} %}
...@@ -13308,8 +13301,10 @@ instruct jmpConU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{ ...@@ -13308,8 +13301,10 @@ instruct jmpConU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "J$cop,us $labl" %} format %{ "J$cop,us $labl" %}
size(2); size(2);
opcode(0x70); ins_encode %{
ins_encode( JccShort( cop, labl) ); Label* L = $labl$$label;
__ jccb((Assembler::Condition)($cop$$cmpcode), *L);
%}
ins_pipe( pipe_jcc ); ins_pipe( pipe_jcc );
ins_short_branch(1); ins_short_branch(1);
%} %}
...@@ -13321,8 +13316,10 @@ instruct jmpConUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ ...@@ -13321,8 +13316,10 @@ instruct jmpConUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "J$cop,us $labl" %} format %{ "J$cop,us $labl" %}
size(2); size(2);
opcode(0x70); ins_encode %{
ins_encode( JccShort( cop, labl) ); Label* L = $labl$$label;
__ jccb((Assembler::Condition)($cop$$cmpcode), *L);
%}
ins_pipe( pipe_jcc ); ins_pipe( pipe_jcc );
ins_short_branch(1); ins_short_branch(1);
%} %}
...@@ -13343,24 +13340,19 @@ instruct jmpConUCF2_short(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{ ...@@ -13343,24 +13340,19 @@ instruct jmpConUCF2_short(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{
} }
%} %}
size(4); size(4);
opcode(0x70);
ins_encode %{ ins_encode %{
Label* l = $labl$$label; Label* l = $labl$$label;
emit_cc(cbuf, $primary, Assembler::parity);
int parity_disp = -1;
if ($cop$$cmpcode == Assembler::notEqual) { if ($cop$$cmpcode == Assembler::notEqual) {
parity_disp = l->loc_pos() - (cbuf.insts_size() + 1); __ jccb(Assembler::parity, *l);
__ jccb(Assembler::notEqual, *l);
} else if ($cop$$cmpcode == Assembler::equal) { } else if ($cop$$cmpcode == Assembler::equal) {
parity_disp = 2; Label done;
__ jccb(Assembler::parity, done);
__ jccb(Assembler::equal, *l);
__ bind(done);
} else { } else {
ShouldNotReachHere(); ShouldNotReachHere();
} }
emit_d8(cbuf, parity_disp);
emit_cc(cbuf, $primary, $cop$$cmpcode);
int disp = l->loc_pos() - (cbuf.insts_size() + 1);
emit_d8(cbuf, disp);
assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp");
assert(-128 <= parity_disp && parity_disp <= 127, "Displacement too large for short jmp");
%} %}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
ins_short_branch(1); ins_short_branch(1);
......
...@@ -1966,7 +1966,12 @@ const uint Matcher::vector_ideal_reg(void) { ...@@ -1966,7 +1966,12 @@ const uint Matcher::vector_ideal_reg(void) {
// //
// NOTE: If the platform does not provide any short branch variants, then // NOTE: If the platform does not provide any short branch variants, then
// this method should return false for offset 0. // this method should return false for offset 0.
bool Matcher::is_short_branch_offset(int rule, int offset) { bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
// The passed offset is relative to address of the branch.
// On 86 a branch displacement is calculated relative to address
// of a next instruction.
offset -= br_size;
// the short version of jmpConUCF2 contains multiple branches, // the short version of jmpConUCF2 contains multiple branches,
// making the reach slightly less // making the reach slightly less
if (rule == jmpConUCF2_rule) if (rule == jmpConUCF2_rule)
...@@ -2426,22 +2431,6 @@ encode %{ ...@@ -2426,22 +2431,6 @@ encode %{
} }
%} %}
enc_class Lbl(label labl)
%{
// GOTO
Label* l = $labl$$label;
emit_d32(cbuf, (l->loc_pos() - (cbuf.insts_size() + 4)));
%}
enc_class LblShort(label labl)
%{
// GOTO
Label* l = $labl$$label;
int disp = l->loc_pos() - (cbuf.insts_size() + 1);
assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp");
emit_d8(cbuf, disp);
%}
enc_class opc2_reg(rRegI dst) enc_class opc2_reg(rRegI dst)
%{ %{
// BSWAP // BSWAP
...@@ -2460,25 +2449,6 @@ encode %{ ...@@ -2460,25 +2449,6 @@ encode %{
emit_rm(cbuf, 0x3, $secondary, $div$$reg & 7); emit_rm(cbuf, 0x3, $secondary, $div$$reg & 7);
%} %}
enc_class Jcc(cmpOp cop, label labl)
%{
// JCC
Label* l = $labl$$label;
$$$emit8$primary;
emit_cc(cbuf, $secondary, $cop$$cmpcode);
emit_d32(cbuf, (l->loc_pos() - (cbuf.insts_size() + 4)));
%}
enc_class JccShort (cmpOp cop, label labl)
%{
// JCC
Label *l = $labl$$label;
emit_cc(cbuf, $primary, $cop$$cmpcode);
int disp = l->loc_pos() - (cbuf.insts_size() + 1);
assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp");
emit_d8(cbuf, disp);
%}
enc_class enc_cmov(cmpOp cop) enc_class enc_cmov(cmpOp cop)
%{ %{
// CMOV // CMOV
...@@ -12011,8 +11981,10 @@ instruct jmpDir(label labl) ...@@ -12011,8 +11981,10 @@ instruct jmpDir(label labl)
ins_cost(300); ins_cost(300);
format %{ "jmp $labl" %} format %{ "jmp $labl" %}
size(5); size(5);
opcode(0xE9); ins_encode %{
ins_encode(OpcP, Lbl(labl)); Label* L = $labl$$label;
__ jmp(*L, false); // Always long jump
%}
ins_pipe(pipe_jmp); ins_pipe(pipe_jmp);
%} %}
...@@ -12025,8 +11997,10 @@ instruct jmpCon(cmpOp cop, rFlagsReg cr, label labl) ...@@ -12025,8 +11997,10 @@ instruct jmpCon(cmpOp cop, rFlagsReg cr, label labl)
ins_cost(300); ins_cost(300);
format %{ "j$cop $labl" %} format %{ "j$cop $labl" %}
size(6); size(6);
opcode(0x0F, 0x80); ins_encode %{
ins_encode(Jcc(cop, labl)); Label* L = $labl$$label;
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
%}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
%} %}
...@@ -12039,8 +12013,10 @@ instruct jmpLoopEnd(cmpOp cop, rFlagsReg cr, label labl) ...@@ -12039,8 +12013,10 @@ instruct jmpLoopEnd(cmpOp cop, rFlagsReg cr, label labl)
ins_cost(300); ins_cost(300);
format %{ "j$cop $labl\t# loop end" %} format %{ "j$cop $labl\t# loop end" %}
size(6); size(6);
opcode(0x0F, 0x80); ins_encode %{
ins_encode(Jcc(cop, labl)); Label* L = $labl$$label;
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
%}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
%} %}
...@@ -12052,8 +12028,10 @@ instruct jmpLoopEndU(cmpOpU cop, rFlagsRegU cmp, label labl) %{ ...@@ -12052,8 +12028,10 @@ instruct jmpLoopEndU(cmpOpU cop, rFlagsRegU cmp, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "j$cop,u $labl\t# loop end" %} format %{ "j$cop,u $labl\t# loop end" %}
size(6); size(6);
opcode(0x0F, 0x80); ins_encode %{
ins_encode(Jcc(cop, labl)); Label* L = $labl$$label;
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
%}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
%} %}
...@@ -12064,8 +12042,10 @@ instruct jmpLoopEndUCF(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{ ...@@ -12064,8 +12042,10 @@ instruct jmpLoopEndUCF(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{
ins_cost(200); ins_cost(200);
format %{ "j$cop,u $labl\t# loop end" %} format %{ "j$cop,u $labl\t# loop end" %}
size(6); size(6);
opcode(0x0F, 0x80); ins_encode %{
ins_encode(Jcc(cop, labl)); Label* L = $labl$$label;
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
%}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
%} %}
...@@ -12077,8 +12057,10 @@ instruct jmpConU(cmpOpU cop, rFlagsRegU cmp, label labl) %{ ...@@ -12077,8 +12057,10 @@ instruct jmpConU(cmpOpU cop, rFlagsRegU cmp, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "j$cop,u $labl" %} format %{ "j$cop,u $labl" %}
size(6); size(6);
opcode(0x0F, 0x80); ins_encode %{
ins_encode(Jcc(cop, labl)); Label* L = $labl$$label;
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
%}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
%} %}
...@@ -12089,8 +12071,10 @@ instruct jmpConUCF(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{ ...@@ -12089,8 +12071,10 @@ instruct jmpConUCF(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{
ins_cost(200); ins_cost(200);
format %{ "j$cop,u $labl" %} format %{ "j$cop,u $labl" %}
size(6); size(6);
opcode(0x0F, 0x80); ins_encode %{
ins_encode(Jcc(cop, labl)); Label* L = $labl$$label;
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
%}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
%} %}
...@@ -12109,26 +12093,19 @@ instruct jmpConUCF2(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{ ...@@ -12109,26 +12093,19 @@ instruct jmpConUCF2(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{
$$emit$$"done:" $$emit$$"done:"
} }
%} %}
size(12);
opcode(0x0F, 0x80);
ins_encode %{ ins_encode %{
Label* l = $labl$$label; Label* l = $labl$$label;
$$$emit8$primary;
emit_cc(cbuf, $secondary, Assembler::parity);
int parity_disp = -1;
if ($cop$$cmpcode == Assembler::notEqual) { if ($cop$$cmpcode == Assembler::notEqual) {
// the two jumps 6 bytes apart so the jump distances are too __ jcc(Assembler::parity, *l, false);
parity_disp = l->loc_pos() - (cbuf.insts_size() + 4); __ jcc(Assembler::notEqual, *l, false);
} else if ($cop$$cmpcode == Assembler::equal) { } else if ($cop$$cmpcode == Assembler::equal) {
parity_disp = 6; Label done;
__ jccb(Assembler::parity, done);
__ jcc(Assembler::equal, *l, false);
__ bind(done);
} else { } else {
ShouldNotReachHere(); ShouldNotReachHere();
} }
emit_d32(cbuf, parity_disp);
$$$emit8$primary;
emit_cc(cbuf, $secondary, $cop$$cmpcode);
int disp = l->loc_pos() - (cbuf.insts_size() + 4);
emit_d32(cbuf, disp);
%} %}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
%} %}
...@@ -12204,8 +12181,10 @@ instruct jmpDir_short(label labl) %{ ...@@ -12204,8 +12181,10 @@ instruct jmpDir_short(label labl) %{
ins_cost(300); ins_cost(300);
format %{ "jmp,s $labl" %} format %{ "jmp,s $labl" %}
size(2); size(2);
opcode(0xEB); ins_encode %{
ins_encode(OpcP, LblShort(labl)); Label* L = $labl$$label;
__ jmpb(*L);
%}
ins_pipe(pipe_jmp); ins_pipe(pipe_jmp);
ins_short_branch(1); ins_short_branch(1);
%} %}
...@@ -12218,8 +12197,10 @@ instruct jmpCon_short(cmpOp cop, rFlagsReg cr, label labl) %{ ...@@ -12218,8 +12197,10 @@ instruct jmpCon_short(cmpOp cop, rFlagsReg cr, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "j$cop,s $labl" %} format %{ "j$cop,s $labl" %}
size(2); size(2);
opcode(0x70); ins_encode %{
ins_encode(JccShort(cop, labl)); Label* L = $labl$$label;
__ jccb((Assembler::Condition)($cop$$cmpcode), *L);
%}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
ins_short_branch(1); ins_short_branch(1);
%} %}
...@@ -12232,8 +12213,10 @@ instruct jmpLoopEnd_short(cmpOp cop, rFlagsReg cr, label labl) %{ ...@@ -12232,8 +12213,10 @@ instruct jmpLoopEnd_short(cmpOp cop, rFlagsReg cr, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "j$cop,s $labl\t# loop end" %} format %{ "j$cop,s $labl\t# loop end" %}
size(2); size(2);
opcode(0x70); ins_encode %{
ins_encode(JccShort(cop, labl)); Label* L = $labl$$label;
__ jccb((Assembler::Condition)($cop$$cmpcode), *L);
%}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
ins_short_branch(1); ins_short_branch(1);
%} %}
...@@ -12246,8 +12229,10 @@ instruct jmpLoopEndU_short(cmpOpU cop, rFlagsRegU cmp, label labl) %{ ...@@ -12246,8 +12229,10 @@ instruct jmpLoopEndU_short(cmpOpU cop, rFlagsRegU cmp, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "j$cop,us $labl\t# loop end" %} format %{ "j$cop,us $labl\t# loop end" %}
size(2); size(2);
opcode(0x70); ins_encode %{
ins_encode(JccShort(cop, labl)); Label* L = $labl$$label;
__ jccb((Assembler::Condition)($cop$$cmpcode), *L);
%}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
ins_short_branch(1); ins_short_branch(1);
%} %}
...@@ -12259,8 +12244,10 @@ instruct jmpLoopEndUCF_short(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{ ...@@ -12259,8 +12244,10 @@ instruct jmpLoopEndUCF_short(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "j$cop,us $labl\t# loop end" %} format %{ "j$cop,us $labl\t# loop end" %}
size(2); size(2);
opcode(0x70); ins_encode %{
ins_encode(JccShort(cop, labl)); Label* L = $labl$$label;
__ jccb((Assembler::Condition)($cop$$cmpcode), *L);
%}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
ins_short_branch(1); ins_short_branch(1);
%} %}
...@@ -12273,8 +12260,10 @@ instruct jmpConU_short(cmpOpU cop, rFlagsRegU cmp, label labl) %{ ...@@ -12273,8 +12260,10 @@ instruct jmpConU_short(cmpOpU cop, rFlagsRegU cmp, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "j$cop,us $labl" %} format %{ "j$cop,us $labl" %}
size(2); size(2);
opcode(0x70); ins_encode %{
ins_encode(JccShort(cop, labl)); Label* L = $labl$$label;
__ jccb((Assembler::Condition)($cop$$cmpcode), *L);
%}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
ins_short_branch(1); ins_short_branch(1);
%} %}
...@@ -12286,8 +12275,10 @@ instruct jmpConUCF_short(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{ ...@@ -12286,8 +12275,10 @@ instruct jmpConUCF_short(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{
ins_cost(300); ins_cost(300);
format %{ "j$cop,us $labl" %} format %{ "j$cop,us $labl" %}
size(2); size(2);
opcode(0x70); ins_encode %{
ins_encode(JccShort(cop, labl)); Label* L = $labl$$label;
__ jccb((Assembler::Condition)($cop$$cmpcode), *L);
%}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
ins_short_branch(1); ins_short_branch(1);
%} %}
...@@ -12308,24 +12299,19 @@ instruct jmpConUCF2_short(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{ ...@@ -12308,24 +12299,19 @@ instruct jmpConUCF2_short(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{
} }
%} %}
size(4); size(4);
opcode(0x70);
ins_encode %{ ins_encode %{
Label* l = $labl$$label; Label* l = $labl$$label;
emit_cc(cbuf, $primary, Assembler::parity);
int parity_disp = -1;
if ($cop$$cmpcode == Assembler::notEqual) { if ($cop$$cmpcode == Assembler::notEqual) {
parity_disp = l->loc_pos() - (cbuf.insts_size() + 1); __ jccb(Assembler::parity, *l);
__ jccb(Assembler::notEqual, *l);
} else if ($cop$$cmpcode == Assembler::equal) { } else if ($cop$$cmpcode == Assembler::equal) {
parity_disp = 2; Label done;
__ jccb(Assembler::parity, done);
__ jccb(Assembler::equal, *l);
__ bind(done);
} else { } else {
ShouldNotReachHere(); ShouldNotReachHere();
} }
emit_d8(cbuf, parity_disp);
emit_cc(cbuf, $primary, $cop$$cmpcode);
int disp = l->loc_pos() - (cbuf.insts_size() + 1);
emit_d8(cbuf, disp);
assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp");
assert(-128 <= parity_disp && parity_disp <= 127, "Displacement too large for short jmp");
%} %}
ins_pipe(pipe_jcc); ins_pipe(pipe_jcc);
ins_short_branch(1); ins_short_branch(1);
......
...@@ -154,7 +154,7 @@ void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { ...@@ -154,7 +154,7 @@ void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
return 5; return MachNode::size(ra_);
} }
%} %}
...@@ -167,7 +167,8 @@ void MachBreakpointNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { ...@@ -167,7 +167,8 @@ void MachBreakpointNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
} }
uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const { uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const {
return 5; // distance could be far and requires load and call through register
return MachNode::size(ra_);
} }
%} %}
...@@ -161,7 +161,7 @@ void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { ...@@ -161,7 +161,7 @@ void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
return 5; return MachNode::size(ra_);
} }
%} %}
...@@ -180,7 +180,8 @@ void MachBreakpointNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const ...@@ -180,7 +180,8 @@ void MachBreakpointNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const
{ {
return 5; // distance could be far and requires load and call through register
return MachNode::size(ra_);
} }
%} %}
...@@ -1181,6 +1181,34 @@ bool InstructForm::check_branch_variant(ArchDesc &AD, InstructForm *short_branch ...@@ -1181,6 +1181,34 @@ bool InstructForm::check_branch_variant(ArchDesc &AD, InstructForm *short_branch
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)) {
// The instructions are equivalent. // The instructions are equivalent.
// Now verify that both instructions have the same parameters and
// the same effects. Both branch forms should have the same inputs
// and resulting projections to correctly replace a long branch node
// with corresponding short branch node during code generation.
bool different = false;
if (short_branch->_components.count() != _components.count()) {
different = true;
} else if (_components.count() > 0) {
short_branch->_components.reset();
_components.reset();
Component *comp;
while ((comp = _components.iter()) != NULL) {
Component *short_comp = short_branch->_components.iter();
if (short_comp == NULL ||
short_comp->_type != comp->_type ||
short_comp->_usedef != comp->_usedef) {
different = true;
break;
}
}
if (short_branch->_components.iter() != NULL)
different = true;
}
if (different) {
globalAD->syntax_err(short_branch->_linenum, "Instruction %s and its short form %s have different parameters\n", _ident, short_branch->_ident);
}
if (AD._short_branch_debug) { if (AD._short_branch_debug) {
fprintf(stderr, "Instruction %s has short form %s\n", _ident, short_branch->_ident); fprintf(stderr, "Instruction %s has short form %s\n", _ident, short_branch->_ident);
} }
......
...@@ -1536,12 +1536,16 @@ void ArchDesc::declareClasses(FILE *fp) { ...@@ -1536,12 +1536,16 @@ void ArchDesc::declareClasses(FILE *fp) {
// Each instruction attribute results in a virtual call of same name. // Each instruction attribute results in a virtual call of same name.
// The ins_cost is not handled here. // The ins_cost is not handled here.
Attribute *attr = instr->_attribs; Attribute *attr = instr->_attribs;
bool avoid_back_to_back = false;
while (attr != NULL) { while (attr != NULL) {
if (strcmp(attr->_ident,"ins_cost") && if (strcmp(attr->_ident,"ins_cost") &&
strcmp(attr->_ident,"ins_short_branch")) { strcmp(attr->_ident,"ins_short_branch")) {
fprintf(fp," int %s() const { return %s; }\n", fprintf(fp," int %s() const { return %s; }\n",
attr->_ident, attr->_val); attr->_ident, attr->_val);
} }
// Check value for ins_avoid_back_to_back, and if it is true (1), set the flag
if (!strcmp(attr->_ident,"ins_avoid_back_to_back") && attr->int_val(*this) != 0)
avoid_back_to_back = true;
attr = (Attribute *)attr->_next; attr = (Attribute *)attr->_next;
} }
...@@ -1704,6 +1708,16 @@ void ArchDesc::declareClasses(FILE *fp) { ...@@ -1704,6 +1708,16 @@ void ArchDesc::declareClasses(FILE *fp) {
} }
} }
// flag: if this instruction should not be generated back to back.
if ( avoid_back_to_back ) {
if ( node_flags_set ) {
fprintf(fp," | Flag_avoid_back_to_back");
} else {
fprintf(fp,"init_flags(Flag_avoid_back_to_back");
node_flags_set = true;
}
}
// Check if machine instructions that USE memory, but do not DEF memory, // Check if machine instructions that USE memory, but do not DEF memory,
// depend upon a node that defines memory in machine-independent graph. // depend upon a node that defines memory in machine-independent graph.
if ( instr->needs_anti_dependence_check(_globalNames) ) { if ( instr->needs_anti_dependence_check(_globalNames) ) {
......
...@@ -80,35 +80,37 @@ void Block_List::print() { ...@@ -80,35 +80,37 @@ void Block_List::print() {
uint Block::code_alignment() { uint Block::code_alignment() {
// Check for Root block // Check for Root block
if( _pre_order == 0 ) return CodeEntryAlignment; if (_pre_order == 0) return CodeEntryAlignment;
// Check for Start block // Check for Start block
if( _pre_order == 1 ) return InteriorEntryAlignment; if (_pre_order == 1) return InteriorEntryAlignment;
// Check for loop alignment // Check for loop alignment
if (has_loop_alignment()) return loop_alignment(); if (has_loop_alignment()) return loop_alignment();
return 1; // no particular alignment return relocInfo::addr_unit(); // no particular alignment
} }
uint Block::compute_loop_alignment() { uint Block::compute_loop_alignment() {
Node *h = head(); Node *h = head();
if( h->is_Loop() && h->as_Loop()->is_inner_loop() ) { int unit_sz = relocInfo::addr_unit();
if (h->is_Loop() && h->as_Loop()->is_inner_loop()) {
// Pre- and post-loops have low trip count so do not bother with // Pre- and post-loops have low trip count so do not bother with
// NOPs for align loop head. The constants are hidden from tuning // NOPs for align loop head. The constants are hidden from tuning
// but only because my "divide by 4" heuristic surely gets nearly // but only because my "divide by 4" heuristic surely gets nearly
// all possible gain (a "do not align at all" heuristic has a // all possible gain (a "do not align at all" heuristic has a
// chance of getting a really tiny gain). // chance of getting a really tiny gain).
if( h->is_CountedLoop() && (h->as_CountedLoop()->is_pre_loop() || if (h->is_CountedLoop() && (h->as_CountedLoop()->is_pre_loop() ||
h->as_CountedLoop()->is_post_loop()) ) h->as_CountedLoop()->is_post_loop())) {
return (OptoLoopAlignment > 4) ? (OptoLoopAlignment>>2) : 1; return (OptoLoopAlignment > 4*unit_sz) ? (OptoLoopAlignment>>2) : unit_sz;
}
// Loops with low backedge frequency should not be aligned. // Loops with low backedge frequency should not be aligned.
Node *n = h->in(LoopNode::LoopBackControl)->in(0); Node *n = h->in(LoopNode::LoopBackControl)->in(0);
if( n->is_MachIf() && n->as_MachIf()->_prob < 0.01 ) { if (n->is_MachIf() && n->as_MachIf()->_prob < 0.01) {
return 1; // Loop does not loop, more often than not! return unit_sz; // Loop does not loop, more often than not!
} }
return OptoLoopAlignment; // Otherwise align loop head return OptoLoopAlignment; // Otherwise align loop head
} }
return 1; // no particular alignment return unit_sz; // no particular alignment
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
...@@ -271,55 +273,55 @@ bool Block::is_uncommon( Block_Array &bbs ) const { ...@@ -271,55 +273,55 @@ bool Block::is_uncommon( Block_Array &bbs ) const {
//------------------------------dump------------------------------------------- //------------------------------dump-------------------------------------------
#ifndef PRODUCT #ifndef PRODUCT
void Block::dump_bidx(const Block* orig) const { void Block::dump_bidx(const Block* orig, outputStream* st) const {
if (_pre_order) tty->print("B%d",_pre_order); if (_pre_order) st->print("B%d",_pre_order);
else tty->print("N%d", head()->_idx); else st->print("N%d", head()->_idx);
if (Verbose && orig != this) { if (Verbose && orig != this) {
// Dump the original block's idx // Dump the original block's idx
tty->print(" ("); st->print(" (");
orig->dump_bidx(orig); orig->dump_bidx(orig, st);
tty->print(")"); st->print(")");
} }
} }
void Block::dump_pred(const Block_Array *bbs, Block* orig) const { void Block::dump_pred(const Block_Array *bbs, Block* orig, outputStream* st) const {
if (is_connector()) { if (is_connector()) {
for (uint i=1; i<num_preds(); i++) { for (uint i=1; i<num_preds(); i++) {
Block *p = ((*bbs)[pred(i)->_idx]); Block *p = ((*bbs)[pred(i)->_idx]);
p->dump_pred(bbs, orig); p->dump_pred(bbs, orig, st);
} }
} else { } else {
dump_bidx(orig); dump_bidx(orig, st);
tty->print(" "); st->print(" ");
} }
} }
void Block::dump_head( const Block_Array *bbs ) const { void Block::dump_head( const Block_Array *bbs, outputStream* st ) const {
// Print the basic block // Print the basic block
dump_bidx(this); dump_bidx(this, st);
tty->print(": #\t"); st->print(": #\t");
// Print the incoming CFG edges and the outgoing CFG edges // Print the incoming CFG edges and the outgoing CFG edges
for( uint i=0; i<_num_succs; i++ ) { for( uint i=0; i<_num_succs; i++ ) {
non_connector_successor(i)->dump_bidx(_succs[i]); non_connector_successor(i)->dump_bidx(_succs[i], st);
tty->print(" "); st->print(" ");
} }
tty->print("<- "); st->print("<- ");
if( head()->is_block_start() ) { if( head()->is_block_start() ) {
for (uint i=1; i<num_preds(); i++) { for (uint i=1; i<num_preds(); i++) {
Node *s = pred(i); Node *s = pred(i);
if (bbs) { if (bbs) {
Block *p = (*bbs)[s->_idx]; Block *p = (*bbs)[s->_idx];
p->dump_pred(bbs, p); p->dump_pred(bbs, p, st);
} else { } else {
while (!s->is_block_start()) while (!s->is_block_start())
s = s->in(0); s = s->in(0);
tty->print("N%d ", s->_idx ); st->print("N%d ", s->_idx );
} }
} }
} else } else
tty->print("BLOCK HEAD IS JUNK "); st->print("BLOCK HEAD IS JUNK ");
// Print loop, if any // Print loop, if any
const Block *bhead = this; // Head of self-loop const Block *bhead = this; // Head of self-loop
...@@ -330,24 +332,24 @@ void Block::dump_head( const Block_Array *bbs ) const { ...@@ -330,24 +332,24 @@ void Block::dump_head( const Block_Array *bbs ) const {
while (bx->is_connector()) { while (bx->is_connector()) {
bx = (*bbs)[bx->pred(1)->_idx]; bx = (*bbs)[bx->pred(1)->_idx];
} }
tty->print("\tLoop: B%d-B%d ", bhead->_pre_order, bx->_pre_order); st->print("\tLoop: B%d-B%d ", bhead->_pre_order, bx->_pre_order);
// Dump any loop-specific bits, especially for CountedLoops. // Dump any loop-specific bits, especially for CountedLoops.
loop->dump_spec(tty); loop->dump_spec(st);
} else if (has_loop_alignment()) { } else if (has_loop_alignment()) {
tty->print(" top-of-loop"); st->print(" top-of-loop");
} }
tty->print(" Freq: %g",_freq); st->print(" Freq: %g",_freq);
if( Verbose || WizardMode ) { if( Verbose || WizardMode ) {
tty->print(" IDom: %d/#%d", _idom ? _idom->_pre_order : 0, _dom_depth); st->print(" IDom: %d/#%d", _idom ? _idom->_pre_order : 0, _dom_depth);
tty->print(" RegPressure: %d",_reg_pressure); st->print(" RegPressure: %d",_reg_pressure);
tty->print(" IHRP Index: %d",_ihrp_index); st->print(" IHRP Index: %d",_ihrp_index);
tty->print(" FRegPressure: %d",_freg_pressure); st->print(" FRegPressure: %d",_freg_pressure);
tty->print(" FHRP Index: %d",_fhrp_index); st->print(" FHRP Index: %d",_fhrp_index);
} }
tty->print_cr(""); st->print_cr("");
} }
void Block::dump() const { dump(0); } void Block::dump() const { dump(NULL); }
void Block::dump( const Block_Array *bbs ) const { void Block::dump( const Block_Array *bbs ) const {
dump_head(bbs); dump_head(bbs);
...@@ -441,9 +443,9 @@ uint PhaseCFG::build_cfg() { ...@@ -441,9 +443,9 @@ uint PhaseCFG::build_cfg() {
Block *bb = new (_bbs._arena) Block(_bbs._arena,p); Block *bb = new (_bbs._arena) Block(_bbs._arena,p);
_bbs.map(p->_idx,bb); _bbs.map(p->_idx,bb);
_bbs.map(x->_idx,bb); _bbs.map(x->_idx,bb);
if( x != p ) // Only for root is x == p if( x != p ) { // Only for root is x == p
bb->_nodes.push((Node*)x); bb->_nodes.push((Node*)x);
}
// Now handle predecessors // Now handle predecessors
++sum; // Count 1 for self block ++sum; // Count 1 for self block
uint cnt = bb->num_preds(); uint cnt = bb->num_preds();
......
...@@ -329,10 +329,10 @@ class Block : public CFGElement { ...@@ -329,10 +329,10 @@ class Block : public CFGElement {
#ifndef PRODUCT #ifndef PRODUCT
// Debugging print of basic block // Debugging print of basic block
void dump_bidx(const Block* orig) const; void dump_bidx(const Block* orig, outputStream* st = tty) const;
void dump_pred(const Block_Array *bbs, Block* orig) const; void dump_pred(const Block_Array *bbs, Block* orig, outputStream* st = tty) const;
void dump_head( const Block_Array *bbs ) const; void dump_head( const Block_Array *bbs, outputStream* st = tty ) const;
void dump( ) const; void dump() const;
void dump( const Block_Array *bbs ) const; void dump( const Block_Array *bbs ) const;
#endif #endif
}; };
......
...@@ -785,11 +785,17 @@ class Compile : public Phase { ...@@ -785,11 +785,17 @@ class Compile : public Phase {
// Process an OopMap Element while emitting nodes // Process an OopMap Element while emitting nodes
void Process_OopMap_Node(MachNode *mach, int code_offset); void Process_OopMap_Node(MachNode *mach, int code_offset);
// Initialize code buffer
CodeBuffer* init_buffer(uint* blk_starts);
// Write out basic block data to code buffer // Write out basic block data to code buffer
void Fill_buffer(); void fill_buffer(CodeBuffer* cb, uint* blk_starts);
// Determine which variable sized branches can be shortened // Determine which variable sized branches can be shortened
void Shorten_branches(Label *labels, int& code_size, int& reloc_size, int& stub_size); void shorten_branches(uint* blk_starts, int& code_size, int& reloc_size, int& stub_size);
// Inserts nops where needed and final shorten branches.
void finalize_offsets_and_shorten(uint* blk_starts);
// Compute the size of first NumberOfLoopInstrToAlign instructions // Compute the size of first NumberOfLoopInstrToAlign instructions
// at the head of a loop. // at the head of a loop.
......
...@@ -188,6 +188,9 @@ public: ...@@ -188,6 +188,9 @@ public:
virtual MachNode *short_branch_version(Compile* C) { return NULL; } virtual MachNode *short_branch_version(Compile* C) { return NULL; }
bool may_be_short_branch() const { return (flags() & Flag_may_be_short_branch) != 0; } bool may_be_short_branch() const { return (flags() & Flag_may_be_short_branch) != 0; }
// Avoid back to back some instructions on some CPUs.
bool avoid_back_to_back() const { return (flags() & Flag_avoid_back_to_back) != 0; }
// First index in _in[] corresponding to operand, or -1 if there is none // First index in _in[] corresponding to operand, or -1 if there is none
int operand_index(uint operand) const; int operand_index(uint operand) const;
......
...@@ -351,7 +351,7 @@ public: ...@@ -351,7 +351,7 @@ public:
virtual int regnum_to_fpu_offset(int regnum); virtual int regnum_to_fpu_offset(int regnum);
// Is this branch offset small enough to be addressed by a short branch? // Is this branch offset small enough to be addressed by a short branch?
bool is_short_branch_offset(int rule, int offset); bool is_short_branch_offset(int rule, int br_size, int offset);
// Optional scaling for the parameter to the ClearArray/CopyArray node. // Optional scaling for the parameter to the ClearArray/CopyArray node.
static const bool init_array_count_is_in_bytes; static const bool init_array_count_is_in_bytes;
......
...@@ -637,7 +637,8 @@ public: ...@@ -637,7 +637,8 @@ public:
Flag_is_Branch = Flag_is_cisc_alternate << 1, Flag_is_Branch = Flag_is_cisc_alternate << 1,
Flag_is_dead_loop_safe = Flag_is_Branch << 1, Flag_is_dead_loop_safe = Flag_is_Branch << 1,
Flag_may_be_short_branch = Flag_is_dead_loop_safe << 1, Flag_may_be_short_branch = Flag_is_dead_loop_safe << 1,
_max_flags = (Flag_may_be_short_branch << 1) - 1 // allow flags combination Flag_avoid_back_to_back = Flag_may_be_short_branch << 1,
_max_flags = (Flag_avoid_back_to_back << 1) - 1 // allow flags combination
}; };
private: private:
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册