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
$Author: release $
33
$Date: 1998/01/17 15:55:46 $
34
$Revision: 1.1.1.1 $
35
$Log: case_opt.c,v $
36
 * Revision 1.1.1.1  1998/01/17  15:55:46  release
37
 * First version to be checked into rolling release.
38
 *
39
 * Revision 1.2  1996/11/18  14:36:49  currie
40
 * case_opt fixes
41
 *
42
 * Revision 1.1  1995/04/06  10:44:05  currie
43
 * Initial revision
44
 *
45
***********************************************************************/
46
/************************************************************
47
  OPTIMIZATION of case_tag's
48
  Author: mjg
49
************************************************************/
50
 
51
#include "config.h"
52
#include "common_types.h"
53
#include "installglob.h"
54
#include "exp.h"
55
#include "expmacs.h"
56
#include "tags.h"
57
#include "check.h"
58
#include "flags.h"
59
#include "check_id.h"
60
#include "const.h"
61
#include "foralls.h"
62
#include "shapemacs.h"
63
#include "glopt.h"
64
#include "inline.h"
65
#include "global_opt.h"
66
#include "case_opt.h"
67
#include "externs.h"
68
#include "me_fns.h"
69
#include "xalloc.h"
70
#include "install_fns.h"
71
#include "szs_als.h"
72
 
73
#ifndef jump_table_density
74
#define jump_table_density  60
75
#endif
76
#ifndef min_jump_table_size
77
#define min_jump_table_size 10
78
#endif
79
#ifndef max_jump_table_size
80
#define max_jump_table_size 100
81
#endif
82
#ifndef min_no_of_default_destinations
83
#define min_no_of_default_destinations 3
84
#endif
85
 
86
static int density PROTO_S ( ( exp *, int, int, int ) ) ;
87
static exp exhaustive_conditional_maker PROTO_S ( ( int, int, exp ) ) ;
88
static exp inexhaustive_conditional_maker PROTO_S ( ( int, int, exp, exp ) ) ;
89
static exp set_up_sequence PROTO_S ( ( exp, exp, ntest, int, exp, int ) ) ;
90
static exp set_up_assign PROTO_S ( ( exp, int ) ) ;
91
static exp set_up_unsigned_test PROTO_S ( ( exp, exp, int, ntest ) ) ;
92
static exp like_me_q1 PROTO_S ( ( int, ntest, exp, exp, exp, unsigned char ) ) ;
93
 
94
 
95
/* VARIABLES */
96
 
97
static int  no_of_nodes;
98
static  exp * node_start;
99
static  exp * node_end;
100
static double *node_weight;
101
static unsigned char *node_start_flag;
102
static unsigned char *node_end_flag;
103
 
104
 
105
/* PROCEDURES */
106
 
107
 
108
 
109
 
110
 
111
/*
112
 * case_optimisation takes a case_tag and an ident_tag and
113
 * splits up the case_tag into parts which it thinks should
114
 * be done as jump tables.
115
 */
116
exp case_optimisation
117
    PROTO_N ( (body, id, shape_of_case, control_expression) )
118
    PROTO_T ( exp body X exp id X shape shape_of_case X exp control_expression )
