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
/*
33
			    VERSION INFORMATION
34
			    ===================
35
 
36
--------------------------------------------------------------------------
37
$Header: /u/g/release/CVSROOT/Source/src/installers/sparc/common/inlinechoice.c,v 1.1.1.1 1998/01/17 15:55:54 release Exp $
38
--------------------------------------------------------------------------
39
$Log: inlinechoice.c,v $
40
 * Revision 1.1.1.1  1998/01/17  15:55:54  release
41
 * First version to be checked into rolling release.
42
 *
43
 * Revision 1.4  1996/08/15  16:26:59  pwe
44
 * add missing file headers
45
 *
46
--------------------------------------------------------------------------
47
*/
48
 
49
 
50
 
51
#include "config.h"
52
#include "common_types.h"
53
#include "installglob.h"
54
#include "exp.h"
55
#include "expmacs.h"
56
#include "tags.h"
57
#include "flags.h"
58
#include "shapemacs.h"
59
#include "myassert.h"
60
#include "sparcins.h"
61
#include "inl_norm.h"
62
 
63
int crit_inline    = 120;
64
int crit_decs	   = 6;
65
int crit_decsatapp = 4;
66
int show_inlining  = 0;
67
 
68
 
69
static int  complexity PROTO_S ((exp e, int count, int newdecs));
70
static last_new_decs = -999;
71
 
72
/*
73
    APPLY COMPLEXITY TO A LIST OF EXPRESSIONS
74
*/
75
 
76
int sbl 
77
    PROTO_N ( ( e, count, newdecs ) )
78
    PROTO_T ( exp e X int count X int newdecs )
79
{
80
    int c = complexity ( e, count, newdecs ) ;
81
    if ( c < 0 ) return ( c ) ;
82
    if ( last ( e ) ) return ( c ) ;
83
    return ( sbl ( bro ( e ), c, newdecs ) ) ;
84
}
85
 
86
/*
87
    FIND THE COMPLEXITY OF AN EXPRESSION
88
 
89
    This routine examines the structure of e to see if its complexity
90
    (roughly the number of nodes) is greater than count.  As soon as the
91
    complexity exceeds this value it stops.  It returns the difference
92
    between count and the calculated complexity.
93
*/
94
 
95
static int complexity 
96
    PROTO_N ( ( e, count, newdecs ) )
97
    PROTO_T ( exp e X int count X int newdecs )
98
{
99
    unsigned char n = name ( e ) ;
100
 
101
    last_new_decs = newdecs;
102
 
103
    if ( count < 0 )
104
      return ( -1 ) ;
105
    if (newdecs > crit_decs )
106
      return ( -2);
107
    if ( son ( e ) == nilexp ) 
108
      return ( count ) ;
109
 
110
    switch ( n ) {
111
 
112
      case apply_tag : {
113
	if ( newdecs > crit_decsatapp ) 
114
	  return ( -3 ) ;
115
	return ( sbl ( son ( e ),  ( count - 3 ),
116
		       ( newdecs + 1 ) ) ) ;
117
      }
118
 
119
      case rep_tag : {
120
	return ( complexity ( bro ( son ( e ) ),  ( count - 1 ),
121
			      (newdecs + 1)));
122
      }
123
 
124
      case res_tag : {
125
	return ( complexity ( son ( e ),  ( count + 1 ),
126
			      newdecs ) ) ;
127
      }
128
 
129
      case ident_tag : {
130
	return ( sbl ( son ( e ),  ( count - 1 ),
131
		       ( newdecs + 1 ) ) ) ;
132
      }
133
 
134
      case top_tag :
135
      case prof_tag :
136
      case clear_tag : {
137
	return ( count ) ;
138
      }
139
 
140
      case case_tag : {
141
	return ( complexity ( son ( e ),  ( count - 1 ),
142
			      newdecs ) ) ;
143
      }
144
 
145
      case name_tag :
146
      case string_tag :
147
      case env_offset_tag : {
148
	return ( count - 1 ) ;
149
      }
150
 
151
      case labst_tag : {
152
	return ( complexity ( bro ( son ( e ) ), count, newdecs ) ) ;
153
      }
154
 
155
      case cond_tag :
156
      case solve_tag :
157
      case seq_tag :
158
      return ( sbl ( son ( e ), count, newdecs ) ) ;
159
 
160
      case val_tag:
161
      return ( SIMM13_SIZE(no(e)) ? count : (count-1));
162
 
163
      default : {
164
	return ( sbl ( son ( e ),  ( count - 1 ), newdecs ) ) ;
165
      }
166
    }
167
    /* NOT REACHED */
168
}
169
 
