// 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">;
: Processor<Name, NoItineraries, Features>;
def : Proc<"generic", []>;
-def : Proc<"v7", []>;
+def : Proc<"v7", [FeatureSoftMulDiv]>;
def : Proc<"v8", []>;
def : Proc<"supersparc", []>;
def : Proc<"sparclite", []>;
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);
// 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()">,
class SparcSubtarget : public SparcGenSubtargetInfo {
Triple TargetTriple;
virtual void anchor();
+ bool UseSoftMulDiv;
bool IsV9;
bool IsLeon;
bool V8DeprecatedInsts;
bool enableMachineScheduler() const override;
+ bool useSoftMulDiv() const { return UseSoftMulDiv; }
bool isV9() const { return IsV9; }
bool isLeon() const { return IsLeon; }
bool isVIS() const { return IsVIS; }
--- /dev/null
+; 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
+}
+