OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [value-prof.c] - Blame information for rev 20

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/* Transformations based on profile information for values.
2
   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
3
 
4
This file is part of GCC.
5
 
6
GCC is free software; you can redistribute it and/or modify it under
7
the terms of the GNU General Public License as published by the Free
8
Software Foundation; either version 2, or (at your option) any later
9
version.
10
 
11
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12
WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14
for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GCC; see the file COPYING.  If not, write to the Free
18
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301, USA.  */
20
 
21
#include "config.h"
22
#include "system.h"
23
#include "coretypes.h"
24
#include "tm.h"
25
#include "rtl.h"
26
#include "expr.h"
27
#include "hard-reg-set.h"
28
#include "basic-block.h"
29
#include "value-prof.h"
30
#include "output.h"
31
#include "flags.h"
32
#include "insn-config.h"
33
#include "recog.h"
34
#include "optabs.h"
35
#include "regs.h"
36
#include "ggc.h"
37
#include "tree-flow.h"
38
#include "tree-flow-inline.h"
39
#include "diagnostic.h"
40
#include "coverage.h"
41
#include "tree.h"
42
#include "gcov-io.h"
43
#include "timevar.h"
44
#include "tree-pass.h"
45
#include "toplev.h"
46
 
47
static struct value_prof_hooks *value_prof_hooks;
48
 
49
/* This is the vector of histograms.  Created in find_values_to_profile.
50
   During profile generation, freed by instrument_values.
51
   During profile use, freed by value_profile_transformations.  */
52
 
53
static histogram_values static_values = NULL;
54
 
55
/* In this file value profile based optimizations are placed.  Currently the
56
   following optimizations are implemented (for more detailed descriptions
57
   see comments at value_profile_transformations):
58
 
59
   1) Division/modulo specialization.  Provided that we can determine that the
60
      operands of the division have some special properties, we may use it to
61
      produce more effective code.
62
   2) Speculative prefetching.  If we are able to determine that the difference
63
      between addresses accessed by a memory reference is usually constant, we
64
      may add the prefetch instructions.
65
      FIXME: This transformation was removed together with RTL based value
66
      profiling.
67
 
68
   Every such optimization should add its requirements for profiled values to
69
   insn_values_to_profile function.  This function is called from branch_prob
70
   in profile.c and the requested values are instrumented by it in the first
71
   compilation with -fprofile-arcs.  The optimization may then read the
72
   gathered data in the second compilation with -fbranch-probabilities.
73
 
74
   The measured data is pointed to from the histograms
75
   field of the statement annotation of the instrumented insns.  It is
76
   kept as a linked list of struct histogram_value_t's, which contain the
77
   same information as above.  */
78
 
79
 
80
static tree tree_divmod_fixed_value (tree, tree, tree, tree,
81
                                    tree, int, gcov_type, gcov_type);
82
static tree tree_mod_pow2 (tree, tree, tree, tree, int, gcov_type, gcov_type);
83
static tree tree_mod_subtract (tree, tree, tree, tree, int, int, int,
84
                                gcov_type, gcov_type, gcov_type);
85
static bool tree_divmod_fixed_value_transform (tree);
86
static bool tree_mod_pow2_value_transform (tree);
87
static bool tree_mod_subtract_transform (tree);
88
 
89
/* The overall number of invocations of the counter should match execution count
90
   of basic block.  Report it as error rather than internal error as it might
91
   mean that user has misused the profile somehow.  */
92
static bool
93
check_counter (tree stmt, const char * name, gcov_type all, gcov_type bb_count)
94
{
95
  if (all != bb_count)
96
    {
97
      location_t * locus;
98
      locus = (stmt != NULL && EXPR_HAS_LOCATION (stmt)
99
               ? EXPR_LOCUS (stmt)
100
               : &DECL_SOURCE_LOCATION (current_function_decl));
101
      error ("%HCorrupted value profile: %s profiler overall count (%d) does not match BB count (%d)",
102
             locus, name, (int)all, (int)bb_count);
103
      return true;
104
    }
105
  return false;
106
}
107
 
