Skip to content

Commit 65b8b17

Browse files
aykevldylanmckay
authored andcommitted
[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
1 parent 93a3b59 commit 65b8b17

File tree

2 files changed

+12
-44
lines changed

2 files changed

+12
-44
lines changed

llvm/lib/Target/AVR/AVRISelLowering.cpp

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,12 @@ AVRTargetLowering::AVRTargetLowering(const AVRTargetMachine &TM,
151151
setOperationAction(ISD::SREM, MVT::i16, Expand);
152152

153153
// Make division and modulus custom
154-
for (MVT VT : MVT::integer_valuetypes()) {
155-
setOperationAction(ISD::UDIVREM, VT, Custom);
156-
setOperationAction(ISD::SDIVREM, VT, Custom);
157-
}
154+
setOperationAction(ISD::UDIVREM, MVT::i8, Custom);
155+
setOperationAction(ISD::UDIVREM, MVT::i16, Custom);
156+
setOperationAction(ISD::UDIVREM, MVT::i32, Custom);
157+
setOperationAction(ISD::SDIVREM, MVT::i8, Custom);
158+
setOperationAction(ISD::SDIVREM, MVT::i16, Custom);
159+
setOperationAction(ISD::SDIVREM, MVT::i32, Custom);
158160

159161
// Do not use MUL. The AVR instructions are closer to SMUL_LOHI &co.
160162
setOperationAction(ISD::MUL, MVT::i8, Expand);
@@ -190,41 +192,29 @@ AVRTargetLowering::AVRTargetLowering(const AVRTargetMachine &TM,
190192
// improvements in how we treat 16-bit "registers" to be feasible.
191193
}
192194

193-
// Division rtlib functions (not supported)
195+
// Division rtlib functions (not supported), use divmod functions instead
194196
setLibcallName(RTLIB::SDIV_I8, nullptr);
195197
setLibcallName(RTLIB::SDIV_I16, nullptr);
196198
setLibcallName(RTLIB::SDIV_I32, nullptr);
197-
setLibcallName(RTLIB::SDIV_I64, nullptr);
198-
setLibcallName(RTLIB::SDIV_I128, nullptr);
199199
setLibcallName(RTLIB::UDIV_I8, nullptr);
200200
setLibcallName(RTLIB::UDIV_I16, nullptr);
201201
setLibcallName(RTLIB::UDIV_I32, nullptr);
202-
setLibcallName(RTLIB::UDIV_I64, nullptr);
203-
setLibcallName(RTLIB::UDIV_I128, nullptr);
204202

205-
// Modulus rtlib functions (not supported)
203+
// Modulus rtlib functions (not supported), use divmod functions instead
206204
setLibcallName(RTLIB::SREM_I8, nullptr);
207205
setLibcallName(RTLIB::SREM_I16, nullptr);
208206
setLibcallName(RTLIB::SREM_I32, nullptr);
209-
setLibcallName(RTLIB::SREM_I64, nullptr);
210-
setLibcallName(RTLIB::SREM_I128, nullptr);
211207
setLibcallName(RTLIB::UREM_I8, nullptr);
212208
setLibcallName(RTLIB::UREM_I16, nullptr);
213209
setLibcallName(RTLIB::UREM_I32, nullptr);
214-
setLibcallName(RTLIB::UREM_I64, nullptr);
215-
setLibcallName(RTLIB::UREM_I128, nullptr);
216210

217211
// Division and modulus rtlib functions
218212
setLibcallName(RTLIB::SDIVREM_I8, "__divmodqi4");
219213
setLibcallName(RTLIB::SDIVREM_I16, "__divmodhi4");
220214
setLibcallName(RTLIB::SDIVREM_I32, "__divmodsi4");
221-
setLibcallName(RTLIB::SDIVREM_I64, "__divmoddi4");
222-
setLibcallName(RTLIB::SDIVREM_I128, "__divmodti4");
223215
setLibcallName(RTLIB::UDIVREM_I8, "__udivmodqi4");
224216
setLibcallName(RTLIB::UDIVREM_I16, "__udivmodhi4");
225217
setLibcallName(RTLIB::UDIVREM_I32, "__udivmodsi4");
226-
setLibcallName(RTLIB::UDIVREM_I64, "__udivmoddi4");
227-
setLibcallName(RTLIB::UDIVREM_I128, "__udivmodti4");
228218

229219
// Several of the runtime library functions use a special calling conv
230220
setLibcallCallingConv(RTLIB::SDIVREM_I8, CallingConv::AVR_BUILTIN);
@@ -357,12 +347,6 @@ SDValue AVRTargetLowering::LowerDivRem(SDValue Op, SelectionDAG &DAG) const {
357347
case MVT::i32:
358348
LC = IsSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
359349
break;
360-
case MVT::i64:
361-
LC = IsSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
362-
break;
363-
case MVT::i128:
364-
LC = IsSigned ? RTLIB::SDIVREM_I128 : RTLIB::UDIVREM_I128;
365-
break;
366350
}
367351

368352
SDValue InChain = DAG.getEntryNode();

llvm/test/CodeGen/AVR/div.ll

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,7 @@ define i32 @sdiv32(i32 %a, i32 %b) {
6565
; Unsigned 64-bit division
6666
define i64 @udiv64(i64 %a, i64 %b) {
6767
; CHECK-LABEL: udiv64:
68-
; CHECK: call __udivmoddi4
69-
; CHECK-NEXT: ldd r18, Y+1
70-
; CHECK-NEXT: ldd r19, Y+2
71-
; CHECK-NEXT: ldd r20, Y+3
72-
; CHECK-NEXT: ldd r21, Y+4
73-
; CHECK-NEXT: ldd r22, Y+5
74-
; CHECK-NEXT: ldd r23, Y+6
75-
; CHECK-NEXT: ldd r24, Y+7
76-
; CHECK-NEXT: ldd r25, Y+8
68+
; CHECK: call __udivdi3
7769
; CHECK: ret
7870
%quot = udiv i64 %a, %b
7971
ret i64 %quot
@@ -82,15 +74,7 @@ define i64 @udiv64(i64 %a, i64 %b) {
8274
; Signed 64-bit division
8375
define i64 @sdiv64(i64 %a, i64 %b) {
8476
; CHECK-LABEL: sdiv64:
85-
; CHECK: call __divmoddi4
86-
; CHECK-NEXT: ldd r18, Y+1
87-
; CHECK-NEXT: ldd r19, Y+2
88-
; CHECK-NEXT: ldd r20, Y+3
89-
; CHECK-NEXT: ldd r21, Y+4
90-
; CHECK-NEXT: ldd r22, Y+5
91-
; CHECK-NEXT: ldd r23, Y+6
92-
; CHECK-NEXT: ldd r24, Y+7
93-
; CHECK-NEXT: ldd r25, Y+8
77+
; CHECK: call __divdi3
9478
; CHECK: ret
9579
%quot = sdiv i64 %a, %b
9680
ret i64 %quot
@@ -99,7 +83,7 @@ define i64 @sdiv64(i64 %a, i64 %b) {
9983
; Unsigned 128-bit division
10084
define i128 @udiv128(i128 %a, i128 %b) {
10185
; CHECK-LABEL: udiv128:
102-
; CHECK: call __udivmodti4
86+
; CHECK: call __udivti3
10387
; CHECK: ret
10488
%quot = udiv i128 %a, %b
10589
ret i128 %quot
@@ -108,7 +92,7 @@ define i128 @udiv128(i128 %a, i128 %b) {
10892
; Signed 128-bit division
10993
define i128 @sdiv128(i128 %a, i128 %b) {
11094
; CHECK-LABEL: sdiv128:
111-
; CHECK: call __divmodti4
95+
; CHECK: call __divti3
11296
; CHECK: ret
11397
%quot = sdiv i128 %a, %b
11498
ret i128 %quot

0 commit comments

Comments
 (0)