119
{
120
  exp t;
121
  exp * ELEMENTS;
122
  int   i;
123
  int   n;
124
  int   no_of_cases = 1;
125
  int jump_table_present = 0;
126
 
127
  no_of_nodes = 0;
128
  /* Calculate the number of cases in the case_tag */
129
  t = body;
130
  while (!last (t)) {
131
    no_of_cases = no_of_cases + 1;
132
    t = bro (t);
133
  }
134
 
135
  ELEMENTS = (exp *) xcalloc (no_of_cases, sizeof (exp));
136
  node_start = (exp *) xcalloc (no_of_cases, sizeof (exp));
137
  node_end = (exp *) xcalloc (no_of_cases, sizeof (exp));
138
  node_weight = (double *) xcalloc (no_of_cases, sizeof (double));
139
 
140
  /* Set up the values of these arrays * First set up the ELEMENTS array
141
  */
142
  t = body;
143
  for (i = 0; i < no_of_cases; i++) {
144
    ELEMENTS[i] = t;
145
    t = bro (t);
146
  }
147
  n = 0;
148
  /* Calculation of where should do jump tables * This sets up the arrays
149
     node_weight, node_start and node_end */
150
  while (n < no_of_cases) {
151
    int   z;
152
    double   node_weight_sum = 0.0;
153
    i = no_of_cases - 1;
154
    while (density (ELEMENTS, n, i, is_signed(sh(control_expression)))
155
		 < jump_table_density)
156
    {
157
      i--;
158
    }
159
    for (z = n; z <= i; z++) {
160
      if (son (ELEMENTS[z]) != nilexp) {
161
	if (is_signed(sh(control_expression)))
162
	  node_weight_sum += ((double) no (son (ELEMENTS[z]))
163
			      - (double) no (ELEMENTS[z]));
164
	else
165
	  node_weight_sum += ((double) (unsigned long) no (son (ELEMENTS[z]))
166
			      - (double) (unsigned long) no (ELEMENTS[z]));
167
      }
168
      node_weight_sum += 1.0;
169
    }
170
 
171
    if (node_weight_sum < (double) min_jump_table_size)
172
    {
173
      i = n;
174
    }
175
    if (node_weight_sum > (double) max_jump_table_size)
176
    {
177
      i=n;
178
    }
179
    if ((i - n) < min_no_of_default_destinations)
180
    {
181
      i = n;
182
    }
183
 
184
    /* Lump together into a jump_table or a single * Sets up the
185
       node_start pointers */
186
    node_start[no_of_nodes] = ELEMENTS[n];
187
 
188
    /* Sets up the node_end pointers */
189
    node_end[no_of_nodes] = (son (ELEMENTS[i]) == nilexp
190
      ? ELEMENTS[i]
191
      : son (ELEMENTS[i]));
192
 
193
    /* sets up the node_weight of the node */
194
    node_weight[no_of_nodes] = 0.0;
195
    for (z = n; z <= i; z++) {
196
      if (son (ELEMENTS[z]) != nilexp) {
197
	if (is_signed(sh(control_expression)))
198
	  node_weight[no_of_nodes] += ((double) no (son (ELEMENTS[z]))
199
				       - (double) no (ELEMENTS[z]));
200
        else
201
	  node_weight[no_of_nodes] += ((double) (unsigned long) no (son (ELEMENTS[z]))
202
				       - (double) (unsigned long) no (ELEMENTS[z]));
203
      }
204
      node_weight[no_of_nodes] += 1.0;
205
    }
206
    if (n != i)
207
    {
208
      jump_table_present = 1;
209
    }
210
 
211
    no_of_nodes = no_of_nodes + 1;
212
    bro (ELEMENTS[i]) = nilexp;
213
    /* Chops up the list for later use */
214
    setlast (ELEMENTS[i]);
215
    /* Sets the last of ELEMENTS[i] so can be substituted directly into
216
       new case_tag's */
217
    n = i + 1;
218
  }
219
 
220
#if has_byte_ops
221
  if (!jump_table_present) {
222
    kill_exp(son(id), son(id));
223
    son(id) = control_expression;
224
    sh(id) = sh(control_expression);
225
    t = body;
226
    for (;;) {
227
      sh(t) = sh(control_expression);
228
      if (son(t) != nilexp)
229
	sh(son(t)) = sh(control_expression);
230
      if (last(t))
231
	break;
232
    }
233
  }
234
  else {
235
    kill_exp(control_expression, control_expression);
236
  }
237
#else
238
  kill_exp(control_expression, control_expression);
239
  UNUSED(jump_table_present);
240
#endif
241
 
242
  /* Set up the node_start_flag and node_end_flag arrays */
243
  node_start_flag =
244
    (unsigned char *) xcalloc (no_of_nodes, sizeof (unsigned char));
245
  node_end_flag =
246
    (unsigned char *) xcalloc (no_of_nodes, sizeof (unsigned char));
247
  for (i=0; i < no_of_nodes; i++) {
248
    node_start_flag[i] = node_end_flag[i] = 0;
249
  }
250
  if (shape_of_case == f_bottom)
251
  {
252
    t = exhaustive_conditional_maker (0, no_of_nodes - 1, id);
253
  }
254
  if (shape_of_case == f_top) {
255
    exp COND__TAG;
256
    exp LABST__TAG;
257
    exp TOP__TAG;
258
    exp CLEAR__TAG;
259
 
260
    TOP__TAG = getexp (f_top, nilexp, 0, nilexp, nilexp, 0, 0, top_tag);
261
    CLEAR__TAG = getexp (f_top, nilexp, 0, nilexp, nilexp,
262
	0, 0, clear_tag);
263
    LABST__TAG = me_b3 (sh (TOP__TAG), CLEAR__TAG, TOP__TAG, labst_tag);
264
    t = inexhaustive_conditional_maker (0, no_of_nodes - 1, id,
265
	LABST__TAG);
266
    COND__TAG = me_b3 (f_top, t, LABST__TAG, cond_tag);
267
    t = COND__TAG;
268
  }
269
  xfree ((void*)ELEMENTS);
270
  xfree ((void*)node_start);
271
  xfree ((void*)node_end);
272
  xfree ((void*)node_weight);
273
  xfree ((void*)node_start_flag);
274
  xfree ((void*)node_end_flag);
275
  return t;
276
}
277
 