108
/* Tree based transformations. */
109
static bool
110
tree_value_profile_transformations (void)
111
{
112
  basic_block bb;
113
  block_stmt_iterator bsi;
114
  bool changed = false;
115
 
116
  FOR_EACH_BB (bb)
117
    {
118
      /* Ignore cold areas -- we are enlarging the code.  */
119
      if (!maybe_hot_bb_p (bb))
120
        continue;
121
 
122
      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
123
        {
124
          tree stmt = bsi_stmt (bsi);
125
          stmt_ann_t ann = get_stmt_ann (stmt);
126
          histogram_value th = ann->histograms;
127
          if (!th)
128
            continue;
129
 
130
          if (dump_file)
131
            {
132
              fprintf (dump_file, "Trying transformations on insn ");
133
              print_generic_stmt (dump_file, stmt, TDF_SLIM);
134
            }
135
 
136
          /* Transformations:  */
137
          /* The order of things in this conditional controls which
138
             transformation is used when more than one is applicable.  */
139
          /* It is expected that any code added by the transformations
140
             will be added before the current statement, and that the
141
             current statement remain valid (although possibly
142
             modified) upon return.  */
143
          if (flag_value_profile_transformations
144
              && (tree_mod_subtract_transform (stmt)
145
                  || tree_divmod_fixed_value_transform (stmt)
146
                  || tree_mod_pow2_value_transform (stmt)))
147
            {
148
              changed = true;
149
              /* Original statement may no longer be in the same block. */
150
              bb = bb_for_stmt (stmt);
151
            }
152
 
153
          /* Free extra storage from compute_value_histograms.  */
154
          while (th)
155
            {
156
              free (th->hvalue.counters);
157
              th = th->hvalue.next;
158
            }
159
          ann->histograms = 0;
160
        }
161
    }
162
 
163
  if (changed)
164
    {
165
      counts_to_freqs ();
166
    }
167
 
168
  return changed;
169
}
170
 
171
/* Generate code for transformation 1 (with OPERATION, operands OP1
172
   and OP2, whose value is expected to be VALUE, parent modify-expr STMT and
173
   probability of taking the optimal path PROB, which is equivalent to COUNT/ALL
174
   within roundoff error).  This generates the result into a temp and returns
175
   the temp; it does not replace or alter the original STMT.  */
176
static tree
177
tree_divmod_fixed_value (tree stmt, tree operation,
178
                         tree op1, tree op2, tree value, int prob, gcov_type count,
179
                         gcov_type all)
180
{
181
  tree stmt1, stmt2, stmt3;
182
  tree tmp1, tmp2, tmpv;
183
  tree label_decl1 = create_artificial_label ();
184
  tree label_decl2 = create_artificial_label ();
185
  tree label_decl3 = create_artificial_label ();
186
  tree label1, label2, label3;
187
  tree bb1end, bb2end, bb3end;
188
  basic_block bb, bb2, bb3, bb4;
189
  tree optype = TREE_TYPE (operation);
190
  edge e12, e13, e23, e24, e34;
191
  block_stmt_iterator bsi;
192
 
193
  bb = bb_for_stmt (stmt);
194
  bsi = bsi_for_stmt (stmt);
195
 
196
  tmpv = create_tmp_var (optype, "PROF");
197
  tmp1 = create_tmp_var (optype, "PROF");
198
  stmt1 = build2 (MODIFY_EXPR, optype, tmpv, fold_convert (optype, value));
199
  stmt2 = build2 (MODIFY_EXPR, optype, tmp1, op2);
200
  stmt3 = build3 (COND_EXPR, void_type_node,
201
            build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
202
            build1 (GOTO_EXPR, void_type_node, label_decl2),
203
            build1 (GOTO_EXPR, void_type_node, label_decl1));
204
  bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
205
  bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
206
  bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
207
  bb1end = stmt3;
208
 
209
  tmp2 = create_tmp_var (optype, "PROF");
210
  label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
211
  stmt1 = build2 (MODIFY_EXPR, optype, tmp2,
212
                  build2 (TREE_CODE (operation), optype, op1, tmpv));
213
  bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
214
  bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
215
  bb2end = stmt1;
216
 
217
  label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
218
  stmt1 = build2 (MODIFY_EXPR, optype, tmp2,
219
                  build2 (TREE_CODE (operation), optype, op1, op2));
220
  bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
221
  bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
222
  bb3end = stmt1;
223
 
224
  label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
225
  bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
226
 
227
  /* Fix CFG. */
228
  /* Edge e23 connects bb2 to bb3, etc. */
229
  e12 = split_block (bb, bb1end);
230
  bb2 = e12->dest;
231
  bb2->count = count;
232
  e23 = split_block (bb2, bb2end);
233
  bb3 = e23->dest;
234
  bb3->count = all - count;
235
  e34 = split_block (bb3, bb3end);
236
  bb4 = e34->dest;
237
  bb4->count = all;
238
 
239
  e12->flags &= ~EDGE_FALLTHRU;
240
  e12->flags |= EDGE_FALSE_VALUE;
241
  e12->probability = prob;
242
  e12->count = count;
243
 
244
  e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
245
  e13->probability = REG_BR_PROB_BASE - prob;
246
  e13->count = all - count;
247
 
248
  remove_edge (e23);
249
 
250
  e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
251
  e24->probability = REG_BR_PROB_BASE;
252
  e24->count = count;
253
 
254
  e34->probability = REG_BR_PROB_BASE;
255
  e34->count = all - count;
256
 
257
  return tmp2;
258
}
259
 
