Commit 0bec0e71 authored by Kazushi (Jam) Marukawa's avatar Kazushi (Jam) Marukawa Committed by Simon Moll
Browse files

[VE] udiv/sdiv/urem/srem/mul isel patterns

Summary:
udiv/sdiv/urem/srem/mul integer isel patterns and tests.
Pretend for now that integer division were always cheap in HW.

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D73623
parent c2dcdf95
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -501,6 +501,14 @@ VETargetLowering::VETargetLowering(const TargetMachine &TM,
  MVT PtrVT = MVT::getIntegerVT(TM.getPointerSizeInBits(0));
  setOperationAction(ISD::GlobalAddress, PtrVT, Custom);

  // VE has no REM or DIVREM operations.
  for (MVT IntVT : MVT::integer_valuetypes()) {
    setOperationAction(ISD::UREM, IntVT, Expand);
    setOperationAction(ISD::SREM, IntVT, Expand);
    setOperationAction(ISD::SDIVREM, IntVT, Expand);
    setOperationAction(ISD::UDIVREM, IntVT, Expand);
  }

  // VE doesn't have instructions for fp<->uint, so expand them by llvm
  setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote); // use i64
  setOperationAction(ISD::UINT_TO_FP, MVT::i32, Promote); // use i64
+3 −0
Original line number Diff line number Diff line
@@ -86,6 +86,9 @@ public:
  bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AS, unsigned Align,
                                      MachineMemOperand::Flags Flags,
                                      bool *Fast) const override;

  // Block s/udiv lowering for now
  bool isIntDivCheap(EVT VT, AttributeList Attr) const override { return true; }
};
} // namespace llvm

+32 −0
Original line number Diff line number Diff line
@@ -630,6 +630,38 @@ defm SBSU : RRm<"subs.w.zx", 0x5A, I32, i32, simm7Op32, uimm6Op32>;
let cx = 0 in
defm SBX : RRNCm<"subs.l", 0x5B, I64, i64, simm7Op64, uimm6Op64, sub>;

// MPY instruction
let cx = 0 in
defm MPY : RRm<"mulu.l", 0x49, I64, i64, simm7Op64, uimm6Op64>;
let cx = 1 in
defm MPYUW : RRm<"mulu.w", 0x49, I32, i32, simm7Op32, uimm6Op32>;

// MPS instruction
let cx = 0 in
defm MPS : RRm<"muls.w.sx", 0x4B, I32, i32, simm7Op32, uimm6Op32, mul>;
let cx = 1 in
defm MPSU : RRm<"muls.w.zx", 0x4B, I32, i32, simm7Op32, uimm6Op32>;

// MPX instruction
let cx = 0 in
defm MPX : RRm<"muls.l", 0x6E, I64, i64, simm7Op64, uimm6Op64, mul>;

// DIV instruction
let cx = 0 in
defm DIV : RRNCm<"divu.l", 0x6F, I64, i64, simm7Op64, uimm6Op64, udiv>;
let cx = 1 in
defm DIVUW : RRNCm<"divu.w", 0x6F, I32, i32, simm7Op32, uimm6Op32, udiv>;

// DVS instruction
let cx = 0 in
defm DVS : RRNCm<"divs.w.sx", 0x7B, I32, i32, simm7Op32, uimm6Op32, sdiv>;
let cx = 1 in
defm DVSU : RRm<"divs.w.zx", 0x7B, I32, i32, simm7Op32, uimm6Op32>;

// DVX instruction
let cx = 0 in
defm DVX : RRNCm<"divs.l", 0x7F, I64, i64, simm7Op64, uimm6Op64, sdiv>;

// CMP instruction
let cx = 0 in
defm CMP : RRm<"cmpu.l", 0x55, I64, i64, simm7Op64, uimm6Op64>;
+175 −0
Original line number Diff line number Diff line
; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s

; Function Attrs: norecurse nounwind readnone
define i64 @divi64(i64 %a, i64 %b) {
; CHECK-LABEL: divi64:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    divs.l %s0, %s0, %s1
; CHECK-NEXT:    or %s11, 0, %s9
  %r = sdiv i64 %a, %b
  ret i64 %r
}

; Function Attrs: norecurse nounwind readnone
define i32 @divi32(i32 %a, i32 %b) {
; CHECK-LABEL: divi32:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    divs.w.sx %s0, %s0, %s1
; CHECK-NEXT:    or %s11, 0, %s9
  %r = sdiv i32 %a, %b
  ret i32 %r
}

; Function Attrs: norecurse nounwind readnone
define i64 @divu64(i64 %a, i64 %b) {
; CHECK-LABEL: divu64:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    divu.l %s0, %s0, %s1
; CHECK-NEXT:    or %s11, 0, %s9
  %r = udiv i64 %a, %b
  ret i64 %r
}

