From 9505b5cb66856a53ef2416aaf65adc85d749fd42 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sat, 18 Apr 2020 23:42:48 +0200 Subject: [PATCH] [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 --- llvm/lib/Target/AVR/AVRISelLowering.cpp | 32 ++++++++------------------------ llvm/test/CodeGen/AVR/div.ll | 24 ++++-------------------- 2 files changed, 12 insertions(+), 44 deletions(-) diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp index be8f8f7..21363bb 100644 --- a/llvm/lib/Target/AVR/AVRISelLowering.cpp +++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp @@ -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(); diff --git a/llvm/test/CodeGen/AVR/div.ll b/llvm/test/CodeGen/AVR/div.ll index 7626ecb..b222294 100644 --- a/llvm/test/CodeGen/AVR/div.ll +++ b/llvm/test/CodeGen/AVR/div.ll @@ -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 -- 2.7.4