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 } 159