From 672b21b7a8a8940d633c4467cea26059a9f58586 Mon Sep 17 00:00:00 2001 From: adlertz Date: Tue, 25 Feb 2014 14:09:02 +0100 Subject: [PATCH] 8032656: Tag the MachSpillCopies with purpose information Summary: Subclassed the MachSpillCopyNode with different subnodes for different spill purposes to enhance debugging / visualization Reviewed-by: kvn, roland --- hotspot/src/share/vm/opto/chaitin.cpp | 2 +- hotspot/src/share/vm/opto/chaitin.hpp | 9 ++-- hotspot/src/share/vm/opto/coalesce.cpp | 6 +-- hotspot/src/share/vm/opto/machnode.hpp | 61 +++++++++++++++++++++++-- hotspot/src/share/vm/opto/reg_split.cpp | 36 +++++++-------- 5 files changed, 84 insertions(+), 30 deletions(-) diff --git a/hotspot/src/share/vm/opto/chaitin.cpp b/hotspot/src/share/vm/opto/chaitin.cpp index d79b62694f..0f64bccd6b 100644 --- a/hotspot/src/share/vm/opto/chaitin.cpp +++ b/hotspot/src/share/vm/opto/chaitin.cpp @@ -1799,7 +1799,7 @@ bool PhaseChaitin::stretch_base_pointer_live_ranges(ResourceArea *a) { Block *phi_block = _cfg.get_block_for_node(phi); if (_cfg.get_block_for_node(phi_block->pred(2)) == block) { const RegMask *mask = C->matcher()->idealreg2spillmask[Op_RegI]; - Node *spill = new (C) MachSpillCopyNode( phi, *mask, *mask ); + Node *spill = new (C) MachSpillCopyNode(MachSpillCopyNode::LoopPhiInput, phi, *mask, *mask); insert_proj( phi_block, 1, spill, maxlrg++ ); n->set_req(1,spill); must_recompute_live = true; diff --git a/hotspot/src/share/vm/opto/chaitin.hpp b/hotspot/src/share/vm/opto/chaitin.hpp index 545e5882bc..f11b5b1f41 100644 --- a/hotspot/src/share/vm/opto/chaitin.hpp +++ b/hotspot/src/share/vm/opto/chaitin.hpp @@ -34,10 +34,9 @@ #include "opto/phase.hpp" #include "opto/regalloc.hpp" #include "opto/regmask.hpp" +#include "opto/machnode.hpp" class LoopTree; -class MachCallNode; -class MachSafePointNode; class Matcher; class PhaseCFG; class PhaseLive; @@ -424,8 +423,8 @@ class PhaseChaitin : public PhaseRegAlloc { uint _simplified; // Linked list head of simplified LRGs // Helper functions for Split() - uint split_DEF( Node *def, Block *b, int loc, uint max, Node **Reachblock, Node **debug_defs, GrowableArray splits, int slidx ); - uint split_USE( Node *def, Block *b, Node *use, uint useidx, uint max, bool def_down, bool cisc_sp, GrowableArray splits, int slidx ); + uint split_DEF(Node *def, Block *b, int loc, uint max, Node **Reachblock, Node **debug_defs, GrowableArray splits, int slidx ); + uint split_USE(MachSpillCopyNode::SpillType spill_type, Node *def, Block *b, Node *use, uint useidx, uint max, bool def_down, bool cisc_sp, GrowableArray splits, int slidx ); //------------------------------clone_projs------------------------------------ // After cloning some rematerialized instruction, clone any MachProj's that @@ -447,7 +446,7 @@ class PhaseChaitin : public PhaseRegAlloc { int slidx, uint *lrg2reach, Node **Reachblock, bool walkThru); // True if lidx is used before any real register is def'd in the block bool prompt_use( Block *b, uint lidx ); - Node *get_spillcopy_wide( Node *def, Node *use, uint uidx ); + Node *get_spillcopy_wide(MachSpillCopyNode::SpillType spill_type, Node *def, Node *use, uint uidx ); // Insert the spill at chosen location. Skip over any intervening Proj's or // Phis. Skip over a CatchNode and projs, inserting in the fall-through block // instead. Update high-pressure indices. Create a new live range. diff --git a/hotspot/src/share/vm/opto/coalesce.cpp b/hotspot/src/share/vm/opto/coalesce.cpp index bd207b584a..5579d90c48 100644 --- a/hotspot/src/share/vm/opto/coalesce.cpp +++ b/hotspot/src/share/vm/opto/coalesce.cpp @@ -291,7 +291,7 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) { _phc.clone_projs(pred, pred->end_idx(), m, copy, _phc._lrg_map); } else { const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()]; - copy = new (C) MachSpillCopyNode(m, *rm, *rm); + copy = new (C) MachSpillCopyNode(MachSpillCopyNode::PhiInput, m, *rm, *rm); // Find a good place to insert. Kinda tricky, use a subroutine insert_copy_with_overlap(pred,copy,phi_name,src_name); } @@ -325,7 +325,7 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) { l += _phc.clone_projs(b, l, m, copy, _phc._lrg_map); } else { const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()]; - copy = new (C) MachSpillCopyNode(m, *rm, *rm); + copy = new (C) MachSpillCopyNode(MachSpillCopyNode::TwoAddress, m, *rm, *rm); // Insert the copy in the basic block, just before us b->insert_node(copy, l++); } @@ -372,7 +372,7 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) { continue; // Live out; do not pre-split // Split the lrg at this use const RegMask *rm = C->matcher()->idealreg2spillmask[inp->ideal_reg()]; - Node *copy = new (C) MachSpillCopyNode( inp, *rm, *rm ); + Node* copy = new (C) MachSpillCopyNode(MachSpillCopyNode::DebugUse, inp, *rm, *rm); // Insert the copy in the use-def chain n->set_req(inpidx, copy ); // Insert the copy in the basic block, just before us diff --git a/hotspot/src/share/vm/opto/machnode.hpp b/hotspot/src/share/vm/opto/machnode.hpp index 5ea42a43fc..55d7e51588 100644 --- a/hotspot/src/share/vm/opto/machnode.hpp +++ b/hotspot/src/share/vm/opto/machnode.hpp @@ -520,12 +520,33 @@ public: // Machine SpillCopy Node. Copies 1 or 2 words from any location to any // location (stack or register). class MachSpillCopyNode : public MachIdealNode { +public: + enum SpillType { + TwoAddress, // Inserted when coalescing of a two-address-instruction node and its input fails + PhiInput, // Inserted when coalescing of a phi node and its input fails + DebugUse, // Inserted as debug info spills to safepoints in non-frequent blocks + LoopPhiInput, // Pre-split compares of loop-phis + Definition, // An lrg marked as spilled will be spilled to memory right after its definition, + // if in high pressure region or the lrg is bound + RegToReg, // A register to register move + RegToMem, // A register to memory move + MemToReg, // A memory to register move + PhiLocationDifferToInputLocation, // When coalescing phi nodes in PhaseChaitin::Split(), a move spill is inserted if + // the phi and its input resides at different locations (i.e. reg or mem) + BasePointerToMem, // Spill base pointer to memory at safepoint + InputToRematerialization, // When rematerializing a node we stretch the inputs live ranges, and they might be + // stretched beyond a new definition point, therefore we split out new copies instead + CallUse, // Spill use at a call + Bound // An lrg marked as spill that is bound and needs to be spilled at a use + }; +private: const RegMask *_in; // RegMask for input const RegMask *_out; // RegMask for output const Type *_type; + const SpillType _spill_type; public: - MachSpillCopyNode( Node *n, const RegMask &in, const RegMask &out ) : - MachIdealNode(), _in(&in), _out(&out), _type(n->bottom_type()) { + MachSpillCopyNode(SpillType spill_type, Node *n, const RegMask &in, const RegMask &out ) : + MachIdealNode(), _spill_type(spill_type), _in(&in), _out(&out), _type(n->bottom_type()) { init_class_id(Class_MachSpillCopy); init_flags(Flag_is_Copy); add_req(NULL); @@ -544,8 +565,42 @@ public: virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const; virtual uint size(PhaseRegAlloc *ra_) const; + #ifndef PRODUCT - virtual const char *Name() const { return "MachSpillCopy"; } + virtual const char *Name() const { + switch (_spill_type) { + case TwoAddress: + return "TwoAddressSpillCopy"; + case PhiInput: + return "PhiInputSpillCopy"; + case DebugUse: + return "DebugUseSpillCopy"; + case LoopPhiInput: + return "LoopPhiInputSpillCopy"; + case Definition: + return "DefinitionSpillCopy"; + case RegToReg: + return "RegToRegSpillCopy"; + case RegToMem: + return "RegToMemSpillCopy"; + case MemToReg: + return "MemToRegSpillCopy"; + case PhiLocationDifferToInputLocation: + return "PhiLocationDifferToInputLocationSpillCopy"; + case BasePointerToMem: + return "BasePointerToMemSpillCopy"; + case InputToRematerialization: + return "InputToRematerializationSpillCopy"; + case CallUse: + return "CallUseSpillCopy"; + case Bound: + return "BoundSpillCopy"; + default: + assert(false, "Must have valid spill type"); + return "MachSpillCopy"; + } + } + virtual void format( PhaseRegAlloc *, outputStream *st ) const; #endif }; diff --git a/hotspot/src/share/vm/opto/reg_split.cpp b/hotspot/src/share/vm/opto/reg_split.cpp index cfcecadd33..7ec346bc6a 100644 --- a/hotspot/src/share/vm/opto/reg_split.cpp +++ b/hotspot/src/share/vm/opto/reg_split.cpp @@ -55,7 +55,7 @@ static const char out_of_nodes[] = "out of nodes during split"; // Get a SpillCopy node with wide-enough masks. Use the 'wide-mask', the // wide ideal-register spill-mask if possible. If the 'wide-mask' does // not cover the input (or output), use the input (or output) mask instead. -Node *PhaseChaitin::get_spillcopy_wide( Node *def, Node *use, uint uidx ) { +Node *PhaseChaitin::get_spillcopy_wide(MachSpillCopyNode::SpillType spill_type, Node *def, Node *use, uint uidx ) { // If ideal reg doesn't exist we've got a bad schedule happening // that is forcing us to spill something that isn't spillable. // Bail rather than abort @@ -93,7 +93,7 @@ Node *PhaseChaitin::get_spillcopy_wide( Node *def, Node *use, uint uidx ) { // Here we assume a trip through memory is required. w_i_mask = &C->FIRST_STACK_mask(); } - return new (C) MachSpillCopyNode( def, *w_i_mask, *w_o_mask ); + return new (C) MachSpillCopyNode(spill_type, def, *w_i_mask, *w_o_mask ); } //------------------------------insert_proj------------------------------------ @@ -159,7 +159,7 @@ uint PhaseChaitin::split_DEF( Node *def, Block *b, int loc, uint maxlrg, Node ** assert( loc >= 0, "must insert past block head" ); // Get a def-side SpillCopy - Node *spill = get_spillcopy_wide(def,NULL,0); + Node *spill = get_spillcopy_wide(MachSpillCopyNode::Definition, def, NULL, 0); // Did we fail to split?, then bail if (!spill) { return 0; @@ -180,7 +180,7 @@ uint PhaseChaitin::split_DEF( Node *def, Block *b, int loc, uint maxlrg, Node ** //------------------------------split_USE-------------------------------------- // Splits at uses can involve redeffing the LRG, so no CISC Spilling there. // Debug uses want to know if def is already stack enabled. -uint PhaseChaitin::split_USE( Node *def, Block *b, Node *use, uint useidx, uint maxlrg, bool def_down, bool cisc_sp, GrowableArray splits, int slidx ) { +uint PhaseChaitin::split_USE(MachSpillCopyNode::SpillType spill_type, Node *def, Block *b, Node *use, uint useidx, uint maxlrg, bool def_down, bool cisc_sp, GrowableArray splits, int slidx ) { #ifdef ASSERT // Increment the counter for this lrg splits.at_put(slidx, splits.at(slidx)+1); @@ -216,7 +216,7 @@ uint PhaseChaitin::split_USE( Node *def, Block *b, Node *use, uint useidx, uint // DEF is UP, so must copy it DOWN and hook in USE // Insert SpillCopy before the USE, which uses DEF as its input, // and defs a new live range, which is used by this node. - Node *spill = get_spillcopy_wide(def,use,useidx); + Node *spill = get_spillcopy_wide(spill_type, def,use,useidx); // did we fail to split? if (!spill) { // Bail @@ -268,7 +268,7 @@ uint PhaseChaitin::split_USE( Node *def, Block *b, Node *use, uint useidx, uint bindex = b->find_node(use); } - Node *spill = get_spillcopy_wide( def, use, useidx ); + Node *spill = get_spillcopy_wide(spill_type, def, use, useidx ); if( !spill ) return 0; // Bailed out // Insert SpillCopy before the USE, which uses the reaching DEF as // its input, and defs a new live range, which is used by this node. @@ -327,7 +327,7 @@ Node *PhaseChaitin::split_Rematerialize( Node *def, Block *b, uint insidx, uint Block *b_def = _cfg.get_block_for_node(def); int idx_def = b_def->find_node(def); - Node *in_spill = get_spillcopy_wide( in, def, i ); + Node *in_spill = get_spillcopy_wide(MachSpillCopyNode::InputToRematerialization, in, def, i ); if( !in_spill ) return 0; // Bailed out insert_proj(b_def,idx_def,in_spill,maxlrg++); if( b_def == b ) @@ -935,7 +935,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { // This def has been rematerialized a couple of times without // progress. It doesn't care if it lives UP or DOWN, so // spill it down now. - maxlrg = split_USE(def,b,n,inpidx,maxlrg,false,false,splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::BasePointerToMem, def,b,n,inpidx,maxlrg,false,false,splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1015,7 +1015,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { !is_vect && umask.is_misaligned_pair())) { // These need a Split regardless of overlap or pressure // SPLIT - NO DEF - NO CISC SPILL - maxlrg = split_USE(def,b,n,inpidx,maxlrg,dup,false, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::Bound, def,b,n,inpidx,maxlrg,dup,false, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1027,7 +1027,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { if (UseFPUForSpilling && n->is_MachCall() && !uup && !dup ) { // The use at the call can force the def down so insert // a split before the use to allow the def more freedom. - maxlrg = split_USE(def,b,n,inpidx,maxlrg,dup,false, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::CallUse, def,b,n,inpidx,maxlrg,dup,false, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1063,7 +1063,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { else { // Both are either up or down, and there is no overlap if( dup ) { // If UP, reg->reg copy // COPY ACROSS HERE - NO DEF - NO CISC SPILL - maxlrg = split_USE(def,b,n,inpidx,maxlrg,false,false, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::RegToReg, def,b,n,inpidx,maxlrg,false,false, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1075,10 +1075,10 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { // First Split-UP to move value into Register uint def_ideal = def->ideal_reg(); const RegMask* tmp_rm = Matcher::idealreg2regmask[def_ideal]; - Node *spill = new (C) MachSpillCopyNode(def, dmask, *tmp_rm); + Node *spill = new (C) MachSpillCopyNode(MachSpillCopyNode::MemToReg, def, dmask, *tmp_rm); insert_proj( b, insidx, spill, maxlrg ); // Then Split-DOWN as if previous Split was DEF - maxlrg = split_USE(spill,b,n,inpidx,maxlrg,false,false, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::RegToMem, spill,b,n,inpidx,maxlrg,false,false, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1103,7 +1103,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { } } // COPY DOWN HERE - NO DEF - NO CISC SPILL - maxlrg = split_USE(def,b,n,inpidx,maxlrg,false,false, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::RegToMem, def,b,n,inpidx,maxlrg,false,false, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1118,7 +1118,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { else { // DOWN, Split-UP and check register pressure if( is_high_pressure( b, &lrgs(useidx), insidx ) ) { // COPY UP HERE - NO DEF - CISC SPILL - maxlrg = split_USE(def,b,n,inpidx,maxlrg,true,true, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::MemToReg, def,b,n,inpidx,maxlrg,true,true, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1126,7 +1126,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { insidx++; // Reset iterator to skip USE side split } else { // LRP // COPY UP HERE - WITH DEF - NO CISC SPILL - maxlrg = split_USE(def,b,n,inpidx,maxlrg,true,false, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::MemToReg, def,b,n,inpidx,maxlrg,true,false, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1229,7 +1229,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { if (C->check_node_count(NodeLimitFudgeFactor, out_of_nodes)) { // Check when generating nodes return 0; } - Node *spill = new (C) MachSpillCopyNode(use,use_rm,def_rm); + Node *spill = new (C) MachSpillCopyNode(MachSpillCopyNode::MemToReg, use,use_rm,def_rm); n->set_req(copyidx,spill); n->as_MachSpillCopy()->set_in_RegMask(def_rm); // Put the spill just before the copy @@ -1336,7 +1336,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { // Grab the UP/DOWN sense for the input u1 = UP[pidx][slidx]; if( u1 != (phi_up != 0)) { - maxlrg = split_USE(def, b, phi, i, maxlrg, !u1, false, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::PhiLocationDifferToInputLocation, def, b, phi, i, maxlrg, !u1, false, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; -- GitLab