278
 
279
 
280
 
281
/*
282
 * density is used for calculating whether the elements of the
283
 * case_tag should be made into jump tables.
284
 */
285
static int   density
286
    PROTO_N ( (ELEMENTS, start, end, sgn) )
287
    PROTO_T ( exp * ELEMENTS X int start X int end X int sgn )
288
{
289
  int   index;
290
  double numerator;
291
  double denominator;
292
 
293
  if (son (ELEMENTS[end]) == nilexp)
294
  {
295
    if (sgn)
296
      denominator = (double) no (ELEMENTS[end]) - (double) no (ELEMENTS[start]);
297
    else
298
      denominator = (double) (unsigned long) no (ELEMENTS[end])
299
	- (double) (unsigned long) no (ELEMENTS[start]);
300
  }
301
  else
302
  {
303
    if (sgn)
304
      denominator = (double) no (son (ELEMENTS[end])) - (double) no (ELEMENTS[start]);
305
    else
306
      denominator = (double) (unsigned long) no (son (ELEMENTS[end]))
307
	- (double) (unsigned long) no (ELEMENTS[start]);
308
  }
309
 
310
  denominator = denominator + 1.0;
311
  numerator = 0.0;
312
  for (index = start; index <= end; index++) {
313
    if (son (ELEMENTS[index]) == nilexp)
314
    {
315
      numerator = numerator + 1.0;
316
    }
317
    else
318
    {
319
      if (sgn)
320
	numerator = numerator + ((double) no (son (ELEMENTS[index]))
321
				 - (double) no (ELEMENTS[index])) + 1.0;
322
      else
323
	numerator = numerator + ((double) (unsigned long) no (son (ELEMENTS[index]))
324
				 - (double) (unsigned long) no (ELEMENTS[index])) + 1.0;
325
    }
326
  }
327
  return ((int) (100.0*(numerator/denominator)));
328
}
329
 
330
 
331
 
332
/*
333
 * set_up_sequence creates a simple sequence with a
334
 * test_tag.
335
 */
336
static exp set_up_sequence
337
    PROTO_N ( (left, right, test, integer_value, id, probability) )
338
    PROTO_T ( exp left X exp right X ntest test X int integer_value X exp id X int probability )
339
{
340
  exp SEQ__TAG;
341
  exp ZERO__TAG;
342
  exp TEST__TAG;
343
  exp NAME__TAG;
344
  exp VAL__TAG;
345
  exp CONT__TAG;
346
 
347
  /* sets up the test_tag                      */
348
  NAME__TAG = me_obtain (id);
349
  CONT__TAG = me_u3 (sh (id), NAME__TAG, cont_tag);
350
  VAL__TAG = me_shint (sh (CONT__TAG), integer_value);
351
  TEST__TAG = like_me_q1 (probability, test, right, CONT__TAG,
352
      VAL__TAG, test_tag);
353
  /* sets up the seq_tag for the conditional   */
354
  ZERO__TAG = me_u3 (f_top, TEST__TAG, 0);
355
  SEQ__TAG = me_b3 (sh (left), ZERO__TAG, left, seq_tag);
356
  return SEQ__TAG;
357
}
358
 
