diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Sparc/LeonPasses.cpp')
-rwxr-xr-x | contrib/llvm/lib/Target/Sparc/LeonPasses.cpp | 645 |
1 files changed, 43 insertions, 602 deletions
diff --git a/contrib/llvm/lib/Target/Sparc/LeonPasses.cpp b/contrib/llvm/lib/Target/Sparc/LeonPasses.cpp index 5d09208..0acc287 100755 --- a/contrib/llvm/lib/Target/Sparc/LeonPasses.cpp +++ b/contrib/llvm/lib/Target/Sparc/LeonPasses.cpp @@ -16,6 +16,7 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/LLVMContext.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -51,8 +52,7 @@ int LEONMachineFunctionPass::GetRegIndexForOperand(MachineInstr &MI, int LEONMachineFunctionPass::getUnusedFPRegister(MachineRegisterInfo &MRI) { for (int RegisterIndex = SP::F0; RegisterIndex <= SP::F31; ++RegisterIndex) { if (!MRI.isPhysRegUsed(RegisterIndex) && - !(std::find(UsedRegisters.begin(), UsedRegisters.end(), - RegisterIndex) != UsedRegisters.end())) { + !is_contained(UsedRegisters, RegisterIndex)) { return RegisterIndex; } } @@ -90,15 +90,6 @@ bool InsertNOPLoad::runOnMachineFunction(MachineFunction &MF) { MachineBasicBlock::iterator NMBBI = std::next(MBBI); BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); Modified = true; - } else if (MI.isInlineAsm()) { - // Look for an inline ld or ldf instruction. - StringRef AsmString = - MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); - if (AsmString.startswith_lower("ld")) { - MachineBasicBlock::iterator NMBBI = std::next(MBBI); - BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); - Modified = true; - } } } } @@ -148,29 +139,6 @@ bool FixFSMULD::runOnMachineFunction(MachineFunction &MF) { Reg1Index = MI.getOperand(0).getReg(); Reg2Index = MI.getOperand(1).getReg(); Reg3Index = MI.getOperand(2).getReg(); - } else if (MI.isInlineAsm()) { - StringRef AsmString = - MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); - if (AsmString.startswith_lower("fsmuld")) { - // this is an inline FSMULD instruction - - unsigned StartOp = InlineAsm::MIOp_FirstOperand; - - // extracts the registers from the inline assembly instruction - for (unsigned i = StartOp, e = MI.getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI.getOperand(i); - if (MO.isReg()) { - if (Reg1Index == UNASSIGNED_INDEX) - Reg1Index = MO.getReg(); - else if (Reg2Index == UNASSIGNED_INDEX) - Reg2Index = MO.getReg(); - else if (Reg3Index == UNASSIGNED_INDEX) - Reg3Index = MO.getReg(); - } - if (Reg3Index != UNASSIGNED_INDEX) - break; - } - } } if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX && @@ -260,28 +228,6 @@ bool ReplaceFMULS::runOnMachineFunction(MachineFunction &MF) { Reg1Index = MI.getOperand(0).getReg(); Reg2Index = MI.getOperand(1).getReg(); Reg3Index = MI.getOperand(2).getReg(); - } else if (MI.isInlineAsm()) { - StringRef AsmString = - MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); - if (AsmString.startswith_lower("fmuls")) { - // this is an inline FMULS instruction - unsigned StartOp = InlineAsm::MIOp_FirstOperand; - - // extracts the registers from the inline assembly instruction - for (unsigned i = StartOp, e = MI.getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI.getOperand(i); - if (MO.isReg()) { - if (Reg1Index == UNASSIGNED_INDEX) - Reg1Index = MO.getReg(); - else if (Reg2Index == UNASSIGNED_INDEX) - Reg2Index = MO.getReg(); - else if (Reg3Index == UNASSIGNED_INDEX) - Reg3Index = MO.getReg(); - } - if (Reg3Index != UNASSIGNED_INDEX) - break; - } - } } if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX && @@ -329,391 +275,22 @@ bool ReplaceFMULS::runOnMachineFunction(MachineFunction &MF) { return Modified; } -//***************************************************************************** -//**** FixAllFDIVSQRT pass -//***************************************************************************** -// This pass fixes the incorrectly working FDIVx and FSQRTx instructions that -// exist for some earlier versions of the LEON processor line. Five NOP -// instructions need to be inserted after these instructions to ensure the -// correct result is placed in the destination registers before they are used. -// -// This pass implements two fixes: -// 1) fixing the FSQRTS and FSQRTD instructions. -// 2) fixing the FDIVS and FDIVD instructions. -// -// FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in -// the pipeline when this option is enabled, so this pass needs only to deal -// with the changes that still need implementing for the "double" versions -// of these instructions. -// -char FixAllFDIVSQRT::ID = 0; - -FixAllFDIVSQRT::FixAllFDIVSQRT(TargetMachine &tm) - : LEONMachineFunctionPass(tm, ID) {} - -bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &MF.getSubtarget<SparcSubtarget>(); - const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - DebugLoc DL = DebugLoc(); - - bool Modified = false; - for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { - MachineBasicBlock &MBB = *MFI; - for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { - MachineInstr &MI = *MBBI; - unsigned Opcode = MI.getOpcode(); - - if (MI.isInlineAsm()) { - StringRef AsmString = - MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); - if (AsmString.startswith_lower("fsqrtd")) { - // this is an inline fsqrts instruction - Opcode = SP::FSQRTD; - } else if (AsmString.startswith_lower("fdivd")) { - // this is an inline fsqrts instruction - Opcode = SP::FDIVD; - } - } - - // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is - // switched on so we don't need to check for them here. They will - // already have been converted to FSQRTD or FDIVD earlier in the - // pipeline. - if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) { - // Insert 5 NOPs before FSQRTD,FDIVD. - for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++) - BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); - - MachineBasicBlock::iterator NMBBI = std::next(MBBI); - // ... and inserting 28 NOPs after FSQRTD,FDIVD. - for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++) - BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); - - Modified = true; - } - } - } - - return Modified; -} - -//***************************************************************************** -//**** ReplaceSDIV pass -//***************************************************************************** -// This pass fixes the incorrectly working SDIV instruction that -// exist for some earlier versions of the LEON processor line. The instruction -// is replaced with an SDIVcc instruction instead, which is working. -// -char ReplaceSDIV::ID = 0; - -ReplaceSDIV::ReplaceSDIV() : LEONMachineFunctionPass(ID) {} - -ReplaceSDIV::ReplaceSDIV(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {} - -bool ReplaceSDIV::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &MF.getSubtarget<SparcSubtarget>(); - const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - - bool Modified = false; - for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { - MachineBasicBlock &MBB = *MFI; - for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { - MachineInstr &MI = *MBBI; - unsigned Opcode = MI.getOpcode(); - if (Opcode == SP::SDIVrr) { - MI.setDesc(TII.get(SP::SDIVCCrr)); - Modified = true; - } else if (Opcode == SP::SDIVri) { - MI.setDesc(TII.get(SP::SDIVCCri)); - Modified = true; - } - } - } - - return Modified; -} - -static RegisterPass<ReplaceSDIV> X("replace-sdiv", "Replase SDIV Pass", false, - false); - -//***************************************************************************** -//**** FixCALL pass -//***************************************************************************** -// This pass restricts the size of the immediate operand of the CALL -// instruction, which can cause problems on some earlier versions of the LEON -// processor, which can interpret some of the call address bits incorrectly. -// -char FixCALL::ID = 0; - -FixCALL::FixCALL(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {} - -bool FixCALL::runOnMachineFunction(MachineFunction &MF) { - bool Modified = false; - - for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { - MachineBasicBlock &MBB = *MFI; - for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { - MachineInstr &MI = *MBBI; - MI.print(errs()); - errs() << "\n"; - - unsigned Opcode = MI.getOpcode(); - if (Opcode == SP::CALL || Opcode == SP::CALLrr) { - unsigned NumOperands = MI.getNumOperands(); - for (unsigned OperandIndex = 0; OperandIndex < NumOperands; - OperandIndex++) { - MachineOperand &MO = MI.getOperand(OperandIndex); - if (MO.isImm()) { - int64_t Value = MO.getImm(); - MO.setImm(Value & 0x000fffffL); - Modified = true; - break; - } - } - } else if (MI.isInlineAsm()) // inline assembly immediate call - { - StringRef AsmString = - MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); - if (AsmString.startswith_lower("call")) { - // this is an inline call instruction - unsigned StartOp = InlineAsm::MIOp_FirstOperand; - - // extracts the registers from the inline assembly instruction - for (unsigned i = StartOp, e = MI.getNumOperands(); i != e; ++i) { - MachineOperand &MO = MI.getOperand(i); - if (MO.isImm()) { - int64_t Value = MO.getImm(); - MO.setImm(Value & 0x000fffffL); - Modified = true; - } - } - } - } - } - } - - return Modified; -} - -//***************************************************************************** -//**** IgnoreZeroFlag pass -//***************************************************************************** -// This erratum fix fixes the overflow behavior of SDIVCC and UDIVCC -// instructions that exists on some earlier LEON processors. Where these -// instructions are detected, they are replaced by a sequence that will -// explicitly write the overflow bit flag if this is required. -// -char IgnoreZeroFlag::ID = 0; - -IgnoreZeroFlag::IgnoreZeroFlag(TargetMachine &tm) - : LEONMachineFunctionPass(tm, ID) {} - -bool IgnoreZeroFlag::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &MF.getSubtarget<SparcSubtarget>(); - const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - DebugLoc DL = DebugLoc(); - - bool Modified = false; - for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { - MachineBasicBlock &MBB = *MFI; - for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { - MachineInstr &MI = *MBBI; - unsigned Opcode = MI.getOpcode(); - if (Opcode == SP::SDIVCCrr || Opcode == SP::SDIVCCri || - Opcode == SP::UDIVCCrr || Opcode == SP::UDIVCCri) { - - // split the current machine basic block - just after the sdivcc/udivcc - // instruction - // create a label that help us skip the zero flag update (of PSR - - // Processor Status Register) - // if conditions are not met - const BasicBlock *LLVM_BB = MBB.getBasicBlock(); - MachineFunction::iterator It = - std::next(MachineFunction::iterator(MBB)); - - MachineBasicBlock *dneBB = MF.CreateMachineBasicBlock(LLVM_BB); - MF.insert(It, dneBB); - - // Transfer the remainder of MBB and its successor edges to dneBB. - dneBB->splice(dneBB->begin(), &MBB, - std::next(MachineBasicBlock::iterator(MI)), MBB.end()); - dneBB->transferSuccessorsAndUpdatePHIs(&MBB); - - MBB.addSuccessor(dneBB); - - MachineBasicBlock::iterator NextMBBI = std::next(MBBI); - - // bvc - branch if overflow flag not set - BuildMI(MBB, NextMBBI, DL, TII.get(SP::BCOND)) - .addMBB(dneBB) - .addImm(SPCC::ICC_VS); - - // bnz - branch if not zero - BuildMI(MBB, NextMBBI, DL, TII.get(SP::BCOND)) - .addMBB(dneBB) - .addImm(SPCC::ICC_NE); - - // use the WRPSR (Write Processor State Register) instruction to set the - // zeo flag to 1 - // create wr %g0, 1, %psr - BuildMI(MBB, NextMBBI, DL, TII.get(SP::WRPSRri)) - .addReg(SP::G0) - .addImm(1); - - BuildMI(MBB, NextMBBI, DL, TII.get(SP::NOP)); - - Modified = true; - } else if (MI.isInlineAsm()) { - StringRef AsmString = - MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); - if (AsmString.startswith_lower("sdivcc") || - AsmString.startswith_lower("udivcc")) { - // this is an inline SDIVCC or UDIVCC instruction - - // split the current machine basic block - just after the - // sdivcc/udivcc instruction - // create a label that help us skip the zero flag update (of PSR - - // Processor Status Register) - // if conditions are not met - const BasicBlock *LLVM_BB = MBB.getBasicBlock(); - MachineFunction::iterator It = - std::next(MachineFunction::iterator(MBB)); - - MachineBasicBlock *dneBB = MF.CreateMachineBasicBlock(LLVM_BB); - MF.insert(It, dneBB); - - // Transfer the remainder of MBB and its successor edges to dneBB. - dneBB->splice(dneBB->begin(), &MBB, - std::next(MachineBasicBlock::iterator(MI)), MBB.end()); - dneBB->transferSuccessorsAndUpdatePHIs(&MBB); - - MBB.addSuccessor(dneBB); - - MachineBasicBlock::iterator NextMBBI = std::next(MBBI); - - // bvc - branch if overflow flag not set - BuildMI(MBB, NextMBBI, DL, TII.get(SP::BCOND)) - .addMBB(dneBB) - .addImm(SPCC::ICC_VS); - - // bnz - branch if not zero - BuildMI(MBB, NextMBBI, DL, TII.get(SP::BCOND)) - .addMBB(dneBB) - .addImm(SPCC::ICC_NE); - - // use the WRPSR (Write Processor State Register) instruction to set - // the zeo flag to 1 - // create wr %g0, 1, %psr - BuildMI(MBB, NextMBBI, DL, TII.get(SP::WRPSRri)) - .addReg(SP::G0) - .addImm(1); - - BuildMI(MBB, NextMBBI, DL, TII.get(SP::NOP)); - - Modified = true; - } - } - } - } - - return Modified; -} - -//***************************************************************************** -//**** InsertNOPDoublePrecision pass -//***************************************************************************** -// This erratum fix for some earlier LEON processors fixes a problem where a -// double precision load will not yield the correct result if used in FMUL, -// FDIV, FADD, FSUB or FSQRT instructions later. If this sequence is detected, -// inserting a NOP between the two instructions will fix the erratum. -// 1.scans the code after register allocation; -// 2.checks for the problem conditions as described in the AT697E erratum -// “Odd-Numbered FPU Register Dependency not Properly Checked in some -// Double-Precision FPU Operations”; -// 3.inserts NOPs if the problem exists. -// -char InsertNOPDoublePrecision::ID = 0; - -InsertNOPDoublePrecision::InsertNOPDoublePrecision(TargetMachine &tm) - : LEONMachineFunctionPass(tm, ID) {} - -bool InsertNOPDoublePrecision::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &MF.getSubtarget<SparcSubtarget>(); - const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - DebugLoc DL = DebugLoc(); - - bool Modified = false; - for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { - MachineBasicBlock &MBB = *MFI; - for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { - MachineInstr &MI = *MBBI; - unsigned Opcode = MI.getOpcode(); - if (Opcode == SP::LDDFri || Opcode == SP::LDDFrr) { - MachineBasicBlock::iterator NMBBI = std::next(MBBI); - MachineInstr &NMI = *NMBBI; - - unsigned NextOpcode = NMI.getOpcode(); - // NMI.print(errs()); - if (NextOpcode == SP::FADDD || NextOpcode == SP::FSUBD || - NextOpcode == SP::FMULD || NextOpcode == SP::FDIVD) { - int RegAIndex = GetRegIndexForOperand(MI, 0); - int RegBIndex = GetRegIndexForOperand(NMI, 0); - int RegCIndex = - GetRegIndexForOperand(NMI, 2); // Second source operand is index 2 - int RegDIndex = - GetRegIndexForOperand(NMI, 1); // Destination operand is index 1 - - if ((RegAIndex == RegBIndex + 1 && RegBIndex == RegDIndex) || - (RegAIndex == RegCIndex + 1 && RegCIndex == RegDIndex) || - (RegAIndex == RegBIndex + 1 && RegCIndex == RegDIndex) || - (RegAIndex == RegCIndex + 1 && RegBIndex == RegDIndex)) { - // Insert NOP between the two instructions. - BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); - Modified = true; - } - - // Check the errata patterns that only happen for FADDD and FMULD - if (Modified == false && - (NextOpcode == SP::FADDD || NextOpcode == SP::FMULD)) { - RegAIndex = GetRegIndexForOperand(MI, 1); - if (RegAIndex == RegBIndex + 1 && RegBIndex == RegCIndex && - RegBIndex == RegDIndex) { - // Insert NOP between the two instructions. - BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); - Modified = true; - } - } - } else if (NextOpcode == SP::FSQRTD) { - int RegAIndex = GetRegIndexForOperand(MI, 1); - int RegBIndex = GetRegIndexForOperand(NMI, 0); - int RegCIndex = GetRegIndexForOperand(NMI, 1); - - if (RegAIndex == RegBIndex + 1 && RegBIndex == RegCIndex) { - // Insert NOP between the two instructions. - BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); - Modified = true; - } - } - } - } - } - - return Modified; -} //***************************************************************************** -//**** PreventRoundChange pass +//**** DetectRoundChange pass //***************************************************************************** // To prevent any explicit change of the default rounding mode, this pass -// detects any call of the fesetround function and removes this call from the -// list of generated operations. +// detects any call of the fesetround function. +// A warning is generated to ensure the user knows this has happened. // -char PreventRoundChange::ID = 0; +// Detects an erratum in UT699 LEON 3 processor -PreventRoundChange::PreventRoundChange(TargetMachine &tm) +char DetectRoundChange::ID = 0; + +DetectRoundChange::DetectRoundChange(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {} -bool PreventRoundChange::runOnMachineFunction(MachineFunction &MF) { +bool DetectRoundChange::runOnMachineFunction(MachineFunction &MF) { Subtarget = &MF.getSubtarget<SparcSubtarget>(); bool Modified = false; @@ -728,10 +305,11 @@ bool PreventRoundChange::runOnMachineFunction(MachineFunction &MF) { if (MO.isGlobal()) { StringRef FuncName = MO.getGlobal()->getName(); if (FuncName.compare_lower("fesetround") == 0) { - MachineBasicBlock::iterator NMBBI = std::next(MBBI); - MI.eraseFromParent(); - MBBI = NMBBI; - Modified = true; + errs() << "Error: You are using the detectroundchange " + "option to detect rounding changes that will " + "cause LEON errata. The only way to fix this " + "is to remove the call to fesetround from " + "the source code.\n"; } } } @@ -740,17 +318,30 @@ bool PreventRoundChange::runOnMachineFunction(MachineFunction &MF) { return Modified; } + //***************************************************************************** -//**** FlushCacheLineSWAP pass +//**** FixAllFDIVSQRT pass //***************************************************************************** -// This pass inserts FLUSHW just before any SWAP atomic instruction. +// This pass fixes the incorrectly working FDIVx and FSQRTx instructions that +// exist for some earlier versions of the LEON processor line. Five NOP +// instructions need to be inserted after these instructions to ensure the +// correct result is placed in the destination registers before they are used. // -char FlushCacheLineSWAP::ID = 0; +// This pass implements two fixes: +// 1) fixing the FSQRTS and FSQRTD instructions. +// 2) fixing the FDIVS and FDIVD instructions. +// +// FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in +// the pipeline when this option is enabled, so this pass needs only to deal +// with the changes that still need implementing for the "double" versions +// of these instructions. +// +char FixAllFDIVSQRT::ID = 0; -FlushCacheLineSWAP::FlushCacheLineSWAP(TargetMachine &tm) +FixAllFDIVSQRT::FixAllFDIVSQRT(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {} -bool FlushCacheLineSWAP::runOnMachineFunction(MachineFunction &MF) { +bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) { Subtarget = &MF.getSubtarget<SparcSubtarget>(); const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); DebugLoc DL = DebugLoc(); @@ -761,170 +352,20 @@ bool FlushCacheLineSWAP::runOnMachineFunction(MachineFunction &MF) { for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { MachineInstr &MI = *MBBI; unsigned Opcode = MI.getOpcode(); - if (Opcode == SP::SWAPrr || Opcode == SP::SWAPri || - Opcode == SP::LDSTUBrr || Opcode == SP::LDSTUBri) { - // insert flush and 5 NOPs before the swap/ldstub instruction - BuildMI(MBB, MBBI, DL, TII.get(SP::FLUSH)); - BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); - BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); - BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); - BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); - BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); - Modified = true; - } else if (MI.isInlineAsm()) { - StringRef AsmString = - MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); - if (AsmString.startswith_lower("swap") || - AsmString.startswith_lower("ldstub")) { - // this is an inline swap or ldstub instruction - - // insert flush and 5 NOPs before the swap/ldstub instruction - BuildMI(MBB, MBBI, DL, TII.get(SP::FLUSH)); - BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); - BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); - BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); - BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); + // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is + // switched on so we don't need to check for them here. They will + // already have been converted to FSQRTD or FDIVD earlier in the + // pipeline. + if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) { + for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++) BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); - Modified = true; - } - } - } - } - - return Modified; -} - -//***************************************************************************** -//**** InsertNOPsLoadStore pass -//***************************************************************************** -// This pass shall insert NOPs between floating point loads and stores when the -// following circumstances are present [5]: -// Pattern 1: -// 1. single-precision load or single-precision FPOP to register %fX, where X is -// the same register as the store being checked; -// 2. single-precision load or single-precision FPOP to register %fY , where Y -// is the opposite register in the same double-precision pair; -// 3. 0-3 instructions of any kind, except stores from %fX or %fY or operations -// with %fX as destination; -// 4. the store (from register %fX) being considered. -// Pattern 2: -// 1. double-precision FPOP; -// 2. any number of operations on any kind, except no double-precision FPOP and -// at most one (less than two) single-precision or single-to-double FPOPs; -// 3. the store (from register %fX) being considered. -// -char InsertNOPsLoadStore::ID = 0; - -InsertNOPsLoadStore::InsertNOPsLoadStore(TargetMachine &tm) - : LEONMachineFunctionPass(tm, ID) {} - -bool InsertNOPsLoadStore::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &MF.getSubtarget<SparcSubtarget>(); - const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - DebugLoc DL = DebugLoc(); - - MachineInstr *Pattern1FirstInstruction = NULL; - MachineInstr *Pattern2FirstInstruction = NULL; - unsigned int StoreInstructionsToCheck = 0; - int FxRegIndex, FyRegIndex; - - bool Modified = false; - for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { - MachineBasicBlock &MBB = *MFI; - for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { - MachineInstr &MI = *MBBI; - - if (StoreInstructionsToCheck > 0) { - if (((MI.getOpcode() == SP::STFrr || MI.getOpcode() == SP::STFri) && - (GetRegIndexForOperand(MI, LAST_OPERAND) == FxRegIndex || - GetRegIndexForOperand(MI, LAST_OPERAND) == FyRegIndex)) || - GetRegIndexForOperand(MI, 0) == FxRegIndex) { - // Insert four NOPs - for (unsigned InsertedCount = 0; InsertedCount < 4; InsertedCount++) { - BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); - } - Modified = true; - } - StoreInstructionsToCheck--; - } - - switch (MI.getOpcode()) { - // Watch for Pattern 1 FPop instructions - case SP::LDrr: - case SP::LDri: - case SP::LDFrr: - case SP::LDFri: - case SP::FADDS: - case SP::FSUBS: - case SP::FMULS: - case SP::FDIVS: - case SP::FSQRTS: - case SP::FCMPS: - case SP::FMOVS: - case SP::FNEGS: - case SP::FABSS: - case SP::FITOS: - case SP::FSTOI: - case SP::FITOD: - case SP::FDTOI: - case SP::FDTOS: - if (Pattern1FirstInstruction != NULL) { - FxRegIndex = GetRegIndexForOperand(*Pattern1FirstInstruction, 0); - FyRegIndex = GetRegIndexForOperand(MI, 0); - - // Check to see if these registers are part of the same double - // precision - // register pair. - int DoublePrecRegIndexForX = (FxRegIndex - SP::F0) / 2; - int DoublePrecRegIndexForY = (FyRegIndex - SP::F0) / 2; - - if (DoublePrecRegIndexForX == DoublePrecRegIndexForY) - StoreInstructionsToCheck = 4; - } + MachineBasicBlock::iterator NMBBI = std::next(MBBI); + for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++) + BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); - Pattern1FirstInstruction = &MI; - break; - // End of Pattern 1 - - // Search for Pattern 2 - case SP::FADDD: - case SP::FSUBD: - case SP::FMULD: - case SP::FDIVD: - case SP::FSQRTD: - case SP::FCMPD: - Pattern2FirstInstruction = &MI; - Pattern1FirstInstruction = NULL; - break; - - case SP::STFrr: - case SP::STFri: - case SP::STDFrr: - case SP::STDFri: - if (Pattern2FirstInstruction != NULL) { - if (GetRegIndexForOperand(MI, LAST_OPERAND) == - GetRegIndexForOperand(*Pattern2FirstInstruction, 0)) { - // Insert four NOPs - for (unsigned InsertedCount = 0; InsertedCount < 4; - InsertedCount++) { - BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); - } - - Pattern2FirstInstruction = NULL; - } - } - Pattern1FirstInstruction = NULL; - break; - // End of Pattern 2 - - default: - // Ensure we don't count debug-only values while we're testing for the - // patterns. - if (!MI.isDebugValue()) - Pattern1FirstInstruction = NULL; - break; + Modified = true; } } } |