forked from OSchip/llvm-project
[AVR] Do not use divmod calls for bigger integers
The avr-libc provides *divmodqi4, *divmodhi4, and *divmodsi4 functions, but does not provide a *divmoddi4. Instead it provides regular *divdi3 and *moddi3 functions. Note that avr-libc doesn't support *divti3 or *modti3 for 128-bit integer manipulation. Source: https://github.com/gcc-mirror/gcc/blob/releases/gcc-5.4.0/libgcc/config/avr/lib1funcs.S Differential Revision: https://reviews.llvm.org/D78437
This commit is contained in:
parent
76e0ab23f6
commit
9505b5cb66
|
@ -151,10 +151,12 @@ AVRTargetLowering::AVRTargetLowering(const AVRTargetMachine &TM,
|
|||
setOperationAction(ISD::SREM, MVT::i16, Expand);
|
||||
|
||||
// Make division and modulus custom
|
||||
for (MVT VT : MVT::integer_valuetypes()) {
|
||||
setOperationAction(ISD::UDIVREM, VT, Custom);
|
||||
setOperationAction(ISD::SDIVREM, VT, Custom);
|
||||
}
|
||||
setOperationAction(ISD::UDIVREM, MVT::i8, Custom);
|
||||
setOperationAction(ISD::UDIVREM, MVT::i16, Custom);
|
||||
setOperationAction(ISD::UDIVREM, MVT::i32, Custom);
|
||||
setOperationAction(ISD::SDIVREM, MVT::i8, Custom);
|
||||
setOperationAction(ISD::SDIVREM, MVT::i16, Custom);
|
||||
setOperationAction(ISD::SDIVREM, MVT::i32, Custom);
|
||||
|
||||
// Do not use MUL. The AVR instructions are closer to SMUL_LOHI &co.
|
||||
setOperationAction(ISD::MUL, MVT::i8, Expand);
|
||||
|
@ -190,41 +192,29 @@ AVRTargetLowering::AVRTargetLowering(const AVRTargetMachine &TM,
|
|||
// improvements in how we treat 16-bit "registers" to be feasible.
|
||||
}
|
||||
|
||||
// Division rtlib functions (not supported)
|
||||
// Division rtlib functions (not supported), use divmod functions instead
|
||||
setLibcallName(RTLIB::SDIV_I8, nullptr);
|
||||
setLibcallName(RTLIB::SDIV_I16, nullptr);
|
||||
setLibcallName(RTLIB::SDIV_I32, nullptr);
|
||||
setLibcallName(RTLIB::SDIV_I64, nullptr);
|
||||
setLibcallName(RTLIB::SDIV_I128, nullptr);
|
||||
setLibcallName(RTLIB::UDIV_I8, nullptr);
|
||||
setLibcallName(RTLIB::UDIV_I16, nullptr);
|
||||
setLibcallName(RTLIB::UDIV_I32, nullptr);
|
||||
setLibcallName(RTLIB::UDIV_I64, nullptr);
|
||||
setLibcallName(RTLIB::UDIV_I128, nullptr);
|
||||
|
||||
// Modulus rtlib functions (not supported)
|
||||
// Modulus rtlib functions (not supported), use divmod functions instead
|
||||
setLibcallName(RTLIB::SREM_I8, nullptr);
|
||||
setLibcallName(RTLIB::SREM_I16, nullptr);
|
||||
setLibcallName(RTLIB::SREM_I32, nullptr);
|
||||
setLibcallName(RTLIB::SREM_I64, nullptr);
|
||||
setLibcallName(RTLIB::SREM_I128, nullptr);
|
||||
setLibcallName(RTLIB::UREM_I8, nullptr);
|
||||
setLibcallName(RTLIB::UREM_I16, nullptr);
|
||||
setLibcallName(RTLIB::UREM_I32, nullptr);
|
||||
setLibcallName(RTLIB::UREM_I64, nullptr);
|
||||
setLibcallName(RTLIB::UREM_I128, nullptr);
|
||||
|
||||
// Division and modulus rtlib functions
|
||||
setLibcallName(RTLIB::SDIVREM_I8, "__divmodqi4");
|
||||
setLibcallName(RTLIB::SDIVREM_I16, "__divmodhi4");
|
||||
setLibcallName(RTLIB::SDIVREM_I32, "__divmodsi4");
|
||||
setLibcallName(RTLIB::SDIVREM_I64, "__divmoddi4");
|
||||
setLibcallName(RTLIB::SDIVREM_I128, "__divmodti4");
|
||||
setLibcallName(RTLIB::UDIVREM_I8, "__udivmodqi4");
|
||||
setLibcallName(RTLIB::UDIVREM_I16, "__udivmodhi4");
|
||||
setLibcallName(RTLIB::UDIVREM_I32, "__udivmodsi4");
|
||||
setLibcallName(RTLIB::UDIVREM_I64, "__udivmoddi4");
|
||||
setLibcallName(RTLIB::UDIVREM_I128, "__udivmodti4");
|
||||
|
||||
// Several of the runtime library functions use a special calling conv
|
||||
setLibcallCallingConv(RTLIB::SDIVREM_I8, CallingConv::AVR_BUILTIN);
|
||||
|
@ -371,12 +361,6 @@ SDValue AVRTargetLowering::LowerDivRem(SDValue Op, SelectionDAG &DAG) const {
|
|||
case MVT::i32:
|
||||
LC = IsSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
|
||||
break;
|
||||
case MVT::i64:
|
||||
LC = IsSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
|
||||
break;
|
||||
case MVT::i128:
|
||||
LC = IsSigned ? RTLIB::SDIVREM_I128 : RTLIB::UDIVREM_I128;
|
||||
break;
|
||||
}
|
||||
|
||||
SDValue InChain = DAG.getEntryNode();
|
||||
|
|
|
@ -65,15 +65,7 @@ define i32 @sdiv32(i32 %a, i32 %b) {
|
|||
; Unsigned 64-bit division
|
||||
define i64 @udiv64(i64 %a, i64 %b) {
|
||||
; CHECK-LABEL: udiv64:
|
||||
; CHECK: call __udivmoddi4
|
||||
; CHECK-NEXT: ldd r18, Y+1
|
||||
; CHECK-NEXT: ldd r19, Y+2
|
||||
; CHECK-NEXT: ldd r20, Y+3
|
||||
; CHECK-NEXT: ldd r21, Y+4
|
||||
; CHECK-NEXT: ldd r22, Y+5
|
||||
; CHECK-NEXT: ldd r23, Y+6
|
||||
; CHECK-NEXT: ldd r24, Y+7
|
||||
; CHECK-NEXT: ldd r25, Y+8
|
||||
; CHECK: call __udivdi3
|
||||
; CHECK: ret
|
||||
%quot = udiv i64 %a, %b
|
||||
ret i64 %quot
|
||||
|
@ -82,15 +74,7 @@ define i64 @udiv64(i64 %a, i64 %b) {
|
|||
; Signed 64-bit division
|
||||
define i64 @sdiv64(i64 %a, i64 %b) {
|
||||
; CHECK-LABEL: sdiv64:
|
||||
; CHECK: call __divmoddi4
|
||||
; CHECK-NEXT: ldd r18, Y+1
|
||||
; CHECK-NEXT: ldd r19, Y+2
|
||||
; CHECK-NEXT: ldd r20, Y+3
|
||||
; CHECK-NEXT: ldd r21, Y+4
|
||||
; CHECK-NEXT: ldd r22, Y+5
|
||||
; CHECK-NEXT: ldd r23, Y+6
|
||||
; CHECK-NEXT: ldd r24, Y+7
|
||||
; CHECK-NEXT: ldd r25, Y+8
|
||||
; CHECK: call __divdi3
|
||||
; CHECK: ret
|
||||
%quot = sdiv i64 %a, %b
|
||||
ret i64 %quot
|
||||
|
@ -99,7 +83,7 @@ define i64 @sdiv64(i64 %a, i64 %b) {
|
|||
; Unsigned 128-bit division
|
||||
define i128 @udiv128(i128 %a, i128 %b) {
|
||||
; CHECK-LABEL: udiv128:
|
||||
; CHECK: call __udivmodti4
|
||||
; CHECK: call __udivti3
|
||||
; CHECK: ret
|
||||
%quot = udiv i128 %a, %b
|
||||
ret i128 %quot
|
||||
|
@ -108,7 +92,7 @@ define i128 @udiv128(i128 %a, i128 %b) {
|
|||
; Signed 128-bit division
|
||||
define i128 @sdiv128(i128 %a, i128 %b) {
|
||||
; CHECK-LABEL: sdiv128:
|
||||
; CHECK: call __divmodti4
|
||||
; CHECK: call __divti3
|
||||
; CHECK: ret
|
||||
%quot = sdiv i128 %a, %b
|
||||
ret i128 %quot
|
||||
|
|
Loading…
Reference in New Issue