Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/**********************************************************************
32
$Author: release $
33
$Date: 1998/01/17 15:55:47 $
34
$Revision: 1.1.1.1 $
35
$Log: inl_norm.c,v $
36
 * Revision 1.1.1.1  1998/01/17  15:55:47  release
37
 * First version to be checked into rolling release.
38
 *
39
 * Revision 1.4  1997/08/23  13:24:07  pwe
40
 * no invert order, and NEWDIAGS inlining
41
 *
42
Revision 1.3  1997/02/18 12:56:27  currie
43
NEW DIAG STRUCTURE
44
 
45
 * Revision 1.2  1995/08/02  13:17:59  currie
46
 * Various bugs reported
47
 *
48
 * Revision 1.1  1995/04/06  10:44:05  currie
49
 * Initial revision
50
 *
51
***********************************************************************/
52
 
53
/* normalised_inlining chooses the order in which inlining is to be
54
   done.
55
*/
56
 
57
#include "config.h"
58
#include "common_types.h"
59
#include "installglob.h"
60
#include "exp.h"
61
#include "expmacs.h"
62
#include "tags.h"
63
#include "check.h"
64
#include "flags.h"
65
#include "check_id.h"
66
#include "const.h"
67
#include "foralls.h"
68
#include "shapemacs.h"
69
#include "glopt.h"
70
#include "inline.h"
71
#include "xalloc.h"
72
#ifdef NEWDIAGS
73
#include "dg_aux.h"
74
#endif
75
#include "inl_norm.h"
76
 
77
 
78
int print_inlines = 0;
79
 
80
/* Procedures */
81
 
82
/*********************************************************************
83
  test a declaration to see that the identifier is only used as an
84
  applied procedure.
85
 *********************************************************************/
86
 
87
 
88
int apply_only
89
    PROTO_N ( (e) )
90
    PROTO_T ( exp e )
91
{
92
  exp t = pt (e);
93
  int ao = 1;
94
  exp f;
95
  while (ao && t != nilexp) {
96
#ifdef NEWDIAGS
97
    if (isdiaginfo(t))
98
      t = pt (t);
99
    else {
100
      f = father(t);
101
      if (name (f) == apply_tag && son(f) == t)
102
        t = pt (t);
103
      else
104
        ao = 0;
105
    };
106
#else
107
    f = father(t);
108
    if (name (f) == apply_tag && son(f) == t)
109
      t = pt (t);
110
    else
111
      ao = 0;
112
#endif
113
  };
114
  return (ao);
115
}
116
 
117
 
118
void normalised_inlining
119
    PROTO_Z ()