260
/* Do transform 1) on INSN if applicable.  */
261
static bool
262
tree_divmod_fixed_value_transform (tree stmt)
263
{
264
  stmt_ann_t ann = get_stmt_ann (stmt);
265
  histogram_value histogram;
266
  enum tree_code code;
267
  gcov_type val, count, all;
268
  tree modify, op, op1, op2, result, value, tree_val;
269
  int prob;
270
 
271
  modify = stmt;
272
  if (TREE_CODE (stmt) == RETURN_EXPR
273
      && TREE_OPERAND (stmt, 0)
274
      && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
275
    modify = TREE_OPERAND (stmt, 0);
276
  if (TREE_CODE (modify) != MODIFY_EXPR)
277
    return false;
278
  op = TREE_OPERAND (modify, 1);
279
  if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
280
    return false;
281
  code = TREE_CODE (op);
282
 
283
  if (code != TRUNC_DIV_EXPR && code != TRUNC_MOD_EXPR)
284
    return false;
285
 
286
  op1 = TREE_OPERAND (op, 0);
287
  op2 = TREE_OPERAND (op, 1);
288
  if (!ann->histograms)
289
    return false;
290
 
291
  for (histogram = ann->histograms; histogram; histogram = histogram->hvalue.next)
292
    if (histogram->type == HIST_TYPE_SINGLE_VALUE)
293
      break;
294
 
295
  if (!histogram)
296
    return false;
297
 
298
  value = histogram->hvalue.value;
299
  val = histogram->hvalue.counters[0];
300
  count = histogram->hvalue.counters[1];
301
  all = histogram->hvalue.counters[2];
302
 
303
  /* We require that count is at least half of all; this means
304
     that for the transformation to fire the value must be constant
305
     at least 50% of time (and 75% gives the guarantee of usage).  */
306
  if (simple_cst_equal (op2, value) != 1 || 2 * count < all)
307
    return false;
308
 
309
  if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count))
310
    return false;
311
 
312
  /* Compute probability of taking the optimal path.  */
313
  prob = (count * REG_BR_PROB_BASE + all / 2) / all;
314
 
315
  tree_val = build_int_cst_wide (get_gcov_type (),
316
                                 (unsigned HOST_WIDE_INT) val,
317
                                 val >> (HOST_BITS_PER_WIDE_INT - 1) >> 1);
318
  result = tree_divmod_fixed_value (stmt, op, op1, op2, tree_val, prob, count, all);
319
 
320
  if (dump_file)
321
    {
322
      fprintf (dump_file, "Div/mod by constant ");
323
      print_generic_expr (dump_file, value, TDF_SLIM);
324
      fprintf (dump_file, "=");
325
      print_generic_expr (dump_file, tree_val, TDF_SLIM);
326
      fprintf (dump_file, " transformation on insn ");
327
      print_generic_stmt (dump_file, stmt, TDF_SLIM);
328
    }
329
 
330
  TREE_OPERAND (modify, 1) = result;
331
 
332
  return true;
333
}
334
 
