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