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