1de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===------ LeonPasses.cpp - Define passes specific to LEON ---------------===// 2de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 3de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// The LLVM Compiler Infrastructure 4de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 5de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source 6de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// License. See LICENSE.TXT for details. 7de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 8de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===----------------------------------------------------------------------===// 9de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 10de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 11de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===----------------------------------------------------------------------===// 12de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 13de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "LeonPasses.h" 14de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/CodeGen/ISDOpcodes.h" 15de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/CodeGen/MachineFunction.h" 16de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/CodeGen/MachineInstr.h" 17de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/CodeGen/MachineInstrBuilder.h" 18de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/CodeGen/MachineRegisterInfo.h" 19de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/IR/LLVMContext.h" 20de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Support/raw_ostream.h" 21de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarusing namespace llvm; 22de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 23de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarLEONMachineFunctionPass::LEONMachineFunctionPass(TargetMachine &tm, char &ID) 24de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar : MachineFunctionPass(ID) {} 25de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 26de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarLEONMachineFunctionPass::LEONMachineFunctionPass(char &ID) 27de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar : MachineFunctionPass(ID) {} 28de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 29de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarint LEONMachineFunctionPass::GetRegIndexForOperand(MachineInstr &MI, 30de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int OperandIndex) { 31de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (MI.getNumOperands() > 0) { 32de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (OperandIndex == LAST_OPERAND) { 33de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar OperandIndex = MI.getNumOperands() - 1; 34de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 35de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 36de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (MI.getNumOperands() > (unsigned)OperandIndex && 37de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MI.getOperand(OperandIndex).isReg()) { 38de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return (int)MI.getOperand(OperandIndex).getReg(); 39de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 40de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 41de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 42de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar static int NotFoundIndex = -10; 43de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Return a different number each time to avoid any comparisons between the 44de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // values returned. 45de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar NotFoundIndex -= 10; 46de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return NotFoundIndex; 47de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 48de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 49de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// finds a new free FP register 50de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// checks also the AllocatedRegisters vector 51de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarint LEONMachineFunctionPass::getUnusedFPRegister(MachineRegisterInfo &MRI) { 52de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (int RegisterIndex = SP::F0; RegisterIndex <= SP::F31; ++RegisterIndex) { 53de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!MRI.isPhysRegUsed(RegisterIndex) && 54de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar !(std::find(UsedRegisters.begin(), UsedRegisters.end(), 55de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar RegisterIndex) != UsedRegisters.end())) { 56de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return RegisterIndex; 57de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 58de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 59de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 60de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return -1; 61de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 62de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 63de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 64de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//**** InsertNOPLoad pass 65de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 66de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This pass fixes the incorrectly working Load instructions that exists for 67de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// some earlier versions of the LEON processor line. NOP instructions must 68de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// be inserted after the load instruction to ensure that the Load instruction 69de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// behaves as expected for these processors. 70de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 71de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This pass inserts a NOP after any LD or LDF instruction. 72de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 73de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarchar InsertNOPLoad::ID = 0; 74de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 75de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarInsertNOPLoad::InsertNOPLoad(TargetMachine &tm) 76de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar : LEONMachineFunctionPass(tm, ID) {} 77de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 78de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool InsertNOPLoad::runOnMachineFunction(MachineFunction &MF) { 79de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Subtarget = &MF.getSubtarget<SparcSubtarget>(); 80de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 81de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DebugLoc DL = DebugLoc(); 82de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 83de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar bool Modified = false; 84de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 85de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock &MBB = *MFI; 86de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 87de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineInstr &MI = *MBBI; 88de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned Opcode = MI.getOpcode(); 89de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) { 90de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock::iterator NMBBI = std::next(MBBI); 91de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); 92de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 93de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else if (MI.isInlineAsm()) { 94de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Look for an inline ld or ldf instruction. 95de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StringRef AsmString = 96de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); 97de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (AsmString.startswith_lower("ld")) { 98de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock::iterator NMBBI = std::next(MBBI); 99de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); 100de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 101de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 102de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 103de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 104de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 105de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 106de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Modified; 107de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 108de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 109de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 110de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//**** FixFSMULD pass 111de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 112de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This pass fixes the incorrectly working FSMULD instruction that exists for 113de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// some earlier versions of the LEON processor line. 114de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 115de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// The pass should convert the FSMULD operands to double precision in scratch 116de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// registers, then calculate the result with the FMULD instruction. Therefore, 117de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// the pass should replace operations of the form: 118de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// fsmuld %f20,%f21,%f8 119de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// with the sequence: 120de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// fstod %f20,%f0 121de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// fstod %f21,%f2 122de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// fmuld %f0,%f2,%f8 123de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 124de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarchar FixFSMULD::ID = 0; 125de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 126de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarFixFSMULD::FixFSMULD(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {} 127de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 128de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool FixFSMULD::runOnMachineFunction(MachineFunction &MF) { 129de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Subtarget = &MF.getSubtarget<SparcSubtarget>(); 130de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 131de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DebugLoc DL = DebugLoc(); 132de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 133de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar bool Modified = false; 134de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 135de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock &MBB = *MFI; 136de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 137de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 138de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineInstr &MI = *MBBI; 139de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned Opcode = MI.getOpcode(); 140de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 141de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const int UNASSIGNED_INDEX = -1; 142de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int Reg1Index = UNASSIGNED_INDEX; 143de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int Reg2Index = UNASSIGNED_INDEX; 144de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int Reg3Index = UNASSIGNED_INDEX; 145de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 146de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Opcode == SP::FSMULD && MI.getNumOperands() == 3) { 147de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // take the registers from fsmuld %f20,%f21,%f8 148de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Reg1Index = MI.getOperand(0).getReg(); 149de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Reg2Index = MI.getOperand(1).getReg(); 150de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Reg3Index = MI.getOperand(2).getReg(); 151de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else if (MI.isInlineAsm()) { 152de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StringRef AsmString = 153de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); 154de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (AsmString.startswith_lower("fsmuld")) { 155de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // this is an inline FSMULD instruction 156de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 157de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned StartOp = InlineAsm::MIOp_FirstOperand; 158de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 159de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // extracts the registers from the inline assembly instruction 160de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (unsigned i = StartOp, e = MI.getNumOperands(); i != e; ++i) { 161de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const MachineOperand &MO = MI.getOperand(i); 162de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (MO.isReg()) { 163de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Reg1Index == UNASSIGNED_INDEX) 164de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Reg1Index = MO.getReg(); 165de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar else if (Reg2Index == UNASSIGNED_INDEX) 166de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Reg2Index = MO.getReg(); 167de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar else if (Reg3Index == UNASSIGNED_INDEX) 168de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Reg3Index = MO.getReg(); 169de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 170de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Reg3Index != UNASSIGNED_INDEX) 171de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 172de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 173de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 174de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 175de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 176de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX && 177de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Reg3Index != UNASSIGNED_INDEX) { 178de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar clearUsedRegisterList(); 179de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock::iterator NMBBI = std::next(MBBI); 180de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Whatever Reg3Index is hasn't been used yet, so we need to reserve it. 181de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar markRegisterUsed(Reg3Index); 182de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo()); 183de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar markRegisterUsed(ScratchReg1Index); 184de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo()); 185de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar markRegisterUsed(ScratchReg2Index); 186de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 187de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (ScratchReg1Index == UNASSIGNED_INDEX || 188de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ScratchReg2Index == UNASSIGNED_INDEX) { 189de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar errs() << "Cannot allocate free scratch registers for the FixFSMULD " 190de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "pass." 191de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar << "\n"; 192de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else { 193de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // create fstod %f20,%f0 194de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD)) 195de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(ScratchReg1Index) 196de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(Reg1Index); 197de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 198de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // create fstod %f21,%f2 199de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD)) 200de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(ScratchReg2Index) 201de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(Reg2Index); 202de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 203de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // create fmuld %f0,%f2,%f8 204de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD)) 205de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(Reg3Index) 206de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(ScratchReg1Index) 207de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(ScratchReg2Index); 208de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 209de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MI.eraseFromParent(); 210de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MBBI = NMBBI; 211de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 212de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 213de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 214de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 215de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 216de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 217de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 218de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Modified; 219de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 220de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 221de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 222de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//**** ReplaceFMULS pass 223de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 224de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This pass fixes the incorrectly working FMULS instruction that exists for 225de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// some earlier versions of the LEON processor line. 226de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 227de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This pass converts the FMULS operands to double precision in scratch 228de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// registers, then calculates the result with the FMULD instruction. 229de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// The pass should replace operations of the form: 230de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// fmuls %f20,%f21,%f8 231de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// with the sequence: 232de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// fstod %f20,%f0 233de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// fstod %f21,%f2 234de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// fmuld %f0,%f2,%f8 235de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 236de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarchar ReplaceFMULS::ID = 0; 237de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 238de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarReplaceFMULS::ReplaceFMULS(TargetMachine &tm) 239de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar : LEONMachineFunctionPass(tm, ID) {} 240de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 241de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool ReplaceFMULS::runOnMachineFunction(MachineFunction &MF) { 242de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Subtarget = &MF.getSubtarget<SparcSubtarget>(); 243de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 244de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DebugLoc DL = DebugLoc(); 245de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 246de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar bool Modified = false; 247de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 248de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock &MBB = *MFI; 249de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 250de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineInstr &MI = *MBBI; 251de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned Opcode = MI.getOpcode(); 252de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 253de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const int UNASSIGNED_INDEX = -1; 254de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int Reg1Index = UNASSIGNED_INDEX; 255de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int Reg2Index = UNASSIGNED_INDEX; 256de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int Reg3Index = UNASSIGNED_INDEX; 257de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 258de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Opcode == SP::FMULS && MI.getNumOperands() == 3) { 259de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // take the registers from fmuls %f20,%f21,%f8 260de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Reg1Index = MI.getOperand(0).getReg(); 261de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Reg2Index = MI.getOperand(1).getReg(); 262de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Reg3Index = MI.getOperand(2).getReg(); 263de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else if (MI.isInlineAsm()) { 264de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StringRef AsmString = 265de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); 266de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (AsmString.startswith_lower("fmuls")) { 267de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // this is an inline FMULS instruction 268de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned StartOp = InlineAsm::MIOp_FirstOperand; 269de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 270de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // extracts the registers from the inline assembly instruction 271de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (unsigned i = StartOp, e = MI.getNumOperands(); i != e; ++i) { 272de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const MachineOperand &MO = MI.getOperand(i); 273de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (MO.isReg()) { 274de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Reg1Index == UNASSIGNED_INDEX) 275de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Reg1Index = MO.getReg(); 276de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar else if (Reg2Index == UNASSIGNED_INDEX) 277de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Reg2Index = MO.getReg(); 278de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar else if (Reg3Index == UNASSIGNED_INDEX) 279de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Reg3Index = MO.getReg(); 280de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 281de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Reg3Index != UNASSIGNED_INDEX) 282de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 283de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 284de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 285de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 286de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 287de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX && 288de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Reg3Index != UNASSIGNED_INDEX) { 289de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar clearUsedRegisterList(); 290de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock::iterator NMBBI = std::next(MBBI); 291de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Whatever Reg3Index is hasn't been used yet, so we need to reserve it. 292de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar markRegisterUsed(Reg3Index); 293de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo()); 294de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar markRegisterUsed(ScratchReg1Index); 295de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo()); 296de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar markRegisterUsed(ScratchReg2Index); 297de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 298de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (ScratchReg1Index == UNASSIGNED_INDEX || 299de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ScratchReg2Index == UNASSIGNED_INDEX) { 300de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar errs() << "Cannot allocate free scratch registers for the " 301de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "ReplaceFMULS pass." 302de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar << "\n"; 303de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else { 304de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // create fstod %f20,%f0 305de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD)) 306de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(ScratchReg1Index) 307de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(Reg1Index); 308de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 309de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // create fstod %f21,%f2 310de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD)) 311de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(ScratchReg2Index) 312de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(Reg2Index); 313de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 314de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // create fmuld %f0,%f2,%f8 315de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD)) 316de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(Reg3Index) 317de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(ScratchReg1Index) 318de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(ScratchReg2Index); 319de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 320de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MI.eraseFromParent(); 321de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MBBI = NMBBI; 322de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 323de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 324de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 325de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 326de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 327de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 328de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 329de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Modified; 330de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 331de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 332de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 333de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//**** FixAllFDIVSQRT pass 334de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 335de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This pass fixes the incorrectly working FDIVx and FSQRTx instructions that 336de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// exist for some earlier versions of the LEON processor line. Five NOP 337de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// instructions need to be inserted after these instructions to ensure the 338de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// correct result is placed in the destination registers before they are used. 339de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 340de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This pass implements two fixes: 341de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 1) fixing the FSQRTS and FSQRTD instructions. 342de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 2) fixing the FDIVS and FDIVD instructions. 343de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 344de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in 345de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// the pipeline when this option is enabled, so this pass needs only to deal 346de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// with the changes that still need implementing for the "double" versions 347de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// of these instructions. 348de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 349de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarchar FixAllFDIVSQRT::ID = 0; 350de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 351de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarFixAllFDIVSQRT::FixAllFDIVSQRT(TargetMachine &tm) 352de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar : LEONMachineFunctionPass(tm, ID) {} 353de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 354de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) { 355de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Subtarget = &MF.getSubtarget<SparcSubtarget>(); 356de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 357de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DebugLoc DL = DebugLoc(); 358de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 359de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar bool Modified = false; 360de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 361de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock &MBB = *MFI; 362de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 363de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineInstr &MI = *MBBI; 364de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned Opcode = MI.getOpcode(); 365de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 366de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (MI.isInlineAsm()) { 367de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StringRef AsmString = 368de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); 369de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (AsmString.startswith_lower("fsqrtd")) { 370de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // this is an inline fsqrts instruction 371de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Opcode = SP::FSQRTD; 372de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else if (AsmString.startswith_lower("fdivd")) { 373de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // this is an inline fsqrts instruction 374de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Opcode = SP::FDIVD; 375de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 376de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 377de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 378de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is 379de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // switched on so we don't need to check for them here. They will 380de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // already have been converted to FSQRTD or FDIVD earlier in the 381de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // pipeline. 382de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) { 383de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Insert 5 NOPs before FSQRTD,FDIVD. 384de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++) 385de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 386de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 387de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock::iterator NMBBI = std::next(MBBI); 388de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // ... and inserting 28 NOPs after FSQRTD,FDIVD. 389de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++) 390de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); 391de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 392de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 393de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 394de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 395de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 396de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 397de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Modified; 398de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 399de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 400de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 401de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//**** ReplaceSDIV pass 402de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 403de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This pass fixes the incorrectly working SDIV instruction that 404de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// exist for some earlier versions of the LEON processor line. The instruction 405de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// is replaced with an SDIVcc instruction instead, which is working. 406de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 407de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarchar ReplaceSDIV::ID = 0; 408de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 409de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarReplaceSDIV::ReplaceSDIV() : LEONMachineFunctionPass(ID) {} 410de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 411de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarReplaceSDIV::ReplaceSDIV(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {} 412de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 413de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool ReplaceSDIV::runOnMachineFunction(MachineFunction &MF) { 414de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Subtarget = &MF.getSubtarget<SparcSubtarget>(); 415de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 416de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 417de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar bool Modified = false; 418de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 419de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock &MBB = *MFI; 420de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 421de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineInstr &MI = *MBBI; 422de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned Opcode = MI.getOpcode(); 423de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Opcode == SP::SDIVrr) { 424de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MI.setDesc(TII.get(SP::SDIVCCrr)); 425de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 426de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else if (Opcode == SP::SDIVri) { 427de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MI.setDesc(TII.get(SP::SDIVCCri)); 428de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 429de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 430de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 431de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 432de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 433de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Modified; 434de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 435de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 436de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic RegisterPass<ReplaceSDIV> X("replace-sdiv", "Replase SDIV Pass", false, 437de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar false); 438de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 439de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 440de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//**** FixCALL pass 441de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 442de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This pass restricts the size of the immediate operand of the CALL 443de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// instruction, which can cause problems on some earlier versions of the LEON 444de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// processor, which can interpret some of the call address bits incorrectly. 445de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 446de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarchar FixCALL::ID = 0; 447de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 448de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarFixCALL::FixCALL(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {} 449de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 450de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool FixCALL::runOnMachineFunction(MachineFunction &MF) { 451de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar bool Modified = false; 452de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 453de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 454de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock &MBB = *MFI; 455de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 456de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineInstr &MI = *MBBI; 457de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MI.print(errs()); 458de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar errs() << "\n"; 459de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 460de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned Opcode = MI.getOpcode(); 461de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Opcode == SP::CALL || Opcode == SP::CALLrr) { 462de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned NumOperands = MI.getNumOperands(); 463de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (unsigned OperandIndex = 0; OperandIndex < NumOperands; 464de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar OperandIndex++) { 465de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineOperand &MO = MI.getOperand(OperandIndex); 466de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (MO.isImm()) { 467de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int64_t Value = MO.getImm(); 468de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MO.setImm(Value & 0x000fffffL); 469de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 470de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 471de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 472de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 473de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else if (MI.isInlineAsm()) // inline assembly immediate call 474de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar { 475de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StringRef AsmString = 476de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); 477de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (AsmString.startswith_lower("call")) { 478de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // this is an inline call instruction 479de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned StartOp = InlineAsm::MIOp_FirstOperand; 480de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 481de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // extracts the registers from the inline assembly instruction 482de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (unsigned i = StartOp, e = MI.getNumOperands(); i != e; ++i) { 483de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineOperand &MO = MI.getOperand(i); 484de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (MO.isImm()) { 485de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int64_t Value = MO.getImm(); 486de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MO.setImm(Value & 0x000fffffL); 487de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 488de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 489de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 490de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 491de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 492de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 493de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 494de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 495de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Modified; 496de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 497de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 498de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 499de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//**** IgnoreZeroFlag pass 500de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 501de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This erratum fix fixes the overflow behavior of SDIVCC and UDIVCC 502de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// instructions that exists on some earlier LEON processors. Where these 503de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// instructions are detected, they are replaced by a sequence that will 504de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// explicitly write the overflow bit flag if this is required. 505de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 506de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarchar IgnoreZeroFlag::ID = 0; 507de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 508de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarIgnoreZeroFlag::IgnoreZeroFlag(TargetMachine &tm) 509de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar : LEONMachineFunctionPass(tm, ID) {} 510de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 511de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool IgnoreZeroFlag::runOnMachineFunction(MachineFunction &MF) { 512de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Subtarget = &MF.getSubtarget<SparcSubtarget>(); 513de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 514de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DebugLoc DL = DebugLoc(); 515de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 516de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar bool Modified = false; 517de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 518de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock &MBB = *MFI; 519de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 520de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineInstr &MI = *MBBI; 521de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned Opcode = MI.getOpcode(); 522de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Opcode == SP::SDIVCCrr || Opcode == SP::SDIVCCri || 523de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Opcode == SP::UDIVCCrr || Opcode == SP::UDIVCCri) { 524de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 525de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // split the current machine basic block - just after the sdivcc/udivcc 526de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // instruction 527de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // create a label that help us skip the zero flag update (of PSR - 528de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Processor Status Register) 529de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // if conditions are not met 530de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const BasicBlock *LLVM_BB = MBB.getBasicBlock(); 531de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineFunction::iterator It = 532de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::next(MachineFunction::iterator(MBB)); 533de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 534de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock *dneBB = MF.CreateMachineBasicBlock(LLVM_BB); 535de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MF.insert(It, dneBB); 536de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 537de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Transfer the remainder of MBB and its successor edges to dneBB. 538de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar dneBB->splice(dneBB->begin(), &MBB, 539de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::next(MachineBasicBlock::iterator(MI)), MBB.end()); 540de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar dneBB->transferSuccessorsAndUpdatePHIs(&MBB); 541de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 542de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MBB.addSuccessor(dneBB); 543de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 544de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock::iterator NextMBBI = std::next(MBBI); 545de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 546de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // bvc - branch if overflow flag not set 547de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, NextMBBI, DL, TII.get(SP::BCOND)) 548de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addMBB(dneBB) 549de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addImm(SPCC::ICC_VS); 550de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 551de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // bnz - branch if not zero 552de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, NextMBBI, DL, TII.get(SP::BCOND)) 553de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addMBB(dneBB) 554de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addImm(SPCC::ICC_NE); 555de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 556de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // use the WRPSR (Write Processor State Register) instruction to set the 557de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // zeo flag to 1 558de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // create wr %g0, 1, %psr 559de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, NextMBBI, DL, TII.get(SP::WRPSRri)) 560de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(SP::G0) 561de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addImm(1); 562de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 563de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, NextMBBI, DL, TII.get(SP::NOP)); 564de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 565de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 566de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else if (MI.isInlineAsm()) { 567de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StringRef AsmString = 568de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); 569de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (AsmString.startswith_lower("sdivcc") || 570de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar AsmString.startswith_lower("udivcc")) { 571de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // this is an inline SDIVCC or UDIVCC instruction 572de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 573de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // split the current machine basic block - just after the 574de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // sdivcc/udivcc instruction 575de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // create a label that help us skip the zero flag update (of PSR - 576de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Processor Status Register) 577de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // if conditions are not met 578de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const BasicBlock *LLVM_BB = MBB.getBasicBlock(); 579de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineFunction::iterator It = 580de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::next(MachineFunction::iterator(MBB)); 581de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 582de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock *dneBB = MF.CreateMachineBasicBlock(LLVM_BB); 583de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MF.insert(It, dneBB); 584de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 585de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Transfer the remainder of MBB and its successor edges to dneBB. 586de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar dneBB->splice(dneBB->begin(), &MBB, 587de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::next(MachineBasicBlock::iterator(MI)), MBB.end()); 588de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar dneBB->transferSuccessorsAndUpdatePHIs(&MBB); 589de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 590de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MBB.addSuccessor(dneBB); 591de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 592de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock::iterator NextMBBI = std::next(MBBI); 593de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 594de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // bvc - branch if overflow flag not set 595de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, NextMBBI, DL, TII.get(SP::BCOND)) 596de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addMBB(dneBB) 597de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addImm(SPCC::ICC_VS); 598de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 599de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // bnz - branch if not zero 600de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, NextMBBI, DL, TII.get(SP::BCOND)) 601de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addMBB(dneBB) 602de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addImm(SPCC::ICC_NE); 603de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 604de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // use the WRPSR (Write Processor State Register) instruction to set 605de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // the zeo flag to 1 606de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // create wr %g0, 1, %psr 607de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, NextMBBI, DL, TII.get(SP::WRPSRri)) 608de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addReg(SP::G0) 609de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar .addImm(1); 610de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 611de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, NextMBBI, DL, TII.get(SP::NOP)); 612de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 613de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 614de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 615de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 616de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 617de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 618de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 619de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Modified; 620de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 621de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 622de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 623de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//**** InsertNOPDoublePrecision pass 624de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 625de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This erratum fix for some earlier LEON processors fixes a problem where a 626de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// double precision load will not yield the correct result if used in FMUL, 627de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// FDIV, FADD, FSUB or FSQRT instructions later. If this sequence is detected, 628de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// inserting a NOP between the two instructions will fix the erratum. 629de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 1.scans the code after register allocation; 630de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 2.checks for the problem conditions as described in the AT697E erratum 631de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// “Odd-Numbered FPU Register Dependency not Properly Checked in some 632de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Double-Precision FPU Operations”; 633de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 3.inserts NOPs if the problem exists. 634de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 635de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarchar InsertNOPDoublePrecision::ID = 0; 636de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 637de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarInsertNOPDoublePrecision::InsertNOPDoublePrecision(TargetMachine &tm) 638de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar : LEONMachineFunctionPass(tm, ID) {} 639de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 640de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool InsertNOPDoublePrecision::runOnMachineFunction(MachineFunction &MF) { 641de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Subtarget = &MF.getSubtarget<SparcSubtarget>(); 642de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 643de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DebugLoc DL = DebugLoc(); 644de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 645de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar bool Modified = false; 646de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 647de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock &MBB = *MFI; 648de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 649de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineInstr &MI = *MBBI; 650de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned Opcode = MI.getOpcode(); 651de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Opcode == SP::LDDFri || Opcode == SP::LDDFrr) { 652de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock::iterator NMBBI = std::next(MBBI); 653de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineInstr &NMI = *NMBBI; 654de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 655de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned NextOpcode = NMI.getOpcode(); 656de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // NMI.print(errs()); 657de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (NextOpcode == SP::FADDD || NextOpcode == SP::FSUBD || 658de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar NextOpcode == SP::FMULD || NextOpcode == SP::FDIVD) { 659de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int RegAIndex = GetRegIndexForOperand(MI, 0); 660de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int RegBIndex = GetRegIndexForOperand(NMI, 0); 661de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int RegCIndex = 662de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GetRegIndexForOperand(NMI, 2); // Second source operand is index 2 663de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int RegDIndex = 664de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GetRegIndexForOperand(NMI, 1); // Destination operand is index 1 665de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 666de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if ((RegAIndex == RegBIndex + 1 && RegBIndex == RegDIndex) || 667de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar (RegAIndex == RegCIndex + 1 && RegCIndex == RegDIndex) || 668de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar (RegAIndex == RegBIndex + 1 && RegCIndex == RegDIndex) || 669de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar (RegAIndex == RegCIndex + 1 && RegBIndex == RegDIndex)) { 670de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Insert NOP between the two instructions. 671de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); 672de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 673de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 674de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 675de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Check the errata patterns that only happen for FADDD and FMULD 676de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Modified == false && 677de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar (NextOpcode == SP::FADDD || NextOpcode == SP::FMULD)) { 678de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar RegAIndex = GetRegIndexForOperand(MI, 1); 679de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (RegAIndex == RegBIndex + 1 && RegBIndex == RegCIndex && 680de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar RegBIndex == RegDIndex) { 681de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Insert NOP between the two instructions. 682de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); 683de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 684de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 685de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 686de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else if (NextOpcode == SP::FSQRTD) { 687de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int RegAIndex = GetRegIndexForOperand(MI, 1); 688de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int RegBIndex = GetRegIndexForOperand(NMI, 0); 689de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int RegCIndex = GetRegIndexForOperand(NMI, 1); 690de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 691de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (RegAIndex == RegBIndex + 1 && RegBIndex == RegCIndex) { 692de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Insert NOP between the two instructions. 693de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); 694de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 695de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 696de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 697de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 698de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 699de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 700de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 701de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Modified; 702de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 703de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 704de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 705de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//**** PreventRoundChange pass 706de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 707de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// To prevent any explicit change of the default rounding mode, this pass 708de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// detects any call of the fesetround function and removes this call from the 709de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// list of generated operations. 710de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 711de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarchar PreventRoundChange::ID = 0; 712de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 713de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarPreventRoundChange::PreventRoundChange(TargetMachine &tm) 714de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar : LEONMachineFunctionPass(tm, ID) {} 715de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 716de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool PreventRoundChange::runOnMachineFunction(MachineFunction &MF) { 717de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Subtarget = &MF.getSubtarget<SparcSubtarget>(); 718de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 719de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar bool Modified = false; 720de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 721de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock &MBB = *MFI; 722de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 723de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineInstr &MI = *MBBI; 724de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned Opcode = MI.getOpcode(); 725de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Opcode == SP::CALL && MI.getNumOperands() > 0) { 726de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineOperand &MO = MI.getOperand(0); 727de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 728de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (MO.isGlobal()) { 729de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StringRef FuncName = MO.getGlobal()->getName(); 730de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (FuncName.compare_lower("fesetround") == 0) { 731de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock::iterator NMBBI = std::next(MBBI); 732de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MI.eraseFromParent(); 733de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MBBI = NMBBI; 734de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 735de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 736de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 737de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 738de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 739de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 740de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 741de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Modified; 742de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 743de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 744de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//**** FlushCacheLineSWAP pass 745de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 746de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This pass inserts FLUSHW just before any SWAP atomic instruction. 747de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 748de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarchar FlushCacheLineSWAP::ID = 0; 749de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 750de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarFlushCacheLineSWAP::FlushCacheLineSWAP(TargetMachine &tm) 751de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar : LEONMachineFunctionPass(tm, ID) {} 752de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 753de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool FlushCacheLineSWAP::runOnMachineFunction(MachineFunction &MF) { 754de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Subtarget = &MF.getSubtarget<SparcSubtarget>(); 755de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 756de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DebugLoc DL = DebugLoc(); 757de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 758de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar bool Modified = false; 759de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 760de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock &MBB = *MFI; 761de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 762de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineInstr &MI = *MBBI; 763de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned Opcode = MI.getOpcode(); 764de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Opcode == SP::SWAPrr || Opcode == SP::SWAPri || 765de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Opcode == SP::LDSTUBrr || Opcode == SP::LDSTUBri) { 766de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // insert flush and 5 NOPs before the swap/ldstub instruction 767de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::FLUSH)); 768de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 769de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 770de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 771de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 772de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 773de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 774de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 775de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else if (MI.isInlineAsm()) { 776de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StringRef AsmString = 777de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); 778de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (AsmString.startswith_lower("swap") || 779de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar AsmString.startswith_lower("ldstub")) { 780de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // this is an inline swap or ldstub instruction 781de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 782de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // insert flush and 5 NOPs before the swap/ldstub instruction 783de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::FLUSH)); 784de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 785de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 786de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 787de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 788de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 789de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 790de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 791de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 792de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 793de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 794de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 795de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 796de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Modified; 797de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 798de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 799de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 800de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//**** InsertNOPsLoadStore pass 801de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//***************************************************************************** 802de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This pass shall insert NOPs between floating point loads and stores when the 803de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// following circumstances are present [5]: 804de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Pattern 1: 805de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 1. single-precision load or single-precision FPOP to register %fX, where X is 806de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// the same register as the store being checked; 807de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 2. single-precision load or single-precision FPOP to register %fY , where Y 808de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// is the opposite register in the same double-precision pair; 809de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 3. 0-3 instructions of any kind, except stores from %fX or %fY or operations 810de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// with %fX as destination; 811de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 4. the store (from register %fX) being considered. 812de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Pattern 2: 813de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 1. double-precision FPOP; 814de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 2. any number of operations on any kind, except no double-precision FPOP and 815de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// at most one (less than two) single-precision or single-to-double FPOPs; 816de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 3. the store (from register %fX) being considered. 817de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 818de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarchar InsertNOPsLoadStore::ID = 0; 819de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 820de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarInsertNOPsLoadStore::InsertNOPsLoadStore(TargetMachine &tm) 821de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar : LEONMachineFunctionPass(tm, ID) {} 822de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 823de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool InsertNOPsLoadStore::runOnMachineFunction(MachineFunction &MF) { 824de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Subtarget = &MF.getSubtarget<SparcSubtarget>(); 825de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 826de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DebugLoc DL = DebugLoc(); 827de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 828de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineInstr *Pattern1FirstInstruction = NULL; 829de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineInstr *Pattern2FirstInstruction = NULL; 830de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned int StoreInstructionsToCheck = 0; 831de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int FxRegIndex, FyRegIndex; 832de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 833de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar bool Modified = false; 834de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { 835de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineBasicBlock &MBB = *MFI; 836de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { 837de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachineInstr &MI = *MBBI; 838de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 839de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (StoreInstructionsToCheck > 0) { 840de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (((MI.getOpcode() == SP::STFrr || MI.getOpcode() == SP::STFri) && 841de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar (GetRegIndexForOperand(MI, LAST_OPERAND) == FxRegIndex || 842de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GetRegIndexForOperand(MI, LAST_OPERAND) == FyRegIndex)) || 843de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GetRegIndexForOperand(MI, 0) == FxRegIndex) { 844de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Insert four NOPs 845de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (unsigned InsertedCount = 0; InsertedCount < 4; InsertedCount++) { 846de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 847de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 848de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modified = true; 849de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 850de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StoreInstructionsToCheck--; 851de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 852de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 853de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar switch (MI.getOpcode()) { 854de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Watch for Pattern 1 FPop instructions 855de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::LDrr: 856de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::LDri: 857de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::LDFrr: 858de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::LDFri: 859de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FADDS: 860de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FSUBS: 861de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FMULS: 862de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FDIVS: 863de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FSQRTS: 864de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FCMPS: 865de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FMOVS: 866de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FNEGS: 867de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FABSS: 868de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FITOS: 869de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FSTOI: 870de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FITOD: 871de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FDTOI: 872de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FDTOS: 873de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Pattern1FirstInstruction != NULL) { 874de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar FxRegIndex = GetRegIndexForOperand(*Pattern1FirstInstruction, 0); 875de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar FyRegIndex = GetRegIndexForOperand(MI, 0); 876de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 877de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Check to see if these registers are part of the same double 878de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // precision 879de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // register pair. 880de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int DoublePrecRegIndexForX = (FxRegIndex - SP::F0) / 2; 881de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int DoublePrecRegIndexForY = (FyRegIndex - SP::F0) / 2; 882de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 883de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (DoublePrecRegIndexForX == DoublePrecRegIndexForY) 884de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StoreInstructionsToCheck = 4; 885de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 886de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 887de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Pattern1FirstInstruction = &MI; 888de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 889de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // End of Pattern 1 890de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 891de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Search for Pattern 2 892de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FADDD: 893de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FSUBD: 894de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FMULD: 895de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FDIVD: 896de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FSQRTD: 897de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::FCMPD: 898de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Pattern2FirstInstruction = &MI; 899de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Pattern1FirstInstruction = NULL; 900de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 901de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 902de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::STFrr: 903de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::STFri: 904de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::STDFrr: 905de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case SP::STDFri: 906de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Pattern2FirstInstruction != NULL) { 907de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (GetRegIndexForOperand(MI, LAST_OPERAND) == 908de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GetRegIndexForOperand(*Pattern2FirstInstruction, 0)) { 909de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Insert four NOPs 910de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (unsigned InsertedCount = 0; InsertedCount < 4; 911de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar InsertedCount++) { 912de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); 913de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 914de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 915de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Pattern2FirstInstruction = NULL; 916de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 917de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 918de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Pattern1FirstInstruction = NULL; 919de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 920de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // End of Pattern 2 921de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 922de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar default: 923de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Ensure we don't count debug-only values while we're testing for the 924de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // patterns. 925de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!MI.isDebugValue()) 926de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Pattern1FirstInstruction = NULL; 927de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 928de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 929de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 930de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 931de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 932de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Modified; 933de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 934