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