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/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/SparcISelDAGToDAG.cpp =================================================================== --- lib/Target/Sparc/SparcISelDAGToDAG.cpp +++ lib/Target/Sparc/SparcISelDAGToDAG.cpp @@ -360,6 +360,12 @@ // FIXME: Handle div by immediate. unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr; + // SDIV is a hardware erratum on some LEON2 processors. Replace it with SDIVcc here. + if (((SparcTargetMachine&)TM).getSubtargetImpl()->performSDIVReplace() + && + Opcode == SP::SDIVrr) { + Opcode = SP::SDIVCCrr; + } CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS, TopPart); return; } 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: test/CodeGen/SPARC/LeonReplaceSDIVPassUT.ll =================================================================== --- test/CodeGen/SPARC/LeonReplaceSDIVPassUT.ll +++ test/CodeGen/SPARC/LeonReplaceSDIVPassUT.ll @@ -0,0 +1,11 @@ +; RUN: llc %s -O0 -march=sparc -o - | FileCheck %s -check-prefix=NO_REPLACE_SDIV +; RUN: llc %s -O0 -march=sparc -mcpu=at697e -o - | FileCheck %s -check-prefix=REPLACE_SDIV + +; REPLACE_SDIV: sdivcc %o0, %o1, %o0 +; NO_REPLACE_SDIV: sdiv %o0, %o1, %o0 + +define i32 @lbr59(i32 %a, i32 %b) +{ + %r = sdiv i32 %a, %b + ret i32 %r +}