1 //===------ LeonPasses.cpp - Define passes specific to LEON ---------------===// 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 // 11 //===----------------------------------------------------------------------===// 12 13 #include "LeonPasses.h" 14 #include "llvm/CodeGen/ISDOpcodes.h" 15 #include "llvm/CodeGen/MachineFunction.h" 16 #include "llvm/CodeGen/MachineInstr.h" 17 #include "llvm/CodeGen/MachineInstrBuilder.h" 18 #include "llvm/CodeGen/MachineRegisterInfo.h" 19 #include "llvm/IR/LLVMContext.h" 20 #include "llvm/Support/raw_ostream.h" 21 using namespace llvm; 22 23 LEONMachineFunctionPass::LEONMachineFunctionPass(TargetMachine &tm, char &ID) 24 : MachineFunctionPass(ID) {} 25 26 LEONMachineFunctionPass::LEONMachineFunctionPass(char &ID) 27 : MachineFunctionPass(ID) {} 28 29 int LEONMachineFunctionPass::GetRegIndexForOperand(MachineInstr &MI, 30 int OperandIndex) { 31 if (MI.getNumOperands() > 0) { 32 if (OperandIndex == LAST_OPERAND) { 33 OperandIndex = MI.getNumOperands() - 1; 34 } 35 36 if (MI.getNumOperands() > (unsigned)OperandIndex && 37 MI.getOperand(OperandIndex).isReg()) { 38 return (int)MI.getOperand(OperandIndex).getReg(); 39 } 40 } 41 42 static int NotFoundIndex = -10; 43 // Return a different number each time to avoid any comparisons between the 44 // values returned. 45 NotFoundIndex -= 10; 46 return NotFoundIndex; 47 } 48 49 // finds a new free FP register 50 // checks also the AllocatedRegisters vector 51 int LEONMachineFunctionPass::getUnusedFPRegister(MachineRegisterInfo &MRI) { 52 for (int RegisterIndex = SP::F0; RegisterIndex <= SP::F31; ++RegisterIndex) { 53 if (!MRI.isPhysRegUsed(RegisterIndex) && 54 !is_contained(UsedRegisters, RegisterIndex)) { 55 return RegisterIndex; 56 } 57 } 58 59 return -1; 60 } 61 62 //***************************************************************************** 63 //**** InsertNOPLoad pass 64 //***************************************************************************** 65 // This pass fixes the incorrectly working Load instructions that exists for 66 // some earlier versions of the LEON processor line. NOP instructions must 67 // be inserted after the load instruction to ensure that the Load instruction 68 // behaves as expected for these processors. 69 // 70 // This pass inserts a NOP after any LD or LDF instruction. 71 // 72 char InsertNOPLoad::ID = 0; 73 74 InsertNOPLoad::InsertNOPLoad(TargetMachine &tm) 75 : LEONMachineFunctionPass(tm, ID) {} 76 77 bool InsertNOPLoad::runOnMachineFunction(MachineFunction &MF) { 78 Subtarget = &MF.getSubtarget<SparcSubtarget>(); 79 const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 80 DebugLoc DL = DebugLoc(); 81 82 bool Modified = false; 83 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 84 MachineBasicBlock &MBB = *MFI; 85 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 86 MachineInstr &MI = *MBBI; 87 unsigned Opcode = MI.getOpcode(); 88 if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) { 89 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 90 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); 91 Modified = true; 92 } 93 } 94 } 95 96 return Modified; 97 } 98 99 //***************************************************************************** 100 //**** FixFSMULD pass 101 //***************************************************************************** 102 // This pass fixes the incorrectly working FSMULD instruction that exists for 103 // some earlier versions of the LEON processor line. 104 // 105 // The pass should convert the FSMULD operands to double precision in scratch 106 // registers, then calculate the result with the FMULD instruction. Therefore, 107 // the pass should replace operations of the form: 108 // fsmuld %f20,%f21,%f8 109 // with the sequence: 110 // fstod %f20,%f0 111 // fstod %f21,%f2 112 // fmuld %f0,%f2,%f8 113 // 114 char FixFSMULD::ID = 0; 115 116 FixFSMULD::FixFSMULD(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {} 117 118 bool FixFSMULD::runOnMachineFunction(MachineFunction &MF) { 119 Subtarget = &MF.getSubtarget<SparcSubtarget>(); 120 const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 121 DebugLoc DL = DebugLoc(); 122 123 bool Modified = false; 124 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 125 MachineBasicBlock &MBB = *MFI; 126 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 127 128 MachineInstr &MI = *MBBI; 129 unsigned Opcode = MI.getOpcode(); 130 131 const int UNASSIGNED_INDEX = -1; 132 int Reg1Index = UNASSIGNED_INDEX; 133 int Reg2Index = UNASSIGNED_INDEX; 134 int Reg3Index = UNASSIGNED_INDEX; 135 136 if (Opcode == SP::FSMULD && MI.getNumOperands() == 3) { 137 // take the registers from fsmuld %f20,%f21,%f8 138 Reg1Index = MI.getOperand(0).getReg(); 139 Reg2Index = MI.getOperand(1).getReg(); 140 Reg3Index = MI.getOperand(2).getReg(); 141 } 142 143 if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX && 144 Reg3Index != UNASSIGNED_INDEX) { 145 clearUsedRegisterList(); 146 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 147 // Whatever Reg3Index is hasn't been used yet, so we need to reserve it. 148 markRegisterUsed(Reg3Index); 149 const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo()); 150 markRegisterUsed(ScratchReg1Index); 151 const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo()); 152 markRegisterUsed(ScratchReg2Index); 153 154 if (ScratchReg1Index == UNASSIGNED_INDEX || 155 ScratchReg2Index == UNASSIGNED_INDEX) { 156 errs() << "Cannot allocate free scratch registers for the FixFSMULD " 157 "pass." 158 << "\n"; 159 } else { 160 // create fstod %f20,%f0 161 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD)) 162 .addReg(ScratchReg1Index) 163 .addReg(Reg1Index); 164 165 // create fstod %f21,%f2 166 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD)) 167 .addReg(ScratchReg2Index) 168 .addReg(Reg2Index); 169 170 // create fmuld %f0,%f2,%f8 171 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD)) 172 .addReg(Reg3Index) 173 .addReg(ScratchReg1Index) 174 .addReg(ScratchReg2Index); 175 176 MI.eraseFromParent(); 177 MBBI = NMBBI; 178 179 Modified = true; 180 } 181 } 182 } 183 } 184 185 return Modified; 186 } 187 188 //***************************************************************************** 189 //**** ReplaceFMULS pass 190 //***************************************************************************** 191 // This pass fixes the incorrectly working FMULS instruction that exists for 192 // some earlier versions of the LEON processor line. 193 // 194 // This pass converts the FMULS operands to double precision in scratch 195 // registers, then calculates the result with the FMULD instruction. 196 // The pass should replace operations of the form: 197 // fmuls %f20,%f21,%f8 198 // with the sequence: 199 // fstod %f20,%f0 200 // fstod %f21,%f2 201 // fmuld %f0,%f2,%f8 202 // 203 char ReplaceFMULS::ID = 0; 204 205 ReplaceFMULS::ReplaceFMULS(TargetMachine &tm) 206 : LEONMachineFunctionPass(tm, ID) {} 207 208 bool ReplaceFMULS::runOnMachineFunction(MachineFunction &MF) { 209 Subtarget = &MF.getSubtarget<SparcSubtarget>(); 210 const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 211 DebugLoc DL = DebugLoc(); 212 213 bool Modified = false; 214 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 215 MachineBasicBlock &MBB = *MFI; 216 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 217 MachineInstr &MI = *MBBI; 218 unsigned Opcode = MI.getOpcode(); 219 220 const int UNASSIGNED_INDEX = -1; 221 int Reg1Index = UNASSIGNED_INDEX; 222 int Reg2Index = UNASSIGNED_INDEX; 223 int Reg3Index = UNASSIGNED_INDEX; 224 225 if (Opcode == SP::FMULS && MI.getNumOperands() == 3) { 226 // take the registers from fmuls %f20,%f21,%f8 227 Reg1Index = MI.getOperand(0).getReg(); 228 Reg2Index = MI.getOperand(1).getReg(); 229 Reg3Index = MI.getOperand(2).getReg(); 230 } 231 232 if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX && 233 Reg3Index != UNASSIGNED_INDEX) { 234 clearUsedRegisterList(); 235 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 236 // Whatever Reg3Index is hasn't been used yet, so we need to reserve it. 237 markRegisterUsed(Reg3Index); 238 const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo()); 239 markRegisterUsed(ScratchReg1Index); 240 const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo()); 241 markRegisterUsed(ScratchReg2Index); 242 243 if (ScratchReg1Index == UNASSIGNED_INDEX || 244 ScratchReg2Index == UNASSIGNED_INDEX) { 245 errs() << "Cannot allocate free scratch registers for the " 246 "ReplaceFMULS pass." 247 << "\n"; 248 } else { 249 // create fstod %f20,%f0 250 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD)) 251 .addReg(ScratchReg1Index) 252 .addReg(Reg1Index); 253 254 // create fstod %f21,%f2 255 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD)) 256 .addReg(ScratchReg2Index) 257 .addReg(Reg2Index); 258 259 // create fmuld %f0,%f2,%f8 260 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD)) 261 .addReg(Reg3Index) 262 .addReg(ScratchReg1Index) 263 .addReg(ScratchReg2Index); 264 265 MI.eraseFromParent(); 266 MBBI = NMBBI; 267 268 Modified = true; 269 } 270 } 271 } 272 } 273 274 return Modified; 275 } 276 277 //***************************************************************************** 278 //**** FixAllFDIVSQRT pass 279 //***************************************************************************** 280 // This pass fixes the incorrectly working FDIVx and FSQRTx instructions that 281 // exist for some earlier versions of the LEON processor line. Five NOP 282 // instructions need to be inserted after these instructions to ensure the 283 // correct result is placed in the destination registers before they are used. 284 // 285 // This pass implements two fixes: 286 // 1) fixing the FSQRTS and FSQRTD instructions. 287 // 2) fixing the FDIVS and FDIVD instructions. 288 // 289 // FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in 290 // the pipeline when this option is enabled, so this pass needs only to deal 291 // with the changes that still need implementing for the "double" versions 292 // of these instructions. 293 // 294 char FixAllFDIVSQRT::ID = 0; 295 296 FixAllFDIVSQRT::FixAllFDIVSQRT(TargetMachine &tm) 297 : LEONMachineFunctionPass(tm, ID) {} 298 299 bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) { 300 Subtarget = &MF.getSubtarget<SparcSubtarget>(); 301 const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 302 DebugLoc DL = DebugLoc(); 303 304 bool Modified = false; 305 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 306 MachineBasicBlock &MBB = *MFI; 307 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 308 MachineInstr &MI = *MBBI; 309 unsigned Opcode = MI.getOpcode(); 310 311 // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is 312 // switched on so we don't need to check for them here. They will 313 // already have been converted to FSQRTD or FDIVD earlier in the 314 // pipeline. 315 if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) { 316 for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++) 317 BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 318 319 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 320 for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++) 321 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); 322 323 Modified = true; 324 } 325 } 326 } 327 328 return Modified; 329 } 330