170
#define MASK 3
171
#define REJ_ONCE (1)
172
#define OK_ONCE  (2)
173
static char *classify[] = { "Impossible","Never","Always","Sometimes"};
174
 
175
int inlinechoice
176
    PROTO_N ( (t, def, cnt) )
177
    PROTO_T ( exp t X exp def X int cnt )
178
	/* delivers 0 if no uses of this proc can be inlined.
179
	   delivers 1 if this use cannot be inlined
180
	   delivers 2 if this use can be inlined.
181
	*/
182
{
183
  int res, left;
184
 
185
  exp apars;
186
  exp fpars;
187
  exp pr_ident;
188
 
189
  int newdecs = 0;
190
  int no_actuals;
191
  int max_complexity;
192
 
193
  int nparam ;
194
  CONST unsigned int CONST_BONUS_UNIT = 16 ;
195
  unsigned int const_param_bonus ;
196
  unsigned int adjusted_max_complexity ;
197
 
198
/*  static exp last_ident = nilexp;
199
  static int last_inlined_times;*/
200
 
201
  nparam = 0 ;
202
  newdecs = 0 ;
203
  const_param_bonus = 0 ;
204
 
205
  pr_ident = son(t);		/* t is name_tag */
206
  assert(name(pr_ident) == ident_tag);
207
 
208
  max_complexity = ( 300 / cnt) ; /* was no(pr_ident), but that changes */
209
 
210
  {
211
#define LOG2_ALLOW_EXTRA 2
212
    int i;
213
    if (cnt >=(1<<LOG2_ALLOW_EXTRA))
214
    {
215
      for (i= cnt >> LOG2_ALLOW_EXTRA ; i>0; i >>=1)
216
      {
217
	max_complexity *= 3;
218
	max_complexity /= 2;
219
      }
220
    }
221
#undef LOG2_ALLOW_EXTRA
222
  }    
223
  if ( max_complexity < 15 ) {
224
    max_complexity = 15 ;
225
  } else if ( max_complexity > crit_inline) {
226
    max_complexity = crit_inline ;
227
  }
228
 
229
  if (show_inlining)
230
  {
231
    exp proc_in = t;
232
 
233
    while (name(proc_in) != proc_tag)
234
    {
235
      proc_in = father(proc_in);
236
      assert (proc_in != nilexp);
237
    }
238
    proc_in = bro(proc_in);
239
    assert (name(proc_in) = ident_tag);
240
 
241
    fprintf(stderr,"Considering %s in %s\n",
242
	    brog(pr_ident)->dec_u.dec_val.dec_id,
243
	    brog(proc_in)->dec_u.dec_val.dec_id);
244
  }
245
 
246
  apars = bro(t);		/* t is name_tag */
247
  no_actuals = last(t);		/* if so then apars is apply_tag... */  
248
  fpars = son(def);      	
249
 
250
  for(;;) {
251
     if (name(fpars)!=ident_tag || !isparam(fpars)) { /* first beyond formals */
252
       if (!last(t))
253
	 newdecs = 10; /* more actuals than formals, since last(apars)->break */
254
       break;
255
     }
256
     nparam++ ;
257
 
258
     switch (name(apars)) {
259
      case val_tag: case real_tag: case string_tag: case name_tag: 
260
      	   break;
261
      case cont_tag: {
262
      	   if (name(son(apars))==name_tag && isvar(son(son(apars))) &&
263
      	        		!isvar(fpars) ) break;
264
      	   } /* ... else continue */
265
      default: newdecs++;
266
     }
267
     switch ( name ( apars ) ) 
268
     {
269
      case val_tag : {
270
	int n = no ( apars ) ;
271
 
272
	/* Simple constant param. Increase desire to
273
	   inline since a constant may cause further
274
	   optimisation, eg strength reduction (mul
275
	   to shift) or dead code savings */
276
 
277
#define IS_POW2( c )	( ( c ) != 0 && ( ( c ) & ( ( c ) - 1 ) ) == 0 )
278
 
279
	if ( !SIMM13_SIZE ( n ) ) {
280
	  /* needs a register - poor */
281
	  const_param_bonus += CONST_BONUS_UNIT / 4 ;
282
	} else if ( n == 0 || ( n > 0 && IS_POW2 ( n ) ) ) {
283
	  /* very good */
284
	  const_param_bonus += CONST_BONUS_UNIT ;
285
	} else {
286
	  /* less good */
287
	  const_param_bonus += CONST_BONUS_UNIT / 2 ;
288
	}
289
	break ;
290
      }
291
 
292
#undef IS_POW2
293
 
294
      case real_tag : 
295
	/* reals not that useful */
296
	const_param_bonus += CONST_BONUS_UNIT / 4 ;
297
	break ;
298
 
299
      case string_tag :
300
       case name_tag : 
301
	 break ;
302
 
303
      case cont_tag : 
304
	if ( name ( son ( apars ) ) == name_tag &&
305
	    isvar ( son ( son ( apars ) ) ) &&
306
	    !isvar ( fpars ) ) {
307
	  break ;
308
	}
309
	/* FALL THROUGH */
310
 
311
      default : {
312
	newdecs++ ;
313
	break ;
314
      }
315
     }
316
     fpars = bro(son(fpars));
317
     if (last(apars)) break;
318
     apars = bro(apars);
319
   }
320
 
321
  adjusted_max_complexity = max_complexity ;
322
 
323
  /* increase to up to 3 times (average around 2) according
324
     to const params */
325
  if ( nparam != 0 ) {
326
    adjusted_max_complexity += 
327
      ( 2 * max_complexity * const_param_bonus ) /
328
	( CONST_BONUS_UNIT * nparam ) ;
329
  }
330
 
331
  /* increase by number of instructions saved for call */
332
    adjusted_max_complexity += nparam - newdecs + 1 ;
333
  if (show_inlining)
334
    fprintf(stderr,"%d params %u complexity, %d newdecs -> ",nparam, 
335
	 adjusted_max_complexity, newdecs);
336
 
337
  if ( (left = complexity ( fpars,  adjusted_max_complexity, newdecs )) >= 0 )
338
    res = 2;
339
  else if (newdecs == 0)
340
    res = 0;
341
  else
342
    res = 1;
343
 
344
  if (show_inlining)
345
  {
346
    switch (res)
347
    {
348
     case 2:
349
      fprintf(stderr,"%d left (%d decs) YES\n",left, last_new_decs);
350
      (ptno(def)) |= OK_ONCE;
351
      break;
352
     case 1:
353
      if (left == -1)
354
	fprintf(stderr,"no (count, %d decs)\n", last_new_decs);
355
      else if (left == -2)
356
	fprintf(stderr,"no (decs)\n");
357
      else
358
	fprintf(stderr,"no (appdecs)\n");
359
 
360
      (ptno(def)) |= REJ_ONCE;
361
      break;
362
     case 0:
363
      fprintf(stderr,"NO WAY\n");
364
    }
365
 
366
    fprintf(stderr,"--%s %s\n",brog(pr_ident)->dec_u.dec_val.dec_id, 
367
	    classify[(ptno(def) & MASK)]);
368
  }
369
 
370
  return res;
371
 
372
}