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