Index: lib/Target/Sparc/LeonFeatures.td =================================================================== --- lib/Target/Sparc/LeonFeatures.td +++ lib/Target/Sparc/LeonFeatures.td @@ -37,6 +37,14 @@ "Enable CASA instruction for LEON3 and LEON4 processors" >; + +def ReplaceSDIV : SubtargetFeature< + "replacesdiv", + "PerformSDIVReplace", + "true", + "AT697E erratum fix: Do not emit SDIV, emit SDIVCC instead" +>; + def InsertNOPLoad: SubtargetFeature< "insertnopload", "InsertNOPLoad", Index: lib/Target/Sparc/LeonPasses.h =================================================================== --- lib/Target/Sparc/LeonPasses.h +++ lib/Target/Sparc/LeonPasses.h @@ -44,6 +44,20 @@ int getUnusedFPRegister(MachineRegisterInfo &MRI); }; +class LLVM_LIBRARY_VISIBILITY ReplaceSDIV : public LEONMachineFunctionPass { +public: + static char ID; + + ReplaceSDIV(); + ReplaceSDIV(TargetMachine &tm); + bool runOnMachineFunction(MachineFunction &MF) override; + + StringRef getPassName() const override { + return "ReplaceSDIV: Leon erratum fix: do not emit SDIV, but emit SDIVCC " + "instead"; + } +}; + class LLVM_LIBRARY_VISIBILITY InsertNOPLoad : public LEONMachineFunctionPass { public: static char ID; Index: lib/Target/Sparc/LeonPasses.cpp =================================================================== --- lib/Target/Sparc/LeonPasses.cpp +++ lib/Target/Sparc/LeonPasses.cpp @@ -275,6 +275,42 @@ } //***************************************************************************** +//**** 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; +} + +//***************************************************************************** //**** FixAllFDIVSQRT pass //***************************************************************************** // This pass fixes the incorrectly working FDIVx and FSQRTx instructions that Index: lib/Target/Sparc/Sparc.td =================================================================== --- lib/Target/Sparc/Sparc.td +++ lib/Target/Sparc/Sparc.td @@ -110,7 +110,7 @@ // LEON 2 FT (AT697E) // TO DO: Place-holder: Processor specific features will be added *very* soon here. def : Processor<"at697e", LEON2Itineraries, - [FeatureLeon, InsertNOPLoad]>; + [FeatureLeon, ReplaceSDIV, InsertNOPLoad]>; // LEON 2 FT (AT697F) // TO DO: Place-holder: Processor specific features will be added *very* soon here. Index: lib/Target/Sparc/SparcISelLowering.cpp =================================================================== --- lib/Target/Sparc/SparcISelLowering.cpp +++ lib/Target/Sparc/SparcISelLowering.cpp @@ -1498,7 +1498,6 @@ setOperationAction(ISD::STORE, MVT::v2i32, Legal); setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v2i32, Legal); setOperationAction(ISD::BUILD_VECTOR, MVT::v2i32, Legal); - // And we need to promote i64 loads/stores into vector load/store setOperationAction(ISD::LOAD, MVT::i64, Custom); setOperationAction(ISD::STORE, MVT::i64, Custom); Index: lib/Target/Sparc/SparcInstrInfo.td =================================================================== --- lib/Target/Sparc/SparcInstrInfo.td +++ lib/Target/Sparc/SparcInstrInfo.td @@ -61,6 +61,9 @@ def HasNoFmulsFix : Predicate<"!Subtarget->replaceFMULS()">; def HasNoFsmuldFix : Predicate<"!Subtarget->fixFSMULD()">; +def HasLeonSdivReplace : Predicate<"Subtarget->performSDIVReplace()">; +def HasNoLeonSdivReplace : Predicate<"!Subtarget->performSDIVReplace()">; + // UseDeprecatedInsts - This predicate is true when the target processor is a // V8, or when it is V9 but the V8 deprecated instructions are efficient enough // to use when appropriate. In either of these cases, the instruction selector @@ -748,10 +751,14 @@ } // Section B.19 - Divide Instructions, p. 115 -let Uses = [Y], Defs = [Y] in { +let Uses = [Y], Defs = [Y] in defm UDIV : F3_12np<"udiv", 0b001110, IIC_iu_div>; + +let Predicates = [HasNoLeonSdivReplace], Uses = [Y], Defs = [Y] in defm SDIV : F3_12np<"sdiv", 0b001111, IIC_iu_div>; -} + +let Predicates = [HasLeonSdivReplace], DecoderNamespace = "leon2", Uses = [Y], Defs = [Y, ICC] in + defm SDIVleon2 : F3_12np<"sdiv", 0b001111, IIC_iu_div>; let Uses = [Y], Defs = [Y, ICC] in { defm UDIVCC : F3_12np<"udivcc", 0b011110, IIC_iu_div>; Index: lib/Target/Sparc/SparcSubtarget.h =================================================================== --- lib/Target/Sparc/SparcSubtarget.h +++ lib/Target/Sparc/SparcSubtarget.h @@ -48,6 +48,7 @@ bool FixFSMULD; bool ReplaceFMULS; bool FixAllFDIVSQRT; + bool PerformSDIVReplace; SparcInstrInfo InstrInfo; SparcTargetLowering TLInfo; @@ -86,6 +87,7 @@ // Leon options bool hasUmacSmac() const { return HasUmacSmac; } + bool performSDIVReplace() const { return PerformSDIVReplace; } bool hasLeonCasa() const { return HasLeonCasa; } bool insertNOPLoad() const { return InsertNOPLoad; } bool fixFSMULD() const { return FixFSMULD; } Index: lib/Target/Sparc/SparcSubtarget.cpp =================================================================== --- lib/Target/Sparc/SparcSubtarget.cpp +++ lib/Target/Sparc/SparcSubtarget.cpp @@ -39,6 +39,7 @@ // Leon features HasLeonCasa = false; HasUmacSmac = false; + PerformSDIVReplace = false; InsertNOPLoad = false; FixFSMULD = false; ReplaceFMULS = false; Index: lib/Target/Sparc/SparcTargetMachine.cpp =================================================================== --- lib/Target/Sparc/SparcTargetMachine.cpp +++ lib/Target/Sparc/SparcTargetMachine.cpp @@ -145,6 +145,9 @@ void SparcPassConfig::addPreEmitPass(){ addPass(createSparcDelaySlotFillerPass(getSparcTargetMachine())); + if (this->getSparcTargetMachine().getSubtargetImpl()->performSDIVReplace()) { + addPass(new ReplaceSDIV(getSparcTargetMachine())); + } if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPLoad()) { addPass(new InsertNOPLoad(getSparcTargetMachine()));