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
/* 80x86/inlinechoice.c */
32
 
33
/**********************************************************************
34
$Author: release $
35
$Date: 1998/01/17 15:55:51 $
36
$Revision: 1.1.1.1 $
37
$Log: inlinechoice.c,v $
38
 * Revision 1.1.1.1  1998/01/17  15:55:51  release
39
 * First version to be checked into rolling release.
40
 *
41
 * Revision 1.8  1996/12/04  17:58:36  pwe
42
 * correct to allow inlining at >1 location
43
 *
44
 * Revision 1.7  1995/09/28  12:45:17  pwe
45
 * tidy for tcc
46
 *
47
 * Revision 1.6  1995/08/04  08:29:20  pwe
48
 * 4.0 general procs implemented
49
 *
50
 * Revision 1.5  1995/02/22  13:34:31  pwe
51
 * no inline if application shape differs from return shape of proc
52
 *
53
 * Revision 1.4  1995/01/30  12:56:15  pwe
54
 * Ownership -> PWE, tidy banners
55
 *
56
**********************************************************************/
57
 
58
 
59
#include "config.h"
60
#include "common_types.h"
61
#include "installglob.h"
62
#include "exp.h"
63
#include "expmacs.h"
64
#include "tags.h"
65
#include "flags.h"
66
#include "shapemacs.h"
67
#include "inl_norm.h"
68
 
69
#define crit_inline	300
70
#define crit_decs	5
71
#define crit_decsatapp	5
72
#define apply_cost      3
73
 
74
static int complexity PROTO_S ((exp e, int count, int newdecs));
75
static last_new_decs = -999;
76
 
77
/*
78
    APPLY COMPLEXITY TO A LIST OF EXPRESSIONS
79
*/
80
 
81
int sbl
82
    PROTO_N ( ( e, count, newdecs ) )
83
    PROTO_T ( exp e X int count X int newdecs )
84
{
85
    int c = complexity ( e, count, newdecs ) ;
86
    if ( c < 0 ) return ( c ) ;
87
    if ( last ( e ) ) return ( c ) ;
88
    return ( sbl ( bro ( e ), c, newdecs ) ) ;
89
}
90
 
91
 
92
/*
93
    FIND THE COMPLEXITY OF AN EXPRESSION
94
 
95
    This routine examines the structure of e to see if its complexity
96
    (roughly the number of nodes) is greater than count.  As soon as the
97
    complexity exceeds this value it stops.  It returns the difference
98
    between count and the calculated complexity.
99
*/
100
 
101
static int complexity
102
    PROTO_N ( ( e, count, newdecs ) )
103
    PROTO_T ( exp e X int count X int newdecs )
104
{
105
    unsigned char n = name ( e ) ;
106
 
107
    last_new_decs = newdecs;
108
 
109
    if ( count < 0 )
110
      return ( -1 ) ;
111
    if (newdecs > crit_decs )
112
      return ( -2);
113
    if ( son ( e ) == nilexp )
114
      return ( count ) ;
115
 
116
    switch ( n ) {
117
 
118
	case apply_tag : {
119
	    if ( newdecs > crit_decsatapp )
120
	      return ( -3 ) ;
121
	    return ( sbl ( son ( e ),  ( count - apply_cost ),
122
			  ( newdecs + 1 ) ) ) ;
123
	}
124
 
125
	case rep_tag : {
126
	    return ( complexity ( bro ( son ( e ) ),  ( count - 1 ),
127
		      (newdecs + 1)
128
				 ));
129
	}
130
 
131
	case res_tag : {
132
	    return ( complexity ( son ( e ),  ( count + 1 ),
133
				  newdecs ) ) ;
134
	}
135
 
136
	case ident_tag : {
137
	    return ( sbl ( son ( e ),  ( count - 1 ),
138
			    ( newdecs + 1 ) ) ) ;
139
	}
140
 
141
	case top_tag :
142
	case clear_tag :
143
	case val_tag : {
144
	    return ( count ) ;
145
	}
146
 
147
	case case_tag : {
148
	    return ( complexity ( son ( e ),  ( count - 1 ),
149
				  newdecs ) ) ;
150
	}
151
 
152
	case name_tag :
153
	case string_tag :
154
	case env_offset_tag : {
155
	    return ( count - 1 ) ;
156
	}
157
 
158
	case labst_tag : {
159
	    return ( complexity ( bro ( son ( e ) ), count, newdecs ) ) ;
160
	}
161
 
162
	case solve_tag :
163
	case seq_tag :
164
	case cond_tag : {
165
	    return ( sbl ( son ( e ), count, newdecs ) ) ;
166
	}
167
 
168
	default : {
169
	    return ( sbl ( son ( e ),  ( count - 1 ), newdecs ) ) ;
170
	}
171
    }
172
    /* NOT REACHED */
173
}
174
 