359
 
360
 
361
 
362
/*
363
 * set_up_conditional creates a conditional based on a simple
364
 * integer test.
365
 */
366
static exp set_up_conditional
367
    PROTO_N ( (left, right, test, integer_value, id, probability) )
368
    PROTO_T ( exp left X exp right X ntest test X int integer_value X exp id X int probability )
369
{
370
  exp CLEAR__TAG;
371
  exp LABST__TAG;
372
  exp NAME__TAG;
373
  exp VAL__TAG;
374
  exp TEST__TAG;
375
  exp ZERO__TAG;
376
  exp SEQ__TAG;
377
  exp COND__TAG;
378
  exp CONT__TAG;
379
 
380
  /* Sets up the labst_tag for the conditional */
381
  CLEAR__TAG = getexp (f_top, nilexp, 0, nilexp, nilexp, 0, 0, clear_tag);
382
  LABST__TAG = me_b3 (sh (right), CLEAR__TAG, right, labst_tag);
383
  /* sets up the test_tag                      */
384
  NAME__TAG = me_obtain (id);
385
  CONT__TAG = me_u3 (sh (id), NAME__TAG, cont_tag);
386
  VAL__TAG = me_shint (sh (CONT__TAG), integer_value);
387
  TEST__TAG = like_me_q1 (probability, test, LABST__TAG,
388
      CONT__TAG, VAL__TAG, test_tag);
389
  /* sets up the seq_tag for the conditional   */
390
  ZERO__TAG = me_u3 (f_top, TEST__TAG, 0);
391
  SEQ__TAG = me_b3 (sh (left), ZERO__TAG, left, seq_tag);
392
  /* sets up the cond_tag                      */
393
  COND__TAG = me_b3 (f_bottom, SEQ__TAG, LABST__TAG, cond_tag);
394
  return COND__TAG;
395
}
396
 
397
 
398
 
399
 
400
/*
401
 * set_up_exhaustive_case does exactly what it suggests.
402
 */
403
static exp set_up_exhaustive_case
404
    PROTO_N ( (body_of_case, id) )
405
    PROTO_T ( exp body_of_case X exp id )
406
{
407
  exp NAME__TAG;
408
  exp CASE__TAG;
409
  exp CONT__TAG;
410
  exp r;
411
 
412
  NAME__TAG = me_obtain (id);
413
  CONT__TAG = me_u3 (sh (id), NAME__TAG, cont_tag);
414
  CASE__TAG = getexp (f_bottom, nilexp, 0, CONT__TAG, nilexp,
415
      0, 0, case_tag);
416
  bro (CONT__TAG) = body_of_case;
417
  clearlast (CONT__TAG);
418
  r = body_of_case;
419
  while (!last (r))
420
  {
421
    r = bro (r);
422
  }
423
 
424
  bro (r) = CASE__TAG;
425
  return CASE__TAG;
426
}
427
 
428
 
429
 
430
 
431
/*
432
 * set_up_inexhaustive_case does exactly what it suggests.
433
 */
434
static exp set_up_inexhaustive_case
435
    PROTO_N ( (body_of_case, id, default_exp) )
436
    PROTO_T ( exp body_of_case X exp id X exp default_exp )
437
{
438
  exp NAME__TAG;
439
  exp GOTO__TAG;
440
  exp CASE__TAG;
441
  exp ZERO__TAG;
442
  exp SEQ__TAG;
443
  exp CONT__TAG;
444
  exp r;
445
 
446
  NAME__TAG = me_obtain (id);
447
  CONT__TAG = me_u3 (sh (id), NAME__TAG, cont_tag);
448
  /* shape of case is f_top since it is not exhaustive */
449
  CASE__TAG = getexp (f_top, nilexp, 0, CONT__TAG, nilexp,
450
      0, 0, case_tag);
451
  bro (CONT__TAG) = body_of_case;
452
  clearlast (CONT__TAG);
453
  r = body_of_case;
454
  while (!last (r))
455
    r = bro (r);
456
  bro (r) = CASE__TAG;
457
  GOTO__TAG = getexp (f_bottom, nilexp, 0, nilexp, nilexp,
458
      0, 0, goto_tag);
459
  pt (GOTO__TAG) = default_exp;
460
  no (son (default_exp))++;
461
  ZERO__TAG = me_u3 (f_top, CASE__TAG, 0);
462
  /* doesn't matter what shape zero_tag is */
463
  SEQ__TAG = me_b3 (f_bottom, ZERO__TAG, GOTO__TAG, seq_tag);
464
  return SEQ__TAG;
465
}
466
 
