From 0e7885981e94615da4e98c783b47434253b1f5b3 Mon Sep 17 00:00:00 2001 From: James Y Knight Date: Fri, 12 Aug 2016 14:48:09 +0000 Subject: [PATCH] Revert "[Sparc] Leon errata fix passes." ...and the two followup commits: Revert "[Sparc][Leon] Missed resetting option flags from check-in 278489." Revert "[Sparc][Leon] Errata fixes for various errata in different versions of the Leon variants of the Sparc 32 bit processor." This reverts commit r274856, r278489, and r278492. llvm-svn: 278511 --- lib/Target/Sparc/LeonFeatures.td | 110 ++- lib/Target/Sparc/LeonPasses.cpp | 680 ++---------------- lib/Target/Sparc/LeonPasses.h | 127 +--- lib/Target/Sparc/Sparc.td | 143 ++-- lib/Target/Sparc/SparcISelLowering.cpp | 19 +- lib/Target/Sparc/SparcSubtarget.cpp | 11 +- lib/Target/Sparc/SparcSubtarget.h | 22 +- lib/Target/Sparc/SparcTargetMachine.cpp | 57 +- test/CodeGen/SPARC/LeonFillDataCachePassUT.ll | 27 - test/CodeGen/SPARC/LeonFixFSMULDPassUT.ll | 36 +- test/CodeGen/SPARC/LeonInsertNOPLoad.ll | 13 - test/CodeGen/SPARC/LeonInsertNOPLoadPassUT.ll | 22 + .../SPARC/LeonInsertNOPsDoublePrecision.ll | 17 - .../SPARC/LeonPreventRoundChangePassUT.ll | 65 -- test/CodeGen/SPARC/LeonReplaceFMULSPassUT.ll | 24 +- test/CodeGen/SPARC/LeonReplaceSDIVPassUT.ll | 9 - 16 files changed, 287 insertions(+), 1095 deletions(-) delete mode 100755 test/CodeGen/SPARC/LeonFillDataCachePassUT.ll delete mode 100644 test/CodeGen/SPARC/LeonInsertNOPLoad.ll delete mode 100644 test/CodeGen/SPARC/LeonInsertNOPsDoublePrecision.ll delete mode 100644 test/CodeGen/SPARC/LeonPreventRoundChangePassUT.ll delete mode 100644 test/CodeGen/SPARC/LeonReplaceSDIVPassUT.ll diff --git a/lib/Target/Sparc/LeonFeatures.td b/lib/Target/Sparc/LeonFeatures.td index 3d1bdbcd027..e2282abbbdb 100755 --- a/lib/Target/Sparc/LeonFeatures.td +++ b/lib/Target/Sparc/LeonFeatures.td @@ -10,85 +10,57 @@ // //===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// CASA Support differs between LEON3-FT GR712RC and LEON3-FT UT699 -// We need to have the option to switch this on and off. -//===----------------------------------------------------------------------===// - -// support to casa instruction; for leon3 subtarget only -def LeonCASA : SubtargetFeature< - "hasleoncasa", "HasLeonCasa", "true", - "Enable CASA instruction for LEON3 and LEON4 processors">; //===----------------------------------------------------------------------===// // UMAC and SMAC support for LEON3 and LEON4 processors. //===----------------------------------------------------------------------===// -// support to casa instruction; for leon3 subtarget only -def UMACSMACSupport - : SubtargetFeature<"hasumacsmac", "HasUmacSmac", "true", - "Enable UMAC and SMAC for LEON3 and LEON4 processors">; +//support to casa instruction; for leon3 subtarget only +def UMACSMACSupport : SubtargetFeature< + "hasumacsmac", + "HasUmacSmac", + "true", + "Enable UMAC and SMAC for LEON3 and LEON4 processors" +>; + //===----------------------------------------------------------------------===// -// LEON Erratum fixes +// CASA Support differs between LEON3-FT GR712RC and LEON3-FT UT699 +// We need to have the option to switch this on and off. //===----------------------------------------------------------------------===// -def ReplaceSDIV - : SubtargetFeature< - "replacesdiv", "PerformSDIVReplace", "true", - "AT697E erratum fix: Do not emit SDIV, emit SDIVCC instead">; +//support to casa instruction; for leon3 subtarget only +def LeonCASA : SubtargetFeature< + "hasleoncasa", + "HasLeonCasa", + "true", + "Enable CASA instruction for LEON3 and LEON4 processors" +>; -def FixCALL - : SubtargetFeature<"fixcall", "FixCallImmediates", "true", - "AT697E erratum fix: Restrict the size of the immediate " - "operand of the CALL instruction to 20 bits">; +def InsertNOPLoad: SubtargetFeature< + "insertnopload", + "InsertNOPLoad", + "true", + "LEON3 erratum fix: Insert a NOP instruction after every single-cycle load instruction when the next instruction is another load/store instruction" +>; -def IgnoreZeroFlag - : SubtargetFeature<"ignrzeroflag", "IgnoreZeroFlag", "true", - "AT697E erratum fix: Do not rely on the zero bit flag " - "on a divide overflow for SDIVCC and UDIVCC">; +def FixFSMULD : SubtargetFeature< + "fixfsmuld", + "FixFSMULD", + "true", + "LEON erratum fix: Do not use FSMULD" +>; -def InsertNOPDoublePrecision - : SubtargetFeature<"insrtnopdblprcsn", "InsertNOPDoublePrecision", "true", - "LEON2 erratum fix: Insert a NOP before the double " - "precision floating point instruction">; +def ReplaceFMULS : SubtargetFeature< + "replacefmuls", + "ReplaceFMULS", + "true", + "LEON erratum fix: Replace FMULS instruction with FMULD and relevant conversion instructions" +>; -def FixFSMULD : SubtargetFeature<"fixfsmuld", "FixFSMULD", "true", - "LEON3 erratum fix: Do not select FSMULD">; - -def ReplaceFMULS - : SubtargetFeature<"replacefmuls", "ReplaceFMULS", "true", - "LEON3 erratum fix: Replace FMULS instruction with a " - "routine using conversions/double precision operations " - "to replace FMULS">; - -def PreventRoundChange - : SubtargetFeature<"prvntroundchange", "PreventRoundChange", "true", - "LEON3 erratum fix: Prevent any rounding mode change " - "request: use only the round-to-nearest rounding mode">; - -def FixAllFDIVSQRT - : SubtargetFeature<"fixallfdivsqrt", "FixAllFDIVSQRT", "true", - "LEON3 erratum fix: Fix FDIVS/FDIVD/FSQRTS/FSQRTD " - "instructions with NOPs and floating-point store">; - -def InsertNOPLoad - : SubtargetFeature<"insertnopload", "InsertNOPLoad", "true", - "LEON3 erratum fix: Insert a NOP instruction after " - "every single-cycle load instruction when the next " - "instruction is another load/store instruction">; - -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.">; +def FixAllFDIVSQRT : SubtargetFeature< + "fixallfdivsqrt", + "FixAllFDIVSQRT", + "true", + "LEON erratum fix: Fix FDIVS/FDIVD/FSQRTS/FSQRTD instructions with NOPs and floating-point store" +>; diff --git a/lib/Target/Sparc/LeonPasses.cpp b/lib/Target/Sparc/LeonPasses.cpp index c0591faf30c..fe57ec7b677 100644 --- a/lib/Target/Sparc/LeonPasses.cpp +++ b/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(); - 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 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(); - 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(); - 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(); - - 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(); - 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(); - 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(); - 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/lib/Target/Sparc/LeonPasses.h b/lib/Target/Sparc/LeonPasses.h index e3b1ed9409d..a544e322fcb 100755 --- a/lib/Target/Sparc/LeonPasses.h +++ b/lib/Target/Sparc/LeonPasses.h @@ -44,83 +44,17 @@ protected: int getUnusedFPRegister(MachineRegisterInfo &MRI); }; -class LLVM_LIBRARY_VISIBILITY ReplaceSDIV : public LEONMachineFunctionPass { +class LLVM_LIBRARY_VISIBILITY InsertNOPLoad : public LEONMachineFunctionPass { public: static char ID; - ReplaceSDIV(); - ReplaceSDIV(TargetMachine &tm); + InsertNOPLoad(TargetMachine &tm); bool runOnMachineFunction(MachineFunction &MF) override; const char *getPassName() const override { - return "ReplaceSDIV: Leon erratum fix: do not emit SDIV, but emit SDIVCC " - "instead"; - } -}; - -class LLVM_LIBRARY_VISIBILITY FixCALL : public LEONMachineFunctionPass { -public: - static char ID; - - FixCALL(TargetMachine &tm); - bool runOnMachineFunction(MachineFunction &MF) override; - - const char *getPassName() const override { - 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; - - IgnoreZeroFlag(TargetMachine &tm); - bool runOnMachineFunction(MachineFunction &MF) override; - - const char *getPassName() const override { - 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: - static char ID; - - InsertNOPDoublePrecision(TargetMachine &tm); - bool runOnMachineFunction(MachineFunction &MF) override; - - const char *getPassName() const override { - return "InsertNOPDoublePrecision: Leon erratum fix: insert a NOP before " - "the double precision floating point instruction"; + return "InsertNOPLoad: Erratum Fix LBR35: insert a NOP instruction after " + "every single-cycle load instruction when the next instruction is " + "another load/store instruction"; } }; @@ -132,7 +66,7 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; const char *getPassName() const override { - return "FixFSMULD: Leon erratum fix: do not utilize FSMULD"; + return "FixFSMULD: Erratum Fix LBR31: do not select FSMULD"; } }; @@ -144,26 +78,12 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; const char *getPassName() const override { - return "ReplaceFMULS: Leon erratum fix: Replace FMULS instruction with a " + return "ReplaceFMULS: Erratum Fix LBR32: replace FMULS instruction with a " "routine using conversions/double precision operations to replace " "FMULS"; } }; -class LLVM_LIBRARY_VISIBILITY PreventRoundChange - : public LEONMachineFunctionPass { -public: - static char ID; - - PreventRoundChange(TargetMachine &tm); - bool runOnMachineFunction(MachineFunction &MF) override; - - const char *getPassName() const override { - return "PreventRoundChange: Leon erratum fix: prevent any rounding mode " - "change request: use only the round-to-nearest rounding mode"; - } -}; - class LLVM_LIBRARY_VISIBILITY FixAllFDIVSQRT : public LEONMachineFunctionPass { public: static char ID; @@ -172,39 +92,10 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; const char *getPassName() const override { - return "FixAllFDIVSQRT: Leon erratum fix: Fix FDIVS/FDIVD/FSQRTS/FSQRTD " + return "FixAllFDIVSQRT: Erratum Fix LBR34: fix FDIVS/FDIVD/FSQRTS/FSQRTD " "instructions with NOPs and floating-point store"; } }; - -class LLVM_LIBRARY_VISIBILITY InsertNOPLoad : public LEONMachineFunctionPass { -public: - static char ID; - - InsertNOPLoad(TargetMachine &tm); - bool runOnMachineFunction(MachineFunction &MF) override; - - const char *getPassName() const override { - 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 InsertNOPsLoadStore - : public LEONMachineFunctionPass { -public: - static char ID; - - InsertNOPsLoadStore(TargetMachine &tm); - bool runOnMachineFunction(MachineFunction &MF) override; - - const char *getPassName() const override { - return "InsertNOPsLoadStore: Leon Erratum Fix: Insert NOPs between " - "single-precision loads and the store, so the number of " - "instructions between is 4"; - } -}; -} // namespace lllvm +} // namespace llvm #endif // LLVM_LIB_TARGET_SPARC_LEON_PASSES_H diff --git a/lib/Target/Sparc/Sparc.td b/lib/Target/Sparc/Sparc.td index 783313a655c..6ae73125c9e 100644 --- a/lib/Target/Sparc/Sparc.td +++ b/lib/Target/Sparc/Sparc.td @@ -21,34 +21,35 @@ include "llvm/Target/Target.td" // def FeatureV9 - : SubtargetFeature<"v9", "IsV9", "true", "Enable SPARC-V9 instructions">; + : SubtargetFeature<"v9", "IsV9", "true", + "Enable SPARC-V9 instructions">; def FeatureV8Deprecated - : SubtargetFeature<"deprecated-v8", "V8DeprecatedInsts", "true", - "Enable deprecated V8 instructions in V9 mode">; + : SubtargetFeature<"deprecated-v8", "V8DeprecatedInsts", "true", + "Enable deprecated V8 instructions in V9 mode">; def FeatureVIS - : SubtargetFeature<"vis", "IsVIS", "true", - "Enable UltraSPARC Visual Instruction Set extensions">; + : SubtargetFeature<"vis", "IsVIS", "true", + "Enable UltraSPARC Visual Instruction Set extensions">; def FeatureVIS2 - : SubtargetFeature<"vis2", "IsVIS2", "true", - "Enable Visual Instruction Set extensions II">; + : SubtargetFeature<"vis2", "IsVIS2", "true", + "Enable Visual Instruction Set extensions II">; def FeatureVIS3 - : SubtargetFeature<"vis3", "IsVIS3", "true", - "Enable Visual Instruction Set extensions III">; + : SubtargetFeature<"vis3", "IsVIS3", "true", + "Enable Visual Instruction Set extensions III">; def FeatureLeon - : SubtargetFeature<"leon", "IsLeon", "true", "Enable LEON extensions">; + : SubtargetFeature<"leon", "IsLeon", "true", + "Enable LEON extensions">; def FeatureHardQuad - : SubtargetFeature<"hard-quad-float", "HasHardQuad", "true", - "Enable quad-word floating point instructions">; + : SubtargetFeature<"hard-quad-float", "HasHardQuad", "true", + "Enable quad-word floating point instructions">; def UsePopc : SubtargetFeature<"popc", "UsePopc", "true", "Use the popc (population count) instruction">; -def FeatureSoftFloat - : SubtargetFeature<"soft-float", "UseSoftFloat", "true", - "Use software emulation for floating point">; +def FeatureSoftFloat : SubtargetFeature<"soft-float", "UseSoftFloat", "true", + "Use software emulation for floating point">; -//==== Features added predmoninantly for LEON subtarget support +//==== Features added predmoninantly for LEON subtarget support include "LeonFeatures.td" //===----------------------------------------------------------------------===// @@ -62,93 +63,87 @@ include "SparcInstrInfo.td" def SparcInstrInfo : InstrInfo; -def SparcAsmParser : AsmParser { bit ShouldEmitMatchRegisterName = 0; } +def SparcAsmParser : AsmParser { + bit ShouldEmitMatchRegisterName = 0; +} //===----------------------------------------------------------------------===// // SPARC processors supported. //===----------------------------------------------------------------------===// class Proc Features> - : Processor; + : Processor; -def : Proc<"generic", []>; -def : Proc<"v7", []>; -def : Proc<"v8", []>; -def : Proc<"supersparc", []>; -def : Proc<"sparclite", []>; -def : Proc<"f934", []>; -def : Proc<"hypersparc", []>; -def : Proc<"sparclite86x", []>; -def : Proc<"sparclet", []>; -def : Proc<"tsc701", []>; -def : Proc<"myriad2", []>; -def : Proc<"myriad2.1", []>; -def : Proc<"myriad2.2", []>; -def : Proc<"v9", [ FeatureV9 ]>; -def : Proc<"ultrasparc", [ FeatureV9, FeatureV8Deprecated, FeatureVIS ]>; -def : Proc<"ultrasparc3", - [ FeatureV9, FeatureV8Deprecated, FeatureVIS, FeatureVIS2 ]>; -def : Proc<"niagara", - [ FeatureV9, FeatureV8Deprecated, FeatureVIS, FeatureVIS2 ]>; -def : Proc<"niagara2", [ - FeatureV9, FeatureV8Deprecated, UsePopc, FeatureVIS, FeatureVIS2 -]>; -def : Proc<"niagara3", [ - FeatureV9, FeatureV8Deprecated, UsePopc, FeatureVIS, FeatureVIS2 -]>; -def : Proc<"niagara4", [ - FeatureV9, FeatureV8Deprecated, UsePopc, FeatureVIS, FeatureVIS2, FeatureVIS3 -]>; +def : Proc<"generic", []>; +def : Proc<"v7", []>; +def : Proc<"v8", []>; +def : Proc<"supersparc", []>; +def : Proc<"sparclite", []>; +def : Proc<"f934", []>; +def : Proc<"hypersparc", []>; +def : Proc<"sparclite86x", []>; +def : Proc<"sparclet", []>; +def : Proc<"tsc701", []>; +def : Proc<"myriad2", []>; +def : Proc<"myriad2.1", []>; +def : Proc<"myriad2.2", []>; +def : Proc<"v9", [FeatureV9]>; +def : Proc<"ultrasparc", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>; +def : Proc<"ultrasparc3", [FeatureV9, FeatureV8Deprecated, FeatureVIS, + FeatureVIS2]>; +def : Proc<"niagara", [FeatureV9, FeatureV8Deprecated, FeatureVIS, + FeatureVIS2]>; +def : Proc<"niagara2", [FeatureV9, FeatureV8Deprecated, UsePopc, + FeatureVIS, FeatureVIS2]>; +def : Proc<"niagara3", [FeatureV9, FeatureV8Deprecated, UsePopc, + FeatureVIS, FeatureVIS2]>; +def : Proc<"niagara4", [FeatureV9, FeatureV8Deprecated, UsePopc, + FeatureVIS, FeatureVIS2, FeatureVIS3]>; // LEON 2 FT generic -def : Processor<"leon2", LEON2Itineraries, [ FeatureLeon ]>; +def : Processor<"leon2", LEON2Itineraries, + [FeatureLeon]>; // LEON 2 FT (AT697E) -// AT697E: Provides full coverage of AT697E - covers all the erratum fixes for -// LEON2 AT697E -def : Processor<"at697e", LEON2Itineraries, [ - FeatureLeon, ReplaceSDIV, FixCALL, IgnoreZeroFlag, InsertNOPDoublePrecision, - FillDataCache, RestoreExecAddress -]>; +// TO DO: Place-holder: Processor specific features will be added *very* soon here. +def : Processor<"at697e", LEON2Itineraries, + [FeatureLeon, InsertNOPLoad]>; // LEON 2 FT (AT697F) -// AT697F: Provides full coverage of AT697F - covers all the erratum fixes for -// LEON2 AT697F +// TO DO: Place-holder: Processor specific features will be added *very* soon here. def : Processor<"at697f", LEON2Itineraries, - [ FeatureLeon, InsertNOPDoublePrecision ]>; + [FeatureLeon, InsertNOPLoad]>; + // LEON 3 FT generic -def : Processor<"leon3", LEON3Itineraries, [ FeatureLeon, UMACSMACSupport ]>; +def : Processor<"leon3", LEON3Itineraries, + [FeatureLeon, UMACSMACSupport]>; // LEON 3 FT (UT699). Provides features for the UT699 processor -// - covers all the erratum fixes for LEON3, but does not support the CASA -// instruction. -def : Processor<"ut699", LEON3Itineraries, [ - FeatureLeon, FixFSMULD, ReplaceFMULS, PreventRoundChange, - FixAllFDIVSQRT, InsertNOPLoad, InsertNOPsLoadStore -]>; +// - covers all the erratum fixes for LEON3, but does not support the CASA instruction. +def : Processor<"ut699", LEON3Itineraries, + [FeatureLeon, InsertNOPLoad, FixFSMULD, ReplaceFMULS, FixAllFDIVSQRT]>; // LEON3 FT (GR712RC). Provides features for the GR712RC processor. -// - covers all the erratum fixed for LEON3 and support for the CASA -// instruction. +// - covers all the erratum fixed for LEON3 and support for the CASA instruction. def : Processor<"gr712rc", LEON3Itineraries, - [ FeatureLeon, LeonCASA ]>; + [FeatureLeon, LeonCASA]>; // LEON 4 FT generic def : Processor<"leon4", LEON4Itineraries, - [ FeatureLeon, LeonCASA ]>; + [FeatureLeon, UMACSMACSupport, LeonCASA]>; -// GR740: Provides full coverage of GR740 - covers all the erratum fixes for -// LEON3 + support to CASA + LEON 4 instruction timings -def : Processor<"gr740", LEON4Itineraries, - [ FeatureLeon, LeonCASA ]> {} +// LEON 4 FT (GR740) +// TO DO: Place-holder: Processor specific features will be added *very* soon here. +def : Processor<"gr740", LEON4Itineraries, + [FeatureLeon, UMACSMACSupport, LeonCASA]>; //===----------------------------------------------------------------------===// // Declare the target which we are implementing //===----------------------------------------------------------------------===// def SparcAsmWriter : AsmWriter { - string AsmWriterClassName = "InstPrinter"; + string AsmWriterClassName = "InstPrinter"; int PassSubtarget = 1; int Variant = 0; } @@ -156,6 +151,6 @@ def SparcAsmWriter : AsmWriter { def Sparc : Target { // Pull in Instruction Info: let InstructionSet = SparcInstrInfo; - let AssemblyParsers = [ SparcAsmParser ]; - let AssemblyWriters = [ SparcAsmWriter ]; + let AssemblyParsers = [SparcAsmParser]; + let AssemblyWriters = [SparcAsmWriter]; } diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index 253dfc06b21..a043d1102a7 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -32,6 +32,7 @@ #include "llvm/Support/ErrorHandling.h" using namespace llvm; + //===----------------------------------------------------------------------===// // Calling Convention Implementation //===----------------------------------------------------------------------===// @@ -1616,7 +1617,9 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM, // Atomics are supported on SparcV9. 32-bit atomics are also // supported by some Leon SparcV8 variants. Otherwise, atomics // are unsupported. - if (Subtarget->isV9() || Subtarget->hasLeonCasa()) + if (Subtarget->isV9()) + setMaxAtomicSizeInBitsSupported(64); + else if (Subtarget->hasLeonCasa()) setMaxAtomicSizeInBitsSupported(64); else setMaxAtomicSizeInBitsSupported(0); @@ -2628,6 +2631,7 @@ static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG, uint64_t depth = Op.getConstantOperandVal(0); return getFRAMEADDR(depth, Op, DAG, Subtarget); + } static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG, @@ -3042,7 +3046,7 @@ MachineBasicBlock * SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const { switch (MI.getOpcode()) { - default: llvm_unreachable("Unknown Custom Instruction!"); + default: llvm_unreachable("Unknown SELECT_CC!"); case SP::SELECT_CC_Int_ICC: case SP::SELECT_CC_FP_ICC: case SP::SELECT_CC_DFP_ICC: @@ -3059,6 +3063,7 @@ SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, case SP::EH_SJLJ_LONGJMP32rr: case SP::EH_SJLJ_LONGJMP32ri: return emitEHSjLjLongJmp(MI, BB); + } } @@ -3329,11 +3334,8 @@ SparcTargetLowering::ConstraintType SparcTargetLowering::getConstraintType(StringRef Constraint) const { if (Constraint.size() == 1) { switch (Constraint[0]) { - default: - break; - case 'f': - case 'r': - return C_RegisterClass; + default: break; + case 'r': return C_RegisterClass; case 'I': // SIMM13 return C_Other; } @@ -3407,9 +3409,6 @@ SparcTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, MVT VT) const { if (Constraint.size() == 1) { switch (Constraint[0]) { - case 'f': - return std::make_pair(0U, &SP::FPRegsRegClass); - case 'r': if (VT == MVT::v2i32) return std::make_pair(0U, &SP::IntPairRegClass); diff --git a/lib/Target/Sparc/SparcSubtarget.cpp b/lib/Target/Sparc/SparcSubtarget.cpp index f38c578cc93..97d4aef3378 100644 --- a/lib/Target/Sparc/SparcSubtarget.cpp +++ b/lib/Target/Sparc/SparcSubtarget.cpp @@ -39,19 +39,10 @@ SparcSubtarget &SparcSubtarget::initializeSubtargetDependencies(StringRef CPU, // Leon features HasLeonCasa = false; HasUmacSmac = false; - PerformSDIVReplace = false; - FixCallImmediates = false; - IgnoreZeroFlag = false; - InsertNOPDoublePrecision = false; + InsertNOPLoad = false; FixFSMULD = false; ReplaceFMULS = false; - PreventRoundChange = false; FixAllFDIVSQRT = false; - InsertNOPLoad = false; - InsertNOPsLoadStore = false; - FillDataCache = false; - RestoreExecAddress = false; - // Determine default and user specified characteristics std::string CPUName = CPU; diff --git a/lib/Target/Sparc/SparcSubtarget.h b/lib/Target/Sparc/SparcSubtarget.h index 7389e9b16fa..9122f54f7c8 100644 --- a/lib/Target/Sparc/SparcSubtarget.h +++ b/lib/Target/Sparc/SparcSubtarget.h @@ -48,15 +48,6 @@ class SparcSubtarget : public SparcGenSubtargetInfo { bool FixFSMULD; bool ReplaceFMULS; bool FixAllFDIVSQRT; - bool UseSoftFpu; - bool PerformSDIVReplace; - bool FixCallImmediates; - bool IgnoreZeroFlag; - bool InsertNOPDoublePrecision; - bool PreventRoundChange; - bool InsertNOPsLoadStore; - bool FillDataCache; - bool RestoreExecAddress; SparcInstrInfo InstrInfo; SparcTargetLowering TLInfo; @@ -94,21 +85,12 @@ public: bool useSoftFloat() const { return UseSoftFloat; } // Leon options - bool useSoftFpu() const { return UseSoftFpu; } - bool hasLeonCasa() const { return HasLeonCasa; } bool hasUmacSmac() const { return HasUmacSmac; } - bool performSDIVReplace() const { return PerformSDIVReplace; } - bool fixCallImmediates() const { return FixCallImmediates; } - bool ignoreZeroFlag() const { return IgnoreZeroFlag; } - bool insertNOPDoublePrecision() const { return InsertNOPDoublePrecision; } + bool hasLeonCasa() const { return HasLeonCasa; } + bool insertNOPLoad() const { return InsertNOPLoad; } bool fixFSMULD() const { return FixFSMULD; } bool replaceFMULS() const { return ReplaceFMULS; } - bool preventRoundChange() const { return PreventRoundChange; } bool fixAllFDIVSQRT() const { return FixAllFDIVSQRT; } - 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/lib/Target/Sparc/SparcTargetMachine.cpp b/lib/Target/Sparc/SparcTargetMachine.cpp index b0ddd98798f..d8a047a72ba 100644 --- a/lib/Target/Sparc/SparcTargetMachine.cpp +++ b/lib/Target/Sparc/SparcTargetMachine.cpp @@ -76,7 +76,7 @@ SparcTargetMachine::SparcTargetMachine(const Target &T, const Triple &TT, SparcTargetMachine::~SparcTargetMachine() {} -const SparcSubtarget * +const SparcSubtarget * SparcTargetMachine::getSubtargetImpl(const Function &F) const { Attribute CPUAttr = F.getFnAttribute("target-cpu"); Attribute FSAttr = F.getFnAttribute("target-features"); @@ -95,7 +95,7 @@ SparcTargetMachine::getSubtargetImpl(const Function &F) const { F.hasFnAttribute("use-soft-float") && F.getFnAttribute("use-soft-float").getValueAsString() == "true"; - if (softFloat) + if (softFloat) FS += FS.empty() ? "+soft-float" : ",+soft-float"; auto &I = SubtargetMap[CPU + FS]; @@ -115,7 +115,7 @@ namespace { class SparcPassConfig : public TargetPassConfig { public: SparcPassConfig(SparcTargetMachine *TM, PassManagerBase &PM) - : TargetPassConfig(TM, PM) {} + : TargetPassConfig(TM, PM) {} SparcTargetMachine &getSparcTargetMachine() const { return getTM(); @@ -142,49 +142,28 @@ bool SparcPassConfig::addInstSelector() { return false; } -void SparcPassConfig::addPreEmitPass() { +void SparcPassConfig::addPreEmitPass(){ addPass(createSparcDelaySlotFillerPass(getSparcTargetMachine())); - if (this->getSparcTargetMachine().getSubtargetImpl()->ignoreZeroFlag()) { - addPass(new IgnoreZeroFlag(getSparcTargetMachine())); - } - if (this->getSparcTargetMachine().getSubtargetImpl()->performSDIVReplace()) { - addPass(new ReplaceSDIV(getSparcTargetMachine())); - } - if (this->getSparcTargetMachine().getSubtargetImpl()->fixCallImmediates()) { - addPass(new FixCALL(getSparcTargetMachine())); - } - if (this->getSparcTargetMachine().getSubtargetImpl()->fixFSMULD()) { - addPass(new FixFSMULD(getSparcTargetMachine())); - } - if (this->getSparcTargetMachine().getSubtargetImpl()->replaceFMULS()) { - addPass(new ReplaceFMULS(getSparcTargetMachine())); - } - if (this->getSparcTargetMachine().getSubtargetImpl()->preventRoundChange()) { - addPass(new PreventRoundChange(getSparcTargetMachine())); - } - if (this->getSparcTargetMachine().getSubtargetImpl()->fixAllFDIVSQRT()) { - addPass(new FixAllFDIVSQRT(getSparcTargetMachine())); - } - if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPsLoadStore()) { - addPass(new InsertNOPsLoadStore(getSparcTargetMachine())); - } - if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPLoad()) { + + if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPLoad()) + { addPass(new InsertNOPLoad(getSparcTargetMachine())); } - if (this->getSparcTargetMachine().getSubtargetImpl()->fillDataCache()) { - addPass(new FillDataCache(getSparcTargetMachine())); + if (this->getSparcTargetMachine().getSubtargetImpl()->fixFSMULD()) + { + addPass(new FixFSMULD(getSparcTargetMachine())); } - if (this->getSparcTargetMachine().getSubtargetImpl()->restoreExecAddr()) { - addPass(new RestoreExecAddress(getSparcTargetMachine())); + if (this->getSparcTargetMachine().getSubtargetImpl()->replaceFMULS()) + { + addPass(new ReplaceFMULS(getSparcTargetMachine())); } - if (this->getSparcTargetMachine() - .getSubtargetImpl() - ->insertNOPDoublePrecision()) { - addPass(new InsertNOPDoublePrecision(getSparcTargetMachine())); + if (this->getSparcTargetMachine().getSubtargetImpl()->fixAllFDIVSQRT()) + { + addPass(new FixAllFDIVSQRT(getSparcTargetMachine())); } } -void SparcV8TargetMachine::anchor() {} +void SparcV8TargetMachine::anchor() { } SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, @@ -194,7 +173,7 @@ SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const Triple &TT, CodeGenOpt::Level OL) : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} -void SparcV9TargetMachine::anchor() {} +void SparcV9TargetMachine::anchor() { } SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, diff --git a/test/CodeGen/SPARC/LeonFillDataCachePassUT.ll b/test/CodeGen/SPARC/LeonFillDataCachePassUT.ll deleted file mode 100755 index 5461642110d..00000000000 --- a/test/CodeGen/SPARC/LeonFillDataCachePassUT.ll +++ /dev/null @@ -1,27 +0,0 @@ -; RUN: llc %s -O0 -march=sparc -mcpu=leon2 -mattr=+filldatacache -o - | FileCheck %s -; RUN: llc %s -O0 -march=sparc -mcpu=at697e -o - | FileCheck %s -; RUN: llc %s -O0 -march=sparc -mcpu=at697f -mattr=+filldatacache -o - | FileCheck %s - -; CHECK-LABEL: test_filldatacache_1 -; CHECK: or %g0, 1, %g1 -; CHECK: nop -; CHECK-NEXT: add %g1, 1, %g1 -; CHECK-NEXT: cmp %g1, 4096 -; CHECK-NEXT: ble {{.+}} -define zeroext i1@test_filldatacache_1(i1 zeroext %a, i1 zeroext %b) { - %1 = tail call zeroext i1 asm sideeffect "udivcc $0, $1, $2", "=r,r,r"(i1 zeroext %a, i1 zeroext %b) - - ret i1 %1 -} - - -; CHECK-LABEL: test_filldatacache_2 -; CHECK-NOT: or %g0, 1, %g1 -; CHECK-NOT: add %g1, 1, %g1 -; CHECK-NOT: cmp %g1, 4096 -; CHECK-NOT: ble {{.+}} -define zeroext i1@test_filldatacache_2(i1 zeroext %a, i1 zeroext %b) { - %1 = tail call zeroext i1 asm sideeffect "sdivcc $0, $1, $2", "=r,r,r"(i1 zeroext %a, i1 zeroext %b) - - ret i1 %1 -} diff --git a/test/CodeGen/SPARC/LeonFixFSMULDPassUT.ll b/test/CodeGen/SPARC/LeonFixFSMULDPassUT.ll index a9fae8e50fc..e2f2323a049 100755 --- a/test/CodeGen/SPARC/LeonFixFSMULDPassUT.ll +++ b/test/CodeGen/SPARC/LeonFixFSMULDPassUT.ll @@ -1,17 +1,31 @@ -; RUN: llc %s -O0 -march=sparc -mattr=fixfsmuld -o - | FileCheck %s -; RUN: llc %s -O0 -march=sparc -o - | FileCheck %s --check-prefix=NOFIX +; RUN: llc %s -O0 -march=sparc -mcpu=ut699 -o - | FileCheck %s ; CHECK-LABEL: test_fix_fsmuld_1 -; CHECK: fstod %f1, %f2 -; CHECK: fstod %f0, %f4 -; CHECK: fmuld %f2, %f4, %f0 -; NOFIX-LABEL: test_fix_fsmuld_1 -; NOFIX: fsmuld %f1, %f0, %f0 -define double @test_fix_fsmuld_1(float %a, float %b) { +; CHECK: fstod %f20, %f2 +; CHECK: fstod %f21, %f3 +; CHECK: fmuld %f2, %f3, %f8 +; CHECK: fstod %f20, %f0 +define double @test_fix_fsmuld_1() { entry: - %0 = fpext float %a to double - %1 = fpext float %b to double - %mul = fmul double %0, %1 + %a = alloca float, align 4 + %b = alloca float, align 4 + store float 0x402ECCCCC0000000, float* %a, align 4 + store float 0x4022333340000000, float* %b, align 4 + %0 = load float, float* %b, align 4 + %1 = load float, float* %a, align 4 + %mul = tail call double asm sideeffect "fsmuld $0, $1, $2", "={f20},{f21},{f8}"(float* %a, float* %b) + + ret double %mul +} + +; CHECK-LABEL: test_fix_fsmuld_2 +; CHECK: fstod %f20, %f2 +; CHECK: fstod %f21, %f3 +; CHECK: fmuld %f2, %f3, %f8 +; CHECK: fstod %f20, %f0 +define double @test_fix_fsmuld_2(float* %a, float* %b) { +entry: + %mul = tail call double asm sideeffect "fsmuld $0, $1, $2", "={f20},{f21},{f8}"(float* %a, float* %b) ret double %mul } diff --git a/test/CodeGen/SPARC/LeonInsertNOPLoad.ll b/test/CodeGen/SPARC/LeonInsertNOPLoad.ll deleted file mode 100644 index 315fc85fca3..00000000000 --- a/test/CodeGen/SPARC/LeonInsertNOPLoad.ll +++ /dev/null @@ -1,13 +0,0 @@ -; RUN: llc %s -O0 -march=sparc -mcpu=ut699 -o - | FileCheck %s - -; CHECK: ld [%o0+%lo(.LCPI0_0)], %f0 -; CHECK-NEXT: nop - - -define float @X() #0 { -entry: - %f = alloca float, align 4 - store float 0x3FF3C08320000000, float* %f, align 4 - %0 = load float, float* %f, align 4 - ret float %0 -} diff --git a/test/CodeGen/SPARC/LeonInsertNOPLoadPassUT.ll b/test/CodeGen/SPARC/LeonInsertNOPLoadPassUT.ll index 9b4ceb7ea6a..57ae16227e7 100755 --- a/test/CodeGen/SPARC/LeonInsertNOPLoadPassUT.ll +++ b/test/CodeGen/SPARC/LeonInsertNOPLoadPassUT.ll @@ -19,3 +19,25 @@ define i32 @ld_i32_test(i32 *%p) { %res = load i32, i32* %p ret i32 %res } + +; CHECK-LABEL: ld_inlineasm_test_1 +; CHECK: ld [%o0], %o0 +; CHECK-NEXT: !NO_APP +; CHECK-NEXT: nop +define float @ld_inlineasm_test_1(float* %a) { +entry: + %res = tail call float asm sideeffect "ld [$1], $0", "=r,r"(float* %a) + + ret float %res +} + +; CHECK-LABEL: ld_inlineasm_test_2 +; CHECK: ld [%o0], %o0 +; CHECK-NEXT: !NO_APP +; CHECK-NEXT: nop +define i32 @ld_inlineasm_test_2(i32* %a) { +entry: + %res = tail call i32 asm sideeffect "ld [$1], $0", "=r,r"(i32* %a) + + ret i32 %res +} \ No newline at end of file diff --git a/test/CodeGen/SPARC/LeonInsertNOPsDoublePrecision.ll b/test/CodeGen/SPARC/LeonInsertNOPsDoublePrecision.ll deleted file mode 100644 index 0ee3d9071a9..00000000000 --- a/test/CodeGen/SPARC/LeonInsertNOPsDoublePrecision.ll +++ /dev/null @@ -1,17 +0,0 @@ -; RUN: llc %s -O0 -march=sparc -mcpu=at697f -o - | FileCheck %s - -; CHECK: ldd -; CHECK: ldd -; CHECK-NEXT: nop - -define double @mult() #0 { -entry: - %x = alloca double, align 8 - %y = alloca double, align 8 - store double 3.141590e+00, double* %x, align 8 - store double 1.234560e+00, double* %y, align 8 - %0 = load double, double* %x, align 8 - %1 = load double, double* %y, align 8 - %mul = fmul double %0, %1 - ret double %mul -} diff --git a/test/CodeGen/SPARC/LeonPreventRoundChangePassUT.ll b/test/CodeGen/SPARC/LeonPreventRoundChangePassUT.ll deleted file mode 100644 index 07172fdb945..00000000000 --- a/test/CodeGen/SPARC/LeonPreventRoundChangePassUT.ll +++ /dev/null @@ -1,65 +0,0 @@ -; RUN: llc %s -O0 -march=sparc -mcpu=ut699 -o - | FileCheck %s -check-prefix=NO_ROUND_FUNC -; RUN: llc %s -O0 -march=sparc -mcpu=leon3 -mattr=+prvntroundchange -o - | FileCheck %s -check-prefix=NO_ROUND_FUNC - -; RUN: llc %s -O0 -march=sparc -mcpu=ut699 -mattr=-prvntroundchange -o - | FileCheck %s -check-prefix=ROUND_FUNC -; RUN: llc %s -O0 -march=sparc -mcpu=leon3 -o - | FileCheck %s -check-prefix=ROUND_FUNC - - -; NO_ROUND_FUNC-LABEL: test_round_change -; NO_ROUND_FUNC-NOT: fesetround - -; ROUND_FUNC-LABEL: test_round_change -; ROUND_FUNC: fesetround - -; ModuleID = '' -target datalayout = "E-m:e-p:32:32-i64:64-f128:64-n32-S64" -target triple = "sparc-unknown--eabi" - -@.str = private unnamed_addr constant [17 x i8] c"-((-a)*b) != a*b\00", align 1 -@.str.1 = private unnamed_addr constant [7 x i8] c"test.c\00", align 1 -@__PRETTY_FUNCTION__.mult = private unnamed_addr constant [12 x i8] c"void mult()\00", align 1 - -; Function Attrs: nounwind -define void @test_round_change() #0 { -entry: - %a = alloca double, align 8 - %b = alloca double, align 8 - %x = alloca float, align 4 - store double 1.100000e+00, double* %a, align 8 - store double 1.010000e+01, double* %b, align 8 - store float 0x400921FA00000000, float* %x, align 4 - %call = call i32 @fesetround(i32 2048) #2 - %0 = load double, double* %a, align 8 - %sub = fsub double -0.000000e+00, %0 - %1 = load double, double* %b, align 8 - %mul = fmul double %sub, %1 - %sub1 = fsub double -0.000000e+00, %mul - %2 = load double, double* %a, align 8 - %3 = load double, double* %b, align 8 - %mul2 = fmul double %2, %3 - %cmp = fcmp une double %sub1, %mul2 - br i1 %cmp, label %cond.true, label %cond.false - -cond.true: ; preds = %entry - br label %cond.end - -cond.false: ; preds = %entry - call void @__assert_fail(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i32 0, i32 0), i32 10, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @__PRETTY_FUNCTION__.mult, i32 0, i32 0)) #3 - unreachable - ; No predecessors! - br label %cond.end - -cond.end: ; preds = %4, %cond.true - ret void -} - -; Function Attrs: nounwind -declare i32 @fesetround(i32) #0 - -; Function Attrs: noreturn nounwind -declare void @__assert_fail(i8*, i8*, i32, i8*) #1 - -attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { noreturn nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { nounwind } -attributes #3 = { noreturn nounwind } \ No newline at end of file diff --git a/test/CodeGen/SPARC/LeonReplaceFMULSPassUT.ll b/test/CodeGen/SPARC/LeonReplaceFMULSPassUT.ll index e9ea7c6c999..7d0950cb1c8 100755 --- a/test/CodeGen/SPARC/LeonReplaceFMULSPassUT.ll +++ b/test/CodeGen/SPARC/LeonReplaceFMULSPassUT.ll @@ -1,13 +1,19 @@ -; RUN: llc %s -O0 -march=sparc -mattr=replacefmuls -o - | FileCheck %s +; RUN: llc %s -O0 -march=sparc -mcpu=ut699 -o - | FileCheck %s -; CHECK-LABEL: test_replace_fmuls -; CHECK: fsmuld %f1, %f0, %f2 -; CHECK: fdtos %f2, %f0 -; NOFIX-LABEL: test_replace_fmuls -; NOFIX: fmuls %f1, %f0, %f0 -define float @test_replace_fmuls(float %a, float %b) { +; CHECK-LABEL: fmuls_fix_test +; CHECK: fstod %f20, %f2 +; CHECK: fstod %f21, %f3 +; CHECK: fmuld %f2, %f3, %f8 +; CHECK: fstod %f20, %f0 +define double @fmuls_fix_test() { entry: - %mul = fmul float %a, %b + %a = alloca float, align 4 + %b = alloca float, align 4 + store float 0x402ECCCCC0000000, float* %a, align 4 + store float 0x4022333340000000, float* %b, align 4 + %0 = load float, float* %b, align 4 + %1 = load float, float* %a, align 4 + %mul = tail call double asm sideeffect "fmuls $0, $1, $2", "={f20},{f21},{f8}"(float* %a, float* %b) - ret float %mul + ret double %mul } diff --git a/test/CodeGen/SPARC/LeonReplaceSDIVPassUT.ll b/test/CodeGen/SPARC/LeonReplaceSDIVPassUT.ll deleted file mode 100644 index 67232d77703..00000000000 --- a/test/CodeGen/SPARC/LeonReplaceSDIVPassUT.ll +++ /dev/null @@ -1,9 +0,0 @@ -; RUN: llc %s -O0 -march=sparc -mcpu=at697e -o - | FileCheck %s - -; CHECK: sdivcc %o0, %o1, %o0 - -define i32 @lbr59(i32 %a, i32 %b) -{ - %r = sdiv i32 %a, %b - ret i32 %r -}