335
/* Generate code for transformation 2 (with OPERATION, operands OP1
336
   and OP2, parent modify-expr STMT and probability of taking the optimal
337
   path PROB, which is equivalent to COUNT/ALL within roundoff error).
338
   This generates the result into a temp and returns
339
   the temp; it does not replace or alter the original STMT.  */
340
static tree
341
tree_mod_pow2 (tree stmt, tree operation, tree op1, tree op2, int prob,
342
               gcov_type count, gcov_type all)
343
{
344
  tree stmt1, stmt2, stmt3, stmt4;
345
  tree tmp1, tmp2, tmp3;
346
  tree label_decl1 = create_artificial_label ();
347
  tree label_decl2 = create_artificial_label ();
348
  tree label_decl3 = create_artificial_label ();
349
  tree label1, label2, label3;
350
  tree bb1end, bb2end, bb3end;
351
  basic_block bb, bb2, bb3, bb4;
352
  tree optype = TREE_TYPE (operation);
353
  edge e12, e13, e23, e24, e34;
354
  block_stmt_iterator bsi;
355
  tree result = create_tmp_var (optype, "PROF");
356
 
357
  bb = bb_for_stmt (stmt);
358
  bsi = bsi_for_stmt (stmt);
359
 
360
  tmp1 = create_tmp_var (optype, "PROF");
361
  tmp2 = create_tmp_var (optype, "PROF");
362
  tmp3 = create_tmp_var (optype, "PROF");
363
  stmt1 = build2 (MODIFY_EXPR, optype, tmp1, fold_convert (optype, op2));
364
  stmt2 = build2 (MODIFY_EXPR, optype, tmp2,
365
                    build2 (PLUS_EXPR, optype, op2, integer_minus_one_node));
366
  stmt3 = build2 (MODIFY_EXPR, optype, tmp3,
367
                    build2 (BIT_AND_EXPR, optype, tmp2, tmp1));
368
  stmt4 = build3 (COND_EXPR, void_type_node,
369
            build2 (NE_EXPR, boolean_type_node, tmp3, integer_zero_node),
370
            build1 (GOTO_EXPR, void_type_node, label_decl2),
371
            build1 (GOTO_EXPR, void_type_node, label_decl1));
372
  bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
373
  bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
374
  bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
375
  bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
376
  bb1end = stmt4;
377
 
378
  /* tmp2 == op2-1 inherited from previous block */
379
  label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
380
  stmt1 = build2 (MODIFY_EXPR, optype, result,
381
                  build2 (BIT_AND_EXPR, optype, op1, tmp2));
382
  bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
383
  bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
384
  bb2end = stmt1;
385
 
386
  label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
387
  stmt1 = build2 (MODIFY_EXPR, optype, result,
388
                  build2 (TREE_CODE (operation), optype, op1, op2));
389
  bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
390
  bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
391
  bb3end = stmt1;
392
 
393
  label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
394
  bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
395
 
396
  /* Fix CFG. */
397
  /* Edge e23 connects bb2 to bb3, etc. */
398
  e12 = split_block (bb, bb1end);
399
  bb2 = e12->dest;
400
  bb2->count = count;
401
  e23 = split_block (bb2, bb2end);
402
  bb3 = e23->dest;
403
  bb3->count = all - count;
404
  e34 = split_block (bb3, bb3end);
405
  bb4 = e34->dest;
406
  bb4->count = all;
407
 
408
  e12->flags &= ~EDGE_FALLTHRU;
409
  e12->flags |= EDGE_FALSE_VALUE;
410
  e12->probability = prob;
411
  e12->count = count;
412
 
413
  e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
414
  e13->probability = REG_BR_PROB_BASE - prob;
415
  e13->count = all - count;
416
 
417
  remove_edge (e23);
418
 
419
  e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
420
  e24->probability = REG_BR_PROB_BASE;
421
  e24->count = count;
422
 
423
  e34->probability = REG_BR_PROB_BASE;
424
  e34->count = all - count;
425
 
426
  return result;
427
}
428
 
