Subversion Repositories tendra.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
7 7u83 2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
33
 
34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
42
 
43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
45
 
46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
49
 
50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
53
 
54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
/* 80x86/inlinechoice.c */
62
 
63
/**********************************************************************
64
$Author: release $
65
$Date: 1998/01/17 15:55:51 $
66
$Revision: 1.1.1.1 $
67
$Log: inlinechoice.c,v $
68
 * Revision 1.1.1.1  1998/01/17  15:55:51  release
69
 * First version to be checked into rolling release.
70
 *
71
 * Revision 1.8  1996/12/04  17:58:36  pwe
72
 * correct to allow inlining at >1 location
73
 *
74
 * Revision 1.7  1995/09/28  12:45:17  pwe
75
 * tidy for tcc
76
 *
77
 * Revision 1.6  1995/08/04  08:29:20  pwe
78
 * 4.0 general procs implemented
79
 *
80
 * Revision 1.5  1995/02/22  13:34:31  pwe
81
 * no inline if application shape differs from return shape of proc
82
 *
83
 * Revision 1.4  1995/01/30  12:56:15  pwe
84
 * Ownership -> PWE, tidy banners
85
 *
86
**********************************************************************/
87
 
88
 
89
#include "config.h"
90
#include "common_types.h"
91
#include "installglob.h"
92
#include "exp.h"
93
#include "expmacs.h"
94
#include "tags.h"
95
#include "flags.h"
96
#include "shapemacs.h"
97
#include "inl_norm.h"
98
 
99
#define crit_inline	300
100
#define crit_decs	5
101
#define crit_decsatapp	5
102
#define apply_cost      3
103
 
7 7u83 104
static int complexity(exp e, int count, int newdecs);
2 7u83 105
static last_new_decs = -999;
106
 
107
/*
108
    APPLY COMPLEXITY TO A LIST OF EXPRESSIONS
109
*/
110
 
111
int sbl
7 7u83 112
(exp e, int count, int newdecs)
2 7u83 113
{
7 7u83 114
    int c = complexity(e, count, newdecs);
115
    if (c < 0) return(c);
116
    if (last(e)) return(c);
117
    return(sbl(bro(e), c, newdecs));
2 7u83 118
}
119
 
120
 
121
/*
122
    FIND THE COMPLEXITY OF AN EXPRESSION
123
 
124
    This routine examines the structure of e to see if its complexity
125
    (roughly the number of nodes) is greater than count.  As soon as the
126
    complexity exceeds this value it stops.  It returns the difference
127
    between count and the calculated complexity.
128
*/
129
 
130
static int complexity
7 7u83 131
(exp e, int count, int newdecs)
2 7u83 132
{
7 7u83 133
    unsigned char n = name(e);
2 7u83 134
 
135
    last_new_decs = newdecs;
136
 
7 7u83 137
    if (count < 0)
138
      return(-1);
139
    if (newdecs > crit_decs)
140
      return(-2);
141
    if (son(e) == nilexp)
142
      return(count);
2 7u83 143
 
7 7u83 144
    switch (n) {
2 7u83 145
 
7 7u83 146
	case apply_tag: {
147
	    if (newdecs > crit_decsatapp)
148
	      return(-3);
149
	    return(sbl(son(e), (count - apply_cost),
150
			 (newdecs + 1)));
2 7u83 151
	}
152
 
7 7u83 153
	case rep_tag: {
154
	    return(complexity(bro(son(e)), (count - 1),
155
		     (newdecs + 1)
156
				));
2 7u83 157
	}
158
 
7 7u83 159
	case res_tag: {
160
	    return(complexity(son(e), (count + 1),
161
				  newdecs));
2 7u83 162
	}
163
 
7 7u83 164
	case ident_tag: {
165
	    return(sbl(son(e), (count - 1),
166
			   (newdecs + 1)));
2 7u83 167
	}
168
 
7 7u83 169
	case top_tag:
170
	case clear_tag:
171
	case val_tag: {
172
	    return(count);
2 7u83 173
	}
174
 
7 7u83 175
	case case_tag: {
176
	    return(complexity(son(e), (count - 1),
177
				  newdecs));
2 7u83 178
	}
179
 
7 7u83 180
	case name_tag:
181
	case string_tag:
182
	case env_offset_tag: {
183
	    return(count - 1);
2 7u83 184
	}
185
 
7 7u83 186
	case labst_tag: {
187
	    return(complexity(bro(son(e)), count, newdecs));
2 7u83 188
	}
189
 
7 7u83 190
	case solve_tag:
191
	case seq_tag:
192
	case cond_tag: {
193
	    return(sbl(son(e), count, newdecs));
2 7u83 194
	}
195
 
196
	default : {
7 7u83 197
	    return(sbl(son(e), (count - 1), newdecs));
2 7u83 198
	}
199
    }
200
    /* NOT REACHED */
201
}
202
 
203
 
