diff options
author | Chris Dewhurst <chris.dewhurst@lero.ie> | 2016-08-12 09:34:26 +0000 |
---|---|---|
committer | Chris Dewhurst <chris.dewhurst@lero.ie> | 2016-08-12 09:34:26 +0000 |
commit | 829f8efe558e1cb2cee75395d1f18a52d2955db2 (patch) | |
tree | 36e5b0fe8e5c5647a7e93ac46663a599a0fdc694 /llvm/lib/Target/Sparc | |
parent | 6604e9638bfbf1af75c6fd7f5ec4b09b23abcaa9 (diff) | |
download | bcm5719-llvm-829f8efe558e1cb2cee75395d1f18a52d2955db2.tar.gz bcm5719-llvm-829f8efe558e1cb2cee75395d1f18a52d2955db2.zip |
[Sparc][Leon] Errata fixes for various errata in different versions of the Leon variants of the Sparc 32 bit processor.
The nature of the errata are listed in the comments preceding the errata fix passes. Relevant unit tests are implemented for each of these.
These changes update older versions of these errata fixes with improvements to code and unit tests.
Differential Revision: https://reviews.llvm.org/D21960
llvm-svn: 278489
Diffstat (limited to 'llvm/lib/Target/Sparc')
-rwxr-xr-x | llvm/lib/Target/Sparc/LeonFeatures.td | 15 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/LeonPasses.cpp | 385 | ||||
-rwxr-xr-x | llvm/lib/Target/Sparc/LeonPasses.h | 61 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/Sparc.td | 5 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcSubtarget.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcSubtarget.h | 6 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcTargetMachine.cpp | 7 |
7 files changed, 250 insertions, 230 deletions
diff --git a/llvm/lib/Target/Sparc/LeonFeatures.td b/llvm/lib/Target/Sparc/LeonFeatures.td index 63f8b33c80c..3d1bdbcd027 100755 --- a/llvm/lib/Target/Sparc/LeonFeatures.td +++ b/llvm/lib/Target/Sparc/LeonFeatures.td @@ -78,14 +78,17 @@ def InsertNOPLoad "every single-cycle load instruction when the next " "instruction is another load/store instruction">; -def FlushCacheLineSWAP - : SubtargetFeature<"flshcachelineswap", "FlushCacheLineSWAP", "true", - "LEON3 erratum fix: Flush cache line containing the " - "lock before performing any of the atomic instructions " - "SWAP and LDSTUB">; - def InsertNOPsLoadStore : SubtargetFeature<"insertnopsloadstore", "InsertNOPsLoadStore", "true", "LEON3 erratum fix: Insert NOPs between " "single-precision loads and the store, so the number of " "instructions between is 4">; + +def FillDataCache : SubtargetFeature<"filldatacache", "FillDataCache", "true", + "LEON2 erratum fix: Ensure data cache is " + "filled so that cache misses do not " + "happen later in program execution.">; + +def RestoreExecAddress + : SubtargetFeature<"restexecaddr", "RestoreExecAddress", "true", + "LEON2 erratum fix: Restore execution address.">; diff --git a/llvm/lib/Target/Sparc/LeonPasses.cpp b/llvm/lib/Target/Sparc/LeonPasses.cpp index cc0f299d65d..c0591faf30c 100644 --- a/llvm/lib/Target/Sparc/LeonPasses.cpp +++ b/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; @@ -89,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; - } } } } @@ -147,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 && @@ -259,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 && @@ -362,18 +309,6 @@ bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) { 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 @@ -453,8 +388,6 @@ bool FixCALL::runOnMachineFunction(MachineFunction &MF) { 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) { @@ -469,24 +402,6 @@ bool FixCALL::runOnMachineFunction(MachineFunction &MF) { 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; - } - } - } } } } @@ -562,55 +477,6 @@ bool IgnoreZeroFlag::runOnMachineFunction(MachineFunction &MF) { 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; - } } } } @@ -652,7 +518,6 @@ bool InsertNOPDoublePrecision::runOnMachineFunction(MachineFunction &MF) { 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); @@ -728,6 +593,12 @@ bool PreventRoundChange::runOnMachineFunction(MachineFunction &MF) { 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; @@ -740,62 +611,6 @@ bool PreventRoundChange::runOnMachineFunction(MachineFunction &MF) { return Modified; } //***************************************************************************** -//**** FlushCacheLineSWAP pass -//***************************************************************************** -// This pass inserts FLUSHW just before any SWAP atomic instruction. -// -char FlushCacheLineSWAP::ID = 0; - -FlushCacheLineSWAP::FlushCacheLineSWAP(TargetMachine &tm) - : LEONMachineFunctionPass(tm, ID) {} - -bool FlushCacheLineSWAP::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::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)); - 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 @@ -930,3 +745,189 @@ bool InsertNOPsLoadStore::runOnMachineFunction(MachineFunction &MF) { 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; +} + diff --git a/llvm/lib/Target/Sparc/LeonPasses.h b/llvm/lib/Target/Sparc/LeonPasses.h index 5e21813ed02..e3b1ed9409d 100755 --- a/llvm/lib/Target/Sparc/LeonPasses.h +++ b/llvm/lib/Target/Sparc/LeonPasses.h @@ -53,7 +53,7 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; const char *getPassName() const override { - return "ReplaceSDIV: Erratum Fix LBR25: do not emit SDIV, but emit SDIVCC " + return "ReplaceSDIV: Leon erratum fix: do not emit SDIV, but emit SDIVCC " "instead"; } }; @@ -66,11 +66,24 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; const char *getPassName() const override { - return "FixCALL: Erratum Fix LBR26: restrict the size of the immediate " + return "FixCALL: Leon erratum fix: restrict the size of the immediate " "operand of the CALL instruction to 20 bits"; } }; +class LLVM_LIBRARY_VISIBILITY RestoreExecAddress : public LEONMachineFunctionPass { +public: + static char ID; + + RestoreExecAddress(TargetMachine &tm); + bool runOnMachineFunction(MachineFunction& MF) override; + + const char *getPassName() const override { + return "RestoreExecAddress: Leon erratum fix: ensure execution " + "address is restored for bad floating point trap handlers."; + } +}; + class LLVM_LIBRARY_VISIBILITY IgnoreZeroFlag : public LEONMachineFunctionPass { public: static char ID; @@ -79,11 +92,24 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; const char *getPassName() const override { - return "IgnoreZeroFlag: Erratum Fix LBR28: do not rely on the zero bit " + return "IgnoreZeroFlag: Leon erratum fix: do not rely on the zero bit " "flag on a divide overflow for SDIVCC and UDIVCC"; } }; +class LLVM_LIBRARY_VISIBILITY FillDataCache : public LEONMachineFunctionPass { +public: + static char ID; + static bool CacheFilled; + + FillDataCache(TargetMachine &tm); + bool runOnMachineFunction(MachineFunction& MF) override; + + const char *getPassName() const override { + return "FillDataCache: Leon erratum fix: fill data cache with values at application startup"; + } +}; + class LLVM_LIBRARY_VISIBILITY InsertNOPDoublePrecision : public LEONMachineFunctionPass { public: @@ -93,7 +119,7 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; const char *getPassName() const override { - return "InsertNOPDoublePrecision: Erratum Fix LBR30: insert a NOP before " + return "InsertNOPDoublePrecision: Leon erratum fix: insert a NOP before " "the double precision floating point instruction"; } }; @@ -106,7 +132,7 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; const char *getPassName() const override { - return "FixFSMULD: Erratum Fix LBR31: do not select FSMULD"; + return "FixFSMULD: Leon erratum fix: do not utilize FSMULD"; } }; @@ -118,7 +144,7 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; const char *getPassName() const override { - return "ReplaceFMULS: Erratum Fix LBR32: replace FMULS instruction with a " + return "ReplaceFMULS: Leon erratum fix: Replace FMULS instruction with a " "routine using conversions/double precision operations to replace " "FMULS"; } @@ -133,7 +159,7 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; const char *getPassName() const override { - return "PreventRoundChange: Erratum Fix LBR33: prevent any rounding mode " + return "PreventRoundChange: Leon erratum fix: prevent any rounding mode " "change request: use only the round-to-nearest rounding mode"; } }; @@ -146,7 +172,7 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; const char *getPassName() const override { - return "FixAllFDIVSQRT: Erratum Fix LBR34: fix FDIVS/FDIVD/FSQRTS/FSQRTD " + return "FixAllFDIVSQRT: Leon erratum fix: Fix FDIVS/FDIVD/FSQRTS/FSQRTD " "instructions with NOPs and floating-point store"; } }; @@ -159,27 +185,12 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; const char *getPassName() const override { - return "InsertNOPLoad: insert a NOP instruction after " + return "InsertNOPLoad: Leon erratum fix: Insert a NOP instruction after " "every single-cycle load instruction when the next instruction is " "another load/store instruction"; } }; -class LLVM_LIBRARY_VISIBILITY FlushCacheLineSWAP - : public LEONMachineFunctionPass { -public: - static char ID; - - FlushCacheLineSWAP(TargetMachine &tm); - bool runOnMachineFunction(MachineFunction &MF) override; - - const char *getPassName() const override { - return "FlushCacheLineSWAP: Erratum Fix LBR36: flush cache line containing " - "the lock before performing any of the atomic instructions SWAP and " - "LDSTUB"; - } -}; - class LLVM_LIBRARY_VISIBILITY InsertNOPsLoadStore : public LEONMachineFunctionPass { public: @@ -189,7 +200,7 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; const char *getPassName() const override { - return "InsertNOPsLoadStore: Erratum Fix LBR37: insert NOPs between " + return "InsertNOPsLoadStore: Leon Erratum Fix: Insert NOPs between " "single-precision loads and the store, so the number of " "instructions between is 4"; } diff --git a/llvm/lib/Target/Sparc/Sparc.td b/llvm/lib/Target/Sparc/Sparc.td index 7a3d12448d5..783313a655c 100644 --- a/llvm/lib/Target/Sparc/Sparc.td +++ b/llvm/lib/Target/Sparc/Sparc.td @@ -107,7 +107,8 @@ def : Processor<"leon2", LEON2Itineraries, [ FeatureLeon ]>; // AT697E: Provides full coverage of AT697E - covers all the erratum fixes for // LEON2 AT697E def : Processor<"at697e", LEON2Itineraries, [ - FeatureLeon, ReplaceSDIV, FixCALL, IgnoreZeroFlag, InsertNOPDoublePrecision + FeatureLeon, ReplaceSDIV, FixCALL, IgnoreZeroFlag, InsertNOPDoublePrecision, + FillDataCache, RestoreExecAddress ]>; // LEON 2 FT (AT697F) @@ -124,7 +125,7 @@ def : Processor<"leon3", LEON3Itineraries, [ FeatureLeon, UMACSMACSupport ]>; // instruction. def : Processor<"ut699", LEON3Itineraries, [ FeatureLeon, FixFSMULD, ReplaceFMULS, PreventRoundChange, - FixAllFDIVSQRT, InsertNOPLoad, FlushCacheLineSWAP, InsertNOPsLoadStore + FixAllFDIVSQRT, InsertNOPLoad, InsertNOPsLoadStore ]>; // LEON3 FT (GR712RC). Provides features for the GR712RC processor. diff --git a/llvm/lib/Target/Sparc/SparcSubtarget.cpp b/llvm/lib/Target/Sparc/SparcSubtarget.cpp index a6a4dc54fae..dd5fa2d6fe7 100644 --- a/llvm/lib/Target/Sparc/SparcSubtarget.cpp +++ b/llvm/lib/Target/Sparc/SparcSubtarget.cpp @@ -48,7 +48,6 @@ SparcSubtarget &SparcSubtarget::initializeSubtargetDependencies(StringRef CPU, PreventRoundChange = false; FixAllFDIVSQRT = false; InsertNOPLoad = false; - FlushCacheLineSWAP = false; InsertNOPsLoadStore = false; // Determine default and user specified characteristics diff --git a/llvm/lib/Target/Sparc/SparcSubtarget.h b/llvm/lib/Target/Sparc/SparcSubtarget.h index 42d69369999..7389e9b16fa 100644 --- a/llvm/lib/Target/Sparc/SparcSubtarget.h +++ b/llvm/lib/Target/Sparc/SparcSubtarget.h @@ -54,8 +54,9 @@ class SparcSubtarget : public SparcGenSubtargetInfo { bool IgnoreZeroFlag; bool InsertNOPDoublePrecision; bool PreventRoundChange; - bool FlushCacheLineSWAP; bool InsertNOPsLoadStore; + bool FillDataCache; + bool RestoreExecAddress; SparcInstrInfo InstrInfo; SparcTargetLowering TLInfo; @@ -104,9 +105,10 @@ public: bool replaceFMULS() const { return ReplaceFMULS; } bool preventRoundChange() const { return PreventRoundChange; } bool fixAllFDIVSQRT() const { return FixAllFDIVSQRT; } - bool flushCacheLineSWAP() const { return FlushCacheLineSWAP; } bool insertNOPsLoadStore() const { return InsertNOPsLoadStore; } bool insertNOPLoad() const { return InsertNOPLoad; } + bool fillDataCache() const { return FillDataCache; } + bool restoreExecAddr() const { return RestoreExecAddress; } /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. diff --git a/llvm/lib/Target/Sparc/SparcTargetMachine.cpp b/llvm/lib/Target/Sparc/SparcTargetMachine.cpp index 17fe86a7084..b0ddd98798f 100644 --- a/llvm/lib/Target/Sparc/SparcTargetMachine.cpp +++ b/llvm/lib/Target/Sparc/SparcTargetMachine.cpp @@ -171,8 +171,11 @@ void SparcPassConfig::addPreEmitPass() { if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPLoad()) { addPass(new InsertNOPLoad(getSparcTargetMachine())); } - if (this->getSparcTargetMachine().getSubtargetImpl()->flushCacheLineSWAP()) { - addPass(new FlushCacheLineSWAP(getSparcTargetMachine())); + if (this->getSparcTargetMachine().getSubtargetImpl()->fillDataCache()) { + addPass(new FillDataCache(getSparcTargetMachine())); + } + if (this->getSparcTargetMachine().getSubtargetImpl()->restoreExecAddr()) { + addPass(new RestoreExecAddress(getSparcTargetMachine())); } if (this->getSparcTargetMachine() .getSubtargetImpl() |