OpenCores
URL https://opencores.org/ocsvn/thor/thor/trunk

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v5/] [software/] [CC64/] [source/] [Optimize.cpp] - Blame information for rev 48

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 48 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2012-2018  Robert Finch, Waterloo
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch<remove>@finitron.ca
6
//       ||
7
//
8
// CC64 - 'C' derived language compiler
9
//  - 64 bit CPU
10
//
11
// This source file is free software: you can redistribute it and/or modify 
12
// it under the terms of the GNU Lesser General Public License as published 
13
// by the Free Software Foundation, either version 3 of the License, or     
14
// (at your option) any later version.                                      
15
//                                                                          
16
// This source file is distributed in the hope that it will be useful,      
17
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
18
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
19
// GNU General Public License for more details.                             
20
//                                                                          
21
// You should have received a copy of the GNU General Public License        
22
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
23
//                                                                          
24
// ============================================================================
25
//
26
#include "stdafx.h"
27
 
28
static void fold_const(ENODE **node);
29
 
30
/*
31
 *      dooper will execute a constant operation in a node and
32
 *      modify the node to be the result of the operation.
33
 */
34
void dooper(ENODE *node)
35
{
36
        ENODE *ep;
37
 
38
    ep = node;
39
    switch( ep->nodetype ) {
40
        case en_abs:
41
            ep->nodetype = en_icon;
42
            ep->i = (ep->p[0]->i >= 0) ? ep->p[0]->i : -ep->p[0]->i;
43
                        break;
44
    case en_add:
45
            ep->nodetype = en_icon;
46
            ep->i = ep->p[0]->i + ep->p[1]->i;
47
            break;
48
    case en_sub:
49
            ep->nodetype = en_icon;
50
            ep->i = ep->p[0]->i - ep->p[1]->i;
51
            break;
52
    case en_mul:
53
        case en_mulu:
54
            ep->nodetype = en_icon;
55
            ep->i = ep->p[0]->i * ep->p[1]->i;
56
            break;
57
    case en_div:
58
        case en_udiv:
59
            ep->nodetype = en_icon;
60
            ep->i = ep->p[0]->i / ep->p[1]->i;
61
            break;
62
        case en_asl:
63
    case en_shl:
64
        case en_shlu:
65
            ep->nodetype = en_icon;
66
            ep->i = ep->p[0]->i << ep->p[1]->i;
67
            break;
68
        case en_asr:
69
    case en_shr:
70
            ep->nodetype = en_icon;
71
            ep->i = ep->p[0]->i >> ep->p[1]->i;
72
            break;
73
    case en_shru:
74
            ep->nodetype = en_icon;
75
            ep->i = (unsigned)ep->p[0]->i >> ep->p[1]->i;
76
            break;
77
    case en_and:
78
            ep->nodetype = en_icon;
79
            ep->i = ep->p[0]->i & ep->p[1]->i;
80
            break;
81
    case en_or:
82
            ep->nodetype = en_icon;
83
            ep->i = ep->p[0]->i | ep->p[1]->i;
84
            break;
85
    case en_xor:
86
            ep->nodetype = en_icon;
87
            ep->i = ep->p[0]->i ^ ep->p[1]->i;
88
            break;
89
        case en_land:
90
                ep->nodetype = en_icon;
91
                ep->i = ep->p[0]->i && ep->p[1]->i;
92
                break;
93
        case en_lor:
94
                ep->nodetype = en_icon;
95
                ep->i = ep->p[0]->i || ep->p[1]->i;
96
                break;
97
        case en_ult:
98
                ep->nodetype = en_icon;
99
                ep->i = (unsigned)ep->p[0]->i < (unsigned)ep->p[1]->i;
100
                break;
101
        case en_ule:
102
                ep->nodetype = en_icon;
103
                ep->i = (unsigned)ep->p[0]->i <= (unsigned)ep->p[1]->i;
104
                break;
105
        case en_ugt:
106
                ep->nodetype = en_icon;
107
                ep->i = (unsigned)ep->p[0]->i > (unsigned)ep->p[1]->i;
108
                break;
109
        case en_uge:
110
                ep->nodetype = en_icon;
111
                ep->i = (unsigned)ep->p[0]->i >= (unsigned)ep->p[1]->i;
112
                break;
113
        case en_lt:
114
                ep->nodetype = en_icon;
115
                ep->i = (signed)ep->p[0]->i < (signed)ep->p[1]->i;
116
                break;
117
        case en_le:
118
                ep->nodetype = en_icon;
119
                ep->i = (signed)ep->p[0]->i <= (signed)ep->p[1]->i;
120
                break;
121
        case en_gt:
122
                ep->nodetype = en_icon;
123
                ep->i = (signed)ep->p[0]->i > (signed)ep->p[1]->i;
124
                break;
125
        case en_ge:
126
                ep->nodetype = en_icon;
127
                ep->i = (signed)ep->p[0]->i >= (signed)ep->p[1]->i;
128
                break;
129
        case en_eq:
130
                ep->nodetype = en_icon;
131
                ep->i = (signed)ep->p[0]->i == (signed)ep->p[1]->i;
132
                break;
133
        case en_ne:
134
                ep->nodetype = en_icon;
135
                ep->i = (signed)ep->p[0]->i != (signed)ep->p[1]->i;
136
                break;
137
        case en_cond:
138
                ep->nodetype = ep->p[1]->p[0]->nodetype;
139
                ep->i = ep->p[0]->i ? ep->p[1]->p[0]->i : ep->p[1]->p[1]->i;
140
                ep->sp = ep->p[0]->i ? ep->p[1]->p[0]->sp : ep->p[1]->p[1]->sp;
141
                break;
142
        case en_sxb:
143
                ep->nodetype = en_icon;
144
                ep->i = (ep->p[0]->i & 0x100LL) ? ep->p[0]->i | 0xffffffffffffff00LL : ep->p[0]->i;
145
                break;
146
        case en_sxc:
147
                ep->nodetype = en_icon;
148
                ep->i = (ep->p[0]->i & 0x10000LL) ? ep->p[0]->i | 0xffffffffffff0000LL : ep->p[0]->i;
149
                break;
150
        case en_sxh:
151
                ep->nodetype = en_icon;
152
                ep->i = (ep->p[0]->i & 0x100000000LL) ? ep->p[0]->i | 0xffffffff00000000LL : ep->p[0]->i;
153
                break;
154
        case en_zxb:
155
                ep->nodetype = en_icon;
156
                ep->i = ep->p[0]->i & 0xffLL;
157
                break;
158
        case en_zxc:
159
                ep->nodetype = en_icon;
160
                ep->i = ep->p[0]->i & 0xffffLL;
161
                break;
162
        case en_zxh:
163
                ep->nodetype = en_icon;
164
                ep->i = ep->p[0]->i & 0xffffffffLL;
165
                break;
166
        }
167
}
168
 