204
/* delivers 0 if no uses of this proc can be inlined.
205
   delivers 1 if this use cannot be inlined
206
   delivers 2 if this use can be inlined.
207
*/
208
int inlinechoice
7 7u83 209
(exp t, exp def, int total_uses)
2 7u83 210
{
211
  int res;
212
 
213
  exp apars;
214
  exp fpars;
215
 
216
  int newdecs = 0;
217
  int no_actuals;
218
  int max_complexity;
219
 
7 7u83 220
  int nparam;
221
  CONST  int CONST_BONUS_UNIT = 16;
222
  int const_param_bonus;
223
  int adjusted_max_complexity;
2 7u83 224
 
225
  shape shdef = pt(def) /* Oh, yes it is! */;
226
 
7 7u83 227
  if (!eq_shape(sh(father(t)), shdef)) {
2 7u83 228
     /* shape required by application is different from definition */
229
	return 1;
230
  }
231
 
7 7u83 232
  nparam = 0;
233
  const_param_bonus = 0;
2 7u83 234
 
235
 
7 7u83 236
  max_complexity = (crit_inline / total_uses);
2 7u83 237
 
238
#if issparc
239
  {
240
#define QQQ 2
241
    int i;
7 7u83 242
    if (total_uses >= (1<<QQQ))
2 7u83 243
    {
7 7u83 244
      for (i= total_uses >> QQQ; i>0; i >>=1)
2 7u83 245
      {
246
	max_complexity *= 3;
247
	max_complexity /= 2;
248
      }
249
    }
250
#undef QQQ
251
  }
252
#endif
253
 
7 7u83 254
  if (max_complexity < 15) {
255
    max_complexity = 15;
256
  } else if (max_complexity > 120) {
257
    max_complexity = 120;
2 7u83 258
  }
259
 
260
  apars = bro(t); /* only uses are applications */
261
  no_actuals = last(t);		/* if so then apars is apply_tag... */
262
  fpars = son(def);
263
 
7 7u83 264
  for (;;) {
2 7u83 265
     if (name(fpars)!=ident_tag || !isparam(fpars)) {
266
		 /* first beyond formals */
267
       if (!no_actuals)
268
	 newdecs = 10;
269
	 /* more actuals than formals, since last(apars)->break */
270
       break;
271
     }
7 7u83 272
     nparam++;
2 7u83 273
 
274
     switch (name(apars)) {
275
      case val_tag: case real_tag: case string_tag: case name_tag:
276
      	   break;
277
      case cont_tag: {
7 7u83 278
      	   if (name(son(apars)) ==name_tag && isvar(son(son(apars))) &&
279
      	        		!isvar(fpars))break;
2 7u83 280
      	   } /* ... else continue */
281
      default: newdecs++;
282
     }
7 7u83 283
     switch (name(apars))
2 7u83 284
     {
7 7u83 285
      case val_tag: {
286
	int n = no(apars);
287
	if (isbigval(apars))break;
2 7u83 288
 
289
	/* Simple constant param. Increase desire to
290
	   inline since a constant may cause further
291
	   optimisation, eg strength reduction (mul
292
	   to shift) or dead code savings */
293
 
7 7u83 294
#define IS_POW2(c)	((c)!= 0 && ((c) & ((c) - 1)) == 0)
2 7u83 295
 
7 7u83 296
	if (0) {
2 7u83 297
	  /* needs a register - poor */
7 7u83 298
	  const_param_bonus += CONST_BONUS_UNIT / 4;
299
	} else if (n == 0 || (n > 0 && IS_POW2(n))) {
2 7u83 300
	  /* very good */
7 7u83 301
	  const_param_bonus += CONST_BONUS_UNIT;
2 7u83 302
	} else {
303
	  /* less good */
7 7u83 304
	  const_param_bonus += CONST_BONUS_UNIT / 2;
2 7u83 305
	}
7 7u83 306
	break;
2 7u83 307
      }
308
 
309
#undef IS_POW2
310
 
7 7u83 311
      case real_tag:
2 7u83 312
	/* reals not that useful */
7 7u83 313
	const_param_bonus += CONST_BONUS_UNIT / 4;
314
	break;
2 7u83 315
 
7 7u83 316
      case string_tag:
317
       case name_tag:
318
	 break;
2 7u83 319
 
7 7u83 320
      case cont_tag:
321
	if (name(son(apars)) == name_tag &&
322
	    isvar(son(son(apars))) &&
323
	    !isvar(fpars)) {
324
	  break;
2 7u83 325
	}
326
	/* FALL THROUGH */
327
 
328
      default : {
7 7u83 329
	newdecs++;
330
	break;
2 7u83 331
      }
332
     }
333
     fpars = bro(son(fpars));
7 7u83 334
     if (last(apars))break;
2 7u83 335
     apars = bro(apars);
336
   }
337
 
7 7u83 338
  adjusted_max_complexity = max_complexity;
2 7u83 339
 
340
  /* increase to up to 3 times (average around 2) according
341
     to const params */
7 7u83 342
  if (nparam != 0) {
2 7u83 343
    adjusted_max_complexity +=
7 7u83 344
     (2 * max_complexity * const_param_bonus) /
345
	(CONST_BONUS_UNIT * nparam);
2 7u83 346
  }
347
 
348
  /* increase by number of instructions saved for call */
7 7u83 349
    adjusted_max_complexity += nparam - newdecs + 1;
2 7u83 350
 
7 7u83 351
  if ((complexity(fpars,  adjusted_max_complexity, newdecs)) >= 0)
2 7u83 352
    res = 2;
353
  else if (newdecs == 0)
354
    res = 0;
355
  else
356
    res = 1;
357
 
358
 
359
  return res;
360
 
361
}
362