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