Remove attribution from file headers, per discussion on llvmdev.
[oota-llvm.git] / lib / Target / Alpha / AlphaLLRP.cpp
1 //===-- AlphaLLRP.cpp - Alpha Load Load Replay Trap elimination pass. -- --===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Here we check for potential replay traps introduced by the spiller
11 // We also align some branch targets if we can do so for free.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #define DEBUG_TYPE "alpha-nops"
16 #include "Alpha.h"
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/Target/TargetMachine.h"
20 #include "llvm/Target/TargetInstrInfo.h"
21 #include "llvm/ADT/SetOperations.h"
22 #include "llvm/ADT/Statistic.h"
23 #include "llvm/Support/CommandLine.h"
24 using namespace llvm;
25
26 STATISTIC(nopintro, "Number of nops inserted");
27 STATISTIC(nopalign, "Number of nops inserted for alignment");
28
29 namespace {
30   cl::opt<bool>
31   AlignAll("alpha-align-all", cl::Hidden,
32                    cl::desc("Align all blocks"));
33
34   struct AlphaLLRPPass : public MachineFunctionPass {
35     /// Target machine description which we query for reg. names, data
36     /// layout, etc.
37     ///
38     AlphaTargetMachine &TM;
39
40     static char ID;
41     AlphaLLRPPass(AlphaTargetMachine &tm) 
42       : MachineFunctionPass((intptr_t)&ID), TM(tm) { }
43
44     virtual const char *getPassName() const {
45       return "Alpha NOP inserter";
46     }
47
48     bool runOnMachineFunction(MachineFunction &F) {
49       const TargetInstrInfo *TII = F.getTarget().getInstrInfo();
50       bool Changed = false;
51       MachineInstr* prev[3] = {0,0,0};
52       unsigned count = 0;
53       for (MachineFunction::iterator FI = F.begin(), FE = F.end();
54            FI != FE; ++FI) {
55         MachineBasicBlock& MBB = *FI;
56         bool ub = false;
57         for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) {
58           if (count%4 == 0)
59             prev[0] = prev[1] = prev[2] = 0; //Slots cleared at fetch boundary
60           ++count;
61           MachineInstr *MI = I++;
62           switch (MI->getOpcode()) {
63           case Alpha::LDQ:  case Alpha::LDL:
64           case Alpha::LDWU: case Alpha::LDBU:
65           case Alpha::LDT: case Alpha::LDS:
66           case Alpha::STQ:  case Alpha::STL:
67           case Alpha::STW:  case Alpha::STB:
68           case Alpha::STT: case Alpha::STS:
69            if (MI->getOperand(2).getReg() == Alpha::R30) {
70              if (prev[0] 
71                  && prev[0]->getOperand(2).getReg() == 
72                  MI->getOperand(2).getReg()
73                  && prev[0]->getOperand(1).getImmedValue() == 
74                  MI->getOperand(1).getImmedValue()) {
75                prev[0] = prev[1];
76                prev[1] = prev[2];
77                prev[2] = 0;
78                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31)
79                  .addReg(Alpha::R31)
80                  .addReg(Alpha::R31); 
81                Changed = true; nopintro += 1;
82                count += 1;
83              } else if (prev[1] 
84                         && prev[1]->getOperand(2).getReg() == 
85                         MI->getOperand(2).getReg()
86                         && prev[1]->getOperand(1).getImmedValue() == 
87                         MI->getOperand(1).getImmedValue()) {
88                prev[0] = prev[2];
89                prev[1] = prev[2] = 0;
90                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31)
91                  .addReg(Alpha::R31)
92                  .addReg(Alpha::R31); 
93                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31)
94                  .addReg(Alpha::R31)
95                  .addReg(Alpha::R31);
96                Changed = true; nopintro += 2;
97                count += 2;
98              } else if (prev[2] 
99                         && prev[2]->getOperand(2).getReg() == 
100                         MI->getOperand(2).getReg()
101                         && prev[2]->getOperand(1).getImmedValue() == 
102                         MI->getOperand(1).getImmedValue()) {
103                prev[0] = prev[1] = prev[2] = 0;
104                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31).addReg(Alpha::R31)
105                  .addReg(Alpha::R31);
106                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31).addReg(Alpha::R31)
107                  .addReg(Alpha::R31);
108                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31).addReg(Alpha::R31)
109                  .addReg(Alpha::R31);
110                Changed = true; nopintro += 3;
111                count += 3;
112              }
113              prev[0] = prev[1];
114              prev[1] = prev[2];
115              prev[2] = MI;
116              break;
117            }
118            prev[0] = prev[1];
119            prev[1] = prev[2];
120            prev[2] = 0;
121            break;
122           case Alpha::ALTENT:
123           case Alpha::MEMLABEL:
124           case Alpha::PCLABEL:
125           case Alpha::IDEF_I:
126           case Alpha::IDEF_F32:
127           case Alpha::IDEF_F64:
128             --count;
129             break;
130           case Alpha::BR:
131           case Alpha::JMP:
132             ub = true;
133             //fall through
134           default:
135             prev[0] = prev[1];
136             prev[1] = prev[2];
137             prev[2] = 0;
138             break;
139           }
140         }
141         if (ub || AlignAll) {
142           //we can align stuff for free at this point
143           while (count % 4) {
144             BuildMI(MBB, MBB.end(), TII->get(Alpha::BISr), Alpha::R31)
145               .addReg(Alpha::R31).addReg(Alpha::R31);
146             ++count;
147             ++nopalign;
148             prev[0] = prev[1];
149             prev[1] = prev[2];
150             prev[2] = 0;
151           }
152         }
153       }
154       return Changed;
155     }
156   };
157   char AlphaLLRPPass::ID = 0;
158 } // end of anonymous namespace
159
160 FunctionPass *llvm::createAlphaLLRPPass(AlphaTargetMachine &tm) {
161   return new AlphaLLRPPass(tm);
162 }