120
{
121
  int proc_count = 0;
122
  dec * my_def;
123
  dec ** to_dec;
124
  exp def;
125
  int i;
126
  int j;
127
  char * consider;
128
  int * order;
129
  char * uses;
130
  int changed;
131
  int low;
132
  int high;
133
  int no_inlined =0;
134
 
135
  if (!do_inlining)
136
    return;
137
 
138
  /* count the defined procedures */
139
 
140
  my_def = top_def;
141
  while (my_def != (dec *) 0) {
142
    exp crt_exp = my_def -> dec_u.dec_val.dec_exp;
143
 
144
    def = son(crt_exp);
145
    if (def != nilexp && !isvar (crt_exp) && name (def) == proc_tag &&
146
        !isrecursive(def) && apply_only (crt_exp) && !proc_has_setjmp(def) &&
147
        !proc_uses_crt_env(def) &&
148
	!proc_has_alloca(def) &&
149
	!proc_has_lv(def)) {
150
      proc_count++;
151
    }
152
    my_def = my_def -> def_next;
153
  }
154
 
155
  /* allocate
156
     a matrix, uses, to hold uses[i, j] - i calls j
157
     a vector, to_dec, to hold dec* (number -> dec)
158
     a vector, consider, 1 if still considering.
159
     a vector, order, of the procedure numbers (+1) ordered
160
  */
161
 
162
  uses = (char*)xcalloc(proc_count * proc_count, sizeof(char));
163
  to_dec = (dec**)xcalloc(proc_count, sizeof(dec*));
164
  consider = (char*)xcalloc(proc_count, sizeof(char));
165
    /* assumes calloc clears consider */
166
  order = (int*)xcalloc(proc_count, sizeof(int));
167
    /* assumes calloc clears order */
168
 
169
 
170
  /* form the to_dec vector and set index in each proc dec.
171
     set consider vector */
172
 
173
  my_def = top_def;
174
  i = 0;
175
  while (my_def != (dec *) 0) {
176
    exp crt_exp = my_def -> dec_u.dec_val.dec_exp;
177
 
178
    def = son(crt_exp);
179
    if (def != nilexp && !isvar (crt_exp) && name (def) == proc_tag &&
180
        !isrecursive(def) && apply_only (crt_exp) && !proc_has_setjmp(def) &&
181
        !proc_uses_crt_env(def) &&
182
	!proc_has_alloca(def) &&
183
	!proc_has_lv(def)) {
184
      to_dec[i] = my_def;
185
      my_def -> dec_u.dec_val.index = i;
186
      consider[i] = 1;
187
      i++;
188
    }
189
    my_def = my_def -> def_next;
190
  }
191
 
192
  /* form uses matrix: uses[i, j] implies i calls j */
193
 
194
  for (i = 0; i < proc_count; i++) {
195
    exp crt_exp = to_dec[i] -> dec_u.dec_val.dec_exp;
196
 
197
    if (no(crt_exp) == 0 || son(crt_exp) == nilexp) {
198
      consider[i] = 0;
199
    }
200
    else {
201
      exp t = pt(crt_exp);
202
 
203
      while (t != nilexp) {
204
	exp k = t;
205
#ifdef NEWDIAGS
206
	if (isdiaginfo(t)) {
207
	  t = pt (t);
208
	  continue;
209
	}
210
#endif
211
	while (k != nilexp && name(k) != hold_tag && name(k) != 102
212
	       && name(k) != proc_tag && name(k) != general_proc_tag)
213
	  k = bro(k);
214
	if (k != nilexp && name(k) == proc_tag) {
215
	  int up = brog(bro(k)) -> dec_u.dec_val.index;
216
	  if (up >=0 && up< proc_count) {
217
	  	uses[proc_count *up + i] = 1;
218
	  }
219
	}
220
	t = pt(t);
221
      }
222
    }
223
  }
224
 
225
  /* form the order list from uses */
226
 
227
  low = 0;
228
  high = proc_count-1;
229
  changed = 1;
230
  while (changed) {
231
    changed = 0;
232
 
233
    for (i = 0; i < proc_count; i++) {
234
      if (consider[i]) {
235
        int good = 1;
236
        for (j = 0; good && j < proc_count; j++) {
237
	  if (consider[j] && uses[i*proc_count+j] == 1)
238
	    good = 0;
239
        }
240
	if (good) {
241
	  consider[i] = 0;
242
	  order[low++] = i+1;
243
	  changed = 1;
244
	}
245
      }
246
    }
247
 
248
    for (i = 0; i < proc_count; i++) {
249
      if (consider[i]) {
250
        int good = 1;
251
        for (j = 0; good && j < proc_count; j++) {
252
	  if (consider[j] && uses[j*proc_count+i] == 1)
253
	    good = 0;
254
        }
255
	if (good) {
256
	  consider[i] = 0;
257
	  order[high--] = i+1;
258
	  changed = 1;
259
	}
260
      }
261
    }
262
  }
263
 
264
  /* permit inlining of static recursive functions */
265
 
266
  for (i = 0; i < proc_count; i++) {
267
    if (consider[i]) {
268
      order[low++] = i+1;
269
    }
270
  }
271
 
272
  /* try to inline in given order */
273
 
274
  for (i = proc_count-1; i >= 0; i--) {
275
    if (order[i] > 0) {
276
      exp crt_exp;
277
      exp t;
278
      exp k;
279
      int total_uses;
280
      int crt_uses;
281
      int this_changed = 1;
282
      my_def = to_dec[order[i] - 1];
283
      crt_exp = my_def -> dec_u.dec_val.dec_exp;
284
      def = son(crt_exp);
285
      total_uses = no(crt_exp);
286
#ifdef NEWDIAGS
287
      if (diagnose)
288
	start_diag_inlining (def, my_def->dec_u.dec_val.diag_info);
289
#endif
290
 
291
      while (this_changed) {
292
        this_changed = 0;
293
	t = pt(crt_exp);
294
	crt_uses = no(crt_exp);
295
        while (t!=nilexp) {
296
      	  exp nextt = pt(t);
297
	  exp dad;
298
#ifdef NEWDIAGS
299
	  if (isdiaginfo(t)) {
300
	    t = pt (t);
301
	    continue;
302
	  }
303
#endif
304
	  dad = father(t);
305
	  if (istoinline(dad)) {
306
	    inline_exp(dad);
307
 
308
	    k = t;
309
	    while (k != nilexp && name(k) != hold_tag && name(k) != proc_tag)
310
	      k = bro(k);
311
	    if (print_inlines)
312
	      IGNORE fprintf(stderr, "%s inlined in %s\n",
313
	      		my_def -> dec_u.dec_val.dec_id,
314
			brog(bro(k)) -> dec_u.dec_val.dec_id);
315
 
316
	    this_changed = 1;
317
	    break;
318
	  }
319
	  else
320
	  if (no_inlined > 10000) {
321
               break; /* pathological expansion in AVS */
322
          }
323
	  else {
324
	    int ch = inlinechoice(t, def, total_uses);
325
	    if (ch == 0)
326
	      break;
327
	    if (ch == 2) {
328
	      inline_exp(dad);
329
	      no_inlined++;
330
 
331
	      k = t;
332
	      while (k != nilexp && name(k) != hold_tag && name(k) != proc_tag)
333
	        k = bro(k);
334
	      if (print_inlines)
335
	        IGNORE fprintf(stderr, "%s inlined in %s\n",
336
	      		my_def -> dec_u.dec_val.dec_id,
337
			brog(bro(k)) -> dec_u.dec_val.dec_id);
338
 
339
	      this_changed = 1;
340
	      break;
341
	    }
342
	  };
343
	  t = nextt;
344
        }
345
	if (crt_uses <= no(crt_exp))
346
	  break;
347
      }
348
#ifdef NEWDIAGS
349
      if (diagnose)
350
	end_diag_inlining (def, my_def->dec_u.dec_val.diag_info);
351
#endif
352
    }
353
  }
354
 
355
  xfree((void*)to_dec);
356
  xfree((void*)uses);
357
  xfree((void*)consider);
358
  xfree((void*)order);
359
 
360
  return;
361
}