src/share/vm/opto/block.hpp

changeset 853
72c5366e5d86
parent 435
a61af66fc99e
child 905
ad8c8ca4ab0f
     1.1 --- a/src/share/vm/opto/block.hpp	Thu Oct 30 17:08:48 2008 -0700
     1.2 +++ b/src/share/vm/opto/block.hpp	Thu Nov 06 14:59:10 2008 -0800
     1.3 @@ -75,6 +75,7 @@
     1.4    void insert( uint i, Block *n );
     1.5    uint size() const { return _cnt; }
     1.6    void reset() { _cnt = 0; }
     1.7 +  void print();
     1.8  };
     1.9  
    1.10  
    1.11 @@ -129,7 +130,11 @@
    1.12    uint _rpo;                    // Number in reverse post order walk
    1.13  
    1.14    virtual bool is_block() { return true; }
    1.15 -  float succ_prob(uint i); // return probability of i'th successor
    1.16 +  float succ_prob(uint i);      // return probability of i'th successor
    1.17 +  int num_fall_throughs();      // How many fall-through candidate this block has
    1.18 +  void update_uncommon_branch(Block* un); // Lower branch prob to uncommon code
    1.19 +  bool succ_fall_through(uint i); // Is successor "i" is a fall-through candidate
    1.20 +  Block* lone_fall_through();   // Return lone fall-through Block or null
    1.21  
    1.22    Block* dom_lca(Block* that);  // Compute LCA in dominator tree.
    1.23  #ifdef ASSERT
    1.24 @@ -144,6 +149,7 @@
    1.25    // Report the alignment required by this block.  Must be a power of 2.
    1.26    // The previous block will insert nops to get this alignment.
    1.27    uint code_alignment();
    1.28 +  uint compute_loop_alignment();
    1.29  
    1.30    // BLOCK_FREQUENCY is a sentinel to mark uses of constant block frequencies.
    1.31    // It is currently also used to scale such frequencies relative to
    1.32 @@ -184,11 +190,12 @@
    1.33        int current_alignment = current_offset & max_pad;
    1.34        if( current_alignment != 0 ) {
    1.35          uint padding = (block_alignment-current_alignment) & max_pad;
    1.36 -        if( !head()->is_Loop() ||
    1.37 -            padding <= (uint)MaxLoopPad ||
    1.38 -            first_inst_size() > padding ) {
    1.39 -          return padding;
    1.40 +        if( has_loop_alignment() &&
    1.41 +            padding > (uint)MaxLoopPad &&
    1.42 +            first_inst_size() <= padding ) {
    1.43 +          return 0;
    1.44          }
    1.45 +        return padding;
    1.46        }
    1.47      }
    1.48      return 0;
    1.49 @@ -202,6 +209,21 @@
    1.50    void set_connector() { _connector = true; }
    1.51    bool is_connector() const { return _connector; };
    1.52  
    1.53 +  // Loop_alignment will be set for blocks which are at the top of loops.
    1.54 +  // The block layout pass may rotate loops such that the loop head may not
    1.55 +  // be the sequentially first block of the loop encountered in the linear
    1.56 +  // list of blocks.  If the layout pass is not run, loop alignment is set
    1.57 +  // for each block which is the head of a loop.
    1.58 +  uint _loop_alignment;
    1.59 +  void set_loop_alignment(Block *loop_top) {
    1.60 +    uint new_alignment = loop_top->compute_loop_alignment();
    1.61 +    if (new_alignment > _loop_alignment) {
    1.62 +      _loop_alignment = new_alignment;
    1.63 +    }
    1.64 +  }
    1.65 +  uint loop_alignment() const { return _loop_alignment; }
    1.66 +  bool has_loop_alignment() const { return loop_alignment() > 0; }
    1.67 +
    1.68    // Create a new Block with given head Node.
    1.69    // Creates the (empty) predecessor arrays.
    1.70    Block( Arena *a, Node *headnode )
    1.71 @@ -219,7 +241,8 @@
    1.72        _raise_LCA_mark(0),
    1.73        _raise_LCA_visited(0),
    1.74        _first_inst_size(999999),
    1.75 -      _connector(false) {
    1.76 +      _connector(false),
    1.77 +      _loop_alignment(0) {
    1.78      _nodes.push(headnode);
    1.79    }
    1.80  
    1.81 @@ -275,6 +298,16 @@
    1.82      return s;
    1.83    }
    1.84  
    1.85 +  // Return true if b is a successor of this block
    1.86 +  bool has_successor(Block* b) const {
    1.87 +    for (uint i = 0; i < _num_succs; i++ ) {
    1.88 +      if (non_connector_successor(i) == b) {
    1.89 +        return true;
    1.90 +      }
    1.91 +    }
    1.92 +    return false;
    1.93 +  }
    1.94 +
    1.95    // Successor block, after forwarding through connectors
    1.96    Block* non_connector_successor(int i) const {
    1.97      return _succs[i]->non_connector();
    1.98 @@ -319,7 +352,6 @@
    1.99  
   1.100    // I'll need a few machine-specific GotoNodes.  Clone from this one.
   1.101    MachNode *_goto;
   1.102 -  void insert_goto_at(uint block_no, uint succ_no);
   1.103  
   1.104    Block* insert_anti_dependences(Block* LCA, Node* load, bool verify = false);
   1.105    void verify_anti_dependences(Block* LCA, Node* load) {
   1.106 @@ -379,10 +411,15 @@
   1.107    // Compute the instruction global latency with a backwards walk
   1.108    void ComputeLatenciesBackwards(VectorSet &visited, Node_List &stack);
   1.109  
   1.110 +  // Set loop alignment
   1.111 +  void set_loop_alignment();
   1.112 +
   1.113    // Remove empty basic blocks
   1.114 -  void RemoveEmpty();
   1.115 -  bool MoveToNext(Block* bx, uint b_index);
   1.116 -  void MoveToEnd(Block* bx, uint b_index);
   1.117 +  void remove_empty();
   1.118 +  void fixup_flow();
   1.119 +  bool move_to_next(Block* bx, uint b_index);
   1.120 +  void move_to_end(Block* bx, uint b_index);
   1.121 +  void insert_goto_at(uint block_no, uint succ_no);
   1.122  
   1.123    // Check for NeverBranch at block end.  This needs to become a GOTO to the
   1.124    // true target.  NeverBranch are treated as a conditional branch that always
   1.125 @@ -413,7 +450,7 @@
   1.126  };
   1.127  
   1.128  
   1.129 -//------------------------------UnionFindInfo----------------------------------
   1.130 +//------------------------------UnionFind--------------------------------------
   1.131  // Map Block indices to a block-index for a cfg-cover.
   1.132  // Array lookup in the optimized case.
   1.133  class UnionFind : public ResourceObj {
   1.134 @@ -508,3 +545,166 @@
   1.135    void dump_tree() const;
   1.136  #endif
   1.137  };
   1.138 +
   1.139 +
   1.140 +//----------------------------------CFGEdge------------------------------------
   1.141 +// A edge between two basic blocks that will be embodied by a branch or a
   1.142 +// fall-through.
   1.143 +class CFGEdge : public ResourceObj {
   1.144 + private:
   1.145 +  Block * _from;        // Source basic block
   1.146 +  Block * _to;          // Destination basic block
   1.147 +  float _freq;          // Execution frequency (estimate)
   1.148 +  int   _state;
   1.149 +  bool  _infrequent;
   1.150 +  int   _from_pct;
   1.151 +  int   _to_pct;
   1.152 +
   1.153 +  // Private accessors
   1.154 +  int  from_pct() const { return _from_pct; }
   1.155 +  int  to_pct()   const { return _to_pct;   }
   1.156 +  int  from_infrequent() const { return from_pct() < BlockLayoutMinDiamondPercentage; }
   1.157 +  int  to_infrequent()   const { return to_pct()   < BlockLayoutMinDiamondPercentage; }
   1.158 +
   1.159 + public:
   1.160 +  enum {
   1.161 +    open,               // initial edge state; unprocessed
   1.162 +    connected,          // edge used to connect two traces together
   1.163 +    interior            // edge is interior to trace (could be backedge)
   1.164 +  };
   1.165 +
   1.166 +  CFGEdge(Block *from, Block *to, float freq, int from_pct, int to_pct) :
   1.167 +    _from(from), _to(to), _freq(freq),
   1.168 +    _from_pct(from_pct), _to_pct(to_pct), _state(open) {
   1.169 +    _infrequent = from_infrequent() || to_infrequent();
   1.170 +  }
   1.171 +
   1.172 +  float  freq() const { return _freq; }
   1.173 +  Block* from() const { return _from; }
   1.174 +  Block* to  () const { return _to;   }
   1.175 +  int  infrequent() const { return _infrequent; }
   1.176 +  int state() const { return _state; }
   1.177 +
   1.178 +  void set_state(int state) { _state = state; }
   1.179 +
   1.180 +#ifndef PRODUCT
   1.181 +  void dump( ) const;
   1.182 +#endif
   1.183 +};
   1.184 +
   1.185 +
   1.186 +//-----------------------------------Trace-------------------------------------
   1.187 +// An ordered list of basic blocks.
   1.188 +class Trace : public ResourceObj {
   1.189 + private:
   1.190 +  uint _id;             // Unique Trace id (derived from initial block)
   1.191 +  Block ** _next_list;  // Array mapping index to next block
   1.192 +  Block ** _prev_list;  // Array mapping index to previous block
   1.193 +  Block * _first;       // First block in the trace
   1.194 +  Block * _last;        // Last block in the trace
   1.195 +
   1.196 +  // Return the block that follows "b" in the trace.
   1.197 +  Block * next(Block *b) const { return _next_list[b->_pre_order]; }
   1.198 +  void set_next(Block *b, Block *n) const { _next_list[b->_pre_order] = n; }
   1.199 +
   1.200 +  // Return the block that preceeds "b" in the trace.
   1.201 +  Block * prev(Block *b) const { return _prev_list[b->_pre_order]; }
   1.202 +  void set_prev(Block *b, Block *p) const { _prev_list[b->_pre_order] = p; }
   1.203 +
   1.204 +  // We've discovered a loop in this trace. Reset last to be "b", and first as
   1.205 +  // the block following "b
   1.206 +  void break_loop_after(Block *b) {
   1.207 +    _last = b;
   1.208 +    _first = next(b);
   1.209 +    set_prev(_first, NULL);
   1.210 +    set_next(_last, NULL);
   1.211 +  }
   1.212 +
   1.213 + public:
   1.214 +
   1.215 +  Trace(Block *b, Block **next_list, Block **prev_list) :
   1.216 +    _first(b),
   1.217 +    _last(b),
   1.218 +    _next_list(next_list),
   1.219 +    _prev_list(prev_list),
   1.220 +    _id(b->_pre_order) {
   1.221 +    set_next(b, NULL);
   1.222 +    set_prev(b, NULL);
   1.223 +  };
   1.224 +
   1.225 +  // Return the id number
   1.226 +  uint id() const { return _id; }
   1.227 +  void set_id(uint id) { _id = id; }
   1.228 +
   1.229 +  // Return the first block in the trace
   1.230 +  Block * first_block() const { return _first; }
   1.231 +
   1.232 +  // Return the last block in the trace
   1.233 +  Block * last_block() const { return _last; }
   1.234 +
   1.235 +  // Insert a trace in the middle of this one after b
   1.236 +  void insert_after(Block *b, Trace *tr) {
   1.237 +    set_next(tr->last_block(), next(b));
   1.238 +    if (next(b) != NULL) {
   1.239 +      set_prev(next(b), tr->last_block());
   1.240 +    }
   1.241 +
   1.242 +    set_next(b, tr->first_block());
   1.243 +    set_prev(tr->first_block(), b);
   1.244 +
   1.245 +    if (b == _last) {
   1.246 +      _last = tr->last_block();
   1.247 +    }
   1.248 +  }
   1.249 +
   1.250 +  void insert_before(Block *b, Trace *tr) {
   1.251 +    Block *p = prev(b);
   1.252 +    assert(p != NULL, "use append instead");
   1.253 +    insert_after(p, tr);
   1.254 +  }
   1.255 +
   1.256 +  // Append another trace to this one.
   1.257 +  void append(Trace *tr) {
   1.258 +    insert_after(_last, tr);
   1.259 +  }
   1.260 +
   1.261 +  // Append a block at the end of this trace
   1.262 +  void append(Block *b) {
   1.263 +    set_next(_last, b);
   1.264 +    set_prev(b, _last);
   1.265 +    _last = b;
   1.266 +  }
   1.267 +
   1.268 +  // Adjust the the blocks in this trace
   1.269 +  void fixup_blocks(PhaseCFG &cfg);
   1.270 +  bool backedge(CFGEdge *e);
   1.271 +
   1.272 +#ifndef PRODUCT
   1.273 +  void dump( ) const;
   1.274 +#endif
   1.275 +};
   1.276 +
   1.277 +//------------------------------PhaseBlockLayout-------------------------------
   1.278 +// Rearrange blocks into some canonical order, based on edges and their frequencies
   1.279 +class PhaseBlockLayout : public Phase {
   1.280 +  PhaseCFG &_cfg;               // Control flow graph
   1.281 +
   1.282 +  GrowableArray<CFGEdge *> *edges;
   1.283 +  Trace **traces;
   1.284 +  Block **next;
   1.285 +  Block **prev;
   1.286 +  UnionFind *uf;
   1.287 +
   1.288 +  // Given a block, find its encompassing Trace
   1.289 +  Trace * trace(Block *b) {
   1.290 +    return traces[uf->Find_compress(b->_pre_order)];
   1.291 +  }
   1.292 + public:
   1.293 +  PhaseBlockLayout(PhaseCFG &cfg);
   1.294 +
   1.295 +  void find_edges();
   1.296 +  void grow_traces();
   1.297 +  void merge_traces(bool loose_connections);
   1.298 +  void reorder_traces(int count);
   1.299 +  void union_traces(Trace* from, Trace* to);
   1.300 +};

mercurial