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
$Log: inlinechoice.c,v $
33
 * Revision 1.1.1.1  1998/01/17  15:56:02  release
34
 * First version to be checked into rolling release.
35
 *
36
 * Revision 1.2  1995/12/18  13:11:37  wfs
37
 * Put hppatrans uder cvs control. Major Changes made since last release
38
 * include:
39
 * (i) PIC code generation.
40
 * (ii) Profiling.
41
 * (iii) Dynamic Initialization.
42
 * (iv) Debugging of Exception Handling and Diagnostics.
43
 *
44
 * Revision 5.0  1995/08/25  13:42:58  wfs
45
 * Preperation for August 25 Glue release
46
 *
47
 * Revision 3.4  1995/08/25  09:39:31  wfs
48
 * A 4.0 "general_env_offset_tag" case added.
49
 *
50
 * Revision 3.4  1995/08/25  09:39:31  wfs
51
 * A 4.0 "general_env_offset_tag" case added.
52
 *
53
 * Revision 3.1  95/04/10  16:26:51  16:26:51  wfs (William Simmonds)
54
 * Apr95 tape version.
55
 * 
56
 * Revision 3.0  95/03/30  11:17:28  11:17:28  wfs (William Simmonds)
57
 * Mar95 tape version with CRCR95_178 bug fix.
58
 * 
59
 * Revision 2.0  95/03/15  15:27:35  15:27:35  wfs (William Simmonds)
60
 * spec 3.1 changes implemented, tests outstanding.
61
 * 
62
 * Revision 1.1  95/01/11  13:09:12  13:09:12  wfs (William Simmonds)
63
 * Initial revision
64
 * 
65
*/
66
 
67
 
68
#include "config.h"
69
#include "common_types.h"
70
#include "installglob.h"
71
#include "exp.h"
72
#include "expmacs.h"
73
#include "tags.h"
74
#include "flags.h"
75
#include "shapemacs.h"
76
#include "inl_norm.h"
77
 
78
#define crit_inline	300
79
#define crit_decs	5
80
#define crit_decsatapp	5
81
#define apply_cost      3
82
 
83
static int  complexity PROTO_S ((exp e, int count, int newdecs));
84
static last_new_decs = -999;
85
 
86
/*
87
    APPLY COMPLEXITY TO A LIST OF EXPRESSIONS
88
*/
89
 
90
int sbl 
91
    PROTO_N ( ( e, count, newdecs ) )
92
    PROTO_T ( exp e X int count X int newdecs )
93
{
94
    int c = complexity ( e, count, newdecs ) ;
95
    if ( c < 0 ) return ( c ) ;
96
    if ( last ( e ) ) return ( c ) ;
97
    return ( sbl ( bro ( e ), c, newdecs ) ) ;
98
}
99
 
100
 
101
/*
102
    FIND THE COMPLEXITY OF AN EXPRESSION
103
 
104
    This routine examines the structure of e to see if its complexity
105
    (roughly the number of nodes) is greater than count.  As soon as the
106
    complexity exceeds this value it stops.  It returns the difference
107
    between count and the calculated complexity.
108
*/
109
 
110
static int complexity 
111
    PROTO_N ( ( e, count, newdecs ) )
112
    PROTO_T ( exp e X int count X int newdecs )
113
{
114
    unsigned char n = name ( e ) ;
115
 
116
    last_new_decs = newdecs;
117
 
118
    if ( count < 0 )
119
      return ( -1 ) ;
120
    if (newdecs > crit_decs )
121
      return ( -2);
122
    if ( son ( e ) == nilexp ) 
123
      return ( count ) ;
124
 
125
    switch ( n ) {
126
 
127
	case apply_tag : {
128
	    if ( newdecs > crit_decsatapp ) 
129
	      return ( -3 ) ;
130
	    return ( sbl ( son ( e ),  ( count - apply_cost ),
131
			  ( newdecs + 1 ) ) ) ;
132
	}
133
 
134
	case rep_tag : {
135
	    return ( complexity ( bro ( son ( e ) ),  ( count - 1 ),
136
		      (newdecs + 1)
137
				 ));
138
	}
139
 
140
	case res_tag : {
141
	    return ( complexity ( son ( e ),  ( count + 1 ),
142
				  newdecs ) ) ;
143
	}
144
 
145
	case ident_tag : {
146
	    return ( sbl ( son ( e ),  ( count - 1 ),
147
			    ( newdecs + 1 ) ) ) ;
148
	}
149
 
150
	case top_tag :
151
	case clear_tag :
152
	case val_tag : {
153
	    return ( count ) ;
154
	}
155
 
156
	case case_tag : {
157
	    return ( complexity ( son ( e ),  ( count - 1 ),
158
				  newdecs ) ) ;
159
	}
160
 
161
	case name_tag :
162
	case string_tag :
163
	case env_offset_tag :
164
	case general_env_offset_tag:
165
	{
166
	    return ( count - 1 ) ;
167
	}
168
 
169
	case labst_tag : {
170
	    return ( complexity ( bro ( son ( e ) ), count, newdecs ) ) ;
171
	}
172
 
173
	case solve_tag :
174
	case seq_tag :
175
	case cond_tag : {
176
	    return ( sbl ( son ( e ), count, newdecs ) ) ;
177
	}
178
 
179
	default : {
180
	    return ( sbl ( son ( e ),  ( count - 1 ), newdecs ) ) ;
181
	}
182
    }
183
    /* NOT REACHED */
184
}
185
 
