Subversion Repositories tendra.SVN

Rev

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