Patch up omissions in DebugLoc propagation.
[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(&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() == MI->getOperand(2).getReg()&&
72                  prev[0]->getOperand(1).getImm() == MI->getOperand(1).getImm()){
73                prev[0] = prev[1];
74                prev[1] = prev[2];
75                prev[2] = 0;
76                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31)
77                  .addReg(Alpha::R31)
78                  .addReg(Alpha::R31); 
79                Changed = true; nopintro += 1;
80                count += 1;
81              } else if (prev[1] 
82                         && prev[1]->getOperand(2).getReg() == 
83                         MI->getOperand(2).getReg()
84                         && prev[1]->getOperand(1).getImm() == 
85                         MI->getOperand(1).getImm()) {
86                prev[0] = prev[2];
87                prev[1] = prev[2] = 0;
88                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31)
89                  .addReg(Alpha::R31)
90                  .addReg(Alpha::R31); 
91                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31)
92                  .addReg(Alpha::R31)
93                  .addReg(Alpha::R31);
94                Changed = true; nopintro += 2;
95                count += 2;
96              } else if (prev[2] 
97                         && prev[2]->getOperand(2).getReg() == 
98                         MI->getOperand(2).getReg()
99                         && prev[2]->getOperand(1).getImm() == 
100                         MI->getOperand(1).getImm()) {
101                prev[0] = prev[1] = prev[2] = 0;
102                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31).addReg(Alpha::R31)
103                  .addReg(Alpha::R31);
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                Changed = true; nopintro += 3;
109                count += 3;
110              }
111              prev[0] = prev[1];
112              prev[1] = prev[2];
113              prev[2] = MI;
114              break;
115            }
116            prev[0] = prev[1];
117            prev[1] = prev[2];
118            prev[2] = 0;
119            break;
120           case Alpha::ALTENT:
121           case Alpha::MEMLABEL:
122           case Alpha::PCLABEL:
123             --count;
124             break;
125           case Alpha::BR:
126           case Alpha::JMP:
127             ub = true;
128             //fall through
129           default:
130             prev[0] = prev[1];
131             prev[1] = prev[2];
132             prev[2] = 0;
133             break;
134           }
135         }
136         if (ub || AlignAll) {
137           //we can align stuff for free at this point
138           while (count % 4) {
139             BuildMI(MBB, MBB.end(), TII->get(Alpha::BISr), Alpha::R31)
140               .addReg(Alpha::R31).addReg(Alpha::R31);
141             ++count;
142             ++nopalign;
143             prev[0] = prev[1];
144             prev[1] = prev[2];
145             prev[2] = 0;
146           }
147         }
148       }
149       return Changed;
150     }
151   };
152   char AlphaLLRPPass::ID = 0;
153 } // end of anonymous namespace
154
155 FunctionPass *llvm::createAlphaLLRPPass(AlphaTargetMachine &tm) {
156   return new AlphaLLRPPass(tm);
157 }