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 if (!Subtarget->insertNOPLoad()) 42 return false; 43 44 const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 45 DebugLoc DL = DebugLoc(); 46 47 bool Modified = false; 48 for (MachineBasicBlock &MBB : MF) { 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 if (!Subtarget->detectRoundChange()) 81 return false; 82 83 bool Modified = false; 84 for (MachineBasicBlock &MBB : MF) { 85 for (MachineInstr &MI : MBB) { 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_insensitive("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 if (!Subtarget->fixAllFDIVSQRT()) 131 return false; 132 133 const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 134 DebugLoc DL = DebugLoc(); 135 136 bool Modified = false; 137 for (MachineBasicBlock &MBB : MF) { 138 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 139 MachineInstr &MI = *MBBI; 140 unsigned Opcode = MI.getOpcode(); 141 142 // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is 143 // switched on so we don't need to check for them here. They will 144 // already have been converted to FSQRTD or FDIVD earlier in the 145 // pipeline. 146 if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) { 147 for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++) 148 BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 149 150 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 151 for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++) 152 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); 153 154 Modified = true; 155 } 156 } 157 } 158 159 return Modified; 160 } 161