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

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v5/] [software/] [CC64/] [source/] [Peepgen.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 AddToPeepList(OCODE *newc);
29
void PrintPeepList();
30
static void Remove();
31
void peep_add(OCODE *ip);
32
static void PeepoptSub(OCODE *ip);
33
void peep_cmp(OCODE *ip);
34
static void opt_peep();
35
void put_ocode(OCODE *p);
36
void CreateControlFlowGraph();
37
extern void ComputeLiveVars();
38
extern void DumpLiveVars();
39
extern Instruction *GetInsn(int);
40
void CreateVars();
41
void ComputeLiveRanges();
42
void DumpLiveRanges();
43
void RemoveMoves();
44
void DumpVarForests();
45
void DumpLiveRegs();
46
void CreateVarForests();
47
void DeleteSets();
48
void RemoveCode();
49
bool Coalesce();
50
void ComputeSpillCosts();
51
extern void CalcDominatorTree();
52
Var *FindVar(int num);
53
void ExpandReturnBlocks();
54
bool RemoveEnabled = true;
55
unsigned int ArgRegCount;
56
int count;
57
Map map;
58
 
59
OCODE *LabelTable[50000];
60
 
61
OCODE    *peep_head = NULL,
62
                *peep_tail = NULL;
63
 
64
extern Var *varlist;
65
 
66
 
67
IGraph iGraph;
68
int optimized;  // something got optimized
69
 
70
void GenerateZeradic(int op)
71
{
72
        dfs.printf("<GenerateZeradic>");
73
        OCODE *cd;
74
        dfs.printf("A");
75
        cd = (OCODE *)allocx(sizeof(OCODE));
76
        dfs.printf("B");
77
        cd->insn = GetInsn(op);
78
        cd->opcode = op;
79
        cd->length = 0;
80
        cd->oper1 = NULL;
81
        dfs.printf("C");
82
        cd->oper2 = NULL;
83
        cd->oper3 = NULL;
84
        cd->oper4 = NULL;
85
        dfs.printf("D");
86
        cd->loop_depth = looplevel;
87
        AddToPeepList(cd);
88
        dfs.printf("</GenerateZeradic>\r\n");
89
}
90
 
91
void GenerateMonadic(int op, int len, Operand *ap1)
92
{
93
        dfs.printf("<GenerateMonadic>");
94
        OCODE *cd;
95
        dfs.printf("A");
96
        cd = (OCODE *)allocx(sizeof(OCODE));
97
        dfs.printf("B");
98
        cd->insn = GetInsn(op);
99
        cd->opcode = op;
100
        cd->length = len;
101
        cd->oper1 = ap1->Clone();
102
        dfs.printf("C");
103
        cd->oper2 = NULL;
104
        cd->oper3 = NULL;
105
        cd->oper4 = NULL;
106
        dfs.printf("D");
107
        cd->loop_depth = looplevel;
108
        AddToPeepList(cd);
109
        dfs.printf("</GenerateMonadic>\n");
110
}
111
 
112
void GenerateDiadic(int op, int len, Operand *ap1, Operand *ap2)
113
{
114
        OCODE *cd;
115
        cd = (OCODE *)xalloc(sizeof(OCODE));
116
        cd->insn = GetInsn(op);
117
        cd->opcode = op;
118
        cd->length = len;
119
        cd->oper1 = ap1->Clone();
120
        cd->oper2 = ap2->Clone();
121
        if (ap2) {
122
                if (ap2->mode == am_ind || ap2->mode==am_indx) {
123
                        //if (ap2->preg==regSP || ap2->preg==regFP)
124
                        //      cd->opcode |= op_ss;
125
                }
126
        }
127
        cd->oper3 = NULL;
128
        cd->oper4 = NULL;
129
        cd->loop_depth = looplevel;
130
        AddToPeepList(cd);
131
}
132
 
133
void GenerateTriadic(int op, int len, Operand *ap1, Operand *ap2, Operand *ap3)
134
{
135
        OCODE    *cd;
136
        cd = (OCODE *)allocx(sizeof(OCODE));
137
        cd->insn = GetInsn(op);
138
        cd->opcode = op;
139
        cd->length = len;
140
        cd->oper1 = ap1->Clone();
141
        cd->oper2 = ap2->Clone();
142
        cd->oper3 = ap3->Clone();
143
        cd->oper4 = NULL;
144
        cd->loop_depth = looplevel;
145
        AddToPeepList(cd);
146
}
147
 
148
void Generate4adic(int op, int len, Operand *ap1, Operand *ap2, Operand *ap3, Operand *ap4)
149
{
150
        OCODE *cd;
151
        cd = (OCODE *)allocx(sizeof(OCODE));
152
        cd->insn = GetInsn(op);
153
        cd->opcode = op;
154
        cd->length = len;
155
        cd->oper1 = ap1->Clone();
156
        cd->oper2 = ap2->Clone();
157
        cd->oper3 = ap3->Clone();
158
        cd->oper4 = ap4->Clone();
159
        cd->loop_depth = looplevel;
160
        AddToPeepList(cd);
161
}
162
 
163
static void AddToPeepList(OCODE *cd)
164
{
165
        if (!dogen)
166
                return;
167
 
168
        if( peep_head == NULL )
169
        {
170
                ArgRegCount = regFirstArg;
171
                peep_head = peep_tail = cd;
172
                cd->fwd = nullptr;
173
                cd->back = nullptr;
174
        }
175
        else
176
        {
177
                cd->fwd = nullptr;
178
                cd->back = peep_tail;
179
                peep_tail->fwd = cd;
180
                peep_tail = cd;
181
        }
182
        if (cd->opcode!=op_label) {
183
                if (cd->oper1 && IsArgumentReg(cd->oper1->preg))
184
                        ArgRegCount = max(ArgRegCount,cd->oper1->preg);
185
                if (cd->oper2 && IsArgumentReg(cd->oper2->preg))
186
                        ArgRegCount = max(ArgRegCount,cd->oper2->preg);
187
                if (cd->oper3 && IsArgumentReg(cd->oper3->preg))
188
                        ArgRegCount = max(ArgRegCount,cd->oper3->preg);
189
                if (cd->oper4 && IsArgumentReg(cd->oper4->preg))
190
                        ArgRegCount = max(ArgRegCount,cd->oper4->preg);
191
        }
192
}
193
 
194
 
195
// Count the length of the peep list from the current position to the end of
196
// the list.
197
 
198
int PeepCount(OCODE *ip)
199
{
200
        int cnt;
201
 
202
        for (cnt = 0; ip && ip != peep_tail; cnt++)
203
                ip = ip->fwd;
204
        return (cnt);
205
}
206
 
207
 
208
/*
209
 *      add a compiler generated label to the peep list.
210
 */
211
void GenerateLabel(int labno)
212
{
213
        OCODE *newl;
214
        newl = (OCODE *)allocx(sizeof(OCODE));
215
        newl->opcode = op_label;
216
        newl->oper1 = (Operand *)labno;
217
        newl->oper2 = (Operand *)my_strdup((char *)currentFn->sym->name->c_str());
218
        AddToPeepList(newl);
219
}
220
 
221
 
222
// Detect references to labels
223
 
224
void PeepOpt::SetLabelReference()
225
{
226
        OCODE *p, *q;
227
        struct clit *ct;
228
        int nn;
229
 
230
        ZeroMemory(LabelTable, sizeof(LabelTable));
231
        for (p = peep_head; p; p = p->fwd) {
232
                if (p->opcode == op_label) {
233
                        LabelTable[(int)p->oper1] = p;
234
                        p->isReferenced = false;
235
                }
236
        }
237
        for (q = peep_head; q; q = q->fwd) {
238
                if (q->opcode!=op_label && q->opcode!=op_nop) {
239
                        if (q->oper1 && (q->oper1->mode==am_direct || q->oper1->mode==am_imm)) {
240
                                if (p = PeepList::FindLabel(q->oper1->offset->i)) {
241
                                        p->isReferenced = true;
242
                                }
243
                        }
244
                        if (q->oper2 && (q->oper2->mode==am_direct || q->oper2->mode==am_imm)) {
245
                                if (p = PeepList::FindLabel(q->oper2->offset->i)) {
246
                                        p->isReferenced = true;
247
                                }
248
                        }
249
                        if (q->oper3 && (q->oper3->mode==am_direct || q->oper3->mode==am_imm)) {
250
                                if (p = PeepList::FindLabel(q->oper3->offset->i)) {
251
                                        p->isReferenced = true;
252
                                }
253
                        }
254
                        if (q->oper4 && (q->oper4->mode==am_direct || q->oper4->mode==am_imm)) {
255
                                if (p = PeepList::FindLabel(q->oper4->offset->i)) {
256
                                        p->isReferenced = true;
257
                                }
258
                        }
259
                        // Now search case tables for label
260
                        for (ct = casetab; ct; ct = ct->next) {
261
                                for (nn = 0; nn < ct->num; nn++)
262
                                        if (p = PeepList::FindLabel(ct->cases[nn].label))
263
                                                p->isReferenced = true;
264
                        }
265
                }
266
        }
267
}
268
 
269
void PeepOpt::EliminateUnreferencedLabels()
270
{
271
        OCODE *p;
272
 
273
        for (p = peep_head; p; p = p->fwd) {
274
                if (p->opcode == op_label)
275
                        p->remove = false;
276
                if (p->opcode == op_label && !p->isReferenced) {
277
                        MarkRemove(p);
278
                        optimized++;
279
                }
280
        }
281
}
282
 
283
 
284
//
285
// Output all code and labels in the peep list.
286
//
287
void flush_peep()
288
{
289
        opt_peep();         /* do the peephole optimizations */
290
        while( peep_head != NULL )
291
        {
292
                if( peep_head->opcode == op_label )
293
                        put_label((int)peep_head->oper1,"",GetNamespace(),'C');
294
                else
295
                        peep_head->store(ofs);
296
                peep_head = peep_head->fwd;
297
        }
298
}
299
 
300
void peep_add(OCODE *ip)
301
{
302
     Operand *a;
303
 
304
     // IF add to SP is followed by a move to SP, eliminate the add
305
     if (ip==NULL)
306
         return;
307
     if (ip->fwd==NULL)
308
         return;
309
         if (ip->fwd->opcode == op_bra) {
310
                 if (ip->oper3->offset) {
311
                         if (ip->oper1->preg == ip->oper2->preg && ip->oper3->offset->i == 1) {
312
                                 ip->opcode = op_ibne;
313
                                 ip->insn = GetInsn(op_ibne);
314
                                 ip->oper2->preg = 0;
315
                                 ip->oper3 = ip->fwd->oper1;
316
                                 MarkRemove(ip->fwd);
317
                                 optimized++;
318
                         }
319
                 }
320
                 return;
321
         }
322
        if (ip->oper1) {
323
            a = ip->oper1;
324
            if (a->mode==am_reg) {
325
                if (a->preg==regSP) {
326
                    if (ip->fwd->opcode==op_mov) {
327
                        if (ip->fwd->oper1->mode==am_reg) {
328
                            if (ip->fwd->oper1->preg == regSP) {
329
                                if (ip->back==NULL)
330
                                    return;
331
                                ip->back->fwd = ip->fwd;
332
                                ip->fwd->back = ip->back;
333
                                                                optimized++;
334
                            }
335
                        }
336
                    }
337
                }
338
            }
339
     }
340
        return;
341
}
342
 
343
static bool IsSubiSP(OCODE *ip)
344
{
345
        if (ip->opcode == op_sub) {
346
                if (ip->oper3->mode == am_imm) {
347
                        if (ip->oper1->preg == regSP && ip->oper2->preg == regSP) {
348
                                return (true);
349
                        }
350
                }
351
        }
352
        return (false);
353
}
354
 
355
// 'subui' followed by a 'bne' gets turned into 'loop'
356
//
357
static void PeepoptSub(OCODE *ip)
358
{
359
        if (IsSubiSP(ip) && ip->fwd)
360
                if (IsSubiSP(ip->fwd)) {
361
                        ip->oper3->offset->i += ip->fwd->oper3->offset->i;
362
                        MarkRemove(ip->fwd);
363
        }
364
        if (IsSubiSP(ip) && ip->oper3->offset->i == 0)
365
                MarkRemove(ip);
366
        return;
367
        if (ip->opcode==op_subui) {
368
                if (ip->oper3) {
369
                        if (ip->oper3->mode==am_imm) {
370
                                if (ip->oper3->offset->nodetype==en_icon && ip->oper3->offset->i==1) {
371
                                        if (ip->fwd) {
372
                                                if (ip->fwd->opcode==op_ne && ip->fwd->oper2->mode==am_reg && ip->fwd->oper2->preg==0) {
373
                                                        if (ip->fwd->oper1->preg==ip->oper1->preg) {
374
                                                                ip->opcode = op_loop;
375
                                                                ip->oper2 = ip->fwd->oper3;
376
                                                                ip->oper3 = NULL;
377
                                                                if (ip->fwd->back) ip->fwd->back = ip;
378
                                                                ip->fwd = ip->fwd->fwd;
379
                                                                optimized++;
380
                                                                return;
381
                                                        }
382
                                                }
383
                                        }
384
                                }
385
                        }
386
                }
387
        }
388
        return;
389
}
390
 
391
static void MergeSubi(OCODE *first, OCODE *last, int64_t amt)
392
{
393
        OCODE *ip;
394
 
395
        if (first==nullptr)
396
                return;
397
 
398
        // First remove all the excess subtracts
399
        for (ip = first; ip && ip != last; ip = ip->fwd) {
400
                if (IsSubiSP(ip)) {
401
                        MarkRemove(ip);
402
                        optimized++;
403
                }
404
        }
405
        // Set the amount of the last subtract to the total amount
406
        if (ip)  {// there should be one
407
                ip->oper3->offset->i = amt;
408
        }
409
}
410
 
411
// 'subui'
412
//
413
static void PeepoptSubSP()
414
{
415
        OCODE *ip;
416
        OCODE *first_subi = nullptr;
417
        OCODE *last_subi = nullptr;
418
        int64_t amt = 0;
419
 
420
        for (ip = peep_head; ip; ip = ip->fwd) {
421
                if (IsSubiSP(ip)) {
422
                        if (first_subi==nullptr)
423
                                last_subi = first_subi = ip;
424
                        else
425
                                last_subi = ip;
426
                        amt += ip->oper3->offset->i;
427
                }
428
                else if (ip->opcode==op_push || ip->insn->IsFlowControl()) {
429
                        MergeSubi(first_subi, last_subi, amt);
430
                        first_subi = last_subi = nullptr;
431
                        amt = 0;
432
                }
433
        }
434
}
435
 
436
/*
437
 *      peephole optimization for compare instructions.
438
 */
439
void peep_cmp(OCODE *ip)
440
{
441
        return;
442
}
443
 
444
/*
445
 *      changes multiplies and divides by convienient values
446
 *      to shift operations. op should be either op_asl or
447
 *      op_asr (for divide).
448
 */
449
void PeepoptMuldiv(OCODE *ip, int op)
450
{
451
        int shcnt;
452
        int64_t num;
453
 
454
        if( ip->oper1->mode != am_imm )
455
                return;
456
        if( ip->oper1->offset->nodetype != en_icon )
457
                return;
458
 
459
        num = ip->oper1->offset->i;
460
 
461
  // remove multiply / divide by 1
462
        // This shouldn't get through Optimize, but does sometimes.
463
  if (num==1) {
464
                if (ip->back)
465
                        ip->back->fwd = ip->fwd;
466
                if (ip->fwd)
467
                        ip->fwd->back = ip->back;
468
                optimized++;
469
                return;
470
        }
471
  for (shcnt = 1; shcnt < 32; shcnt++) {
472
    if (num == (int64_t)1 << shcnt) {
473
      num = shcnt;
474
                optimized++;
475
      break;
476
    }
477
  }
478
  if (shcnt==32)
479
    return;
480
  ip->oper1->offset->i = num;
481
  ip->opcode = op;
482
  ip->length = 2;
483
        optimized++;
484
}
485
 
486
// Optimize unconditional control flow transfers
487
// Instructions that follow an unconditional transfer won't be executed
488
// unless there is a label to branch to them.
489
//
490
void PeepoptUctran(OCODE *ip)
491
{
492
        if (uctran_off) return;
493
        while( ip->fwd != NULL && ip->fwd->opcode != op_label)
494
        {
495
                ip->fwd = ip->fwd->fwd;
496
                if( ip->fwd != NULL )
497
                        ip->fwd->back = ip;
498
                optimized++;
499
        }
500
}
501
 
502
void PeepoptJAL(OCODE *ip)
503
{
504
        if (ip->oper1->preg!=0)
505
                return;
506
        PeepoptUctran(ip);
507
}
508
 
509
// Remove instructions that branch to the next label.
510
//
511
void PeepoptBranch(OCODE *ip)
512
{
513
        OCODE *p;
514
 
515
        for (p = ip->fwd; p && p->opcode==op_label; p = p->fwd)
516
                if (ip->oper1->offset->i == (int)p->oper1) {
517
                        MarkRemove(ip);
518
                        optimized++;
519
                        return;
520
                }
521
        return;
522
}
523
 
524
// Look for the following sequence and convert it into a set operation.
525
// Bcc lab1
526
// ldi  rn,#1
527
// bra lab2
528
// lab1:
529
// ldi  rn,#0
530
// lab2:
531
 
532
void PeepoptBcc(OCODE * ip)
533
{
534
     OCODE *fwd1, *fwd2, *fwd3, *fwd4, *fwd5;
535
     if (!ip->fwd)
536
         return;
537
     fwd1 = ip->fwd;
538
     if (fwd1->opcode != op_ldi || fwd1->oper2->mode != am_imm)
539
         return;
540
     fwd2 = fwd1->fwd;
541
     if (!fwd2)
542
         return;
543
     if (fwd2->opcode != op_bra)
544
         return;
545
     fwd3 = fwd2->fwd;
546
     if (!fwd3)
547
         return;
548
     if (fwd3->opcode != op_label)
549
         return;
550
     fwd4 = fwd3->fwd;
551
     if (!fwd4)
552
         return;
553
     if (fwd4->opcode != op_ldi || fwd4->oper2->mode != am_imm)
554
         return;
555
     fwd5 = fwd4->fwd;
556
     if (!fwd5)
557
         return;
558
     if (fwd5->opcode != op_label)
559
         return;
560
     // now check labels match up
561
     if (ip->oper2!=fwd3->oper1)
562
         return;
563
     if (fwd2->oper1!=fwd5->oper1)
564
         return;
565
     // check for same target register
566
     if (!OCODE::IsEqualOperand(fwd1->oper1,fwd4->oper1))
567
         return;
568
     // check ldi values
569
     if (fwd1->oper2->offset->i != 1)
570
         return;
571
     if (fwd4->oper2->offset->i != 0)
572
         return;
573
// *****
574
// need to check branch targets to make sure no other code targets the label.
575
// or this code might not work.
576
}
577
 
578
void PeepoptLc(OCODE *ip)
579
{
580
        if (ip->fwd) {
581
                if (ip->fwd->opcode==op_sext16 || ip->fwd->opcode==op_sxc ||
582
                        (ip->fwd->opcode==op_bfext && ip->fwd->oper3->offset->i==0 && ip->fwd->oper4->offset->i==15)) {
583
                        if (ip->fwd->oper1->preg == ip->oper1->preg) {
584
                                if (ip->fwd->fwd) {
585
                                        ip->fwd->fwd->back = ip;
586
                                }
587
                                ip->fwd = ip->fwd->fwd;
588
                        }
589
                }
590
        }
591
}
592
 
593
// LEA followed by a push of the same register gets translated to PEA.
594
// If LEA is followed by the push of more than one register, then leave it
595
// alone. The register order of the push matters.
596
 
597
void PeepoptLea(OCODE *ip)
598
{
599
        OCODE *ip2;
600
        int whop;
601
 
602
        return;
603
  whop = 0;
604
        ip2 = ip->fwd;
605
        if (!ip2)
606
           return;
607
  if (ip2->opcode != op_push)
608
    return;
609
  whop =  ((ip2->oper1 != NULL) ? 1 : 0) +
610
          ((ip2->oper2 != NULL) ? 1 : 0) +
611
          ((ip2->oper3 != NULL) ? 1 : 0) +
612
          ((ip2->oper4 != NULL) ? 1 : 0);
613
  if (whop > 1)
614
    return;
615
  // Pushing a single register     
616
  if (ip2->oper1->mode != am_reg)
617
     return;
618
  // And it's the same register as the LEA
619
  if (ip2->oper1->preg != ip->oper1->preg)
620
     return;
621
  ip->opcode = op_pea;
622
  ip->oper1 = ip->oper2->Clone();
623
  ip->oper2 = NULL;
624
  ip->fwd = ip2->fwd;
625
}
626
 
627
// LW followed by a push of the same register gets translated to PUSH.
628
 
629
void PeepoptLw(OCODE *ip)
630
{
631
        OCODE *ip2;
632
 
633
        return;
634
        ip2 = ip->fwd;
635
        if (!ip2)
636
           return;
637
    if (ip2->opcode != op_push)
638
       return;
639
    if (ip2->oper1->mode != am_reg)
640
       return;
641
    if (ip->oper2->mode != am_ind && ip->oper2->mode != am_indx)
642
       return;
643
    if (ip->oper1->preg != ip2->oper1->preg)
644
       return;
645
    ip->opcode = op_push;
646
    ip->oper1 = ip->oper2->Clone();
647
    ip->oper2 = NULL;
648
    ip->fwd = ip2->fwd;
649
}
650
 
651
// LC0I followed by a push of the same register gets translated to PUSH.
652
 
653
void PeepoptLc0i(OCODE *ip)
654
{
655
        OCODE *ip2;
656
 
657
    if (!isFISA64)
658
       return;
659
        ip2 = ip->fwd;
660
        if (!ip2)
661
           return;
662
    if (ip2->opcode != op_push)
663
       return;
664
    if (ip->oper2->offset->i > 0x1fffLL || ip->oper2->offset->i <= -0x1fffLL)
665
       return;
666
    ip->opcode = op_push;
667
    ip->oper1 = ip->oper2->Clone();
668
    ip->oper2 = NULL;
669
    ip->fwd = ip2->fwd;
670
}
671
 
672
 
673
// Combine a chain of push operations into a single push
674
 
675
void PeepoptPushPop(OCODE *ip)
676
{
677
        OCODE *ip2,*ip3,*ip4;
678
 
679
        return;
680
        if (ip->opcode==op_pop) {
681
                ip2 = ip->fwd;
682
                if (ip2 && ip2->opcode==op_push) {
683
                        ip3 = ip2->fwd;
684
                        if (ip3 && ip3->opcode==op_ldi) {
685
                                if (ip3->oper1->preg==ip2->oper1->preg && ip3->oper1->preg==ip->oper1->preg) {
686
                                        ip->back->fwd = ip2->fwd;
687
                                        ip->back->fwd->comment = ip2->comment;
688
                                }
689
                        }
690
                }
691
        }
692
        return;
693
    if (!isTable888)
694
        return;
695
        if (ip->oper1->mode == am_imm)
696
                return;
697
        ip2 = ip->fwd;
698
        if (!ip2)
699
                return;
700
        if (ip2->opcode!=ip->opcode)
701
                return;
702
        if (ip2->oper1->mode==am_imm)
703
                return;
704
        ip->oper2 = ip2->oper1->Clone();
705
        ip->fwd = ip2->fwd;
706
        ip3 = ip2->fwd;
707
        if (!ip3)
708
                return;
709
        if (ip3->opcode!=ip->opcode)
710
                return;
711
        if (ip3->oper1->mode==am_imm)
712
                return;
713
        ip->oper3 = ip3->oper1->Clone();
714
        ip->fwd = ip3->fwd;
715
        ip4 = ip3->fwd;
716
        if (!ip4)
717
                return;
718
        if (ip4->opcode!=ip->opcode)
719
                return;
720
        if (ip4->oper1->mode==am_imm)
721
                return;
722
        ip->oper4 = ip4->oper1->Clone();
723
        ip->fwd = ip4->fwd;
724
}
725
 
726
 
727
// Strip out useless masking operations generated by type conversions.
728
 
729
void peep_ld(OCODE *ip)
730
{
731
        if (ip->oper2->mode != am_imm)
732
                return;
733
        if (ip->oper2->offset->i==0) {
734
                ip->opcode = op_mov;
735
                ip->oper2->mode = am_reg;
736
                ip->oper2->preg = 0;
737
                optimized++;
738
                return;
739
        }
740
        if (!ip->fwd)
741
                return;
742
        if (ip->fwd->opcode!=op_and)
743
                return;
744
        if (ip->fwd->oper1->preg != ip->oper1->preg)
745
                return;
746
        if (ip->fwd->oper2->preg != ip->oper1->preg)
747
                return;
748
        if (ip->fwd->oper3->mode != am_imm)
749
                return;
750
        ip->oper2->offset->i = ip->oper2->offset->i & ip->fwd->oper3->offset->i;
751
        if (ip->fwd->fwd)
752
                ip->fwd->fwd->back = ip;
753
        ip->fwd = ip->fwd->fwd;
754
        optimized++;
755
}
756
 
757
 
758
void PeepoptLd(OCODE *ip)
759
{
760
    return;
761
}
762
 
763
 
764
// Remove extra labels at end of subroutines
765
 
766
void PeepoptLabel(OCODE *ip)
767
{
768
    if (!ip)
769
        return;
770
    if (ip->fwd)
771
        return;
772
        if (ip->back)
773
                ip->back->fwd = nullptr;
774
        optimized++;
775
}
776
 
777
// Optimize away duplicate sign extensions that the compiler sometimes
778
// generates. This handles sxb, sxcm and sxh.
779
 
780
void PeepoptSxb(OCODE *ip)
781
{
782
        // Optimize away sign extension of a signed load
783
        if (ip->back) {
784
                if (ip->back->opcode == op_lb && ip->opcode == op_sxb) {
785
                        if (ip->back->oper1->preg == ip->oper1->preg && ip->oper1->preg==ip->oper2->preg) {
786
                                MarkRemove(ip);
787
                                optimized++;
788
                                return;
789
                        }
790
                }
791
                if (ip->back->opcode == op_lc && ip->opcode == op_sxc) {
792
                        if (ip->back->oper1->preg == ip->oper1->preg && ip->oper1->preg == ip->oper2->preg) {
793
                                MarkRemove(ip);
794
                                optimized++;
795
                                return;
796
                        }
797
                }
798
                if (ip->back->opcode == op_lh && ip->opcode == op_sxh) {
799
                        if (ip->back->oper1->preg == ip->oper1->preg && ip->oper1->preg == ip->oper2->preg) {
800
                                MarkRemove(ip);
801
                                optimized++;
802
                                return;
803
                        }
804
                }
805
        }
806
     if (!ip->fwd)
807
         return;
808
     if (ip->fwd->opcode != ip->opcode)
809
         return;
810
     if (ip->fwd->oper1->preg != ip->oper1->preg)
811
         return;
812
     if (ip->fwd->oper2->preg != ip->oper2->preg)
813
         return;
814
     // Now we must have the same instruction twice in a row. ELiminate the
815
     // duplicate.
816
     ip->fwd = ip->fwd->fwd;
817
     if (ip->fwd->fwd)
818
          ip->fwd->fwd->back = ip;
819
        optimized++;
820
}
821
void PeepoptSxbAnd(OCODE *ip)
822
{
823
     if (!ip->fwd)
824
         return;
825
     if (ip->opcode != op_sxb)
826
         return;
827
     if (ip->fwd->opcode != op_and)
828
         return;
829
         if (ip->fwd->oper3->mode != am_imm)
830
                 return;
831
     if (ip->fwd->oper3->offset->i != 255)
832
         return;
833
        MarkRemove(ip);
834
        optimized++;
835
}
836
 
837
 
838
// Eliminate branchs to the next line of code.
839
 
840
static void opt_nbr()
841
{
842
        OCODE *ip,*pip;
843
 
844
        ip = peep_head;
845
        pip = peep_head;
846
        while(ip) {
847
                if (ip->opcode==op_label) {
848
                        if (pip->opcode==op_br || pip->opcode==op_bra) {
849
                                if ((int64_t)ip->oper1==pip->oper1->offset->i)  {
850
                                        pip->back->fwd = pip->fwd;
851
                                        ip->back = pip->back;
852
                                        optimized++;
853
                                }
854
                        }
855
                }
856
                pip = ip;
857
                ip = ip->fwd;
858
        }
859
}
860
 
861
 
862
// Process compiler hint opcodes
863
 
864
static void PeepoptHint(OCODE *ip)
865
{
866
        OCODE *fwd, *back;
867
        Operand *am;
868
 
869
        if ((ip->back && ip->back->opcode==op_label) || (ip->fwd && ip->fwd->opcode==op_label))
870
                return;
871
        if (ip->remove)
872
                return;
873
 
874
        switch (ip->oper1->offset->i) {
875
 
876
        // hint #1
877
        // Takes care of redundant moves at the parameter setup point
878
        // Code Like:
879
        //    MOV r3,#constant
880
        //    MOV r18,r3
881
        // Translated to:
882
        //    MOV r18,#constant
883
        case 1:
884
                if (ip->fwd && ip->fwd->opcode != op_mov) {
885
                        MarkRemove(ip);
886
                        optimized++;
887
                        return;
888
                }
889
 
890
                if (ip->fwd && ip->fwd->oper1->preg >= 18 && ip->fwd->oper1->preg < 24) {
891
                        if (OCODE::IsEqualOperand(ip->fwd->oper2, ip->back->oper1)) {
892
                                ip->back->oper1 = ip->fwd->oper1;
893
                                MarkRemove(ip);
894
                                MarkRemove(ip->fwd);
895
                                optimized++;
896
                                return;
897
                        }
898
                }
899
 
900
                if (ip->back && ip->back->opcode != op_mov) {
901
                        MarkRemove(ip);
902
                        optimized++;
903
                        return;
904
                }
905
 
906
                if (OCODE::IsEqualOperand(ip->fwd->oper2, ip->back->oper1)) {
907
                        ip->back->oper1 = ip->fwd->oper1;
908
                        MarkRemove(ip);
909
                        MarkRemove(ip->fwd);
910
                        optimized++;
911
                }
912
                else {
913
                        MarkRemove(ip);
914
                        optimized++;
915
                }
916
                break;
917
 
918
        // Can't do this optimization:
919
        // what if x = (~(y=(a & b)))
920
        // The embedded assignment to y which might be used later would be lost.
921
        //
922
        // hint #2
923
        // Takes care of redundant moves at the function return point
924
        // Code like:
925
        //     MOV R3,arg
926
        //     MOV R1,R3
927
        // Translated to:
928
        //     MOV r1,arg
929
        case 2:
930
                return;
931
                if (ip->fwd==nullptr || ip->back==nullptr)
932
                        break;
933
                if (ip->fwd->remove || ip->back->remove)
934
                        break;
935
                if (OCODE::IsEqualOperand(ip->fwd->oper2, ip->back->oper1)) {
936
                        if (ip->back->HasTargetReg()) {
937
                                if (!(ip->fwd->oper1->mode == am_fpreg && ip->back->opcode==op_ldi)) {
938
                                        ip->back->oper1 = ip->fwd->oper1;
939
                                        MarkRemove(ip->fwd);
940
                                        optimized++;
941
                                }
942
                        }
943
                }
944
                else {
945
                        MarkRemove(ip);
946
                        optimized++;
947
                }
948
                break;
949
 
950
        // hint #3
951
        //         and r5,r2,r3
952
        //     com r1,r5
953
        // Translates to:
954
        //     nand r5,r2,r3
955
        case 3:
956
                if (ip->back == nullptr || ip->fwd == nullptr)
957
                        break;
958
                if (ip->fwd->remove || ip->back->remove)
959
                        break;
960
                // If not all in registers
961
                if (ip->back->oper1->mode != am_reg
962
                        || ip->back->oper2->mode != am_reg
963
                        || (ip->back->oper3 && ip->back->oper3->mode != am_reg))
964
                        break;
965
                if (ip->back->opcode != op_and
966
                        && ip->back->opcode != op_or
967
                        && ip->back->opcode != op_xor
968
                        )
969
                        break;
970
                if (ip->fwd->opcode != op_com)
971
                        break;
972
                if (ip->fwd->oper2->mode != am_reg)
973
                        break;
974
                if (ip->back->oper1->preg != ip->fwd->oper2->preg)
975
                        break;
976
                if (ip->fwd->opcode != op_com)
977
                        break;
978
                switch (ip->back->opcode) {
979
                case op_and:
980
                        ip->back->opcode = op_nand;
981
                        ip->back->insn = GetInsn(op_nand);
982
                        ip->back->oper1->preg = ip->fwd->oper1->preg;
983
                        MarkRemove(ip->fwd);
984
                        optimized++;
985
                        break;
986
                case op_or:
987
                        ip->back->opcode = op_nor;
988
                        ip->back->insn = GetInsn(op_nor);
989
                        ip->back->oper1->preg = ip->fwd->oper1->preg;
990
                        MarkRemove(ip->fwd);
991
                        optimized++;
992
                        break;
993
                case op_xor:
994
                        ip->back->opcode = op_xnor;
995
                        ip->back->insn = GetInsn(op_xnor);
996
                        ip->back->oper1->preg = ip->fwd->oper1->preg;
997
                        MarkRemove(ip->fwd);
998
                        optimized++;
999
                        break;
1000
                }
1001
                break;
1002
 
1003
        // hint #9
1004
        // Index calc.
1005
        //              shl r1,r3,#3
1006
        //              sw r4,[r11+r1]
1007
        // Becomes:
1008
        //              sw r4,[r11+r3*8]
1009
        case 9:
1010
                if (ip->fwd==nullptr || ip->back==nullptr)
1011
                        break;
1012
                if (ip->fwd->oper2==nullptr || ip->back->oper3==nullptr)
1013
                        break;
1014
                if (ip->fwd->oper2->mode != am_indx2)
1015
                        break;
1016
                if (ip->fwd->oper2->preg == ip->back->oper1->preg) {
1017
                        if ((ip->back->opcode == op_shl) && ip->back->oper3->offset &&
1018
                                (ip->back->oper3->offset->i == 1
1019
                                        || ip->back->oper3->offset->i == 2
1020
                                        || ip->back->oper3->offset->i == 3)) {
1021
                                ip->fwd->oper2->preg = ip->back->oper2->preg;
1022
                                ip->fwd->oper2->scale = 1 << ip->back->oper3->offset->i;
1023
                                MarkRemove(ip->back);
1024
                                optimized++;
1025
                                am = ip->back->oper1;
1026
                                fwd = ip->fwd->fwd;
1027
                                back = ip->back->back;
1028
                                while (back->opcode == op_hint) // It should be
1029
                                        back = back->back;
1030
                                // We search backwards for another shl related to a forward op to
1031
                                // accomodate assignment operations. Assignment operations may
1032
                                // generate indexed code like the following:
1033
                                //    shl for target
1034
                                //    shl for source
1035
                                //    load source
1036
                                //    store target
1037
                                if (fwd->oper2) {
1038
                                        if ((back->opcode == op_shl) && back->oper3->offset &&
1039
                                                (am->preg != fwd->oper2->preg && am->preg != fwd->oper2->sreg) &&
1040
                                                (back->oper3->offset->i == 1
1041
                                                        || back->oper3->offset->i == 2
1042
                                                        || back->oper3->offset->i == 3)
1043
                                                ) {
1044
                                                fwd->oper2->preg = back->oper2->preg;
1045
                                                fwd->oper2->scale = 1 << back->oper3->offset->i;
1046
                                                MarkRemove(back);
1047
                                                optimized++;
1048
                                        }
1049
                                }
1050
                        }
1051
                }
1052
                break;
1053
        }
1054
}
1055
 
1056
// A store followed by a load of the same address removes
1057
// the load operation.
1058
// Eg.
1059
// SH   r3,Address
1060
// LH   r3,Address
1061
// Turns into
1062
// SH   r3,Address
1063
// Note this optimization won't be performed for volatile
1064
// addresses.
1065
 
1066
static void Swap(OCODE *ip1, OCODE *ip2)
1067
{
1068
        OCODE *ip1b = ip1->back, *ip1f = ip1->fwd;
1069
        OCODE *ip2b = ip2->back, *ip2f = ip2->fwd;
1070
        ip1b->fwd = ip2;
1071
        ip2f->back = ip1;
1072
        ip1->fwd = ip2f;
1073
        ip1->back = ip2;
1074
        ip2->fwd = ip1;
1075
        ip2->back = ip1b;
1076
}
1077
 
1078
static void PeepoptSh(OCODE *ip)
1079
{
1080
        if (ip->back && (ip->back->opcode==op_bfextu || ip->back->opcode==op_bfext)) {
1081
                if (ip->back->oper1->preg==ip->oper1->preg) {
1082
                        if (ip->back->oper3->offset->i == 0 && ip->back->oper4->offset->i==31) {
1083
                                Swap(ip->back,ip);
1084
                        }
1085
                }
1086
        }
1087
}
1088
 
1089
static void PeepoptStore(OCODE *ip)
1090
{
1091
        if (ip->opcode==op_sh)
1092
                PeepoptSh(ip);
1093
        if (ip->opcode==op_label || ip->fwd->opcode==op_label)
1094
                return;
1095
        if (!OCODE::IsEqualOperand(ip->oper1, ip->fwd->oper1))
1096
                return;
1097
        if (!OCODE::IsEqualOperand(ip->oper2, ip->fwd->oper2))
1098
                return;
1099
        if (ip->opcode==op_sh && ip->fwd->opcode!=op_lh)
1100
                return;
1101
        if (ip->opcode==op_sw && ip->fwd->opcode!=op_lw)
1102
                return;
1103
        if (ip->fwd->isVolatile)
1104
                return;
1105
        MarkRemove(ip->fwd);
1106
        optimized++;
1107
}
1108
 
1109
// This optimization eliminates an 'AND' instruction when the value
1110
// in the register is a constant less than one of the two special
1111
// constants 255 or 65535. This is typically a result of a zero
1112
// extend operation.
1113
//
1114
// So code like:
1115
//              ld              r3,#4
1116
//              and             r3,r3,#255
1117
// Eliminates the useless 'and' operation.
1118
 
1119
static void PeepoptAnd(OCODE *ip)
1120
{
1121
        // This doesn't work properly yet in all cases.
1122
        if (ip->oper1 && ip->oper2 && ip->oper3) {
1123
                if (ip->oper1->mode==am_reg && ip->oper2->mode==am_reg && ip->oper3->mode == am_imm) {
1124
                        if (ip->oper1->preg==ip->oper2->preg && ip->oper3->offset->i==-1) {
1125
                                MarkRemove(ip);
1126
                                optimized++;
1127
                        }
1128
                }
1129
        }
1130
        return;
1131
        if (ip->oper2==nullptr || ip->oper3==nullptr)
1132
                throw new C64PException(ERR_NULLPOINTER,0x50);
1133
        if (ip->oper2->offset == nullptr || ip->oper3->offset==nullptr)
1134
                return;
1135
        if (ip->oper2->offset->constflag==false)
1136
                return;
1137
        if (ip->oper3->offset->constflag==false)
1138
                return;
1139
        if (
1140
                ip->oper3->offset->i != 1 &&
1141
                ip->oper3->offset->i != 3 &&
1142
                ip->oper3->offset->i != 7 &&
1143
                ip->oper3->offset->i != 15 &&
1144
                ip->oper3->offset->i != 31 &&
1145
                ip->oper3->offset->i != 63 &&
1146
                ip->oper3->offset->i != 127 &&
1147
                ip->oper3->offset->i != 255 &&
1148
                ip->oper3->offset->i != 511 &&
1149
                ip->oper3->offset->i != 1023 &&
1150
                ip->oper3->offset->i != 2047 &&
1151
                ip->oper3->offset->i != 4095 &&
1152
                ip->oper3->offset->i != 8191 &&
1153
                ip->oper3->offset->i != 16383 &&
1154
                ip->oper3->offset->i != 32767 &&
1155
                ip->oper3->offset->i != 65535)
1156
                // Could do this up to 32 bits
1157
                return;
1158
        if (ip->oper2->offset->i < ip->oper3->offset->i) {
1159
                MarkRemove(ip);
1160
        }
1161
}
1162
 
1163
// Check for references to the base pointer. If nothing refers to the
1164
// base pointer then the stack linkage instructions can be removed.
1165
 
1166
static int CountBPReferences()
1167
{
1168
        int refBP = 0;
1169
        OCODE *ip;
1170
 
1171
        for (ip = peep_head; ip != NULL; ip = ip->fwd)
1172
        {
1173
                if (ip->opcode != op_label && ip->opcode!=op_nop
1174
                        && ip->opcode != op_link && ip->opcode != op_unlk) {
1175
                        if (ip->oper1) {
1176
                                if (ip->oper1->preg==regFP || ip->oper1->sreg==regFP)
1177
                                        refBP++;
1178
                        }
1179
                        if (ip->oper2) {
1180
                                if (ip->oper2->preg==regFP || ip->oper2->sreg==regFP)
1181
                                        refBP++;
1182
                        }
1183
                        if (ip->oper3) {
1184
                                if (ip->oper3->preg==regFP || ip->oper3->sreg==regFP)
1185
                                        refBP++;
1186
                        }
1187
                        if (ip->oper4) {
1188
                                if (ip->oper4->preg==regFP || ip->oper4->sreg==regFP)
1189
                                        refBP++;
1190
                        }
1191
                }
1192
        }
1193
        return (refBP);
1194
}
1195
 
1196
void MarkRemove(OCODE *ip)
1197
{
1198
        ip->remove = true;
1199
}
1200
 
1201
void MarkRemove2(OCODE *ip)
1202
{
1203
        ip->remove2 = true;
1204
}
1205
 
1206
static void MarkAllKeep()
1207
{
1208
        OCODE *ip;
1209
 
1210
        for (ip = peep_head; ip != NULL; ip = ip->fwd )
1211
        {
1212
                ip->remove = false;
1213
        }
1214
}
1215
 
1216
void Remove()
1217
{
1218
        OCODE *ip, *ip1, *ip2;
1219
 
1220
        if (RemoveEnabled)
1221
        for (ip = peep_head; ip; ip = ip1) {
1222
                ip1 = ip->fwd;
1223
                ip2 = ip->back;
1224
                if (ip->remove) {
1225
                        if (ip1 && ip1->comment==nullptr)
1226
                                ip1->comment = ip->comment;
1227
                        if (ip2)
1228
                                ip2->fwd = ip1;
1229
                        if (ip1)
1230
                                ip1->back = ip2;
1231
                }
1232
        }
1233
}
1234
 
1235
void IRemove()
1236
{
1237
        Remove();
1238
}
1239
 
1240
static void Remove2()
1241
{
1242
        OCODE *ip, *ip1, *ip2;
1243
 
1244
        if (RemoveEnabled)
1245
        for (ip = peep_head; ip; ip = ip1) {
1246
                ip1 = ip->fwd;
1247
                ip2 = ip->back;
1248
                if (ip->remove2) {
1249
                        if (ip1 && ip1->comment==nullptr)
1250
                                ip1->comment = ip->comment;
1251
                        if (ip2)
1252
                                ip2->fwd = ip1;
1253
                        if (ip1)
1254
                                ip1->back = ip2;
1255
                }
1256
        }
1257
}
1258
 
1259
static void RemoveDoubleTargets(OCODE *ip)
1260
{
1261
        OCODE *ip2;
1262
        int rg1, rg2, rg3, rg4;
1263
 
1264
        if (!ip->HasTargetReg())
1265
                return;
1266
        for (ip2 = ip->fwd; ip2 && (ip2->opcode==op_rem || ip2->opcode==op_hint); ip2 = ip2->fwd);
1267
        if (ip2==nullptr)
1268
                return;
1269
        if (!ip2->HasTargetReg())
1270
                return;
1271
        ip2->GetTargetReg(&rg1, &rg2);
1272
        ip->GetTargetReg(&rg3, &rg4);
1273
        if (rg1 != rg3)
1274
                return;
1275
        if (ip2->HasSourceReg(rg3))
1276
                return;
1277
        if (rg3==regSP)
1278
                return;
1279
        MarkRemove(ip);
1280
        optimized++;
1281
}
1282
 
1283
 
1284
// Remove stack linkage code for when there are no references to the base 
1285
// pointer.
1286
 
1287
static void RemoveLinkUnlink()
1288
{
1289
        OCODE *ip;
1290
 
1291
        for (ip = peep_head; ip != NULL; ip = ip->fwd)
1292
        {
1293
                if (ip->opcode==op_link || ip->opcode==op_unlk) {
1294
                        MarkRemove(ip);
1295
                }
1296
        }
1297
}
1298
 
1299
static void RemoveCompilerHints()
1300
{
1301
        OCODE *ip;
1302
 
1303
    for(ip = peep_head; ip != NULL; ip = ip->fwd)
1304
    {
1305
        if (ip->opcode==op_hint) {
1306
                        MarkRemove(ip);
1307
                }
1308
        }
1309
}
1310
 
1311
 
1312
// Potentially any called routine could throw an exception. So call
1313
// instructions could act like branches to the default catch tacked
1314
// onto the end of a subroutine. This is important to prevent the
1315
// default catch from being optimized away. It's possible that there's
1316
// no other way to reach the catch.
1317
// A bex instruction, which isn't a real instruction, is added to the
1318
// instruction stream so that links are created in the CFG to the
1319
// catch handlers. At a later stage of the compile all the bex
1320
// instructions are removed, since they were there only to aid in
1321
// compiler optimizations.
1322
 
1323
static void RemoveCompilerHints2()
1324
{
1325
        OCODE *ip;
1326
 
1327
    for(ip = peep_head; ip != NULL; ip = ip->fwd)
1328
    {
1329
                if (ip->opcode==op_bex)
1330
                        MarkRemove(ip);
1331
        }
1332
        Remove();
1333
}
1334
 
1335
//
1336
//      peephole optimizer. This routine calls the instruction
1337
//      specific optimization routines above for each instruction
1338
//      in the peep list.
1339
//
1340
static void opt_peep()
1341
{
1342
        OCODE *ip;
1343
        int rep;
1344
 
1345
        PrintPeepList();
1346
        // Move the return code pointer past the label which may be removed by
1347
        // optimization.
1348
        if (currentFn->rcode)
1349
                currentFn->rcode = currentFn->rcode->fwd;
1350
 
1351
        // Remove any dead code identified by the code generator.
1352
        Remove();
1353
 
1354
        if (!::opt_nopeep) {
1355
 
1356
                opt_nbr();
1357
 
1358
                // Performing peephole optimizations may lead to further optimizations so do
1359
                // the optimization step a few times.
1360
                optimized = 0;
1361
                for (rep = 0; (rep < 5) || (optimized && rep < 10); rep++)
1362
                {
1363
                        // Peephole optimizations might lead to unreferenced labels, which may make
1364
                        // further peephole optimizations possible.
1365
                        PeepOpt::SetLabelReference();
1366
                        PeepOpt::EliminateUnreferencedLabels();
1367
                        Remove();
1368
                        //MarkAllKeep();
1369
                        for (ip = peep_head; ip != NULL; ip = ip->fwd )
1370
                        {
1371
                                if (!ip->remove) {
1372
                                switch( ip->opcode )
1373
                                {
1374
                                case op_rem:
1375
                                        if (ip->fwd) {
1376
                                                ip->fwd->comment = ip;
1377
                                                MarkRemove(ip);
1378
                                        }
1379
                                        break;
1380
                                case op_ld:
1381
                                        peep_ld(ip);
1382
                                        PeepoptLd(ip);
1383
                                break;
1384
                                case op_mov:
1385
                                        ip->OptMove();
1386
                                        break;
1387
                                case op_add:
1388
                                case op_addu:
1389
                                case op_addui:
1390
                                                peep_add(ip);
1391
                                                break;
1392
                                case op_sub:
1393
                                                PeepoptSub(ip);
1394
                                                break;
1395
                                case op_cmp:
1396
                                                peep_cmp(ip);
1397
                                                break;
1398
                                case op_mul:
1399
        //                    PeepoptMuldiv(ip,op_shl);
1400
                                                break;
1401
                                case op_lc:
1402
                                                PeepoptLc(ip);
1403
                                                break;
1404
                                case op_lw:
1405
                                                //PeepoptLw(ip);
1406
                                                break;
1407
                                case op_sxb:
1408
                                case op_sxc:
1409
                                case op_sxh:
1410
                                                PeepoptSxb(ip);
1411
                                                PeepoptSxbAnd(ip);
1412
                                                break;
1413
                                case op_br:
1414
                                case op_bra:
1415
                                                PeepoptBranch(ip);
1416
                                                PeepoptUctran(ip);
1417
                                                break;
1418
                                case op_pop:
1419
                                case op_push:
1420
                                                PeepoptPushPop(ip);
1421
                                                break;
1422
                                case op_lea:
1423
                                                PeepoptLea(ip);
1424
                                                break;
1425
                                case op_jal:
1426
                                                PeepoptJAL(ip);
1427
                                                break;
1428
                                case op_brk:
1429
                                case op_jmp:
1430
                                case op_ret:
1431
                                case op_rts:
1432
                                case op_rte:
1433
                                case op_rtd:
1434
                                                PeepoptUctran(ip);
1435
                                                break;
1436
                                case op_label:
1437
                                                PeepoptLabel(ip);
1438
                                                break;
1439
                                case op_hint:
1440
                                                PeepoptHint(ip);
1441
                                                break;
1442
                                case op_sh:
1443
                                case op_sw:
1444
                                                PeepoptStore(ip);
1445
                                                break;
1446
                                case op_and:
1447
                                                PeepoptAnd(ip);
1448
                                                break;
1449
                                case op_redor:
1450
                                        ip->OptRedor();
1451
                                        break;
1452
                                }
1453
                                }
1454
                        }
1455
                        Remove();
1456
 
1457
                        for (ip = peep_head; ip != NULL; ip = ip->fwd )
1458
                                RemoveDoubleTargets(ip);
1459
                        Remove();
1460
 
1461
                }
1462
                //PeepoptSubSP();
1463
 
1464
                // Remove the link and unlink instructions if no references
1465
                // to BP.
1466
                if (CountBPReferences()==0)
1467
                        RemoveLinkUnlink();
1468
                Remove();
1469
        }
1470
 
1471
        // Get rid of extra labels that clutter up the output
1472
        PeepOpt::SetLabelReference();
1473
        PeepOpt::EliminateUnreferencedLabels();
1474
 
1475
        // Remove all the compiler hints that didn't work out.
1476
        RemoveCompilerHints();
1477
        Remove();
1478
 
1479
        currentFn->RootBlock = BasicBlock::Blockize(peep_head);
1480
        dfs.printf("<PeepList:1>\n");
1481
        PrintPeepList();
1482
        dfs.printf("</PeepList:1>\n");
1483
        forest.func = currentFn;
1484
//      RootBlock->ExpandReturnBlocks();
1485
        CFG::Create();
1486
 
1487
        RemoveMoves();
1488
        currentFn->ComputeLiveVars();
1489
        MarkAllKeep();
1490
 
1491
        currentFn->DumpLiveVars();
1492
        currentFn->CreateVars();
1493
        Var::CreateForests();
1494
        Var::DumpForests(0);
1495
        CFG::CalcDominanceFrontiers();
1496
        CFG::InsertPhiInsns();
1497
        RemoveCompilerHints2();
1498
        CFG::Rename();
1499
        count = 0;
1500
        forest.pass = 0;
1501
        do {
1502
                forest.pass++;
1503
                if (!opt_vreg)
1504
                        return;
1505
                forest.Renumber();
1506
                BasicBlock::ComputeSpillCosts();
1507
                RemoveCode();
1508
                iGraph.frst = &forest;
1509
                iGraph.BuildAndCoalesce();
1510
                iGraph.Print(3);
1511
                forest.Simplify();
1512
                iGraph.Print(4);
1513
                forest.Select();
1514
                Var::DumpForests(1);
1515
                forest.SpillCode();
1516
        } while (!forest.IsAllTreesColored() && forest.pass < 32);
1517
        dfs.printf("Loops for color graphing allocator: %d\n", forest.pass);
1518
 
1519
        // Substitute real registers for virtual ones.
1520
        BasicBlock::ColorAll();
1521
        if (count == 2) {
1522
                dfs.printf("Register allocator max loops.\n");
1523
        }
1524
        Var::DumpForests(2);
1525
        //DumpLiveRegs();
1526
 
1527
        dfs.printf("<PeepList:2>\n");
1528
        PrintPeepList();
1529
        dfs.printf("</PeepList:2>\n");
1530
}
1531
 
1532
// Remove move instructions which will create false interferences.
1533
// The move instructions are just marked for removal so they aren't
1534
// considered during live variable computation. They are unmarked
1535
// later, but may be subsequently removed if ranges are coalesced.
1536
 
1537
void RemoveMoves()
1538
{
1539
        OCODE *ip;
1540
        int reg1, reg2;
1541
        bool foundMove;
1542
        foundMove = false;
1543
 
1544
        for (ip = peep_head; ip; ip = ip->fwd) {
1545
                if (ip->opcode==op_mov) {
1546
                        foundMove = true;
1547
                        reg1 = ip->oper1->preg;
1548
                        reg2 = ip->oper2->preg;
1549
                        // Registers used as register parameters cannot be coalesced.
1550
                        if (IsArgumentReg(reg1) || IsArgumentReg(reg2))
1551
                                continue;
1552
                        // Remove the move instruction
1553
                        MarkRemove(ip);
1554
                }
1555
        }
1556
        if (!foundMove)
1557
                dfs.printf("No move instruction joins live ranges.\n");
1558
}
1559
 
1560
// Remove useless code where there are no output links from the basic block.
1561
 
1562
void RemoveCode()
1563
{
1564
        int nn,mm;
1565
        Var *v;
1566
        Tree *t;
1567
        OCODE *p;
1568
        int count;
1569
        int rg1, rg2;
1570
 
1571
        count = 0;
1572
        //printf((char *)currentFn->name->c_str());
1573
        //printf("\r\n");
1574
        for (v = currentFn->varlist; v; v = v->next) {
1575
                if (IsCalleeSave(v->num))
1576
                        continue;
1577
                if (v->num < 5 || v->num==regLR || v->num==regXLR)
1578
                        continue;
1579
                for (mm = 0; mm < v->trees.treecount; mm++) {
1580
                        t = v->trees.trees[mm];
1581
                        nn = t->blocks->lastMember();
1582
                        do {
1583
                                for (p = basicBlocks[nn]->lcode; p && !p->leader; p = p->back) {
1584
                                        if (p->opcode==op_label)
1585
                                                continue;
1586
                                        if (p->opcode==op_ret)
1587
                                                continue;
1588
                                        p->GetTargetReg(&rg1, &rg2);
1589
                                        if (rg1 == v->num && rg2==0) {
1590
                                                if (p->bb->ohead==nullptr) {
1591
                                                        MarkRemove2(p);
1592
                                                        count++;
1593
                                                }
1594
                                        }
1595
                                        if (!p->remove && p->HasSourceReg(v->num))
1596
                                                goto j1;
1597
                                }
1598
                        } while((nn = t->blocks->prevMember()) >= 0);
1599
j1:     ;
1600
                }
1601
                //Remove2();
1602
        }
1603
        dfs.printf("<CodeRemove>%d</CodeRemove>\n", count);
1604
}
1605
 
1606
 
1607
void PrintPeepList()
1608
{
1609
        OCODE *ip;
1610
        Instruction *insn;
1611
 
1612
        return;
1613
        for (ip = peep_head; ip; ip = ip->fwd) {
1614
                if (ip == currentFn->rcode)
1615
                        dfs.printf("***rcode***");
1616
                insn = GetInsn(ip->opcode);
1617
                if (insn)
1618
                        dfs.printf("%s ", insn->mnem);
1619
                else if (ip->opcode == op_label)
1620
                        dfs.printf("%s%d:", (char *)ip->oper2, (int)ip->oper1);
1621
                else
1622
                        dfs.printf("op(%d)", ip->opcode);
1623
                if (ip->bb)
1624
                        dfs.printf("bb:%d\n", ip->bb->num);
1625
                else
1626
                        dfs.printf("bb nul\n");
1627
        }
1628
}
1629
 

powered by: WebSVN 2.1.0

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