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