429
/* Do transform 2) on INSN if applicable.  */
430
static bool
431
tree_mod_pow2_value_transform (tree stmt)
432
{
433
  stmt_ann_t ann = get_stmt_ann (stmt);
434
  histogram_value histogram;
435
  enum tree_code code;
436
  gcov_type count, wrong_values, all;
437
  tree modify, op, op1, op2, result, value;
438
  int prob;
439
 
440
  modify = stmt;
441
  if (TREE_CODE (stmt) == RETURN_EXPR
442
      && TREE_OPERAND (stmt, 0)
443
      && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
444
    modify = TREE_OPERAND (stmt, 0);
445
  if (TREE_CODE (modify) != MODIFY_EXPR)
446
    return false;
447
  op = TREE_OPERAND (modify, 1);
448
  if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
449
    return false;
450
  code = TREE_CODE (op);
451
 
452
  if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (TREE_TYPE (op)))
453
    return false;
454
 
455
  op1 = TREE_OPERAND (op, 0);
456
  op2 = TREE_OPERAND (op, 1);
457
  if (!ann->histograms)
458
    return false;
459
 
460
  for (histogram = ann->histograms; histogram; histogram = histogram->hvalue.next)
461
    if (histogram->type == HIST_TYPE_POW2)
462
      break;
463
 
464
  if (!histogram)
465
    return false;
466
 
467
  value = histogram->hvalue.value;
468
  wrong_values = histogram->hvalue.counters[0];
469
  count = histogram->hvalue.counters[1];
470
 
471
  /* We require that we hit a power of 2 at least half of all evaluations.  */
472
  if (simple_cst_equal (op2, value) != 1 || count < wrong_values)
473
    return false;
474
 
475
  if (dump_file)
476
    {
477
      fprintf (dump_file, "Mod power of 2 transformation on insn ");
478
      print_generic_stmt (dump_file, stmt, TDF_SLIM);
479
    }
480
 
481
  /* Compute probability of taking the optimal path.  */
482
  all = count + wrong_values;
483
  if (check_counter (stmt, "pow2", all, bb_for_stmt (stmt)->count))
484
    return false;
485
 
486
  prob = (count * REG_BR_PROB_BASE + all / 2) / all;
487
 
488
  result = tree_mod_pow2 (stmt, op, op1, op2, prob, count, all);
489
 
490
  TREE_OPERAND (modify, 1) = result;
491
 
492
  return true;
493
}
494
 
495
/* Generate code for transformations 3 and 4 (with OPERATION, operands OP1
496
   and OP2, parent modify-expr STMT, and NCOUNTS the number of cases to
497
   support.  Currently only NCOUNTS==0 or 1 is supported and this is
498
   built into this interface.  The probabilities of taking the optimal
499
   paths are PROB1 and PROB2, which are equivalent to COUNT1/ALL and
500
   COUNT2/ALL respectively within roundoff error).  This generates the
501
   result into a temp and returns the temp; it does not replace or alter
502
   the original STMT.  */
503
/* FIXME: Generalize the interface to handle NCOUNTS > 1.  */
504
 
505
static tree
506
tree_mod_subtract (tree stmt, tree operation, tree op1, tree op2,
507
                    int prob1, int prob2, int ncounts,
508
                    gcov_type count1, gcov_type count2, gcov_type all)
