LLVM API Documentation
00001 //===-- AlphaLLRP.cpp - Alpha Load Load Replay Trap elimination pass. -- --===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // Here we check for potential replay traps introduced by the spiller 00011 // We also align some branch targets if we can do so for free. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #define DEBUG_TYPE "alpha-nops" 00016 #include "Alpha.h" 00017 #include "llvm/CodeGen/MachineFunctionPass.h" 00018 #include "llvm/CodeGen/MachineInstrBuilder.h" 00019 #include "llvm/Target/TargetMachine.h" 00020 #include "llvm/Target/TargetInstrInfo.h" 00021 #include "llvm/ADT/SetOperations.h" 00022 #include "llvm/ADT/Statistic.h" 00023 #include "llvm/Support/CommandLine.h" 00024 using namespace llvm; 00025 00026 STATISTIC(nopintro, "Number of nops inserted"); 00027 STATISTIC(nopalign, "Number of nops inserted for alignment"); 00028 00029 namespace { 00030 cl::opt<bool> 00031 AlignAll("alpha-align-all", cl::Hidden, 00032 cl::desc("Align all blocks")); 00033 00034 struct AlphaLLRPPass : public MachineFunctionPass { 00035 /// Target machine description which we query for reg. names, data 00036 /// layout, etc. 00037 /// 00038 AlphaTargetMachine &TM; 00039 00040 static char ID; 00041 AlphaLLRPPass(AlphaTargetMachine &tm) 00042 : MachineFunctionPass(&ID), TM(tm) { } 00043 00044 virtual const char *getPassName() const { 00045 return "Alpha NOP inserter"; 00046 } 00047 00048 bool runOnMachineFunction(MachineFunction &F) { 00049 const TargetInstrInfo *TII = F.getTarget().getInstrInfo(); 00050 bool Changed = false; 00051 MachineInstr* prev[3] = {0,0,0}; 00052 unsigned count = 0; 00053 for (MachineFunction::iterator FI = F.begin(), FE = F.end(); 00054 FI != FE; ++FI) { 00055 MachineBasicBlock& MBB = *FI; 00056 bool ub = false; 00057 for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) { 00058 if (count%4 == 0) 00059 prev[0] = prev[1] = prev[2] = 0; //Slots cleared at fetch boundary 00060 ++count; 00061 MachineInstr *MI = I++; 00062 switch (MI->getOpcode()) { 00063 case Alpha::LDQ: case Alpha::LDL: 00064 case Alpha::LDWU: case Alpha::LDBU: 00065 case Alpha::LDT: case Alpha::LDS: 00066 case Alpha::STQ: case Alpha::STL: 00067 case Alpha::STW: case Alpha::STB: 00068 case Alpha::STT: case Alpha::STS: 00069 if (MI->getOperand(2).getReg() == Alpha::R30) { 00070 if (prev[0] && 00071 prev[0]->getOperand(2).getReg() == MI->getOperand(2).getReg()&& 00072 prev[0]->getOperand(1).getImm() == MI->getOperand(1).getImm()){ 00073 prev[0] = prev[1]; 00074 prev[1] = prev[2]; 00075 prev[2] = 0; 00076 BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31) 00077 .addReg(Alpha::R31) 00078 .addReg(Alpha::R31); 00079 Changed = true; nopintro += 1; 00080 count += 1; 00081 } else if (prev[1] 00082 && prev[1]->getOperand(2).getReg() == 00083 MI->getOperand(2).getReg() 00084 && prev[1]->getOperand(1).getImm() == 00085 MI->getOperand(1).getImm()) { 00086 prev[0] = prev[2]; 00087 prev[1] = prev[2] = 0; 00088 BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31) 00089 .addReg(Alpha::R31) 00090 .addReg(Alpha::R31); 00091 BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31) 00092 .addReg(Alpha::R31) 00093 .addReg(Alpha::R31); 00094 Changed = true; nopintro += 2; 00095 count += 2; 00096 } else if (prev[2] 00097 && prev[2]->getOperand(2).getReg() == 00098 MI->getOperand(2).getReg() 00099 && prev[2]->getOperand(1).getImm() == 00100 MI->getOperand(1).getImm()) { 00101 prev[0] = prev[1] = prev[2] = 0; 00102 BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31).addReg(Alpha::R31) 00103 .addReg(Alpha::R31); 00104 BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31).addReg(Alpha::R31) 00105 .addReg(Alpha::R31); 00106 BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31).addReg(Alpha::R31) 00107 .addReg(Alpha::R31); 00108 Changed = true; nopintro += 3; 00109 count += 3; 00110 } 00111 prev[0] = prev[1]; 00112 prev[1] = prev[2]; 00113 prev[2] = MI; 00114 break; 00115 } 00116 prev[0] = prev[1]; 00117 prev[1] = prev[2]; 00118 prev[2] = 0; 00119 break; 00120 case Alpha::ALTENT: 00121 case Alpha::MEMLABEL: 00122 case Alpha::PCLABEL: 00123 --count; 00124 break; 00125 case Alpha::BR: 00126 case Alpha::JMP: 00127 ub = true; 00128 //fall through 00129 default: 00130 prev[0] = prev[1]; 00131 prev[1] = prev[2]; 00132 prev[2] = 0; 00133 break; 00134 } 00135 } 00136 if (ub || AlignAll) { 00137 //we can align stuff for free at this point 00138 while (count % 4) { 00139 BuildMI(MBB, MBB.end(), TII->get(Alpha::BISr), Alpha::R31) 00140 .addReg(Alpha::R31).addReg(Alpha::R31); 00141 ++count; 00142 ++nopalign; 00143 prev[0] = prev[1]; 00144 prev[1] = prev[2]; 00145 prev[2] = 0; 00146 } 00147 } 00148 } 00149 return Changed; 00150 } 00151 }; 00152 char AlphaLLRPPass::ID = 0; 00153 } // end of anonymous namespace 00154 00155 FunctionPass *llvm::createAlphaLLRPPass(AlphaTargetMachine &tm) { 00156 return new AlphaLLRPPass(tm); 00157 }