467
/*
468
 * like_me_q1 sets up a test_tag and is very similar to me_q1.
469
 * me_q1 is found in me_fns.c
470
 */
471
static exp like_me_q1
472
    PROTO_N ( (prob, nt, lab, arg1, arg2, nm) )
473
    PROTO_T ( int prob X ntest nt X exp lab X exp arg1 X exp arg2 X unsigned char nm )
474
{
475
  exp r;
476
 
477
  r = getexp (f_top, nilexp, 0, arg1, lab, 0, 0, nm);
478
  no (r) = prob;
479
  settest_number (r, nt);
480
  setbro (arg1, arg2);
481
  clearlast (arg1);
482
  ++no (son (lab));
483
  setfather (r, arg2);
484
  return r;
485
}
486
 
487
 
488
 
489
 
490
/*
491
 *  find_the_split_value is used by exhaustive_conditional_maker
492
 *  and inexhaustive_conditional_maker in order to calculate
493
 *  where to do a comparison.
494
 */
495
static int   find_the_split_value
496
    PROTO_N ( (start, end) )
497
    PROTO_T ( int start X int end )
498
{
499
  int   w;
500
  int   split_value;
501
  double   halfway_value;
502
  double   best_diff;
503
  double   count;
504
 
505
  count = 0.0;
506
  halfway_value = 0.0;
507
  for (w = start; w <= end; w++)
508
  {
509
    halfway_value += node_weight[w];
510
  }
511
  halfway_value = halfway_value / 2.0;
512
  best_diff = node_weight[start] - halfway_value;
513
  if (best_diff < 0.0)
514
  {
515
    best_diff = - best_diff;
516
  }
517
  split_value = start;
518
  for (w = start; w <= end; w++) {
519
    count += node_weight[w];
520
    if ((count - halfway_value) < best_diff
521
	&& (halfway_value - count) < best_diff)
522
    {
523
      split_value = w;
524
      best_diff = count - halfway_value;
525
      if (best_diff < 0.0)
526
      {
527
	best_diff = - best_diff;
528
      }
529
    }
530
  }
531
  return split_value;
532
}
533
 
534
 
535
 
536
 
537
/*
538
 * exhaustive_conditional_maker is the recursive routine for
539
 * making the internal transformed tdf in the case of an
540
 * exhaustive case_tag.
541
 */
542
static exp exhaustive_conditional_maker
543
    PROTO_N ( (start, end, id) )
544
    PROTO_T ( int start X int end X exp id )
545
{
546
  int   split_value;
547
  exp option_left;
548
  exp option_right;
549
  exp t;
550
 
551
  /* first test to see if we have only one node */
552
  if (start == end) {
553
    /* Check to see if not a jump table      */
554
    if (bro (node_start[start]) == nilexp) {
555
      t = getexp (f_bottom, nilexp, 0, nilexp, nilexp, 0, 0, goto_tag);
556
      pt (t) = pt (node_start[start]);
557
      return t;
558
    }
559
    else {
560
      /* We must have to make a jump table    */
561
      return set_up_exhaustive_case (node_start[start], id);
562
    }
563
  }
564
  split_value = find_the_split_value (start, end);
565
  if (split_value == end)
566
    split_value --;
567
  option_left = exhaustive_conditional_maker (split_value + 1, end, id);
568
  option_right = exhaustive_conditional_maker (start, split_value, id);
569
  return set_up_conditional (option_left, option_right,
570
      f_greater_than_or_equal,
571
      no (node_start[split_value + 1]),
572
      id, 1000);
573
}
574
 
575
 
576
 
577
 
