Index: llvm/trunk/lib/Target/Sparc/Sparc.td =================================================================== --- llvm/trunk/lib/Target/Sparc/Sparc.td +++ llvm/trunk/lib/Target/Sparc/Sparc.td @@ -20,6 +20,10 @@ // SPARC Subtarget features. // +def FeatureSoftMulDiv + : SubtargetFeature<"soft-mul-div", "UseSoftMulDiv", "true", + "Use software emulation for integer multiply and divide">; + def FeatureV9 : SubtargetFeature<"v9", "IsV9", "true", "Enable SPARC-V9 instructions">; @@ -75,7 +79,7 @@ : Processor; def : Proc<"generic", []>; -def : Proc<"v7", []>; +def : Proc<"v7", [FeatureSoftMulDiv]>; def : Proc<"v8", []>; def : Proc<"supersparc", []>; def : Proc<"sparclite", []>; Index: llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp +++ llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp @@ -1689,6 +1689,19 @@ setOperationAction(ISD::MULHS, MVT::i32, Expand); setOperationAction(ISD::MUL, MVT::i32, Expand); + if (Subtarget->useSoftMulDiv()) { + // .umul works for both signed and unsigned + setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); + setLibcallName(RTLIB::MUL_I32, ".umul"); + + setOperationAction(ISD::SDIV, MVT::i32, Expand); + setLibcallName(RTLIB::SDIV_I32, ".div"); + + setOperationAction(ISD::UDIV, MVT::i32, Expand); + setLibcallName(RTLIB::UDIV_I32, ".udiv"); + } + if (Subtarget->is64Bit()) { setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); Index: llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td +++ llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td @@ -27,6 +27,9 @@ // True when generating 64-bit code. This also implies HasV9. def Is64Bit : Predicate<"Subtarget->is64Bit()">; +def UseSoftMulDiv : Predicate<"Subtarget->useSoftMulDiv()">, + AssemblerPredicate<"FeatureSoftMulDiv">; + // HasV9 - This predicate is true when the target processor supports V9 // instructions. Note that the machine may be running in 32-bit mode. def HasV9 : Predicate<"Subtarget->isV9()">, Index: llvm/trunk/lib/Target/Sparc/SparcSubtarget.h =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcSubtarget.h +++ llvm/trunk/lib/Target/Sparc/SparcSubtarget.h @@ -32,6 +32,7 @@ class SparcSubtarget : public SparcGenSubtargetInfo { Triple TargetTriple; virtual void anchor(); + bool UseSoftMulDiv; bool IsV9; bool IsLeon; bool V8DeprecatedInsts; @@ -76,6 +77,7 @@ bool enableMachineScheduler() const override; + bool useSoftMulDiv() const { return UseSoftMulDiv; } bool isV9() const { return IsV9; } bool isLeon() const { return IsLeon; } bool isVIS() const { return IsVIS; } Index: llvm/trunk/test/CodeGen/SPARC/soft-mul-div.ll =================================================================== --- llvm/trunk/test/CodeGen/SPARC/soft-mul-div.ll +++ llvm/trunk/test/CodeGen/SPARC/soft-mul-div.ll @@ -0,0 +1,65 @@ +; RUN: llc -march=sparc -mcpu=v7 -O0 < %s | FileCheck %s + +define i32 @test_mul32(i32 %a, i32 %b) #0 { + ; CHECK-LABEL: test_mul32 + ; CHECK: call .umul + %m = mul i32 %a, %b + ret i32 %m +} + +define i16 @test_mul16(i16 %a, i16 %b) #0 { + ; CHECK-LABEL: test_mul16 + ; CHECK: call .umul + %m = mul i16 %a, %b + ret i16 %m +} + +define i8 @test_mul8(i8 %a, i8 %b) #0 { + ; CHECK-LABEL: test_mul8 + ; CHECK: call .umul + %m = mul i8 %a, %b + ret i8 %m +} + +define i32 @test_sdiv32(i32 %a, i32 %b) #0 { + ; CHECK-LABEL: test_sdiv32 + ; CHECK: call .div + %d = sdiv i32 %a, %b + ret i32 %d +} + +define i16 @test_sdiv16(i16 %a, i16 %b) #0 { + ; CHECK-LABEL: test_sdiv16 + ; CHECK: call .div + %d = sdiv i16 %a, %b + ret i16 %d +} + +define i8 @test_sdiv8(i8 %a, i8 %b) #0 { + ; CHECK-LABEL: test_sdiv8 + ; CHECK: call .div + %d = sdiv i8 %a, %b + ret i8 %d +} + +define i32 @test_udiv32(i32 %a, i32 %b) #0 { + ; CHECK-LABEL: test_udiv32 + ; CHECK: call .udiv + %d = udiv i32 %a, %b + ret i32 %d +} + +define i16 @test_udiv16(i16 %a, i16 %b) #0 { + ; CHECK-LABEL: test_udiv16 + ; CHECK: call .udiv + %d = udiv i16 %a, %b + ret i16 %d +} + +define i8 @test_udiv8(i8 %a, i8 %b) #0 { + ; CHECK-LABEL: test_udiv8 + ; CHECK: call .udiv + %d = udiv i8 %a, %b + ret i8 %d +} +