169
/*
170
 *      return which power of two i is or -1.
171
 */
172
int pwrof2(int64_t i)
173
{
174
        int p;
175
        int64_t q;
176
 
177
    q = 1;
178
    p = 0;
179
    while( q > 0 )
180
    {
181
                if( q == i )
182
                        return (p);
183
                q <<= 1LL;
184
                ++p;
185
    }
186
    return (-1);
187
}
188
 
189
/*
190
 *      make a mod mask for a power of two.
191
 */
192
int mod_mask(int i)
193
{
194
        int m;
195
    m = 0;
196
    while( i-- )
197
        m = (m << 1) | 1;
198
    return (m);
199
}
200
 
201
/*
202
 *      opt0 - delete useless expressions and combine constants.
203
 *
204
 *      opt0 will delete expressions such as x + 0, x - 0, x * 0,
205
 *      x * 1, 0 / x, x / 1, x mod 0, etc from the tree pointed to
206
 *      by node and combine obvious constant operations. It cannot
207
 *      combine name and label constants but will combine icon type
208
 *      nodes.
209
 */
210
static void opt0(ENODE **node)
211
{
212
        ENODE *ep;
213
    int sc;
214
        int64_t val;
215
 
216
    ep = *node;
217
    if( ep == (ENODE *)NULL )
218
        return;
219
    switch( (*node)->nodetype ) {
220
        case en_vector_ref:
221
        case en_ref32: case en_ref32u:
222
            case en_b_ref:
223
                        case en_c_ref:
224
                        case en_h_ref:
225
            case en_w_ref:          /* optimize unary node */
226
            case en_ub_ref:
227
                        case en_uc_ref:
228
                        case en_uh_ref:
229
            case en_uw_ref:          /* optimize unary node */
230
                        case en_flt_ref:
231
                        case en_dbl_ref:
232
                        case en_quad_ref:
233
                        case en_wp_ref:
234
                        case en_hp_ref:
235
                        case en_cubw:
236
                        case en_cucw:
237
                        case en_cuhw:
238
                        case en_cubu:
239
                        case en_cucu:
240
                        case en_cuhu:
241
                        case en_cbu:
242
                        case en_ccu:
243
                        case en_chu:
244
                        case en_cbc:
245
                        case en_cbh:
246
                        case en_cbw:
247
                        case en_cch:
248
                        case en_ccw:
249
                        case en_chw:
250
                        case en_ccwp:
251
                        case en_cucwp:
252
                    opt0( &((*node)->p[0]));
253
                    return;
254
                        case en_sxb:
255
                        case en_sxc:
256
                        case en_sxh:
257
                        case en_zxb: case en_zxc: case en_zxh:
258
                        case en_abs:
259
                    opt0( &(ep->p[0]));
260
                    if( ep->p[0]->nodetype == en_icon )
261
                                                dooper(*node);
262
                    return;
263
                        case en_compl:
264
                    opt0( &(ep->p[0]));
265
                    if( ep->p[0]->nodetype == en_icon )
266
                    {
267
                        ep->nodetype = en_icon;
268
                        ep->i = ~ep->p[0]->i;
269
                    }
270
                    return;
271
                        case en_not:
272
                    opt0( &(ep->p[0]));
273
                    if( ep->p[0]->nodetype == en_icon )
274
                    {
275
                        ep->nodetype = en_icon;
276
                        ep->i = !ep->p[0]->i;
277
                    }
278
                    return;
279
            case en_uminus:
280
                    opt0( &(ep->p[0]));
281
                    if( ep->p[0]->nodetype == en_icon )
282
                    {
283
                        ep->nodetype = en_icon;
284
                        ep->i = -ep->p[0]->i;
285
                    }
286
                    return;
287
            case en_tempref:
288
                    opt0( &(ep->p[0]));
289
                    if( ep->p[0] && ep->p[0]->nodetype == en_icon )
290
                    {
291
                        ep->nodetype = en_icon;
292
                        ep->i = ep->p[0]->i;
293
                    }
294
                    return;
295
            case en_tempfpref:
296
                    opt0( &(ep->p[0]));
297
                    if( ep->p[0] && ep->p[0]->nodetype == en_fcon )
298
                    {
299
                        ep->nodetype = en_fcon;
300
                        ep->f = ep->p[0]->f;
301
                                                Float128::Assign(&ep->f128,&ep->p[0]->f128);
302
                    }
303
                    return;
304
                        case en_vadd:
305
                        case en_vsub:
306
            case en_add:
307
            case en_sub:
308
                    opt0(&(ep->p[0]));
309
                    opt0(&(ep->p[1]));
310
                    if( ep->p[0]->nodetype == en_icon ) {
311
                        if( ep->p[1]->nodetype == en_icon ) {
312
                            dooper(*node);
313
                            return;
314
                        }
315
                        if( ep->p[0]->i == 0 ) {
316
                                                        if( ep->nodetype == en_sub )
317
                                                        {
318
                                                                ep->p[0] = ep->p[1];
319
                                ep->nodetype = en_uminus;
320
                                                        }
321
                                                        else
322
                                                                *node = ep->p[1];
323
                                                                return;
324
                        }
325
                                                // Place the constant node second in the add to allow
326
                                                // use of immediate mode instructions.
327
                                                if (ep->nodetype==en_add)
328
                                                        swap_nodes(ep);
329
                    }
330
                                        // Add or subtract of zero gets eliminated.
331
                    else if( ep->p[1]->nodetype == en_icon ) {
332
                        if( ep->p[1]->i == 0 ) {
333
                            *node = ep->p[0];
334
                            return;
335
                        }
336
                    }
337
                    return;
338
                        case en_vmul:
339
                        case en_vmuls:
340
            case en_mul:
341
                        case en_mulu:
342
                    opt0(&(ep->p[0]));
343
                    opt0(&(ep->p[1]));
344
                    if( ep->p[0]->nodetype == en_icon ) {
345
                        if( ep->p[1]->nodetype == en_icon ) {
346
                            dooper(*node);
347
                            return;
348
                        }
349
                        val = ep->p[0]->i;
350
                        if( val == 0 ) {
351
                            *node = ep->p[0];
352
                            return;
353
                        }
354
                        if( val == 1 ) {
355
                            *node = ep->p[1];
356
                            return;
357
                        }
358
                        sc = pwrof2(val);
359
                        if( sc != -1 )
360
                        {
361
                            swap_nodes(ep);
362
                            ep->p[1]->i = sc;
363
                            ep->nodetype = en_shl;
364
                                                        return;
365
                        }
366
                                                // Place constant as oper2
367
                                                swap_nodes(ep);
368
                    }
369
                    else if( ep->p[1]->nodetype == en_icon ) {
370
                        val = ep->p[1]->i;
371
                        if( val == 0 ) {
372
                            *node = ep->p[1];
373
                            return;
374
                        }
375
                        if( val == 1 ) {
376
                            *node = ep->p[0];
377
                            return;
378
                        }
379
                        sc = pwrof2(val);
380
                        if( sc != -1 )
381
                        {
382
                                                        ep->p[1]->i = sc;
383
                                                        ep->nodetype = en_shl;
384
                                                        return;
385
                        }
386
                    }
387
                    break;
388
            case en_div:
389
                        case en_udiv:
390
                    opt0(&(ep->p[0]));
391
                    opt0(&(ep->p[1]));
392
                    if( ep->p[0]->nodetype == en_icon ) {
393
                            if( ep->p[1]->nodetype == en_icon ) {
394
                                    dooper(*node);
395
                                    return;
396
                                    }
397
                            if( ep->p[0]->i == 0 ) {    /* 0/x */
398
                                    *node = ep->p[0];
399
                                    return;
400
                                    }
401
                            }
402
                    else if( ep->p[1]->nodetype == en_icon ) {
403
                            val = ep->p[1]->i;
404
                            if( val == 1 ) {        /* x/1 */
405
                                    *node = ep->p[0];
406
                                    return;
407
                                    }
408
                            sc = pwrof2(val);
409
                            if( sc != -1 )
410
                                    {
411
                                    ep->p[1]->i = sc;
412
                                                                        if ((*node)->nodetype == en_udiv)
413
                                                                                ep->nodetype = en_shru;
414
                                                                        else
415
                                                                                ep->nodetype = ep->p[0]->isUnsigned ? en_shru : en_shr;
416
                                    }
417
                            }
418
                    break;
419
            case en_mod:
420
                    opt0(&(ep->p[0]));
421
                    opt0(&(ep->p[1]));
422
                    if( ep->p[1]->nodetype == en_icon )
423
                            {
424
                            if( ep->p[0]->nodetype == en_icon )
425
                                    {
426
                                    dooper(*node);
427
                                    return;
428
                                    }
429
                            sc = pwrof2(ep->p[1]->i);
430
                            if( sc != -1 )
431
                                    {
432
                                    ep->p[1]->i = mod_mask(sc);
433
                                    ep->nodetype = en_and;
434
                                    }
435
                            }
436
                    break;
437
 
438
                        case en_and:
439
            case en_or:
440
                        case en_xor:
441
                    opt0(&(ep->p[0]));
442
                    opt0(&(ep->p[1]));
443
                                        if (ep->p[0]->nodetype == en_icon &&
444
                                                ep->p[1]->nodetype == en_icon)
445
                                                dooper(*node);
446
                                        else if (ep->p[0]->nodetype == en_icon)
447
                                                swap_nodes(ep);
448
                                        break;
449
 
450
                        case en_shr:    case en_shru:   case en_asr:
451
                        case en_asl:    case en_shl:    case en_shlu:
452
                    opt0(&(ep->p[0]));
453
                    opt0(&(ep->p[1]));
454
                    if( ep->p[0]->nodetype == en_icon &&
455
                            ep->p[1]->nodetype == en_icon )
456
                            dooper(*node);
457
                                        // Shift by zero....
458
                    else if( ep->p[1]->nodetype == en_icon ) {
459
                        if( ep->p[1]->i == 0 ) {
460
                            *node = ep->p[0];
461
                            return;
462
                        }
463
                    }
464
                    break;
465
 
466
            case en_land:
467
                    opt0(&(ep->p[0]));
468
                    opt0(&(ep->p[1]));
469
                                        if (ep->p[0]->nodetype==en_icon && ep->p[1]->nodetype==en_icon) {
470
                                                dooper(*node);
471
                                                break;
472
                    }
473
                    break;
474
            case en_lor:
475
                    opt0(&(ep->p[0]));
476
                    opt0(&(ep->p[1]));
477
                                        if (ep->p[0]->nodetype==en_icon && ep->p[1]->nodetype==en_icon) {
478
                                                dooper(*node);
479
                                                break;
480
                    }
481
                    break;
482
                        case en_ult:    case en_ule:
483
                        case en_ugt:    case en_uge:
484
                        case en_lt:             case en_le:
485
                        case en_gt:             case en_ge:
486
                        case en_eq:             case en_ne:
487
                    opt0(&(ep->p[0]));
488
                    opt0(&(ep->p[1]));
489
                                        if (ep->p[0]->nodetype==en_icon && ep->p[1]->nodetype==en_icon)
490
                                                dooper(*node);
491
                    break;
492
                case en_feq:    case en_fne:
493
                case en_flt:    case en_fle:
494
                case en_fgt:    case en_fge:
495
                case en_veq:    case en_vne:
496
                case en_vlt:    case en_vle:
497
                case en_vgt:    case en_vge:
498
                    opt0(&(ep->p[0]));
499
                    opt0(&(ep->p[1]));
500
                    break;
501
                        case en_cond:
502
                    opt0(&(ep->p[0]));
503
                                        opt0(&(ep->p[1]->p[0]));
504
                                        opt0(&(ep->p[1]->p[1]));
505
                                        if ((ep->p[0]->nodetype==en_icon||ep->p[0]->nodetype==en_cnacon) &&
506
                                                 (ep->p[1]->p[0]->nodetype==en_icon || ep->p[1]->p[0]->nodetype==en_cnacon) &&
507
                                                 (ep->p[1]->p[1]->nodetype==en_icon || ep->p[1]->p[1]->nodetype==en_cnacon))
508
                                                dooper(*node);
509
                                        break;
510
            case en_chk:
511
                    opt0(&(ep->p[0]));
512
                                        opt0(&(ep->p[1]));
513
                                        opt0(&(ep->p[2]));
514
                                        break;
515
            case en_asand:  case en_asor:
516
            case en_asadd:  case en_assub:
517
            case en_asmul:  case en_asdiv:
518
            case en_asmod:  case en_asrsh:
519
            case en_aslsh:
520
            case en_fcall:  case en_void:
521
                    opt0(&(ep->p[0]));
522
                    opt0(&(ep->p[1]));
523
                    break;
524
            case en_assign:
525
                    opt0(&(ep->p[0]));
526
                    opt0(&(ep->p[1]));
527
                    break;
528
            }
529
}
530
 
