Merge branch 'master' into msp430
[llvm/msp430.git] / lib / Target / Alpha / AlphaLLRP.cpp
blob0c51bc554be949e8d2893577a3a1acf436115f11
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.
13 //===----------------------------------------------------------------------===//
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;
26 STATISTIC(nopintro, "Number of nops inserted");
27 STATISTIC(nopalign, "Number of nops inserted for alignment");
29 namespace {
30 cl::opt<bool>
31 AlignAll("alpha-align-all", cl::Hidden,
32 cl::desc("Align all blocks"));
34 struct AlphaLLRPPass : public MachineFunctionPass {
35 /// Target machine description which we query for reg. names, data
36 /// layout, etc.
37 ///
38 AlphaTargetMachine &TM;
40 static char ID;
41 AlphaLLRPPass(AlphaTargetMachine &tm)
42 : MachineFunctionPass(&ID), TM(tm) { }
44 virtual const char *getPassName() const {
45 return "Alpha NOP inserter";
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 = DebugLoc::getUnknownLoc();
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;
112 prev[0] = prev[1];
113 prev[1] = prev[2];
114 prev[2] = MI;
115 break;
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;
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;
150 return Changed;
153 char AlphaLLRPPass::ID = 0;
154 } // end of anonymous namespace
156 FunctionPass *llvm::createAlphaLLRPPass(AlphaTargetMachine &tm) {
157 return new AlphaLLRPPass(tm);