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