; Function Attrs: norecurse nounwind readnone
define i32 @divu32(i32 %a, i32 %b) {
; CHECK-LABEL: divu32:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    divu.w %s0, %s0, %s1
; CHECK-NEXT:    or %s11, 0, %s9
  %r = udiv i32 %a, %b
  ret i32 %r
}

; Function Attrs: norecurse nounwind readnone
define signext i16 @divi16(i16 signext %a, i16 signext %b) {
; CHECK-LABEL: divi16:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    divs.w.sx %s0, %s0, %s1
; CHECK-NEXT:    sla.w.sx %s0, %s0, 16
; CHECK-NEXT:    sra.w.sx %s0, %s0, 16
; CHECK-NEXT:    or %s11, 0, %s9
  %a32 = sext i16 %a to i32
  %b32 = sext i16 %b to i32
  %r32 = sdiv i32 %a32, %b32
  %r = trunc i32 %r32 to i16
  ret i16 %r
}

; Function Attrs: norecurse nounwind readnone
define zeroext i16 @divu16(i16 zeroext %a, i16 zeroext %b) {
; CHECK-LABEL: divu16:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    divu.w %s0, %s0, %s1
; CHECK-NEXT:    or %s11, 0, %s9
  %r = udiv i16 %a, %b
  ret i16 %r
}

; Function Attrs: norecurse nounwind readnone
define signext i8 @divi8(i8 signext %a, i8 signext %b) {
; CHECK-LABEL: divi8:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    divs.w.sx %s0, %s0, %s1
; CHECK-NEXT:    sla.w.sx %s0, %s0, 24
; CHECK-NEXT:    sra.w.sx %s0, %s0, 24
; CHECK-NEXT:    or %s11, 0, %s9
  %a32 = sext i8 %a to i32
  %b32 = sext i8 %b to i32
  %r32 = sdiv i32 %a32, %b32
  %r = trunc i32 %r32 to i8
  ret i8 %r
}

; Function Attrs: norecurse nounwind readnone
define zeroext i8 @divu8(i8 zeroext %a, i8 zeroext %b) {
; CHECK-LABEL: divu8:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    divu.w %s0, %s0, %s1
; CHECK-NEXT:    or %s11, 0, %s9
  %r = udiv i8 %a, %b
  ret i8 %r
}

; Function Attrs: norecurse nounwind readnone
define i64 @divi64ri(i64 %a, i64 %b) {
; CHECK-LABEL: divi64ri:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    or %s1, 3, (0)1
; CHECK-NEXT:    divs.l %s0, %s0, %s1
; CHECK-NEXT:    or %s11, 0, %s9
  %r = sdiv i64 %a, 3
  ret i64 %r
}

; Function Attrs: norecurse nounwind readnone
define i32 @divi32ri(i32 %a, i32 %b) {
; CHECK-LABEL: divi32ri:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    or %s1, 3, (0)1
; CHECK-NEXT:    divs.w.sx %s0, %s0, %s1
; CHECK-NEXT:    or %s11, 0, %s9
  %r = sdiv i32 %a, 3
  ret i32 %r
}

; Function Attrs: norecurse nounwind readnone
define i64 @divu64ri(i64 %a, i64 %b) {
; CHECK-LABEL: divu64ri:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    or %s1, 3, (0)1
; CHECK-NEXT:    divu.l %s0, %s0, %s1
; CHECK-NEXT:    or %s11, 0, %s9
  %r = udiv i64 %a, 3
  ret i64 %r
}

; Function Attrs: norecurse nounwind readnone
define i32 @divu32ri(i32 %a, i32 %b) {
; CHECK-LABEL: divu32ri:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    or %s1, 3, (0)1
; CHECK-NEXT:    divu.w %s0, %s0, %s1
; CHECK-NEXT:    or %s11, 0, %s9
  %r = udiv i32 %a, 3
  ret i32 %r
}

; Function Attrs: norecurse nounwind readnone
define i64 @divi64li(i64 %a, i64 %b) {
; CHECK-LABEL: divi64li:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    divs.l %s0, 3, %s1
; CHECK-NEXT:    or %s11, 0, %s9
  %r = sdiv i64 3, %b
  ret i64 %r
}

; Function Attrs: norecurse nounwind readnone
define i32 @divi32li(i32 %a, i32 %b) {
; CHECK-LABEL: divi32li:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    divs.w.sx %s0, 3, %s1
; CHECK-NEXT:    or %s11, 0, %s9
  %r = sdiv i32 3, %b
  ret i32 %r
}

; Function Attrs: norecurse nounwind readnone
define i64 @divu64li(i64 %a, i64 %b) {
; CHECK-LABEL: divu64li:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    divu.l %s0, 3, %s1
; CHECK-NEXT:    or %s11, 0, %s9
  %r = udiv i64 3, %b
  ret i64 %r
}