531
/*
532
 *      xfold will remove constant nodes and return the values to
533
 *      the calling routines.
534
 */
535
static int64_t xfold(ENODE *node)
536
{
537
        int64_t i;
538
 
539
        if( node == NULL )
540
                return 0;
541
        switch( node->nodetype )
542
        {
543
                case en_icon:
544
                        i = node->i;
545
                        node->i = 0;
546
                        return i;
547
                                case en_sxb: case en_sxc: case en_sxh:
548
                                case en_zxb: case en_zxc: case en_zxh:
549
                                case en_abs:
550
                                        return (0);
551
                                                return xfold(node->p[0]);
552
                case en_add:
553
                        return xfold(node->p[0]) + xfold(node->p[1]);
554
                case en_sub:
555
                        return xfold(node->p[0]) - xfold(node->p[1]);
556
                case en_mul:
557
                                case en_mulu:
558
                        if( node->p[0]->nodetype == en_icon )
559
                                return xfold(node->p[1]) * node->p[0]->i;
560
                        else if( node->p[1]->nodetype == en_icon )
561
                                return xfold(node->p[0]) * node->p[1]->i;
562
                        else return 0;
563
                                case en_asl:
564
                                case en_shl:    case en_shlu:
565
                        if( node->p[0]->nodetype == en_icon )
566
                                return xfold(node->p[1]) << node->p[0]->i;
567
                        else if( node->p[1]->nodetype == en_icon )
568
                                return xfold(node->p[0]) << node->p[1]->i;
569
                        else return 0;
570
                case en_uminus:
571
                        return - xfold(node->p[0]);
572
                                case en_shr:    case en_div:    case en_udiv:   case en_shru: case en_asr:
573
                case en_mod:    case en_asadd:
574
                case en_assub:  case en_asmul:
575
                case en_asdiv:  case en_asmod:
576
                case en_and:    case en_land:
577
                                case en_or:             case en_lor:
578
                case en_xor:    case en_asand:
579
                case en_asor:   case en_void:
580
                case en_fcall:  case en_assign:
581
                        fold_const(&node->p[0]);
582
                        fold_const(&node->p[1]);
583
                        return 0;
584
                                case en_ref32: case en_ref32u:
585
                                case en_ub_ref: case en_uw_ref:
586
                                case en_uc_ref: case en_uh_ref:
587
                case en_b_ref:  case en_w_ref:
588
                                case en_c_ref:  case en_h_ref:
589
                                case en_wp_ref: case en_hp_ref:
590
                                case en_vector_ref:
591
                case en_compl:
592
                case en_not:
593
                        fold_const(&node->p[0]);
594
                        return 0;
595
                }
596
        return 0;
597
}
598
 
