--- old/src/share/vm/adlc/archDesc.cpp Mon Aug 15 17:13:55 2011 +++ new/src/share/vm/adlc/archDesc.cpp Mon Aug 15 17:13:55 2011 @@ -331,6 +331,11 @@ // 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 && --- old/src/share/vm/adlc/formssel.cpp Mon Aug 15 17:13:56 2011 +++ new/src/share/vm/adlc/formssel.cpp Mon Aug 15 17:13:55 2011 @@ -340,12 +340,11 @@ 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_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 --- old/src/share/vm/adlc/output_c.cpp Mon Aug 15 17:13:56 2011 +++ new/src/share/vm/adlc/output_c.cpp Mon Aug 15 17:13:56 2011 @@ -3094,6 +3094,13 @@ 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"); } } --- old/src/share/vm/adlc/output_h.cpp Mon Aug 15 17:13:57 2011 +++ new/src/share/vm/adlc/output_h.cpp Mon Aug 15 17:13:57 2011 @@ -1519,8 +1519,9 @@ // 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 @@ -1676,16 +1677,6 @@ fprintf(fp,"init_flags(Flag_is_Con"); node_flags_set = true; } - } - - // 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 --- old/src/share/vm/opto/block.cpp Mon Aug 15 17:13:57 2011 +++ new/src/share/vm/opto/block.cpp Mon Aug 15 17:13:57 2011 @@ -839,7 +839,7 @@ // 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 --- old/src/share/vm/opto/compile.cpp Mon Aug 15 17:13:58 2011 +++ new/src/share/vm/opto/compile.cpp Mon Aug 15 17:13:58 2011 @@ -519,15 +519,18 @@ // 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); --- old/src/share/vm/opto/idealGraphPrinter.cpp Mon Aug 15 17:13:58 2011 +++ new/src/share/vm/opto/idealGraphPrinter.cpp Mon Aug 15 17:13:58 2011 @@ -441,9 +441,6 @@ 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"); } --- old/src/share/vm/opto/machnode.cpp Mon Aug 15 17:13:59 2011 +++ new/src/share/vm/opto/machnode.cpp Mon Aug 15 17:13:59 2011 @@ -389,12 +389,6 @@ } -//------------------------------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 @@ 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::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; --- old/src/share/vm/opto/machnode.hpp Mon Aug 15 17:13:59 2011 +++ new/src/share/vm/opto/machnode.hpp Mon Aug 15 17:13:59 2011 @@ -185,7 +185,6 @@ 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,9 +271,6 @@ // 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 ); @@ -281,9 +277,6 @@ // 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,6 +507,22 @@ #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 @@ -520,19 +529,19 @@ // 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 @@ //------------------------------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 @@ //------------------------------MachGotoNode----------------------------------- // Machine-specific versions of GotoNodes -class MachGotoNode : public MachNode { +class MachGotoNode : public MachBranchNode { public: - MachGotoNode() : MachNode() { + MachGotoNode() : MachBranchNode() { init_class_id(Class_MachGoto); } }; --- old/src/share/vm/opto/node.hpp Mon Aug 15 17:14:00 2011 +++ new/src/share/vm/opto/node.hpp Mon Aug 15 17:14:00 2011 @@ -77,6 +77,7 @@ class LoadStoreNode; class LockNode; class LoopNode; +class MachBranchNode; class MachCallDynamicJavaNode; class MachCallJavaNode; class MachCallLeafNode; @@ -572,13 +573,14 @@ 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 @@ 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 @@ 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 @@ // 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 --- old/src/share/vm/opto/output.cpp Mon Aug 15 17:14:00 2011 +++ new/src/share/vm/opto/output.cpp Mon Aug 15 17:14:00 2011 @@ -420,7 +420,7 @@ } } if (mach->may_be_short_branch()) { - if (!nj->is_Branch()) { + if (!nj->is_MachBranch()) { #ifndef PRODUCT nj->dump(3); #endif @@ -473,7 +473,7 @@ 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 @@ 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 @@ 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 @@ } // 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 @@ // 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 @@ // 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()) {