175
 
176
/* delivers 0 if no uses of this proc can be inlined.
177
   delivers 1 if this use cannot be inlined
178
   delivers 2 if this use can be inlined.
179
*/
180
int inlinechoice
181
    PROTO_N ( (t, def, total_uses) )
182
    PROTO_T ( exp t X exp def X int total_uses )
183
{
184
  int res;
185
 
186
  exp apars;
187
  exp fpars;
188
 
189
  int newdecs = 0;
190
  int no_actuals;
191
  int max_complexity;
192
 
193
  int nparam ;
194
  CONST  int CONST_BONUS_UNIT = 16 ;
195
  int const_param_bonus ;
196
  int adjusted_max_complexity ;
197
 
198
  shape shdef = pt(def) /* Oh, yes it is! */;
199
 
200
  if (!eq_shape(sh(father(t)), shdef) ) {
201
     /* shape required by application is different from definition */
202
	return 1;
203
  }
204
 
205
  nparam = 0 ;
206
  const_param_bonus = 0 ;
207
 
208
 
209
  max_complexity = ( crit_inline / total_uses ) ;
210
 
211
#if issparc
212
  {
213
#define QQQ 2
214
    int i;
215
    if (total_uses >=(1<<QQQ))
216
    {
217
      for (i= total_uses >> QQQ ; i>0; i >>=1)
218
      {
219
	max_complexity *= 3;
220
	max_complexity /= 2;
221
      }
222
    }
223
#undef QQQ
224
  }
225
#endif
226
 
227
  if ( max_complexity < 15 ) {
228
    max_complexity = 15 ;
229
  } else if ( max_complexity > 120 ) {
230
    max_complexity = 120 ;
231
  }
232
 
233
  apars = bro(t); /* only uses are applications */
234
  no_actuals = last(t);		/* if so then apars is apply_tag... */
235
  fpars = son(def);
236
 
237
  for(;;) {
238
     if (name(fpars)!=ident_tag || !isparam(fpars)) {
239
		 /* first beyond formals */
240
       if (!no_actuals)
241
	 newdecs = 10;
242
	 /* more actuals than formals, since last(apars)->break */
243
       break;
244
     }
245
     nparam++ ;
246
 
247
     switch (name(apars)) {
248
      case val_tag: case real_tag: case string_tag: case name_tag:
249
      	   break;
250
      case cont_tag: {
251
      	   if (name(son(apars))==name_tag && isvar(son(son(apars))) &&
252
      	        		!isvar(fpars) ) break;
253
      	   } /* ... else continue */
254
      default: newdecs++;
255
     }
256
     switch ( name ( apars ) )
257
     {
258
      case val_tag : {
259
	int n = no ( apars ) ;
260
	if (isbigval(apars)) break;
261
 
262
	/* Simple constant param. Increase desire to
263
	   inline since a constant may cause further
264
	   optimisation, eg strength reduction (mul
265
	   to shift) or dead code savings */
266
 
267
#define IS_POW2( c )	( ( c ) != 0 && ( ( c ) & ( ( c ) - 1 ) ) == 0 )
268
 
269
	if ( 0 ) {
270
	  /* needs a register - poor */
271
	  const_param_bonus += CONST_BONUS_UNIT / 4 ;
272
	} else if ( n == 0 || ( n > 0 && IS_POW2 ( n ) ) ) {
273
	  /* very good */
274
	  const_param_bonus += CONST_BONUS_UNIT ;
275
	} else {
276
	  /* less good */
277
	  const_param_bonus += CONST_BONUS_UNIT / 2 ;
278
	}
279
	break ;
280
      }
281
 
282
#undef IS_POW2
283
 
284
      case real_tag :
285
	/* reals not that useful */
286
	const_param_bonus += CONST_BONUS_UNIT / 4 ;
287
	break ;
288
 
289
      case string_tag :
290
       case name_tag :
291
	 break ;
292
 
293
      case cont_tag :
294
	if ( name ( son ( apars ) ) == name_tag &&
295
	    isvar ( son ( son ( apars ) ) ) &&
296
	    !isvar ( fpars ) ) {
297
	  break ;
298
	}
299
	/* FALL THROUGH */
300
 
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
  return res;
333
 
334
}
335