578
/*
579
 * inexhaustive_conditional_maker is the recursive routine for
580
 * making the internal transformed tdf in the case of an
581
 * inexhaustive case_tag.
582
 */
583
static exp inexhaustive_conditional_maker
584
    PROTO_N ( (start, end, id, default_exp) )
585
    PROTO_T ( int start X int end X exp id X exp default_exp )
586
{
587
  int   split_value;
588
  exp option_left;
589
  exp option_right;
590
  exp spare;
591
 
592
  if (start == end) {
593
    /* Single range to single destination */
594
    if (node_start[start] == node_end[start]) {
595
      if ((node_start_flag[start] == 1) && (node_end_flag[start] == 1)) {
596
	spare = getexp (f_bottom, nilexp, 0, nilexp, nilexp,
597
	    0, 0, goto_tag);
598
	pt (spare) = pt (node_start[start]);
599
	return spare;
600
      }
601
      else {
602
	option_left = getexp (f_bottom, nilexp, 0, nilexp, nilexp,
603
	    0, 0, goto_tag);
604
	pt (option_left) = default_exp;
605
	no (son (default_exp))++;
606
	no (son (pt (node_start[start])))--;
607
	return set_up_sequence (option_left, pt (node_start[start]),
608
	    f_not_equal, no (node_start[start]), id, 1000);
609
      }
610
    }
611
    /* Multi range to single destination */
612
    if (son (node_start[start]) == node_end[start]) {
613
      if ((node_start_flag[start] == 1) && (node_end_flag[start] == 1)) {
614
	spare = getexp (f_bottom, nilexp, 0, nilexp, nilexp,
615
	    0, 0, goto_tag);
616
	pt (spare) = pt (node_start[start]);
617
	return spare;
618
      }
619
      if ((node_start_flag[start] == 1) && (node_end_flag[start] == 0)) {
620
	option_left = getexp (f_bottom, nilexp, 0, nilexp, nilexp,
621
	    0, 0, goto_tag);
622
	pt (option_left) = default_exp;
623
	no (son (default_exp))++;
624
	no (son (pt (node_start[start])))--;
625
	node_end_flag[start] = 1;
626
	return set_up_sequence (option_left, pt (node_start[start]),
627
	    f_greater_than, no (node_end[start]), id, 1000);
628
      }
629
      if ((node_start_flag[start] == 0) && (node_end_flag[start] == 1)) {
630
	option_left = getexp (f_bottom, nilexp, 0, nilexp, nilexp,
631
	    0, 0, goto_tag);
632
	pt (option_left) = default_exp;
633
	no (son (default_exp))++;
634
	no (son (pt (node_start[start])))--;
635
	node_start_flag[start] = 1;
636
	return set_up_sequence (option_left, pt (node_start[start]),
637
	    f_less_than, no (node_start[start]), id, 1000);
638
      }
639
      /* We may as well do a subtraction and a comparison */
640
      node_start_flag[start] = node_end_flag[start] = 1;
641
 
642
      {
643
	exp SEQUENCE__TAG;
644
	exp ZERO__TAG;
645
	exp GOTO__TAG;
646
	int   subtract_value = no (node_start[start]);
647
 
648
	GOTO__TAG = getexp (f_bottom, nilexp, 0, nilexp, nilexp,
649
	    0, 0, goto_tag);
650
	pt (GOTO__TAG) = default_exp;
651
	no (son (default_exp))++;
652
	no (son (pt (node_start[start])))--;
653
	ZERO__TAG =
654
	  me_b3 (f_top, set_up_assign (id, -subtract_value),
655
	    set_up_unsigned_test (pt (node_start[start]), id,
656
	      (no (node_end[start]) - subtract_value),
657
	      f_greater_than), 0);
658
	SEQUENCE__TAG = me_b3 (f_bottom, ZERO__TAG, GOTO__TAG, seq_tag);
659
	return SEQUENCE__TAG;
660
      }
661
    }
662
    /* We must have to do a jump table */
663
    if ((node_start_flag[start] == 1) && (node_end_flag[start] == 1))
664
      return set_up_inexhaustive_case (node_start[start], id,
665
	  default_exp);
666
    if ((node_start_flag[start] == 1) && (node_end_flag[start] == 0)) {
667
      option_left =
668
	set_up_inexhaustive_case (node_start[start], id, default_exp);
669
      node_end_flag[start] = 1;
670
      return set_up_sequence (option_left, default_exp,
671
	  f_less_than_or_equal,
672
	  no (node_end[start]),
673
	  id, 1000);
674
    }
675
    if ((node_start_flag[start] == 0) && (node_end_flag[start] == 1)) {
676
      option_left =
677
	set_up_inexhaustive_case (node_start[start], id, default_exp);
678
      node_start_flag[start] = 1;
679
      return set_up_sequence (option_left, default_exp,
680
	  f_greater_than_or_equal,
681
	  no (node_start[start]),
682
	  id, 1000);
683
    }
684
    /* Put in a jump table by doing a subtraction first and comparison for
685
       both sides */
686
    node_start_flag[start] = node_end_flag[start] = 1;
687
    {
688
      exp ZERO__TAG;
689
      exp SEQUENCE__TAG;
690
      exp SPARE__TAG;
691
      exp r;
692
      int   subtract_value;
693
      subtract_value = no (node_start[start]);
694
 
695
      ZERO__TAG =
696
	me_b3 (f_top, set_up_assign (id, -subtract_value),
697
	  set_up_unsigned_test (default_exp,
698
	    id, (no (node_end[start]) - subtract_value),
699
	    f_less_than_or_equal),
700
	  0);
701
      r = node_start[start];
702
      while (r != nilexp) {
703
	no (r) = no (r) - subtract_value;
704
	if (son (r) != nilexp)
705
	  no (son (r)) = no (son (r)) - subtract_value;
706
	r = bro (r);
707
      }
708
      SPARE__TAG =
709
	set_up_inexhaustive_case (node_start[start], id, default_exp);
710
      SEQUENCE__TAG = me_b3 (sh (SPARE__TAG), ZERO__TAG, SPARE__TAG,
711
	  seq_tag);
712
      return SEQUENCE__TAG;
713
    }
714
  }
715
  split_value = find_the_split_value (start, end);
716
  /* assert that node_start_flag[split_value+1] and
717
     node_end_flag[split_value] should be zero 		or split_value = end */
718
  if (split_value == start && (node_start[start] == node_end[start])) {
719
    /* This is the case when we have a simple single range node in the 1:n
720
       split */
721
    option_left =
722
      inexhaustive_conditional_maker (start+1, end, id,
723
	default_exp);
724
    no (son (pt (node_start[start])))--;
725
    return set_up_sequence (option_left, pt (node_start[start]),
726
	f_not_equal, no (node_start[start]),
727
	id, 1000);
728
  }
729
  if (split_value >= end-1
730
	    && (node_start[end] == node_end[end])) {
731
    /* This is the case when we have a simple single range node in the n:1
732
       split */
733
    option_left =
734
      inexhaustive_conditional_maker (start, end-1, id, default_exp);
735
    no (son (pt (node_start[end])))--;
736
    return set_up_sequence (option_left, pt (node_start[end]),
737
	f_not_equal, no (node_start[end]), id, 1000);
738
  }
739
  if (split_value == start &&
740
      (son (node_start[start]) == node_end[start]) &&
741
      node_start_flag[start] == 1) {
742
    /* This is the case when we have a multi range to the in the 1:n split
743
       where the left hand comparison has been done */
744
 
745
    /* If we have a close together split there is no need to recompare */
746
    if (no(node_end[start]) == (no(node_start[start+1])-1) )
747
      node_start_flag[start+1] = 1;
748
 
749
    option_left =
750
      inexhaustive_conditional_maker (start+1, end, id, default_exp);
751
    no (son (pt (node_start[start])))--;
752
    return set_up_sequence (option_left, pt (node_start[start]),
753
	f_greater_than, no (node_end[start]), id, 1000);
754
  }
755
  if (split_value >= end-1
756
	    && (son (node_start[end]) == node_end[end])
757
	    && node_end_flag[end] == 1) {
758
    /* This is the case when we have a multi range to the in the n:1 split
759
       where the right hand comparison has been done */
760
 
761
    /* If we have a close together split there is no need to recompare */
762
    if (no(node_end[end-1]) == (no(node_start[end])-1))
763
      node_end_flag[end-1] = 1;
764
 
765
    option_left =
766
      inexhaustive_conditional_maker (start, end-1, id, default_exp);
767
    no (son (pt (node_start[end])))--;
768
    return set_up_sequence (option_left, pt (node_start[end]),
769
	f_less_than, no (node_start[end]), id, 1000);
770
  }
771
  if (split_value == end)
772
    split_value --;
773
  /* If we have a multi range or a jump table to the left or right of the
774
     split, it is better to do one of those comparisons because it will
775
     save a comparison whereas doing a comparison against a single range
776
     saves nothing */
777
  if (node_start[split_value] == node_end[split_value]) {
778
    /* do the comparison against split_value+1 */
779
    node_start_flag[split_value + 1] = 1;
780
 
781
    /* If we have a close together split there is no need to recompare */
782
    if (no(node_end[split_value]) == (no(node_start[split_value+1])-1))
783
      node_end_flag[split_value] = 1;
784
 
785
    option_right =
786
      inexhaustive_conditional_maker (start, split_value,
787
	id, default_exp);
788
    option_left =
789
      inexhaustive_conditional_maker (split_value + 1, end,
790
	id, default_exp);
791
    return set_up_conditional (option_left, option_right,
792
	f_greater_than_or_equal,
793
	no (node_start[split_value + 1]), id, 1000);
794
  }
795
  else {
796
    /* do the comparison against split_value */
797
    node_end_flag[split_value] = 1;
798
    /* If we have a close together split there is no need to recompare */
799
    if (no(node_end[split_value]) == (no(node_start[split_value+1])-1) )
800
      node_start_flag[split_value+1] = 1;
801
 
802
    option_right =
803
      inexhaustive_conditional_maker (start, split_value,
804
	id, default_exp);
805
    option_left =
806
      inexhaustive_conditional_maker (split_value + 1, end,
807
	id, default_exp);
808
    return set_up_conditional (option_left, option_right,
809
	f_greater_than, no (node_end[split_value]), id, 1000);
810
  }
811
}
812
 
