Index: lib/Target/Sparc/CMakeLists.txt =================================================================== --- lib/Target/Sparc/CMakeLists.txt +++ lib/Target/Sparc/CMakeLists.txt @@ -14,6 +14,7 @@ add_llvm_target(SparcCodeGen DelaySlotFiller.cpp LeonPasses.cpp + LeonFloatOptimisations.cpp SparcAsmPrinter.cpp SparcInstrInfo.cpp SparcISelDAGToDAG.cpp Index: lib/Target/Sparc/LeonFeatures.td =================================================================== --- lib/Target/Sparc/LeonFeatures.td +++ lib/Target/Sparc/LeonFeatures.td @@ -78,12 +78,6 @@ "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 " Index: lib/Target/Sparc/LeonPasses.h =================================================================== --- lib/Target/Sparc/LeonPasses.h +++ lib/Target/Sparc/LeonPasses.h @@ -71,6 +71,18 @@ } }; +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: "; + } +}; + class LLVM_LIBRARY_VISIBILITY IgnoreZeroFlag : public LEONMachineFunctionPass { public: static char ID; @@ -84,6 +96,19 @@ } }; +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: Erratum Fix LBR29: fill data cache with values at application startup"; + } +}; + class LLVM_LIBRARY_VISIBILITY InsertNOPDoublePrecision : public LEONMachineFunctionPass { public: @@ -165,21 +190,6 @@ } }; -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: Index: lib/Target/Sparc/LeonPasses.cpp =================================================================== --- lib/Target/Sparc/LeonPasses.cpp +++ 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; @@ -90,15 +91,6 @@ MachineBasicBlock::iterator NMBBI = std::next(MBBI); BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); Modified = true; - } else if (MI.isInlineAsm()) { - // Look for an inline ld or ldf instruction. - StringRef AsmString = - MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); - if (AsmString.startswith_lower("ld")) { - MachineBasicBlock::iterator NMBBI = std::next(MBBI); - BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); - Modified = true; - } } } } @@ -148,29 +140,6 @@ Reg1Index = MI.getOperand(0).getReg(); Reg2Index = MI.getOperand(1).getReg(); Reg3Index = MI.getOperand(2).getReg(); - } else if (MI.isInlineAsm()) { - StringRef AsmString = - MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName(); - if (AsmString.startswith_lower("fsmuld")) { - // this is an inline FSMULD instruction - - unsigned StartOp = InlineAsm::MIOp_FirstOperand; - - // extracts the registers from the inline assembly instruction - for (unsigned i = StartOp, e = MI.getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI.getOperand(i); - if (MO.isReg()) { - if (Reg1Index == UNASSIGNED_INDEX) - Reg1Index = MO.getReg(); - else if (Reg2Index == UNASSIGNED_INDEX) - Reg2Index = MO.getReg(); - else if (Reg3Index == UNASSIGNED_INDEX) - Reg3Index = MO.getReg(); - } - if (Reg3Index != UNASSIGNED_INDEX) - break; - } - } } if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX && @@ -260,28 +229,6 @@ 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 && @@ -363,18 +310,6 @@ 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 @@ -454,8 +389,6 @@ 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) { @@ -470,24 +403,6 @@ 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; - } - } - } } } } @@ -563,55 +478,6 @@ 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; - } } } } @@ -653,7 +519,6 @@ 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); @@ -729,6 +594,12 @@ 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; @@ -741,62 +612,6 @@ 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(); - 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 @@ -931,3 +746,189 @@ 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; +} + Index: lib/Target/Sparc/Sparc.td =================================================================== --- lib/Target/Sparc/Sparc.td +++ lib/Target/Sparc/Sparc.td @@ -124,7 +124,7 @@ // 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. Index: lib/Target/Sparc/SparcSubtarget.h =================================================================== --- lib/Target/Sparc/SparcSubtarget.h +++ lib/Target/Sparc/SparcSubtarget.h @@ -54,7 +54,6 @@ bool IgnoreZeroFlag; bool InsertNOPDoublePrecision; bool PreventRoundChange; - bool FlushCacheLineSWAP; bool InsertNOPsLoadStore; SparcInstrInfo InstrInfo; @@ -104,7 +103,6 @@ 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; } Index: lib/Target/Sparc/SparcSubtarget.cpp =================================================================== --- lib/Target/Sparc/SparcSubtarget.cpp +++ lib/Target/Sparc/SparcSubtarget.cpp @@ -48,7 +48,6 @@ PreventRoundChange = false; FixAllFDIVSQRT = false; InsertNOPLoad = false; - FlushCacheLineSWAP = false; InsertNOPsLoadStore = false; // Determine default and user specified characteristics Index: lib/Target/Sparc/SparcTargetMachine.cpp =================================================================== --- lib/Target/Sparc/SparcTargetMachine.cpp +++ lib/Target/Sparc/SparcTargetMachine.cpp @@ -171,9 +171,6 @@ if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPLoad()) { addPass(new InsertNOPLoad(getSparcTargetMachine())); } - if (this->getSparcTargetMachine().getSubtargetImpl()->flushCacheLineSWAP()) { - addPass(new FlushCacheLineSWAP(getSparcTargetMachine())); - } if (this->getSparcTargetMachine() .getSubtargetImpl() ->insertNOPDoublePrecision()) { Index: test/CodeGen/SPARC/LeonFillDataCachePassUT.ll =================================================================== --- test/CodeGen/SPARC/LeonFillDataCachePassUT.ll +++ test/CodeGen/SPARC/LeonFillDataCachePassUT.ll @@ -0,0 +1,27 @@ +; RUN: llc %s -O0 -march=sparc -mcpu=leon2 -mattr=+flldatacache -o - | FileCheck %s +; RUN: llc %s -O0 -march=sparc -mcpu=at697e -o - | FileCheck %s +; RUN: llc %s -O0 -march=sparc -mcpu=at697f -mattr=+flldatacache -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 +} \ No newline at end of file Index: test/CodeGen/SPARC/LeonFixCALLPassUT.ll =================================================================== --- test/CodeGen/SPARC/LeonFixCALLPassUT.ll +++ test/CodeGen/SPARC/LeonFixCALLPassUT.ll @@ -1,20 +0,0 @@ -; RUN: llc %s -O0 -march=sparc -mcpu=at697e -o - | FileCheck %s -check-prefix=FIXCALL -; RUN: llc %s -O0 -march=sparc -mcpu=leon2 -mattr=+fixcall -o - | FileCheck %s -check-prefix=FIXCALL - -; RUN: llc %s -O0 -march=sparc -mcpu=at697e -mattr=-fixcall -o - | FileCheck %s -check-prefix=NO_FIXCALL -; RUN: llc %s -O0 -march=sparc -mcpu=leon2 -o - | FileCheck %s -check-prefix=NO_FIXCALL - - -; FIXCALL-LABEL: immediate_call_test -; FIXCALL: call 763288 - -; NO_FIXCALL-LABEL: immediate_call_test -; NO_FIXCALL: call 2047583640 -define void @immediate_call_test() nounwind { -entry: - call void asm sideeffect "call $0", "i"(i32 2047583640) nounwind - ret void -} - - - Index: test/CodeGen/SPARC/LeonInsertNOPLoadPassUT.ll =================================================================== --- test/CodeGen/SPARC/LeonInsertNOPLoadPassUT.ll +++ test/CodeGen/SPARC/LeonInsertNOPLoadPassUT.ll @@ -19,25 +19,3 @@ %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 Index: test/CodeGen/SPARC/LeonRestExecAddrPassUT.ll =================================================================== --- test/CodeGen/SPARC/LeonRestExecAddrPassUT.ll +++ test/CodeGen/SPARC/LeonRestExecAddrPassUT.ll @@ -0,0 +1,65 @@ +; RUN: llc %s -O0 -march=sparc -mcpu=leon2 -mattr=+restexecaddr -o - | FileCheck %s +; RUN: llc %s -O0 -march=sparc -mcpu=at697e -o - | FileCheck %s +; RUN: llc %s -O0 -march=sparc -mcpu=at697f -mattr=+restexecaddr -o - | FileCheck %s +; RUN: llc %s -O0 -march=sparc -mcpu=leon2 -o - | FileCheck %s -check-prefix=FixOff + +declare void @llvm.trap() + +; CHECK-LABEL: test_restexecaddr_1 +; CHECK: ta 5 +; CHECK: st %fsr, [%l7] +; CHECK-NEXT: ld [%l7], %l7 +; CHECK-NEXT: and %l7, 15, %l7 +; CHECK-NEXT: cmp %l7, 0 +; CHECK-NEXT: be +; CHECK-NEXT: rett %l2+4 +; CHECK: rett %g0 +; FixOff-LABEL: test_restexecaddr_1 +; FixOff-NOT: st %fsr, [%l7] +; FixOff-NOT: ld [%l7], %l7 +; FixOff-NOT: and %l7, 15, %l7 +; FixOff-NOT: cmp %l7, 0 +; FixOff-NOT: be +; FixOff-NOT: rett %l2+4 +define void @test_restexecaddr_1() { + call void @llvm.trap() + call void asm sideeffect "rett %g0", ""() + + ret void +} + +; CHECK-LABEL: test_restexecaddr_2 +; CHECK-NOT: st %fsr, [%l7] +; CHECK-NOT: ld [%l7], %l7 +; CHECK-NOT: and %l7, 15, %l7 +; CHECK-NOT: cmp %l7, 0 +; CHECK-NOT: be +; CHECK-NOT: rett %l2+4 +define zeroext i1@test_restexecaddr_2(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_restexecaddr_3 +; CHECK: ta 5 +; CHECK: st %fsr, [%l7] +; CHECK-NEXT: ld [%l7], %l7 +; CHECK-NEXT: and %l7, 15, %l7 +; CHECK-NEXT: cmp %l7, 0 +; CHECK-NEXT: be +; CHECK-NEXT: rett %l2+4 +; CHECK: rett %g0 +; FixOff-LABEL: test_restexecaddr_3 +; FixOff-NOT: st %fsr, [%l7] +; FixOff-NOT: ld [%l7], %l7 +; FixOff-NOT: and %l7, 15, %l7 +; FixOff-NOT: cmp %l7, 0 +; FixOff-NOT: be +; FixOff-NOT: rett %l2+4 +define void @test_restexecaddr_3() { + call void @llvm.trap() + call void asm sideeffect "rett %g0", ""() + + ret void +} \ No newline at end of file