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 //***************************************************************************** 28 //**** InsertNOPLoad pass 29 //***************************************************************************** 30 // This pass fixes the incorrectly working Load instructions that exists for 31 // some earlier versions of the LEON processor line. NOP instructions must 32 // be inserted after the load instruction to ensure that the Load instruction 33 // behaves as expected for these processors. 34 // 35 // This pass inserts a NOP after any LD or LDF instruction. 36 // 37 char InsertNOPLoad::ID = 0; 38 39 InsertNOPLoad::InsertNOPLoad() : LEONMachineFunctionPass(ID) {} 40 41 bool InsertNOPLoad::runOnMachineFunction(MachineFunction &MF) { 42 Subtarget = &MF.getSubtarget<SparcSubtarget>(); 43 const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 44 DebugLoc DL = DebugLoc(); 45 46 bool Modified = false; 47 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 48 MachineBasicBlock &MBB = *MFI; 49 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 50 MachineInstr &MI = *MBBI; 51 unsigned Opcode = MI.getOpcode(); 52 if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) { 53 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 54 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); 55 Modified = true; 56 } 57 } 58 } 59 60 return Modified; 61 } 62 63 64 65 //***************************************************************************** 66 //**** DetectRoundChange pass 67 //***************************************************************************** 68 // To prevent any explicit change of the default rounding mode, this pass 69 // detects any call of the fesetround function. 70 // A warning is generated to ensure the user knows this has happened. 71 // 72 // Detects an erratum in UT699 LEON 3 processor 73 74 char DetectRoundChange::ID = 0; 75 76 DetectRoundChange::DetectRoundChange() : LEONMachineFunctionPass(ID) {} 77 78 bool DetectRoundChange::runOnMachineFunction(MachineFunction &MF) { 79 Subtarget = &MF.getSubtarget<SparcSubtarget>(); 80 81 bool Modified = false; 82 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 83 MachineBasicBlock &MBB = *MFI; 84 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 85 MachineInstr &MI = *MBBI; 86 unsigned Opcode = MI.getOpcode(); 87 if (Opcode == SP::CALL && MI.getNumOperands() > 0) { 88 MachineOperand &MO = MI.getOperand(0); 89 90 if (MO.isGlobal()) { 91 StringRef FuncName = MO.getGlobal()->getName(); 92 if (FuncName.compare_lower("fesetround") == 0) { 93 errs() << "Error: You are using the detectroundchange " 94 "option to detect rounding changes that will " 95 "cause LEON errata. The only way to fix this " 96 "is to remove the call to fesetround from " 97 "the source code.\n"; 98 } 99 } 100 } 101 } 102 } 103 104 return Modified; 105 } 106 107 //***************************************************************************** 108 //**** FixAllFDIVSQRT pass 109 //***************************************************************************** 110 // This pass fixes the incorrectly working FDIVx and FSQRTx instructions that 111 // exist for some earlier versions of the LEON processor line. Five NOP 112 // instructions need to be inserted after these instructions to ensure the 113 // correct result is placed in the destination registers before they are used. 114 // 115 // This pass implements two fixes: 116 // 1) fixing the FSQRTS and FSQRTD instructions. 117 // 2) fixing the FDIVS and FDIVD instructions. 118 // 119 // FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in 120 // the pipeline when this option is enabled, so this pass needs only to deal 121 // with the changes that still need implementing for the "double" versions 122 // of these instructions. 123 // 124 char FixAllFDIVSQRT::ID = 0; 125 126 FixAllFDIVSQRT::FixAllFDIVSQRT() : LEONMachineFunctionPass(ID) {} 127 128 bool FixAllFDIVSQRT::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 MachineInstr &MI = *MBBI; 138 unsigned Opcode = MI.getOpcode(); 139 140 // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is 141 // switched on so we don't need to check for them here. They will 142 // already have been converted to FSQRTD or FDIVD earlier in the 143 // pipeline. 144 if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) { 145 for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++) 146 BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 147 148 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 149 for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++) 150 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); 151 152 Modified = true; 153 } 154 } 155 } 156 157 return Modified; 158 } 159