Revert r110396 to fix buildbots.
[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       DebugLoc dl;
53       unsigned count = 0;
54       for (MachineFunction::iterator FI = F.begin(), FE = F.end();
55            FI != FE; ++FI) {
56         MachineBasicBlock& MBB = *FI;
57         bool ub = false;
58         for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) {
59           if (count%4 == 0)
60             prev[0] = prev[1] = prev[2] = 0; //Slots cleared at fetch boundary
61           ++count;
62           MachineInstr *MI = I++;
63           switch (MI->getOpcode()) {
64           case Alpha::LDQ:  case Alpha::LDL:
65           case Alpha::LDWU: case Alpha::LDBU:
66           case Alpha::LDT: case Alpha::LDS:
67           case Alpha::STQ:  case Alpha::STL:
68           case Alpha::STW:  case Alpha::STB:
69           case Alpha::STT: case Alpha::STS:
70            if (MI->getOperand(2).getReg() == Alpha::R30) {
71              if (prev[0] && 
72                  prev[0]->getOperand(2).getReg() == MI->getOperand(2).getReg()&&
73                  prev[0]->getOperand(1).getImm() == MI->getOperand(1).getImm()){
74                prev[0] = prev[1];
75                prev[1] = prev[2];
76                prev[2] = 0;
77                BuildMI(MBB, MI, dl, TII->get(Alpha::BISr), Alpha::R31)
78                  .addReg(Alpha::R31)
79                  .addReg(Alpha::R31); 
80                Changed = true; nopintro += 1;
81                count += 1;
82              } else if (prev[1] 
83                         && prev[1]->getOperand(2).getReg() == 
84                         MI->getOperand(2).getReg()
85                         && prev[1]->getOperand(1).getImm() == 
86                         MI->getOperand(1).getImm()) {
87                prev[0] = prev[2];
88                prev[1] = prev[2] = 0;
89                BuildMI(MBB, MI, dl, TII->get(Alpha::BISr), Alpha::R31)
90                  .addReg(Alpha::R31)
91                  .addReg(Alpha::R31); 
92                BuildMI(MBB, MI, dl, TII->get(Alpha::BISr), Alpha::R31)
93                  .addReg(Alpha::R31)
94                  .addReg(Alpha::R31);
95                Changed = true; nopintro += 2;
96                count += 2;
97              } else if (prev[2] 
98                         && prev[2]->getOperand(2).getReg() == 
99                         MI->getOperand(2).getReg()
100                         && prev[2]->getOperand(1).getImm() == 
101                         MI->getOperand(1).getImm()) {
102                prev[0] = prev[1] = prev[2] = 0;
103                BuildMI(MBB, MI, dl, TII->get(Alpha::BISr), Alpha::R31)
104                  .addReg(Alpha::R31).addReg(Alpha::R31);
105                BuildMI(MBB, MI, dl, TII->get(Alpha::BISr), Alpha::R31)
106                  .addReg(Alpha::R31).addReg(Alpha::R31);
107                BuildMI(MBB, MI, dl, TII->get(Alpha::BISr), Alpha::R31)
108                  .addReg(Alpha::R31).addReg(Alpha::R31);
109                Changed = true; nopintro += 3;
110                count += 3;
111              }
112              prev[0] = prev[1];
113              prev[1] = prev[2];
114              prev[2] = MI;
115              break;
116            }
117            prev[0] = prev[1];
118            prev[1] = prev[2];
119            prev[2] = 0;
120            break;
121           case Alpha::ALTENT:
122           case Alpha::MEMLABEL:
123           case Alpha::PCLABEL:
124             --count;
125             break;
126           case Alpha::BR:
127           case Alpha::JMP:
128             ub = true;
129             //fall through
130           default:
131             prev[0] = prev[1];
132             prev[1] = prev[2];
133             prev[2] = 0;
134             break;
135           }
136         }
137         if (ub || AlignAll) {
138           //we can align stuff for free at this point
139           while (count % 4) {
140             BuildMI(MBB, MBB.end(), dl, TII->get(Alpha::BISr), Alpha::R31)
141               .addReg(Alpha::R31).addReg(Alpha::R31);
142             ++count;
143             ++nopalign;
144             prev[0] = prev[1];
145             prev[1] = prev[2];
146             prev[2] = 0;
147           }
148         }
149       }
150       return Changed;
151     }
152   };
153   char AlphaLLRPPass::ID = 0;
154 } // end of anonymous namespace
155
156 FunctionPass *llvm::createAlphaLLRPPass(AlphaTargetMachine &tm) {
157   return new AlphaLLRPPass(tm);
158 }