diff options
Diffstat (limited to 'llvm/lib/Target/Sparc/LeonPasses.cpp')
-rw-r--r-- | llvm/lib/Target/Sparc/LeonPasses.cpp | 680 |
1 files changed, 76 insertions, 604 deletions
diff --git a/llvm/lib/Target/Sparc/LeonPasses.cpp b/llvm/lib/Target/Sparc/LeonPasses.cpp index c0591faf30c..fe57ec7b677 100644 --- a/llvm/lib/Target/Sparc/LeonPasses.cpp +++ b/llvm/lib/Target/Sparc/LeonPasses.cpp @@ -16,7 +16,6 @@ #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; @@ -90,6 +89,15 @@ 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; + } } } } @@ -139,6 +147,32 @@ bool FixFSMULD::runOnMachineFunction(MachineFunction &MF) { Reg1Index = MI.getOperand(0).getReg(); Reg2Index = MI.getOperand(1).getReg(); Reg3Index = MI.getOperand(2).getReg(); + } else if (MI.isInlineAsm()) { + std::string AsmString( + MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName()); + std::string FMULSOpCoode("fsmuld"); + std::transform(AsmString.begin(), AsmString.end(), AsmString.begin(), + ::tolower); + if (AsmString.find(FMULSOpCoode) == + 0) { // 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 && @@ -228,6 +262,31 @@ bool ReplaceFMULS::runOnMachineFunction(MachineFunction &MF) { Reg1Index = MI.getOperand(0).getReg(); Reg2Index = MI.getOperand(1).getReg(); Reg3Index = MI.getOperand(2).getReg(); + } else if (MI.isInlineAsm()) { + std::string AsmString( + MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName()); + std::string FMULSOpCoode("fmuls"); + std::transform(AsmString.begin(), AsmString.end(), AsmString.begin(), + ::tolower); + if (AsmString.find(FMULSOpCoode) == + 0) { // 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 && @@ -309,17 +368,31 @@ bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) { MachineInstr &MI = *MBBI; unsigned Opcode = MI.getOpcode(); + if (MI.isInlineAsm()) { + std::string AsmString( + MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName()); + std::string FSQRTDOpCode("fsqrtd"); + std::string FDIVDOpCode("fdivd"); + std::transform(AsmString.begin(), AsmString.end(), AsmString.begin(), + ::tolower); + if (AsmString.find(FSQRTDOpCode) == + 0) { // this is an inline fsqrts instruction + Opcode = SP::FSQRTD; + } else if (AsmString.find(FDIVDOpCode) == + 0) { // 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)); @@ -330,604 +403,3 @@ bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) { 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; - - 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; - } - } - } - } - } - - 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; - } - } - } - - 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(); - 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 -//***************************************************************************** -// 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. -// -char PreventRoundChange::ID = 0; - -PreventRoundChange::PreventRoundChange(TargetMachine &tm) - : LEONMachineFunctionPass(tm, ID) {} - -bool PreventRoundChange::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &MF.getSubtarget<SparcSubtarget>(); - - 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::CALL && MI.getNumOperands() > 0) { - MachineOperand &MO = MI.getOperand(0); - - if (MO.isGlobal()) { - StringRef FuncName = MO.getGlobal()->getName(); - if (FuncName.compare_lower("fesetround") == 0) { - MachineBasicBlock::iterator NMBBI = std::next(MBBI); - emitOptimizationRemark( - MF.getFunction()->getContext(), getPassName(), *MF.getFunction(), - MI.getDebugLoc(), "Warning: You are using the prvntroundchange " - "option to prevent rounding changes caused " - "by LEON errata. A call to fesetround to be " - "removed from the output."); - MI.eraseFromParent(); - MBBI = NMBBI; - 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; - } - - 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; - } - } - } - - return Modified; -} - - -//**************************************************************************************************************** -//**** FillDataCache pass -//**************************************************************************************************************** -// This erratum fix inserts after the first operand a loop performing 4096 NOP -// instructions. -// -// mov 0, %l0 -// mov 4096, %l1 -// loop1: -// inc %l0 -// cmp %l0, %l1 -// ble loop1 - -char FillDataCache::ID = 0; -bool FillDataCache::CacheFilled = false; - -FillDataCache::FillDataCache(TargetMachine &tm) - : LEONMachineFunctionPass(tm, ID) {} - -bool FillDataCache::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &MF.getSubtarget<SparcSubtarget>(); - const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - DebugLoc DL = DebugLoc(); - - unsigned int CountInstr = 0; - - bool Modified = false; - if (!CacheFilled) { - for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { - - if (CacheFilled) - break; - - MachineBasicBlock &MBB = *MFI; - - for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { - MachineInstr &MI = *MBBI; - - CountInstr++; - MachineBasicBlock::iterator NextMBBI = std::next(MBBI); - MBBI = NextMBBI; - - // insert the following sequence right after the first instruction - // initializing the stack pointer (sp register) - // or %g0, 1, %g1 - // loop1: - // nop - // add %g1, 1, %g1 - // cmp %g1, 4096 - // ble .LBB0_1 - if (CountInstr == 1) { - BuildMI(MBB, NextMBBI, DL, TII.get(SP::ORrr)) - .addReg(SP::G1) - .addReg(SP::G0) - .addImm(1); - } else { - const BasicBlock *LLVM_BB = MBB.getBasicBlock(); - MachineBasicBlock *dneBB = MF.CreateMachineBasicBlock(LLVM_BB); - - MachineFunction::iterator It = - std::next(MachineFunction::iterator(MBB)); - - MF.insert(It, dneBB); - - BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); - - BuildMI(MBB, MBBI, DL, TII.get(SP::ADDri)) - .addReg(SP::G1) - .addReg(SP::G1) - .addImm(1); - - BuildMI(MBB, MBBI, DL, TII.get(SP::CMPri)) - .addReg(SP::G1) - .addImm(4096); - - BuildMI(MBB, MBBI, DL, TII.get(SP::BCOND)) - .addMBB(dneBB) - .addImm(SPCC::ICC_LE); - - dneBB->splice(dneBB->begin(), &MBB, - std::next(MachineBasicBlock::iterator(MI)), MBB.end()); - dneBB->transferSuccessorsAndUpdatePHIs(&MBB); - - MBB.addSuccessor(dneBB); - - CacheFilled = true; - Modified = true; - break; - } - } - } - } - - return Modified; -} - - -//**************************************************************************************************************** -//**** RestoreExecAddress pass -//**************************************************************************************************************** -// This erratum fix should handle user traps of FPU exceptions and restore the -// execution address by skipping the trapped FPU instruction. -// The algorithm: -// find rett - return from trap -// insert code before rett to: -// 1. load the FSR register -// 2. check if there is an FPU exception -// 3. branch to old rett if there is no exception -// 4. rett to a restored exec address -char RestoreExecAddress::ID = 0; - -RestoreExecAddress::RestoreExecAddress(TargetMachine &tm) - : LEONMachineFunctionPass(tm, ID) {} - -bool RestoreExecAddress::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; - bool ExecAddressRestored = false; - for (auto NMBBI = MBB.begin(), E = MBB.end(); NMBBI != E; ++NMBBI) { - - if (NMBBI != E && !ExecAddressRestored) { - MachineBasicBlock::iterator MBBI = std::next(NMBBI); - MachineInstr &MI = *MBBI; - unsigned Opcode = MI.getOpcode(); - - if (Opcode == SP::RETTrr || Opcode == SP::RETTri) { - - const BasicBlock *LLVM_BB = MBB.getBasicBlock(); - - MachineBasicBlock *dneBB = MF.CreateMachineBasicBlock(LLVM_BB); - - // gets the FSR - floating point status register; - // the firts 4 bits are *cexc* - current exception flags - BuildMI(MBB, MBBI, DL, TII.get(SP::STFSRrr)).addReg(SP::L7).addImm(0); - - BuildMI(MBB, MBBI, DL, TII.get(SP::LDrr)) - .addReg(SP::L7) - .addReg(SP::L7) - .addImm(0); - - // performs a bitwise AND with b1111 to check the first 4 bits of FSR - // (cexc) - // if cexc is not zero, then it is an FPU exception - BuildMI(MBB, MBBI, DL, TII.get(SP::ANDri)) - .addReg(SP::L7) - .addReg(SP::L7) - .addImm(15); - - BuildMI(MBB, MBBI, DL, TII.get(SP::CMPri)).addReg(SP::L7).addImm(0); - - BuildMI(MBB, MBBI, DL, TII.get(SP::BCOND)) - .addMBB(dneBB) - .addImm(SPCC::ICC_E); - // BuildMI(&MBB, DL, - // TII.get(SP::BCOND)).addMBB(dneBB).addImm(SPCC::ICC_E); - - BuildMI(MBB, MBBI, DL, TII.get(SP::RETTri)).addReg(SP::L2).addImm(4); - - MachineFunction::iterator It = - std::next(MachineFunction::iterator(MBB)); - MF.insert(It, dneBB); - - // Transfer the remainder of MBB and its successor edges to dneBB. - dneBB->splice(dneBB->begin(), &MBB, MachineBasicBlock::iterator(MI), - MBB.end()); - dneBB->transferSuccessorsAndUpdatePHIs(&MBB); - - MBB.addSuccessor(dneBB); - - ExecAddressRestored = true; - Modified = true; - } - } - } - } - - return Modified; -} - |