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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [rtl-profile.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
/* Calculate branch probabilities, and basic block execution counts.
2
   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
3
   2000, 2001, 2002, 2003, 2005  Free Software Foundation, Inc.
4
   Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
5
   based on some ideas from Dain Samples of UC Berkeley.
6
   Further mangling by Bob Manson, Cygnus Support.
7
 
8
This file is part of GCC.
9
 
10
GCC is free software; you can redistribute it and/or modify it under
11
the terms of the GNU General Public License as published by the Free
12
Software Foundation; either version 2, or (at your option) any later
13
version.
14
 
15
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16
WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18
for more details.
19
 
20
You should have received a copy of the GNU General Public License
21
along with GCC; see the file COPYING.  If not, write to the Free
22
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
23
02110-1301, USA.  */
24
 
25
/* Generate basic block profile instrumentation and auxiliary files.
26
   RTL-based version.  See profile.c for overview.  */
27
 
28
#include "config.h"
29
#include "system.h"
30
#include "coretypes.h"
31
#include "tm.h"
32
#include "rtl.h"
33
#include "flags.h"
34
#include "output.h"
35
#include "regs.h"
36
#include "expr.h"
37
#include "function.h"
38
#include "toplev.h"
39
#include "coverage.h"
40
#include "value-prof.h"
41
#include "tree.h"
42
#include "ggc.h"
43
 
44
/* Do initialization work for the edge profiler.  */
45
 
46
static void
47
rtl_init_edge_profiler (void)
48
{
49
  /* gen_edge_profiler calls safe_insert_insn_on_edge which needs
50
     register liveness data to be available.  */
51
  life_analysis (NULL, 0);
52
}
53
 
54
/* Output instructions as RTL to increment the edge execution count.  */
55
 
56
static void
57
rtl_gen_edge_profiler (int edgeno, edge e)
58
{
59
  rtx ref = rtl_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
60
  rtx tmp;
61
  enum machine_mode mode = GET_MODE (ref);
62
  rtx sequence;
63
 
64
  start_sequence ();
65
  ref = validize_mem (ref);
66
 
67
  tmp = expand_simple_binop (mode, PLUS, ref, const1_rtx,
68
                             ref, 0, OPTAB_WIDEN);
69
 
70
  if (tmp != ref)
71
    emit_move_insn (copy_rtx (ref), tmp);
72
 
73
  sequence = get_insns ();
74
  end_sequence ();
75
  safe_insert_insn_on_edge (sequence, e);
76
  rebuild_jump_labels (e->insns.r);
77
}
78
 
79
/* Output instructions as RTL to increment the interval histogram counter.
80
   VALUE is the expression whose value is profiled.  TAG is the tag of the
81
   section for counters, BASE is offset of the counter position.  */
82
 
83
static void
84
rtl_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
85
{
86
  enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
87
  rtx mem_ref, tmp, tmp1, mr, val;
88
  rtx sequence;
89
  rtx more_label = gen_label_rtx ();
90
  rtx less_label = gen_label_rtx ();
91
  rtx end_of_code_label = gen_label_rtx ();
92
  int per_counter = GCOV_TYPE_SIZE / BITS_PER_UNIT;
93
  edge e = split_block (BLOCK_FOR_INSN (value->hvalue.rtl.insn),
94
                   PREV_INSN (value->hvalue.rtl.insn));
95
 
96
  start_sequence ();
97
 
98
  if (value->hvalue.rtl.seq)
99
    emit_insn (value->hvalue.rtl.seq);
100
 
101
  mr = gen_reg_rtx (Pmode);
102
 
103
  tmp = rtl_coverage_counter_ref (tag, base);
104
  tmp = force_reg (Pmode, XEXP (tmp, 0));
105
 
106
  val = expand_simple_binop (value->hvalue.rtl.mode, MINUS,
107
                             copy_rtx (value->hvalue.rtl.value),
108
                             GEN_INT (value->hdata.intvl.int_start),
109
                             NULL_RTX, 0, OPTAB_WIDEN);
110
 
111
    do_compare_rtx_and_jump (copy_rtx (val), GEN_INT (value->hdata.intvl.steps),
112
                           GE, 0, value->hvalue.rtl.mode, NULL_RTX, NULL_RTX,
113
                           more_label);
114
  do_compare_rtx_and_jump (copy_rtx (val), const0_rtx, LT, 0,
115
                           value->hvalue.rtl.mode,
116
                             NULL_RTX, NULL_RTX, less_label);
117
 
118
  /* We are in range.  */
119
  tmp1 = expand_simple_binop (value->hvalue.rtl.mode, MULT,
120
                              copy_rtx (val), GEN_INT (per_counter),
121
                              NULL_RTX, 0, OPTAB_WIDEN);
122
  tmp1 = expand_simple_binop (Pmode, PLUS, copy_rtx (tmp), tmp1, mr,
123
                              0, OPTAB_WIDEN);
124
  if (tmp1 != mr)
125
    emit_move_insn (copy_rtx (mr), tmp1);
126
 
127
      emit_jump_insn (gen_jump (end_of_code_label));
128
      emit_barrier ();
129
 
130
  /* Above the interval.  */
131
      emit_label (more_label);
132
      tmp1 = expand_simple_binop (Pmode, PLUS, copy_rtx (tmp),
133
                                  GEN_INT (per_counter * value->hdata.intvl.steps),
134
                                  mr, 0, OPTAB_WIDEN);
135
      if (tmp1 != mr)
136
        emit_move_insn (copy_rtx (mr), tmp1);
137
          emit_jump_insn (gen_jump (end_of_code_label));
138
          emit_barrier ();
139
 
140
  /* Below the interval.  */
141
      emit_label (less_label);
142
      tmp1 = expand_simple_binop (Pmode, PLUS, copy_rtx (tmp),
143
                        GEN_INT (per_counter * (value->hdata.intvl.steps +1)),
144
                mr, 0, OPTAB_WIDEN);
145
      if (tmp1 != mr)
146
        emit_move_insn (copy_rtx (mr), tmp1);
147
 
148
    emit_label (end_of_code_label);
149
 
150
  mem_ref = validize_mem (gen_rtx_MEM (mode, mr));
151
 
152
  tmp = expand_simple_binop (mode, PLUS, copy_rtx (mem_ref), const1_rtx,
153
                             mem_ref, 0, OPTAB_WIDEN);
154
 
155
  if (tmp != mem_ref)
156
    emit_move_insn (copy_rtx (mem_ref), tmp);
157
 
158
  sequence = get_insns ();
159
  end_sequence ();
160
  rebuild_jump_labels (sequence);
161
  safe_insert_insn_on_edge (sequence, e);
162
}
163
 
164
/* Output instructions as RTL to increment the power of two histogram counter.
165
   VALUE is the expression whose value is profiled.  TAG is the tag of the
166
   section for counters, BASE is offset of the counter position.  */
167
 
168
static void
169
rtl_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
170
{
171
  enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
172
  rtx mem_ref, tmp, mr, uval;
173
  rtx sequence;
174
  rtx end_of_code_label = gen_label_rtx ();
175
  int per_counter = GCOV_TYPE_SIZE / BITS_PER_UNIT;
176
  edge e = split_block (BLOCK_FOR_INSN (value->hvalue.rtl.insn),
177
                        PREV_INSN (value->hvalue.rtl.insn));
178
 
179
  start_sequence ();
180
 
181
  if (value->hvalue.rtl.seq)
182
    emit_insn (value->hvalue.rtl.seq);
183
 
184
  mr = gen_reg_rtx (Pmode);
185
  tmp = rtl_coverage_counter_ref (tag, base);
186
  tmp = force_reg (Pmode, XEXP (tmp, 0));
187
  emit_move_insn (mr, tmp);
188
 
189
  uval = gen_reg_rtx (value->hvalue.rtl.mode);
190
  emit_move_insn (uval, copy_rtx (value->hvalue.rtl.value));
191
 
192
  /* Check for non-power of 2.  */
193
  do_compare_rtx_and_jump (copy_rtx (uval), const0_rtx, LE, 0, value->hvalue.rtl.mode,
194
                           NULL_RTX, NULL_RTX, end_of_code_label);
195
  tmp = expand_simple_binop (value->hvalue.rtl.mode, PLUS, copy_rtx (uval),
196
                             constm1_rtx, NULL_RTX, 0, OPTAB_WIDEN);
197
  tmp = expand_simple_binop (value->hvalue.rtl.mode, AND, copy_rtx (uval), tmp,
198
                             NULL_RTX, 0, OPTAB_WIDEN);
199
  do_compare_rtx_and_jump (tmp, const0_rtx, NE, 0, value->hvalue.rtl.mode, NULL_RTX,
200
                           NULL_RTX, end_of_code_label);
201
 
202
  tmp = expand_simple_binop (Pmode, PLUS, copy_rtx (mr), GEN_INT (per_counter),
203
                             mr, 0, OPTAB_WIDEN);
204
  if (tmp != mr)
205
    emit_move_insn (copy_rtx (mr), tmp);
206
 
207
  /* Increase the counter.  */
208
  emit_label (end_of_code_label);
209
 
210
  mem_ref = validize_mem (gen_rtx_MEM (mode, mr));
211
 
212
  tmp = expand_simple_binop (mode, PLUS, copy_rtx (mem_ref), const1_rtx,
213
                             mem_ref, 0, OPTAB_WIDEN);
214
 
215
  if (tmp != mem_ref)
216
    emit_move_insn (copy_rtx (mem_ref), tmp);
217
 
218
  sequence = get_insns ();
219
  end_sequence ();
220
  rebuild_jump_labels (sequence);
221
  safe_insert_insn_on_edge (sequence, e);
222
}
223
 
224
/* Output instructions as RTL for code to find the most common value.
225
   VALUE is the expression whose value is profiled.  TAG is the tag of the
226
   section for counters, BASE is offset of the counter position.  */
227
 
228
static rtx
229
rtl_gen_one_value_profiler_no_edge_manipulation (histogram_value value,
230
                                                 unsigned tag, unsigned base)
231
{
232
  enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
233
  rtx stored_value_ref, counter_ref, all_ref, stored_value, counter, all;
234
  rtx tmp, uval;
235
  rtx sequence;
236
  rtx same_label = gen_label_rtx ();
237
  rtx zero_label = gen_label_rtx ();
238
  rtx end_of_code_label = gen_label_rtx ();
239
 
240
  start_sequence ();
241
 
242
  if (value->hvalue.rtl.seq)
243
    emit_insn (value->hvalue.rtl.seq);
244
 
245
  stored_value_ref = rtl_coverage_counter_ref (tag, base);
246
  counter_ref = rtl_coverage_counter_ref (tag, base + 1);
247
  all_ref = rtl_coverage_counter_ref (tag, base + 2);
248
  stored_value = validize_mem (stored_value_ref);
249
  counter = validize_mem (counter_ref);
250
  all = validize_mem (all_ref);
251
 
252
  uval = gen_reg_rtx (mode);
253
  convert_move (uval, copy_rtx (value->hvalue.rtl.value), 0);
254
 
255
  /* Check if the stored value matches.  */
256
  do_compare_rtx_and_jump (copy_rtx (uval), copy_rtx (stored_value), EQ,
257
                           0, mode, NULL_RTX, NULL_RTX, same_label);
258
 
259
  /* Does not match; check whether the counter is zero.  */
260
  do_compare_rtx_and_jump (copy_rtx (counter), const0_rtx, EQ, 0, mode,
261
                           NULL_RTX, NULL_RTX, zero_label);
262
 
263
  /* The counter is not zero yet.  */
264
  tmp = expand_simple_binop (mode, PLUS, copy_rtx (counter), constm1_rtx,
265
                             counter, 0, OPTAB_WIDEN);
266
 
267
  if (tmp != counter)
268
    emit_move_insn (copy_rtx (counter), tmp);
269
 
270
  emit_jump_insn (gen_jump (end_of_code_label));
271
  emit_barrier ();
272
 
273
  emit_label (zero_label);
274
  /* Set new value.  */
275
  emit_move_insn (copy_rtx (stored_value), copy_rtx (uval));
276
 
277
  emit_label (same_label);
278
  /* Increase the counter.  */
279
  tmp = expand_simple_binop (mode, PLUS, copy_rtx (counter), const1_rtx,
280
                             counter, 0, OPTAB_WIDEN);
281
 
282
  if (tmp != counter)
283
    emit_move_insn (copy_rtx (counter), tmp);
284
 
285
  emit_label (end_of_code_label);
286
 
287
  /* Increase the counter of all executions; this seems redundant given
288
     that ve have counts for edges in cfg, but it may happen that some
289
     optimization will change the counts for the block (either because
290
     it is unable to update them correctly, or because it will duplicate
291
     the block or its part).  */
292
  tmp = expand_simple_binop (mode, PLUS, copy_rtx (all), const1_rtx,
293
                             all, 0, OPTAB_WIDEN);
294
 
295
  if (tmp != all)
296
    emit_move_insn (copy_rtx (all), tmp);
297
  sequence = get_insns ();
298
  end_sequence ();
299
  return sequence;
300
}
301
 
302
/* Output instructions as RTL for code to find the most common value.
303
   VALUE is the expression whose value is profiled.  TAG is the tag of the
304
   section for counters, BASE is offset of the counter position.  */
305
 
306
static void
307
rtl_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
308
{
309
  edge e = split_block (BLOCK_FOR_INSN (value->hvalue.rtl.insn),
310
                   PREV_INSN (value->hvalue.rtl.insn));
311
  rtx sequence = rtl_gen_one_value_profiler_no_edge_manipulation (value,
312
                        tag, base);
313
  rebuild_jump_labels (sequence);
314
  safe_insert_insn_on_edge (sequence, e);
315
}
316
 
317
/* Output instructions as RTL for code to find the most common value of
318
   a difference between two evaluations of an expression.
319
   VALUE is the expression whose value is profiled.  TAG is the tag of the
320
   section for counters, BASE is offset of the counter position.  */
321
 
322
static void
323
rtl_gen_const_delta_profiler (histogram_value value, unsigned tag, unsigned base)
324
{
325
  histogram_value one_value_delta;
326
  enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
327
  rtx stored_value_ref, stored_value, tmp, uval;
328
  rtx sequence;
329
  edge e = split_block (BLOCK_FOR_INSN (value->hvalue.rtl.insn),
330
                   PREV_INSN (value->hvalue.rtl.insn));
331
 
332
  start_sequence ();
333
 
334
  if (value->hvalue.rtl.seq)
335
    emit_insn (value->hvalue.rtl.seq);
336
 
337
  stored_value_ref = rtl_coverage_counter_ref (tag, base);
338
  stored_value = validize_mem (stored_value_ref);
339
 
340
  uval = gen_reg_rtx (mode);
341
  convert_move (uval, copy_rtx (value->hvalue.rtl.value), 0);
342
  tmp = expand_simple_binop (mode, MINUS,
343
                             copy_rtx (uval), copy_rtx (stored_value),
344
                             NULL_RTX, 0, OPTAB_WIDEN);
345
 
346
  one_value_delta = ggc_alloc (sizeof (*one_value_delta));
347
  one_value_delta->hvalue.rtl.value = tmp;
348
  one_value_delta->hvalue.rtl.mode = mode;
349
  one_value_delta->hvalue.rtl.seq = NULL_RTX;
350
  one_value_delta->hvalue.rtl.insn = value->hvalue.rtl.insn;
351
  one_value_delta->type = HIST_TYPE_SINGLE_VALUE;
352
  emit_insn (rtl_gen_one_value_profiler_no_edge_manipulation (one_value_delta,
353
                                                              tag, base + 1));
354
  emit_move_insn (copy_rtx (stored_value), uval);
355
  sequence = get_insns ();
356
  end_sequence ();
357
  rebuild_jump_labels (sequence);
358
  safe_insert_insn_on_edge (sequence, e);
359
}
360
 
361
/* Return the file on which profile dump output goes, if any.  */
362
 
363
static FILE *rtl_profile_dump_file (void) {
364
  return dump_file;
365
}
366
 
367
struct profile_hooks rtl_profile_hooks =
368
{
369
  rtl_init_edge_profiler,
370
  rtl_gen_edge_profiler,
371
  rtl_gen_interval_profiler,
372
  rtl_gen_pow2_profiler,
373
  rtl_gen_one_value_profiler,
374
  rtl_gen_const_delta_profiler,
375
  rtl_profile_dump_file
376
};

powered by: WebSVN 2.1.0

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