813
 
814
 
815
/*
816
 * set_up_assign takes a variable and adds an integer to
817
 * it, and replaces it.
818
 */
819
static exp set_up_assign
820
    PROTO_N ( (id, number) )
821
    PROTO_T ( exp id X int number )
822
{
823
  exp NAME__TAG;
824
  exp VAL__TAG;
825
  exp CONT__TAG;
826
  exp PLUS__TAG;
827
  exp ASSIGN__TAG;
828
 
829
  NAME__TAG = me_obtain (id);
830
  VAL__TAG = me_shint (sh (id), number);
831
  CONT__TAG = me_u3 (sh (id), NAME__TAG, cont_tag);
832
  PLUS__TAG = me_b3 (sh (id), CONT__TAG, VAL__TAG, plus_tag);
833
  ASSIGN__TAG = me_b3 (f_top, me_obtain (id), PLUS__TAG, ass_tag);
834
  return ASSIGN__TAG;
835
}
836
/*
837
 * set_up_unsigned_test returns a test_tag. The test is
838
 * specified, along with the value to be tested against
839
 * the default_exp labst_tag and the var_tag to test
840
 * against.
841
 */
842
static exp set_up_unsigned_test
843
    PROTO_N ( (default_exp, id, test_value, test) )
844
    PROTO_T ( exp default_exp X exp id X int test_value X ntest test )
845
{
846
  exp NAME__TAG;
847
  exp CHVAR__TAG;
848
  exp CONT__TAG;
849
  exp VAL__TAG;
850
  exp TEST__TAG;
851
 
852
  NAME__TAG = me_obtain (id);
853
  CONT__TAG = me_u3 (sh (id), NAME__TAG, cont_tag);
854
  CHVAR__TAG = hold_check(me_u3 (ulongsh, CONT__TAG, chvar_tag));
855
  VAL__TAG = me_shint (ulongsh, test_value);
856
  TEST__TAG = like_me_q1 (1000, test, default_exp, CHVAR__TAG,
857
      VAL__TAG, test_tag);
858
  return TEST__TAG;
859
}