@@ -221,41 +221,60 @@ PhaseChaitin::PhaseChaitin(uint unique, PhaseCFG &cfg, Matcher &matcher, bool sc
221221 _high_frequency_lrg = MIN2 (double (OPTO_LRG_HIGH_FREQ), _cfg.get_outer_loop_frequency ());
222222
223223 // Build a list of basic blocks, sorted by frequency
224- _blks = NEW_RESOURCE_ARRAY (Block *, _cfg.number_of_blocks ());
225224 // Experiment with sorting strategies to speed compilation
225+ uint nr_blocks = _cfg.number_of_blocks ();
226226 double cutoff = BLOCK_FREQUENCY (1.0 ); // Cutoff for high frequency bucket
227227 Block **buckets[NUMBUCKS]; // Array of buckets
228228 uint buckcnt[NUMBUCKS]; // Array of bucket counters
229229 double buckval[NUMBUCKS]; // Array of bucket value cutoffs
230+
231+ // The space which our buckets point into.
232+ Block** start = NEW_RESOURCE_ARRAY (Block *, nr_blocks*NUMBUCKS);
233+
230234 for (uint i = 0 ; i < NUMBUCKS; i++) {
231- buckets[i] = NEW_RESOURCE_ARRAY (Block *, _cfg. number_of_blocks ()) ;
235+ buckets[i] = &start[i*nr_blocks] ;
232236 buckcnt[i] = 0 ;
233237 // Bump by three orders of magnitude each time
234238 cutoff *= 0.001 ;
235239 buckval[i] = cutoff;
236- for (uint j = 0 ; j < _cfg.number_of_blocks (); j++) {
237- buckets[i][j] = nullptr ;
238- }
239240 }
241+
240242 // Sort blocks into buckets
241- for (uint i = 0 ; i < _cfg. number_of_blocks () ; i++) {
243+ for (uint i = 0 ; i < nr_blocks ; i++) {
242244 for (uint j = 0 ; j < NUMBUCKS; j++) {
243- if ((j == NUMBUCKS - 1 ) || (_cfg.get_block (i)->_freq > buckval[j])) {
245+ double bval = buckval[j];
246+ Block* blk = _cfg.get_block (i);
247+ if (j == NUMBUCKS - 1 || blk->_freq > bval) {
248+ uint cnt = buckcnt[j];
244249 // Assign block to end of list for appropriate bucket
245- buckets[j][buckcnt[j]++] = _cfg.get_block (i);
250+ buckets[j][cnt] = blk;
251+ buckcnt[j] = cnt+1 ;
246252 break ; // kick out of inner loop
247253 }
248254 }
249255 }
250- // Dump buckets into final block array
256+
257+ // Squash the partially filled buckets together into the first one.
258+ static_assert (NUMBUCKS >= 2 , " must" ); // If this isn't true then it'll mess up the squashing.
259+ Block** offset = &buckets[0 ][buckcnt[0 ]];
260+ for (int i = 1 ; i < NUMBUCKS; i++) {
261+ ::memmove (offset, buckets[i], buckcnt[i]*sizeof (Block*));
262+ offset += buckcnt[i];
263+ }
264+ assert ((&buckets[0 ][0 ] + nr_blocks) == offset, " should be" );
265+
266+ // Free the now unused memory
267+ FREE_RESOURCE_ARRAY (Block*, buckets[1 ], (NUMBUCKS-1 )*nr_blocks);
268+ // Finally, point the _blks to our memory
269+ _blks = buckets[0 ];
270+
271+ #ifdef ASSERT
251272 uint blkcnt = 0 ;
252273 for (uint i = 0 ; i < NUMBUCKS; i++) {
253- for (uint j = 0 ; j < buckcnt[i]; j++) {
254- _blks[blkcnt++] = buckets[i][j];
255- }
274+ blkcnt += buckcnt[i];
256275 }
257-
258- assert (blkcnt == _cfg. number_of_blocks (), " Block array not totally filled " );
276+ assert (blkcnt == nr_blocks, " Block array not totally filled " );
277+ # endif
259278}
260279
261280// union 2 sets together.
0 commit comments