509
{
510
  tree stmt1, stmt2, stmt3;
511
  tree tmp1;
512
  tree label_decl1 = create_artificial_label ();
513
  tree label_decl2 = create_artificial_label ();
514
  tree label_decl3 = create_artificial_label ();
515
  tree label1, label2, label3;
516
  tree bb1end, bb2end = NULL_TREE, bb3end;
517
  basic_block bb, bb2, bb3, bb4;
518
  tree optype = TREE_TYPE (operation);
519
  edge e12, e23 = 0, e24, e34, e14;
520
  block_stmt_iterator bsi;
521
  tree result = create_tmp_var (optype, "PROF");
522
 
523
  bb = bb_for_stmt (stmt);
524
  bsi = bsi_for_stmt (stmt);
525
 
526
  tmp1 = create_tmp_var (optype, "PROF");
527
  stmt1 = build2 (MODIFY_EXPR, optype, result, op1);
528
  stmt2 = build2 (MODIFY_EXPR, optype, tmp1, op2);
529
  stmt3 = build3 (COND_EXPR, void_type_node,
530
            build2 (LT_EXPR, boolean_type_node, result, tmp1),
531
            build1 (GOTO_EXPR, void_type_node, label_decl3),
532
            build1 (GOTO_EXPR, void_type_node,
533
                    ncounts ? label_decl1 : label_decl2));
534
  bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
535
  bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
536
  bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
537
  bb1end = stmt3;
538
 
539
  if (ncounts)  /* Assumed to be 0 or 1 */
540
    {
541
      label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
542
      stmt1 = build2 (MODIFY_EXPR, optype, result,
543
                      build2 (MINUS_EXPR, optype, result, tmp1));
544
      stmt2 = build3 (COND_EXPR, void_type_node,
545
                build2 (LT_EXPR, boolean_type_node, result, tmp1),
546
                build1 (GOTO_EXPR, void_type_node, label_decl3),
547
                build1 (GOTO_EXPR, void_type_node, label_decl2));
548
      bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
549
      bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
550
      bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
551
      bb2end = stmt2;
552
    }
553
 
554
  /* Fallback case. */
555
  label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
556
  stmt1 = build2 (MODIFY_EXPR, optype, result,
557
                    build2 (TREE_CODE (operation), optype, result, tmp1));
558
  bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
559
  bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
560
  bb3end = stmt1;
561
 
562
  label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
563
  bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
564
 
565
  /* Fix CFG. */
566
  /* Edge e23 connects bb2 to bb3, etc. */
567
  /* However block 3 is optional; if it is not there, references
568
     to 3 really refer to block 2. */
569
  e12 = split_block (bb, bb1end);
570
  bb2 = e12->dest;
571
  bb2->count = all - count1;
572
 
573
  if (ncounts)  /* Assumed to be 0 or 1.  */
574
    {
575
      e23 = split_block (bb2, bb2end);
576
      bb3 = e23->dest;
577
      bb3->count = all - count1 - count2;
578
    }
579
 
580
  e34 = split_block (ncounts ? bb3 : bb2, bb3end);
581
  bb4 = e34->dest;
582
  bb4->count = all;
583
 
584
  e12->flags &= ~EDGE_FALLTHRU;
585
  e12->flags |= EDGE_FALSE_VALUE;
586
  e12->probability = REG_BR_PROB_BASE - prob1;
587
  e12->count = all - count1;
588
 
589
  e14 = make_edge (bb, bb4, EDGE_TRUE_VALUE);
590
  e14->probability = prob1;
591
  e14->count = count1;
592
 
593
  if (ncounts)  /* Assumed to be 0 or 1.  */
594
    {
595
      e23->flags &= ~EDGE_FALLTHRU;
596
      e23->flags |= EDGE_FALSE_VALUE;
597
      e23->count = all - count1 - count2;
598
      e23->probability = REG_BR_PROB_BASE - prob2;
599
 
600
      e24 = make_edge (bb2, bb4, EDGE_TRUE_VALUE);
601
      e24->probability = prob2;
602
      e24->count = count2;
603
    }
604
 
605
  e34->probability = REG_BR_PROB_BASE;
606
  e34->count = all - count1 - count2;
607
 
608
  return result;
609
}
610
 