; Function Attrs: norecurse nounwind readnone
define i32 @divu32li(i32 %a, i32 %b) {
; CHECK-LABEL: divu32li:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    divu.w %s0, 3, %s1
; CHECK-NEXT:    or %s11, 0, %s9
  %r = udiv i32 3, %b
  ret i32 %r
}
+175 −0
Original line number Diff line number Diff line
; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s

define signext i8 @func1(i8 signext %a, i8 signext %b) {
; CHECK-LABEL: func1:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.w.sx %s0, %s1, %s0
; CHECK-NEXT:    sla.w.sx %s0, %s0, 24
; CHECK-NEXT:    sra.w.sx %s0, %s0, 24
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul i8 %b, %a
  ret i8 %r
}

define signext i16 @func2(i16 signext %a, i16 signext %b) {
; CHECK-LABEL: func2:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.w.sx %s0, %s1, %s0
; CHECK-NEXT:    sla.w.sx %s0, %s0, 16
; CHECK-NEXT:    sra.w.sx %s0, %s0, 16
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul i16 %b, %a
  ret i16 %r
}

define i32 @func3(i32 %a, i32 %b) {
; CHECK-LABEL: func3:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.w.sx %s0, %s1, %s0
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul nsw i32 %b, %a
  ret i32 %r
}

define i64 @func4(i64 %a, i64 %b) {
; CHECK-LABEL: func4:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.l %s0, %s1, %s0
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul nsw i64 %b, %a
  ret i64 %r
}

define zeroext i8 @func5(i8 zeroext %a, i8 zeroext %b) {
; CHECK-LABEL: func5:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.w.sx %s0, %s1, %s0
; CHECK-NEXT:    and %s0, %s0, (56)0
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul i8 %b, %a
  ret i8 %r
}

define zeroext i16 @func6(i16 zeroext %a, i16 zeroext %b) {
; CHECK-LABEL: func6:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.w.sx %s0, %s1, %s0
; CHECK-NEXT:    and %s0, %s0, (48)0
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul i16 %b, %a
  ret i16 %r
}

define i32 @func7(i32 %a, i32 %b) {
; CHECK-LABEL: func7:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.w.sx %s0, %s1, %s0
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul i32 %b, %a
  ret i32 %r
}

define i64 @func8(i64 %a, i64 %b) {
; CHECK-LABEL: func8:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.l %s0, %s1, %s0
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul i64 %b, %a
  ret i64 %r
}

define signext i8 @func9(i8 signext %a) {
; CHECK-LABEL: func9:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.w.sx %s0, 5, %s0
; CHECK-NEXT:    sla.w.sx %s0, %s0, 24
; CHECK-NEXT:    sra.w.sx %s0, %s0, 24
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul i8 %a, 5
  ret i8 %r
}

define signext i16 @func10(i16 signext %a) {
; CHECK-LABEL: func10:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.w.sx %s0, 5, %s0
; CHECK-NEXT:    sla.w.sx %s0, %s0, 16
; CHECK-NEXT:    sra.w.sx %s0, %s0, 16
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul i16 %a, 5
  ret i16 %r
}

define i32 @func11(i32 %a) {
; CHECK-LABEL: func11:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.w.sx %s0, 5, %s0
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul nsw i32 %a, 5
  ret i32 %r
}

define i64 @func12(i64 %a) {
; CHECK-LABEL: func12:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.l %s0, 5, %s0
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul nsw i64 %a, 5
  ret i64 %r
}

define zeroext i8 @func13(i8 zeroext %a) {
; CHECK-LABEL: func13:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.w.sx %s0, 5, %s0
; CHECK-NEXT:    and %s0, %s0, (56)0
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul i8 %a, 5
  ret i8 %r
}

define zeroext i16 @func14(i16 zeroext %a) {
; CHECK-LABEL: func14:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.w.sx %s0, 5, %s0
; CHECK-NEXT:    and %s0, %s0, (48)0
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul i16 %a, 5
  ret i16 %r
}

define i32 @func15(i32 %a) {
; CHECK-LABEL: func15:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.w.sx %s0, 5, %s0
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul i32 %a, 5
  ret i32 %r
}

define i64 @func16(i64 %a) {
; CHECK-LABEL: func16:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    muls.l %s0, 5, %s0
; CHECK-NEXT:    or %s11, 0, %s9
  %r = mul i64 %a, 5
  ret i64 %r
}

define i32 @func17(i32 %a) {
; CHECK-LABEL: func17:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    sla.w.sx %s0, %s0, 31
; CHECK-NEXT:    or %s11, 0, %s9
  %r = shl i32 %a, 31
  ret i32 %r
}

define i64 @func18(i64 %a) {
; CHECK-LABEL: func18:
; CHECK:       .LBB{{[0-9]+}}_2:
; CHECK-NEXT:    sll %s0, %s0, 31
; CHECK-NEXT:    or %s11, 0, %s9
  %r = shl nsw i64 %a, 31
  ret i64 %r
}
Loading