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 !(std::find(UsedRegisters.begin(), UsedRegisters.end(), 55 RegisterIndex) != UsedRegisters.end())) { 56 return RegisterIndex; 57 } 58 } 59 60 return -1; 61 } 62 63 //***************************************************************************** 64 //**** InsertNOPLoad pass 65 //***************************************************************************** 66 // This pass fixes the incorrectly working Load instructions that exists for 67 // some earlier versions of the LEON processor line. NOP instructions must 68 // be inserted after the load instruction to ensure that the Load instruction 69 // behaves as expected for these processors. 70 // 71 // This pass inserts a NOP after any LD or LDF instruction. 72 // 73 char InsertNOPLoad::ID = 0; 74 75 InsertNOPLoad::InsertNOPLoad(TargetMachine &tm) 76 : LEONMachineFunctionPass(tm, ID) {} 77 78 bool InsertNOPLoad::runOnMachineFunction(MachineFunction &MF) { 79 Subtarget = &MF.getSubtarget<SparcSubtarget>(); 80 const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 81 DebugLoc DL = DebugLoc(); 82 83 bool Modified = false; 84 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 85 MachineBasicBlock &MBB = *MFI; 86 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 87 MachineInstr &MI = *MBBI; 88 unsigned Opcode = MI.getOpcode(); 89 if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) { 90 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 91 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); 92 Modified = true; 93 } else if (MI.isInlineAsm()) { 94 // Look for an inline ld or ldf instruction. 95 StringRef AsmString = 96 MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); 97 if (AsmString.startswith_lower("ld")) { 98 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 99 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); 100 Modified = true; 101 } 102 } 103 } 104 } 105 106 return Modified; 107 } 108 109 //***************************************************************************** 110 //**** FixFSMULD pass 111 //***************************************************************************** 112 // This pass fixes the incorrectly working FSMULD instruction that exists for 113 // some earlier versions of the LEON processor line. 114 // 115 // The pass should convert the FSMULD operands to double precision in scratch 116 // registers, then calculate the result with the FMULD instruction. Therefore, 117 // the pass should replace operations of the form: 118 // fsmuld %f20,%f21,%f8 119 // with the sequence: 120 // fstod %f20,%f0 121 // fstod %f21,%f2 122 // fmuld %f0,%f2,%f8 123 // 124 char FixFSMULD::ID = 0; 125 126 FixFSMULD::FixFSMULD(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {} 127 128 bool FixFSMULD::runOnMachineFunction(MachineFunction &MF) { 129 Subtarget = &MF.getSubtarget<SparcSubtarget>(); 130 const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 131 DebugLoc DL = DebugLoc(); 132 133 bool Modified = false; 134 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 135 MachineBasicBlock &MBB = *MFI; 136 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 137 138 MachineInstr &MI = *MBBI; 139 unsigned Opcode = MI.getOpcode(); 140 141 const int UNASSIGNED_INDEX = -1; 142 int Reg1Index = UNASSIGNED_INDEX; 143 int Reg2Index = UNASSIGNED_INDEX; 144 int Reg3Index = UNASSIGNED_INDEX; 145 146 if (Opcode == SP::FSMULD && MI.getNumOperands() == 3) { 147 // take the registers from fsmuld %f20,%f21,%f8 148 Reg1Index = MI.getOperand(0).getReg(); 149 Reg2Index = MI.getOperand(1).getReg(); 150 Reg3Index = MI.getOperand(2).getReg(); 151 } else if (MI.isInlineAsm()) { 152 std::string AsmString( 153 MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName()); 154 std::string FMULSOpCoode("fsmuld"); 155 std::transform(AsmString.begin(), AsmString.end(), AsmString.begin(), 156 ::tolower); 157 if (AsmString.find(FMULSOpCoode) == 158 0) { // this is an inline FSMULD instruction 159 160 unsigned StartOp = InlineAsm::MIOp_FirstOperand; 161 162 // extracts the registers from the inline assembly instruction 163 for (unsigned i = StartOp, e = MI.getNumOperands(); i != e; ++i) { 164 const MachineOperand &MO = MI.getOperand(i); 165 if (MO.isReg()) { 166 if (Reg1Index == UNASSIGNED_INDEX) 167 Reg1Index = MO.getReg(); 168 else if (Reg2Index == UNASSIGNED_INDEX) 169 Reg2Index = MO.getReg(); 170 else if (Reg3Index == UNASSIGNED_INDEX) 171 Reg3Index = MO.getReg(); 172 } 173 if (Reg3Index != UNASSIGNED_INDEX) 174 break; 175 } 176 } 177 } 178 179 if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX && 180 Reg3Index != UNASSIGNED_INDEX) { 181 clearUsedRegisterList(); 182 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 183 // Whatever Reg3Index is hasn't been used yet, so we need to reserve it. 184 markRegisterUsed(Reg3Index); 185 const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo()); 186 markRegisterUsed(ScratchReg1Index); 187 const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo()); 188 markRegisterUsed(ScratchReg2Index); 189 190 if (ScratchReg1Index == UNASSIGNED_INDEX || 191 ScratchReg2Index == UNASSIGNED_INDEX) { 192 errs() << "Cannot allocate free scratch registers for the FixFSMULD " 193 "pass." 194 << "\n"; 195 } else { 196 // create fstod %f20,%f0 197 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD)) 198 .addReg(ScratchReg1Index) 199 .addReg(Reg1Index); 200 201 // create fstod %f21,%f2 202 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD)) 203 .addReg(ScratchReg2Index) 204 .addReg(Reg2Index); 205 206 // create fmuld %f0,%f2,%f8 207 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD)) 208 .addReg(Reg3Index) 209 .addReg(ScratchReg1Index) 210 .addReg(ScratchReg2Index); 211 212 MI.eraseFromParent(); 213 MBBI = NMBBI; 214 215 Modified = true; 216 } 217 } 218 } 219 } 220 221 return Modified; 222 } 223 224 //***************************************************************************** 225 //**** ReplaceFMULS pass 226 //***************************************************************************** 227 // This pass fixes the incorrectly working FMULS instruction that exists for 228 // some earlier versions of the LEON processor line. 229 // 230 // This pass converts the FMULS operands to double precision in scratch 231 // registers, then calculates the result with the FMULD instruction. 232 // The pass should replace operations of the form: 233 // fmuls %f20,%f21,%f8 234 // with the sequence: 235 // fstod %f20,%f0 236 // fstod %f21,%f2 237 // fmuld %f0,%f2,%f8 238 // 239 char ReplaceFMULS::ID = 0; 240 241 ReplaceFMULS::ReplaceFMULS(TargetMachine &tm) 242 : LEONMachineFunctionPass(tm, ID) {} 243 244 bool ReplaceFMULS::runOnMachineFunction(MachineFunction &MF) { 245 Subtarget = &MF.getSubtarget<SparcSubtarget>(); 246 const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 247 DebugLoc DL = DebugLoc(); 248 249 bool Modified = false; 250 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 251 MachineBasicBlock &MBB = *MFI; 252 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 253 MachineInstr &MI = *MBBI; 254 unsigned Opcode = MI.getOpcode(); 255 256 const int UNASSIGNED_INDEX = -1; 257 int Reg1Index = UNASSIGNED_INDEX; 258 int Reg2Index = UNASSIGNED_INDEX; 259 int Reg3Index = UNASSIGNED_INDEX; 260 261 if (Opcode == SP::FMULS && MI.getNumOperands() == 3) { 262 // take the registers from fmuls %f20,%f21,%f8 263 Reg1Index = MI.getOperand(0).getReg(); 264 Reg2Index = MI.getOperand(1).getReg(); 265 Reg3Index = MI.getOperand(2).getReg(); 266 } else if (MI.isInlineAsm()) { 267 std::string AsmString( 268 MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName()); 269 std::string FMULSOpCoode("fmuls"); 270 std::transform(AsmString.begin(), AsmString.end(), AsmString.begin(), 271 ::tolower); 272 if (AsmString.find(FMULSOpCoode) == 273 0) { // this is an inline FMULS instruction 274 unsigned StartOp = InlineAsm::MIOp_FirstOperand; 275 276 // extracts the registers from the inline assembly instruction 277 for (unsigned i = StartOp, e = MI.getNumOperands(); i != e; ++i) { 278 const MachineOperand &MO = MI.getOperand(i); 279 if (MO.isReg()) { 280 if (Reg1Index == UNASSIGNED_INDEX) 281 Reg1Index = MO.getReg(); 282 else if (Reg2Index == UNASSIGNED_INDEX) 283 Reg2Index = MO.getReg(); 284 else if (Reg3Index == UNASSIGNED_INDEX) 285 Reg3Index = MO.getReg(); 286 } 287 if (Reg3Index != UNASSIGNED_INDEX) 288 break; 289 } 290 } 291 } 292 293 if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX && 294 Reg3Index != UNASSIGNED_INDEX) { 295 clearUsedRegisterList(); 296 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 297 // Whatever Reg3Index is hasn't been used yet, so we need to reserve it. 298 markRegisterUsed(Reg3Index); 299 const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo()); 300 markRegisterUsed(ScratchReg1Index); 301 const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo()); 302 markRegisterUsed(ScratchReg2Index); 303 304 if (ScratchReg1Index == UNASSIGNED_INDEX || 305 ScratchReg2Index == UNASSIGNED_INDEX) { 306 errs() << "Cannot allocate free scratch registers for the " 307 "ReplaceFMULS pass." 308 << "\n"; 309 } else { 310 // create fstod %f20,%f0 311 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD)) 312 .addReg(ScratchReg1Index) 313 .addReg(Reg1Index); 314 315 // create fstod %f21,%f2 316 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD)) 317 .addReg(ScratchReg2Index) 318 .addReg(Reg2Index); 319 320 // create fmuld %f0,%f2,%f8 321 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD)) 322 .addReg(Reg3Index) 323 .addReg(ScratchReg1Index) 324 .addReg(ScratchReg2Index); 325 326 MI.eraseFromParent(); 327 MBBI = NMBBI; 328 329 Modified = true; 330 } 331 } 332 } 333 } 334 335 return Modified; 336 } 337 338 //***************************************************************************** 339 //**** FixAllFDIVSQRT pass 340 //***************************************************************************** 341 // This pass fixes the incorrectly working FDIVx and FSQRTx instructions that 342 // exist for some earlier versions of the LEON processor line. Five NOP 343 // instructions need to be inserted after these instructions to ensure the 344 // correct result is placed in the destination registers before they are used. 345 // 346 // This pass implements two fixes: 347 // 1) fixing the FSQRTS and FSQRTD instructions. 348 // 2) fixing the FDIVS and FDIVD instructions. 349 // 350 // FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in 351 // the pipeline when this option is enabled, so this pass needs only to deal 352 // with the changes that still need implementing for the "double" versions 353 // of these instructions. 354 // 355 char FixAllFDIVSQRT::ID = 0; 356 357 FixAllFDIVSQRT::FixAllFDIVSQRT(TargetMachine &tm) 358 : LEONMachineFunctionPass(tm, ID) {} 359 360 bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) { 361 Subtarget = &MF.getSubtarget<SparcSubtarget>(); 362 const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 363 DebugLoc DL = DebugLoc(); 364 365 bool Modified = false; 366 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 367 MachineBasicBlock &MBB = *MFI; 368 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 369 MachineInstr &MI = *MBBI; 370 unsigned Opcode = MI.getOpcode(); 371 372 if (MI.isInlineAsm()) { 373 std::string AsmString( 374 MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName()); 375 std::string FSQRTDOpCode("fsqrtd"); 376 std::string FDIVDOpCode("fdivd"); 377 std::transform(AsmString.begin(), AsmString.end(), AsmString.begin(), 378 ::tolower); 379 if (AsmString.find(FSQRTDOpCode) == 380 0) { // this is an inline fsqrts instruction 381 Opcode = SP::FSQRTD; 382 } else if (AsmString.find(FDIVDOpCode) == 383 0) { // this is an inline fsqrts instruction 384 Opcode = SP::FDIVD; 385 } 386 } 387 388 // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is 389 // switched on so we don't need to check for them here. They will 390 // already have been converted to FSQRTD or FDIVD earlier in the 391 // pipeline. 392 if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) { 393 for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++) 394 BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 395 396 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 397 for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++) 398 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); 399 400 Modified = true; 401 } 402 } 403 } 404 405 return Modified; 406 } 407