599
/*
600
 *      reorganize an expression for optimal constant grouping.
601
 */
602
static void fold_const(ENODE **node)
603
{
604
        ENODE *ep;
605
    int64_t i;
606
 
607
        ep = *node;
608
        if( ep == 0 )
609
                return;
610
        if( ep->nodetype == en_add )
611
                {
612
                if( ep->p[0]->nodetype == en_icon )
613
                        {
614
                        ep->p[0]->i += xfold(ep->p[1]);
615
                        return;
616
                        }
617
                else if( ep->p[1]->nodetype == en_icon )
618
                        {
619
                        ep->p[1]->i += xfold(ep->p[0]);
620
                        return;
621
                        }
622
                }
623
        else if( ep->nodetype == en_sub )
624
                {
625
                if( ep->p[0]->nodetype == en_icon )
626
                        {
627
                        ep->p[0]->i -= xfold(ep->p[1]);
628
                        return;
629
                        }
630
                else if( ep->p[1]->nodetype == en_icon )
631
                        {
632
                        ep->p[1]->i -= xfold(ep->p[0]);
633
                        return;
634
                        }
635
                }
636
        i = xfold(ep);
637
        if( i != 0 )
638
                {
639
                ep = makeinode(en_icon,i);
640
                                ep->etype = (*node)->etype;
641
                                ep->tp = (*node)->tp;
642
                ep = makenode(en_add,ep,*node);
643
                                ep->etype = (*node)->etype;
644
                                ep->tp = (*node)->tp;
645
                                *node = ep;
646
                }
647
}
648
 
649
//
650
//      apply all constant optimizations.
651
//
652
void opt_const(ENODE **node)
653
{
654
        dfs.printf("<OptConst>");
655
    if (opt_noexpr==FALSE) {
656
        opt0(node);
657
        fold_const(node);
658
        opt0(node);
659
    }
660
        dfs.printf("</OptConst>");
661
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.