186
#define MASK 3
187
#define REJ_ONCE (1)
188
#define OK_ONCE  (2)
189
 
190
 
191
int inlinechoice
192
    PROTO_N ( ( t, def, total_uses ) )
193
    PROTO_T ( exp t X exp def X int total_uses )
194
	/* delivers 0 if no uses of this proc can be inlined.
195
	   delivers 1 if this use cannot be inlined
196
	   delivers 2 if this use can be inlined.
197
	*/
198
{
199
  int res;
200
 
201
  exp apars;
202
  exp fpars;
203
 
204
  int newdecs = 0;
205
 
206
  int max_complexity;
207
 
208
  int nparam ;
209
  CONST unsigned int CONST_BONUS_UNIT = 16 ;
210
  int const_param_bonus ;
211
  int adjusted_max_complexity ;
212
 
213
#if 1
214
  shape shdef = pt(def);
215
  if (!eq_shape(sh(father(t)), shdef) ) 
216
  {
217
    /* shape required by application is different from definition */
218
    return 1;
219
  }
220
#endif
221
 
222
  nparam = 0 ;
223
  const_param_bonus = 0 ;
224
 
225
 
226
  max_complexity = ( crit_inline / total_uses ) ;
227
 
228
 
229
 
230
#if ishppa  
231
  {
232
#define QQQ 2
233
    int i;
234
    if (total_uses >=(1<<QQQ))
235
    {
236
      for (i= total_uses >> QQQ ; i>0; i >>=1)
237
      {
238
	max_complexity *= 3;
239
	max_complexity /= 2;
240
      }
241
    }
242
#undef QQQ
243
  }
244
#endif
245
 
246
  if ( max_complexity < 15 ) {
247
    max_complexity = 15 ;
248
  } else if ( max_complexity > 120 ) {
249
    max_complexity = 120 ;
250
  }
251
 
252
  apars = bro(t); /* only uses are applications */
253
  fpars = son(def);      	
254
 
255
  for(;;) {
256
     if (name(fpars)!=ident_tag || !isparam(fpars)) {
257
       if (name(apars) != top_tag) newdecs = 10;
258
      	 break;
259
     }
260
     nparam++ ;
261
 
262
     switch (name(apars)) {
263
      case val_tag: case real_tag: case string_tag: case name_tag: 
264
      	   break;
265
      case cont_tag: {
266
      	   if (name(son(apars))==name_tag && isvar(son(son(apars))) &&
267
      	        		!isvar(fpars) ) break;
268
      	   } /* ... else continue */
269
      default: newdecs++;
270
     }
271
     switch ( name ( apars ) ) 
272
     {
273
      case val_tag : {
274
	int n = no ( apars ) ;
275
 
276
	/* Simple constant param. Increase desire to
277
	   inline since a constant may cause further
278
	   optimisation, eg strength reduction (mul
279
	   to shift) or dead code savings */
280
 
281
#define IS_POW2( c )	( ( c ) != 0 && ( ( c ) & ( ( c ) - 1 ) ) == 0 )
282
 
283
	if ( 0 ) {
284
	  /* needs a register - poor */
285
	  const_param_bonus += CONST_BONUS_UNIT / 4 ;
286
	} else if ( n == 0 || ( n > 0 && IS_POW2 ( n ) ) ) {
287
	  /* very good */
288
	  const_param_bonus += CONST_BONUS_UNIT ;
289
	} else {
290
	  /* less good */
291
	  const_param_bonus += CONST_BONUS_UNIT / 2 ;
292
	}
293
	break ;
294
      }
295
 
296
#undef IS_POW2
297
 
298
      case real_tag : 
299
	/* reals not that useful */
300
	const_param_bonus += CONST_BONUS_UNIT / 4 ;
301
	break ;
302
 
303
      case string_tag :
304
       case name_tag : 
305
	 break ;
306
 
307
      case cont_tag : 
308
	if ( name ( son ( apars ) ) == name_tag &&
309
	    isvar ( son ( son ( apars ) ) ) &&
310
	    !isvar ( fpars ) ) {
311
	  break ;
312
	}
313
	/* FALL THROUGH */
314
 
315
      default : {
316
	newdecs++ ;
317
	break ;
318
      }
319
     }
320
     fpars = bro(son(fpars));
321
     if (last(apars)) break;
322
     apars = bro(apars);
323
   }
324
 
325
  adjusted_max_complexity = max_complexity ;
326
 
327
  /* increase to up to 3 times (average around 2) according
328
     to const params */
329
  if ( nparam != 0 ) {
330
    adjusted_max_complexity += 
331
      ( 2 * max_complexity * const_param_bonus ) /
332
	( CONST_BONUS_UNIT * nparam ) ;
333
  }
334
 
335
  /* increase by number of instructions saved for call */
336
    adjusted_max_complexity += nparam - newdecs + 1 ;
337
 
338
  if ( (complexity ( fpars,  adjusted_max_complexity, newdecs )) >= 0 )
339
    res = 2;
340
  else if (newdecs == 0)
341
    res = 0;
342
  else
343
    res = 1;
344
 
345
 
346
  switch (res)
347
  {
348
   case 2:
349
    (ptno(def)) |= OK_ONCE;
350
    break;
351
   case 1:
352
 
353
    (ptno(def)) |= REJ_ONCE;
354
    break;
355
   case 0:
356
    ;
357
  }
358
 
359
  return res;
360
 
361
}
362