611
/* Do transforms 3) and 4) on INSN if applicable.  */
612
static bool
613
tree_mod_subtract_transform (tree stmt)
614
{
615
  stmt_ann_t ann = get_stmt_ann (stmt);
616
  histogram_value histogram;
617
  enum tree_code code;
618
  gcov_type count, wrong_values, all;
619
  tree modify, op, op1, op2, result, value;
620
  int prob1, prob2;
621
  unsigned int i;
622
 
623
  modify = stmt;
624
  if (TREE_CODE (stmt) == RETURN_EXPR
625
      && TREE_OPERAND (stmt, 0)
626
      && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
627
    modify = TREE_OPERAND (stmt, 0);
628
  if (TREE_CODE (modify) != MODIFY_EXPR)
629
    return false;
630
  op = TREE_OPERAND (modify, 1);
631
  if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
632
    return false;
633
  code = TREE_CODE (op);
634
 
635
  if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (TREE_TYPE (op)))
636
    return false;
637
 
638
  op1 = TREE_OPERAND (op, 0);
639
  op2 = TREE_OPERAND (op, 1);
640
  if (!ann->histograms)
641
    return false;
642
 
643
  for (histogram = ann->histograms; histogram; histogram = histogram->hvalue.next)
644
    if (histogram->type == HIST_TYPE_INTERVAL)
645
      break;
646
 
647
  if (!histogram)
648
    return false;
649
 
650
  value = histogram->hvalue.value;
651
  all = 0;
652
  wrong_values = 0;
653
  for (i = 0; i < histogram->hdata.intvl.steps; i++)
654
    all += histogram->hvalue.counters[i];
655
 
656
  wrong_values += histogram->hvalue.counters[i];
657
  wrong_values += histogram->hvalue.counters[i+1];
658
  all += wrong_values;
659
 
660
  /* Compute probability of taking the optimal path.  */
661
  if (check_counter (stmt, "interval", all, bb_for_stmt (stmt)->count))
662
    return false;
663
 
664
  /* We require that we use just subtractions in at least 50% of all
665
     evaluations.  */
666
  count = 0;
667
  for (i = 0; i < histogram->hdata.intvl.steps; i++)
668
    {
669
      count += histogram->hvalue.counters[i];
670
      if (count * 2 >= all)
671
        break;
672
    }
673
  if (i == histogram->hdata.intvl.steps)
674
    return false;
675
 
676
  if (dump_file)
677
    {
678
      fprintf (dump_file, "Mod subtract transformation on insn ");
679
      print_generic_stmt (dump_file, stmt, TDF_SLIM);
680
    }
681
 
682
  /* Compute probability of taking the optimal path(s).  */
683
  prob1 = (histogram->hvalue.counters[0] * REG_BR_PROB_BASE + all / 2) / all;
684
  prob2 = (histogram->hvalue.counters[1] * REG_BR_PROB_BASE + all / 2) / all;
685
 
686
  /* In practice, "steps" is always 2.  This interface reflects this,
687
     and will need to be changed if "steps" can change.  */
688
  result = tree_mod_subtract (stmt, op, op1, op2, prob1, prob2, i,
689
                            histogram->hvalue.counters[0],
690
                            histogram->hvalue.counters[1], all);
691
 
692
  TREE_OPERAND (modify, 1) = result;
693
 
694
  return true;
695
}
696
 
697
struct value_prof_hooks {
698
  /* Find list of values for which we want to measure histograms.  */
699
  void (*find_values_to_profile) (histogram_values *);
700
 
701
  /* Identify and exploit properties of values that are hard to analyze
702
     statically.  See value-prof.c for more detail.  */
703
  bool (*value_profile_transformations) (void);
704
};
705
 
706
/* Find values inside STMT for that we want to measure histograms for
707
   division/modulo optimization.  */
708
static void
709
tree_divmod_values_to_profile (tree stmt, histogram_values *values)
710
{
711
  tree assign, lhs, rhs, divisor, op0, type;
712
  histogram_value hist;
713
 
714
  if (TREE_CODE (stmt) == RETURN_EXPR)
715
    assign = TREE_OPERAND (stmt, 0);
716
  else
717
    assign = stmt;
718
 
719
  if (!assign
720
      || TREE_CODE (assign) != MODIFY_EXPR)
721
    return;
722
  lhs = TREE_OPERAND (assign, 0);
723
  type = TREE_TYPE (lhs);
724
  if (!INTEGRAL_TYPE_P (type))
725
    return;
726
 
727
  rhs = TREE_OPERAND (assign, 1);
728
  switch (TREE_CODE (rhs))
729
    {
730
    case TRUNC_DIV_EXPR:
731
    case TRUNC_MOD_EXPR:
732
      divisor = TREE_OPERAND (rhs, 1);
733
      op0 = TREE_OPERAND (rhs, 0);
734
 
735
      VEC_reserve (histogram_value, heap, *values, 3);
736
 
737
      if (is_gimple_reg (divisor))
738
        {
739
          /* Check for the case where the divisor is the same value most
740
             of the time.  */
741
          hist = ggc_alloc (sizeof (*hist));
742
          hist->hvalue.value = divisor;
743
          hist->hvalue.stmt = stmt;
744
          hist->type = HIST_TYPE_SINGLE_VALUE;
745
          VEC_quick_push (histogram_value, *values, hist);
746
        }
747
 
748
      /* For mod, check whether it is not often a noop (or replaceable by
749
         a few subtractions).  */
750
      if (TREE_CODE (rhs) == TRUNC_MOD_EXPR
751
          && TYPE_UNSIGNED (type))
752
        {
753
          /* Check for a special case where the divisor is power of 2.  */
754
          hist = ggc_alloc (sizeof (*hist));
755
          hist->hvalue.value = divisor;
756
          hist->hvalue.stmt = stmt;
757
          hist->type = HIST_TYPE_POW2;
758
          VEC_quick_push (histogram_value, *values, hist);
759
 
760
          hist = ggc_alloc (sizeof (*hist));
761
          hist->hvalue.stmt = stmt;
762
          hist->hvalue.value
763
                  = build2 (TRUNC_DIV_EXPR, type, op0, divisor);
764
          hist->type = HIST_TYPE_INTERVAL;
765
          hist->hdata.intvl.int_start = 0;
766
          hist->hdata.intvl.steps = 2;
767
          VEC_quick_push (histogram_value, *values, hist);
768
        }
769
      return;
770
 
771
    default:
772
      return;
773
    }
774
}
775
 
