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" 21using namespace llvm; 22 23LEONMachineFunctionPass::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// 36char InsertNOPLoad::ID = 0; 37 38InsertNOPLoad::InsertNOPLoad() : LEONMachineFunctionPass(ID) {} 39 40bool 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 73char DetectRoundChange::ID = 0; 74 75DetectRoundChange::DetectRoundChange() : LEONMachineFunctionPass(ID) {} 76 77bool 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// 123char FixAllFDIVSQRT::ID = 0; 124 125FixAllFDIVSQRT::FixAllFDIVSQRT() : LEONMachineFunctionPass(ID) {} 126 127bool 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