提交 2161afbd 编写于 作者: K kvn

7079317: Incorrect branch's destination block in PrintoOptoAssembly output

Summary: save/restore label and block in scratch_emit_size()
Reviewed-by: never
上级 af93316f
......@@ -331,6 +331,11 @@ void ArchDesc::inspectInstructions() {
// Find result type for match
const char *result = instr->reduce_result();
if ( instr->is_ideal_branch() && instr->label_position() == -1 ||
!instr->is_ideal_branch() && instr->label_position() != -1) {
syntax_err(instr->_linenum, "%s: Only branches to a label are supported\n", rootOp);
}
Attribute *attr = instr->_attribs;
while (attr != NULL) {
if (strcmp(attr->_ident,"ins_short_branch") == 0 &&
......
......@@ -340,12 +340,11 @@ bool InstructForm::is_ideal_jump() const {
return _matrule->is_ideal_jump();
}
// Return 'true' if instruction matches ideal 'If' | 'Goto' |
// 'CountedLoopEnd' | 'Jump'
// Return 'true' if instruction matches ideal 'If' | 'Goto' | 'CountedLoopEnd'
bool InstructForm::is_ideal_branch() const {
if( _matrule == NULL ) return false;
return _matrule->is_ideal_if() || _matrule->is_ideal_goto() || _matrule->is_ideal_jump();
return _matrule->is_ideal_if() || _matrule->is_ideal_goto();
}
......@@ -383,7 +382,7 @@ bool InstructForm::is_ideal_nop() const {
bool InstructForm::is_ideal_control() const {
if ( ! _matrule) return false;
return is_ideal_return() || is_ideal_branch() || is_ideal_halt();
return is_ideal_return() || is_ideal_branch() || _matrule->is_ideal_jump() || is_ideal_halt();
}
// Return 'true' if this instruction matches an ideal 'Call' node
......
......@@ -3094,6 +3094,13 @@ void ArchDesc::defineClasses(FILE *fp) {
fprintf(fp," oper->_label = label;\n");
fprintf(fp," oper->_block_num = block_num;\n");
fprintf(fp,"}\n");
// Save the label
fprintf(fp,"void %sNode::save_label( Label** label, uint* block_num ) {\n", instr->_ident);
fprintf(fp," labelOper* oper = (labelOper*)(opnd_array(%d));\n",
label_position );
fprintf(fp," *label = oper->_label;\n");
fprintf(fp," *block_num = oper->_block_num;\n");
fprintf(fp,"}\n");
}
}
......
......@@ -1519,8 +1519,9 @@ void ArchDesc::declareClasses(FILE *fp) {
// Declare Node::methods that set operand Label's contents
int label_position = instr->label_position();
if( label_position != -1 ) {
// Set the label, stored in labelOper::_branch_label
// Set/Save the label, stored in labelOper::_branch_label
fprintf(fp," virtual void label_set( Label* label, uint block_num );\n");
fprintf(fp," virtual void save_label( Label** label, uint* block_num );\n");
}
// If this instruction contains a methodOper
......@@ -1678,16 +1679,6 @@ void ArchDesc::declareClasses(FILE *fp) {
}
}
// flag: if instruction matches 'If' | 'Goto' | 'CountedLoopEnd | 'Jump'
if ( instr->is_ideal_branch() ) {
if ( node_flags_set ) {
fprintf(fp," | Flag_is_Branch");
} else {
fprintf(fp,"init_flags(Flag_is_Branch");
node_flags_set = true;
}
}
// flag: if this instruction is cisc alternate
if ( can_cisc_spill() && instr->is_cisc_alternate() ) {
if ( node_flags_set ) {
......
......@@ -839,7 +839,7 @@ void PhaseCFG::fixup_flow() {
// Make sure we TRUE branch to the target
if( proj0->Opcode() == Op_IfFalse ) {
iff->negate();
iff->as_MachIf()->negate();
}
b->_nodes.pop(); // Remove IfFalse & IfTrue projections
......
......@@ -519,15 +519,18 @@ uint Compile::scratch_emit_size(const Node* n) {
// Do the emission.
Label fakeL; // Fake label for branch instructions.
bool is_branch = n->is_Branch() && n->as_Mach()->ideal_Opcode() != Op_Jump;
Label* saveL = NULL;
uint save_bnum = 0;
bool is_branch = n->is_MachBranch();
if (is_branch) {
MacroAssembler masm(&buf);
masm.bind(fakeL);
n->as_Mach()->label_set(&fakeL, 0);
n->as_MachBranch()->save_label(&saveL, &save_bnum);
n->as_MachBranch()->label_set(&fakeL, 0);
}
n->emit(buf, this->regalloc());
if (is_branch) // Clear the reference to fake label.
n->as_Mach()->label_set(NULL, 0);
if (is_branch) // Restore label.
n->as_MachBranch()->label_set(saveL, save_bnum);
// End scratch_emit_size section.
set_in_scratch_emit_size(false);
......
......@@ -441,9 +441,6 @@ void IdealGraphPrinter::visit_node(Node *n, void *param) {
if (flags & Node::Flag_is_cisc_alternate) {
print_prop("is_cisc_alternate", "true");
}
if (flags & Node::Flag_is_Branch) {
print_prop("is_branch", "true");
}
if (flags & Node::Flag_is_dead_loop_safe) {
print_prop("is_dead_loop_safe", "true");
}
......
......@@ -389,12 +389,6 @@ int MachNode::operand_index( uint operand ) const {
}
//------------------------------negate-----------------------------------------
// Negate conditional branches. Error for non-branch Nodes
void MachNode::negate() {
ShouldNotCallThis();
}
//------------------------------peephole---------------------------------------
// Apply peephole rule(s) to this instruction
MachNode *MachNode::peephole( Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile* C ) {
......@@ -407,12 +401,6 @@ void MachNode::add_case_label( int index_num, Label* blockLabel) {
ShouldNotCallThis();
}
//------------------------------label_set--------------------------------------
// Set the Label for a LabelOper, if an operand for this instruction
void MachNode::label_set( Label* label, uint block_num ) {
ShouldNotCallThis();
}
//------------------------------method_set-------------------------------------
// Set the absolute address of a method
void MachNode::method_set( intptr_t addr ) {
......@@ -517,6 +505,9 @@ void MachNullCheckNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
void MachNullCheckNode::label_set(Label* label, uint block_num) {
// Nothing to emit
}
void MachNullCheckNode::save_label( Label** label, uint* block_num ) {
// Nothing to emit
}
const RegMask &MachNullCheckNode::in_RegMask( uint idx ) const {
if( idx == 0 ) return RegMask::Empty;
......
......@@ -185,7 +185,6 @@ public:
virtual void use_cisc_RegMask();
// Support for short branches
virtual MachNode *short_branch_version(Compile* C) { return NULL; }
bool may_be_short_branch() const { return (flags() & Flag_may_be_short_branch) != 0; }
// Avoid back to back some instructions on some CPUs.
......@@ -272,18 +271,12 @@ public:
// Call "get_base_and_disp" to decide which category of memory is used here.
virtual const class TypePtr *adr_type() const;
// Negate conditional branches. Error for non-branch Nodes
virtual void negate();
// Apply peephole rule(s) to this instruction
virtual MachNode *peephole( Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile* C );
// Top-level ideal Opcode matched
virtual int ideal_Opcode() const { return Op_Node; }
// Set the branch inside jump MachNodes. Error for non-branch Nodes.
virtual void label_set( Label* label, uint block_num );
// Adds the label for the case
virtual void add_case_label( int switch_val, Label* blockLabel);
......@@ -514,25 +507,41 @@ public:
#endif
};
//------------------------------MachBranchNode--------------------------------
// Abstract machine branch Node
class MachBranchNode : public MachIdealNode {
public:
MachBranchNode() : MachIdealNode() {
init_class_id(Class_MachBranch);
}
virtual void label_set(Label* label, uint block_num) = 0;
virtual void save_label(Label** label, uint* block_num) = 0;
// Support for short branches
virtual MachNode *short_branch_version(Compile* C) { return NULL; }
virtual bool pinned() const { return true; };
};
//------------------------------MachNullChkNode--------------------------------
// Machine-dependent null-pointer-check Node. Points a real MachNode that is
// also some kind of memory op. Turns the indicated MachNode into a
// conditional branch with good latency on the ptr-not-null path and awful
// latency on the pointer-is-null path.
class MachNullCheckNode : public MachIdealNode {
class MachNullCheckNode : public MachBranchNode {
public:
const uint _vidx; // Index of memop being tested
MachNullCheckNode( Node *ctrl, Node *memop, uint vidx ) : MachIdealNode(), _vidx(vidx) {
MachNullCheckNode( Node *ctrl, Node *memop, uint vidx ) : MachBranchNode(), _vidx(vidx) {
init_class_id(Class_MachNullCheck);
init_flags(Flag_is_Branch);
add_req(ctrl);
add_req(memop);
}
virtual uint size_of() const { return sizeof(*this); }
virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const;
virtual void label_set(Label* label, uint block_num);
virtual bool pinned() const { return true; };
virtual void save_label(Label** label, uint* block_num);
virtual void negate() { }
virtual const class Type *bottom_type() const { return TypeTuple::IFBOTH; }
virtual uint ideal_reg() const { return NotAMachineReg; }
......@@ -578,14 +587,16 @@ public:
//------------------------------MachIfNode-------------------------------------
// Machine-specific versions of IfNodes
class MachIfNode : public MachNode {
class MachIfNode : public MachBranchNode {
virtual uint size_of() const { return sizeof(*this); } // Size is bigger
public:
float _prob; // Probability branch goes either way
float _fcnt; // Frequency counter
MachIfNode() : MachNode() {
MachIfNode() : MachBranchNode() {
init_class_id(Class_MachIf);
}
// Negate conditional branches.
virtual void negate() = 0;
#ifndef PRODUCT
virtual void dump_spec(outputStream *st) const;
#endif
......@@ -593,9 +604,9 @@ public:
//------------------------------MachGotoNode-----------------------------------
// Machine-specific versions of GotoNodes
class MachGotoNode : public MachNode {
class MachGotoNode : public MachBranchNode {
public:
MachGotoNode() : MachNode() {
MachGotoNode() : MachBranchNode() {
init_class_id(Class_MachGoto);
}
};
......
......@@ -77,6 +77,7 @@ class LoadNode;
class LoadStoreNode;
class LockNode;
class LoopNode;
class MachBranchNode;
class MachCallDynamicJavaNode;
class MachCallJavaNode;
class MachCallLeafNode;
......@@ -572,13 +573,14 @@ public:
DEFINE_CLASS_ID(MachCallDynamicJava, MachCallJava, 1)
DEFINE_CLASS_ID(MachCallRuntime, MachCall, 1)
DEFINE_CLASS_ID(MachCallLeaf, MachCallRuntime, 0)
DEFINE_CLASS_ID(MachSpillCopy, Mach, 1)
DEFINE_CLASS_ID(MachNullCheck, Mach, 2)
DEFINE_CLASS_ID(MachIf, Mach, 3)
DEFINE_CLASS_ID(MachTemp, Mach, 4)
DEFINE_CLASS_ID(MachConstantBase, Mach, 5)
DEFINE_CLASS_ID(MachConstant, Mach, 6)
DEFINE_CLASS_ID(MachGoto, Mach, 7)
DEFINE_CLASS_ID(MachBranch, Mach, 1)
DEFINE_CLASS_ID(MachIf, MachBranch, 0)
DEFINE_CLASS_ID(MachGoto, MachBranch, 1)
DEFINE_CLASS_ID(MachNullCheck, MachBranch, 2)
DEFINE_CLASS_ID(MachSpillCopy, Mach, 2)
DEFINE_CLASS_ID(MachTemp, Mach, 3)
DEFINE_CLASS_ID(MachConstantBase, Mach, 4)
DEFINE_CLASS_ID(MachConstant, Mach, 5)
DEFINE_CLASS_ID(Type, Node, 2)
DEFINE_CLASS_ID(Phi, Type, 0)
......@@ -634,8 +636,7 @@ public:
Flag_is_macro = Flag_needs_anti_dependence_check << 1,
Flag_is_Con = Flag_is_macro << 1,
Flag_is_cisc_alternate = Flag_is_Con << 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_cisc_alternate << 1,
Flag_may_be_short_branch = Flag_is_dead_loop_safe << 1,
Flag_avoid_back_to_back = Flag_may_be_short_branch << 1,
_max_flags = (Flag_avoid_back_to_back << 1) - 1 // allow flags combination
......@@ -721,6 +722,7 @@ public:
DEFINE_CLASS_QUERY(Lock)
DEFINE_CLASS_QUERY(Loop)
DEFINE_CLASS_QUERY(Mach)
DEFINE_CLASS_QUERY(MachBranch)
DEFINE_CLASS_QUERY(MachCall)
DEFINE_CLASS_QUERY(MachCallDynamicJava)
DEFINE_CLASS_QUERY(MachCallJava)
......@@ -787,9 +789,6 @@ public:
// skip some other important test.)
virtual bool depends_only_on_test() const { assert(!is_CFG(), ""); return true; };
// defined for MachNodes that match 'If' | 'Goto' | 'CountedLoopEnd' | 'Jump'
bool is_Branch() const { return (_flags & Flag_is_Branch) != 0; }
// When building basic blocks, I need to have a notion of block beginning
// Nodes, next block selector Nodes (block enders), and next block
// projections. These calls need to work on their machine equivalents. The
......
......@@ -420,7 +420,7 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size
}
}
if (mach->may_be_short_branch()) {
if (!nj->is_Branch()) {
if (!nj->is_MachBranch()) {
#ifndef PRODUCT
nj->dump(3);
#endif
......@@ -473,7 +473,7 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size
MachNode* mach = (idx == -1) ? NULL: b->_nodes[idx]->as_Mach();
if (mach != NULL && mach->may_be_short_branch()) {
#ifdef ASSERT
assert(jmp_size[i] > 0 && mach->is_Branch(), "sanity");
assert(jmp_size[i] > 0 && mach->is_MachBranch(), "sanity");
int j;
// Find the branch; ignore trailing NOPs.
for (j = b->_nodes.size()-1; j>=0; j--) {
......@@ -500,7 +500,7 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size
if (_matcher->is_short_branch_offset(mach->rule(), br_size, offset)) {
// We've got a winner. Replace this branch.
MachNode* replacement = mach->short_branch_version(this);
MachNode* replacement = mach->as_MachBranch()->short_branch_version(this);
// Update the jmp_size.
int new_size = replacement->size(_regalloc);
......@@ -670,7 +670,7 @@ void Compile::finalize_offsets_and_shorten(uint* blk_starts) {
if (_matcher->is_short_branch_offset(mach->rule(), br_size, offset)) {
// We've got a winner. Replace this branch.
MachNode* replacement = mach->short_branch_version(this);
MachNode* replacement = mach->as_MachBranch()->short_branch_version(this);
// Update the jmp_size.
int new_size = replacement->size(_regalloc);
......@@ -1525,25 +1525,21 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) {
}
// If this is a branch, then fill in the label with the target BB's label
else if (mach->is_Branch()) {
if (mach->ideal_Opcode() == Op_Jump) {
for (uint h = 0; h < b->_num_succs; h++) {
Block* succs_block = b->_succs[h];
for (uint j = 1; j < succs_block->num_preds(); j++) {
Node* jpn = succs_block->pred(j);
if (jpn->is_JumpProj() && jpn->in(0) == mach) {
uint block_num = succs_block->non_connector()->_pre_order;
Label *blkLabel = &blk_labels[block_num];
mach->add_case_label(jpn->as_JumpProj()->proj_no(), blkLabel);
}
else if (mach->is_MachBranch()) {
// This requires the TRUE branch target be in succs[0]
uint block_num = b->non_connector_successor(0)->_pre_order;
mach->as_MachBranch()->label_set( &blk_labels[block_num], block_num );
} else if (mach->ideal_Opcode() == Op_Jump) {
for (uint h = 0; h < b->_num_succs; h++) {
Block* succs_block = b->_succs[h];
for (uint j = 1; j < succs_block->num_preds(); j++) {
Node* jpn = succs_block->pred(j);
if (jpn->is_JumpProj() && jpn->in(0) == mach) {
uint block_num = succs_block->non_connector()->_pre_order;
Label *blkLabel = &blk_labels[block_num];
mach->add_case_label(jpn->as_JumpProj()->proj_no(), blkLabel);
}
}
} else {
// For Branchs
// This requires the TRUE branch target be in succs[0]
uint block_num = b->non_connector_successor(0)->_pre_order;
mach->label_set( &blk_labels[block_num], block_num );
}
}
......@@ -2229,7 +2225,7 @@ void Scheduling::AddNodeToBundle(Node *n, const Block *bb) {
// the first instruction at the branch target is
// copied to the delay slot, and the branch goes to
// the instruction after that at the branch target
if ( n->is_Mach() && n->is_Branch() ) {
if ( n->is_MachBranch() ) {
assert( !n->is_MachNullCheck(), "should not look for delay slot for Null Check" );
assert( !n->is_Catch(), "should not look for delay slot for Catch" );
......@@ -2890,7 +2886,7 @@ void Scheduling::ComputeRegisterAntidependencies(Block *b) {
// Kill projections on a branch should appear to occur on the
// branch, not afterwards, so grab the masks from the projections
// and process them.
if (n->is_Branch()) {
if (n->is_MachBranch() || n->is_Mach() && n->as_Mach()->ideal_Opcode() == Op_Jump) {
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
Node* use = n->fast_out(i);
if (use->is_Proj()) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册