776
/* Find values inside STMT for that we want to measure histograms and adds
777
   them to list VALUES.  */
778
 
779
static void
780
tree_values_to_profile (tree stmt, histogram_values *values)
781
{
782
  if (flag_value_profile_transformations)
783
    tree_divmod_values_to_profile (stmt, values);
784
}
785
 
786
static void
787
tree_find_values_to_profile (histogram_values *values)
788
{
789
  basic_block bb;
790
  block_stmt_iterator bsi;
791
  unsigned i;
792
  histogram_value hist;
793
 
794
  *values = NULL;
795
  FOR_EACH_BB (bb)
796
    for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
797
      tree_values_to_profile (bsi_stmt (bsi), values);
798
  static_values = *values;
799
 
800
  for (i = 0; VEC_iterate (histogram_value, *values, i, hist); i++)
801
    {
802
      switch (hist->type)
803
        {
804
        case HIST_TYPE_INTERVAL:
805
          if (dump_file)
806
            {
807
              fprintf (dump_file, "Interval counter for tree ");
808
              print_generic_expr (dump_file, hist->hvalue.stmt,
809
                                  TDF_SLIM);
810
              fprintf (dump_file, ", range %d -- %d.\n",
811
                     hist->hdata.intvl.int_start,
812
                     (hist->hdata.intvl.int_start
813
                      + hist->hdata.intvl.steps - 1));
814
            }
815
          hist->n_counters = hist->hdata.intvl.steps + 2;
816
          break;
817
 
818
        case HIST_TYPE_POW2:
819
          if (dump_file)
820
            {
821
              fprintf (dump_file, "Pow2 counter for tree ");
822
              print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
823
              fprintf (dump_file, ".\n");
824
            }
825
          hist->n_counters = 2;
826
          break;
827
 
828
        case HIST_TYPE_SINGLE_VALUE:
829
          if (dump_file)
830
            {
831
              fprintf (dump_file, "Single value counter for tree ");
832
              print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
833
              fprintf (dump_file, ".\n");
834
            }
835
          hist->n_counters = 3;
836
          break;
837
 
838
        case HIST_TYPE_CONST_DELTA:
839
          if (dump_file)
840
            {
841
              fprintf (dump_file, "Constant delta counter for tree ");
842
              print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
843
              fprintf (dump_file, ".\n");
844
            }
845
          hist->n_counters = 4;
846
          break;
847
 
848
        default:
849
          gcc_unreachable ();
850
        }
851
    }
852
}
853
 
854
static struct value_prof_hooks tree_value_prof_hooks = {
855
  tree_find_values_to_profile,
856
  tree_value_profile_transformations
857
};
858
 
859
void
860
tree_register_value_prof_hooks (void)
861
{
862
  value_prof_hooks = &tree_value_prof_hooks;
863
  gcc_assert (ir_type ());
864
}
865
 
866
/* IR-independent entry points.  */
867
void
868
find_values_to_profile (histogram_values *values)
869
{
870
  (value_prof_hooks->find_values_to_profile) (values);
871
}
872
 
873
bool
874
value_profile_transformations (void)
875
{
876
  bool retval = (value_prof_hooks->value_profile_transformations) ();
877
  VEC_free (histogram_value, heap, static_values);
878
  return retval;
879
}
880
 
881
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.