Skip to content

Commit c7a4efa

Browse files
authored
[AVR] Fix 16-bit LDDs with immediate overflows (#104923)
16-bit loads are expanded into a pair of 8-bit loads, so the maximum offset of such 16-bit loads must be 62, not 63.
1 parent 8f96be9 commit c7a4efa

File tree

3 files changed

+288
-2
lines changed

3 files changed

+288
-2
lines changed

llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,13 @@ bool AVRDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
122122
// offset allowed.
123123
MVT VT = cast<MemSDNode>(Op)->getMemoryVT().getSimpleVT();
124124

125-
// We only accept offsets that fit in 6 bits (unsigned).
126-
if (isUInt<6>(RHSC) && (VT == MVT::i8 || VT == MVT::i16)) {
125+
// We only accept offsets that fit in 6 bits (unsigned), with the exception
126+
// of 16-bit loads - those can only go up to 62, because we desugar them
127+
// into a pair of 8-bit loads like `ldd rx, RHSC` + `ldd ry, RHSC + 1`.
128+
bool OkI8 = VT == MVT::i8 && RHSC <= 63;
129+
bool OkI16 = VT == MVT::i16 && RHSC <= 62;
130+
131+
if (OkI8 || OkI16) {
127132
Base = N.getOperand(0);
128133
Disp = CurDAG->getTargetConstant(RHSC, dl, MVT::i8);
129134

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
; RUN: llc -march=avr -filetype=asm -O1 < %s | FileCheck %s
2+
3+
define void @check60(ptr %1) {
4+
; CHECK-LABEL: check60:
5+
; CHECK-NEXT: %bb.0
6+
; CHECK-NEXT: mov r30, r24
7+
; CHECK-NEXT: mov r31, r25
8+
; CHECK-NEXT: ldd r24, Z+60
9+
; CHECK-NEXT: ldd r25, Z+61
10+
; CHECK-NEXT: ldd r18, Z+62
11+
; CHECK-NEXT: ldd r19, Z+63
12+
; CHECK-NEXT: sts 3, r19
13+
; CHECK-NEXT: sts 2, r18
14+
; CHECK-NEXT: sts 1, r25
15+
; CHECK-NEXT: sts 0, r24
16+
; CHECK-NEXT: ret
17+
18+
bb0:
19+
%2 = getelementptr i8, ptr %1, i16 60
20+
%3 = load i32, ptr %2, align 1
21+
store i32 %3, ptr null, align 1
22+
ret void
23+
}
24+
25+
define void @check61(ptr %1) {
26+
; CHECK-LABEL: check61:
27+
; CHECK-NEXT: %bb.0
28+
; CHECK-NEXT: mov r30, r24
29+
; CHECK-NEXT: mov r31, r25
30+
; CHECK-NEXT: ldd r18, Z+61
31+
; CHECK-NEXT: ldd r19, Z+62
32+
; CHECK-NEXT: adiw r24, 63
33+
; CHECK-NEXT: mov r30, r24
34+
; CHECK-NEXT: mov r31, r25
35+
; CHECK-NEXT: ld r24, Z
36+
; CHECK-NEXT: ldd r25, Z+1
37+
; CHECK-NEXT: sts 3, r25
38+
; CHECK-NEXT: sts 2, r24
39+
; CHECK-NEXT: sts 1, r19
40+
; CHECK-NEXT: sts 0, r18
41+
; CHECK-NEXT: ret
42+
43+
bb0:
44+
%2 = getelementptr i8, ptr %1, i16 61
45+
%3 = load i32, ptr %2, align 1
46+
store i32 %3, ptr null, align 1
47+
ret void
48+
}
49+
50+
define void @check62(ptr %1) {
51+
; CHECK-LABEL: check62:
52+
; CHECK-NEXT: %bb.0
53+
; CHECK-NEXT: mov r30, r24
54+
; CHECK-NEXT: mov r31, r25
55+
; CHECK-NEXT: ldd r18, Z+62
56+
; CHECK-NEXT: ldd r19, Z+63
57+
; CHECK-NEXT: adiw r24, 62
58+
; CHECK-NEXT: mov r30, r24
59+
; CHECK-NEXT: mov r31, r25
60+
; CHECK-NEXT: ldd r24, Z+2
61+
; CHECK-NEXT: ldd r25, Z+3
62+
; CHECK-NEXT: sts 3, r25
63+
; CHECK-NEXT: sts 2, r24
64+
; CHECK-NEXT: sts 1, r19
65+
; CHECK-NEXT: sts 0, r18
66+
; CHECK-NEXT: ret
67+
68+
bb0:
69+
%2 = getelementptr i8, ptr %1, i16 62
70+
%3 = load i32, ptr %2, align 1
71+
store i32 %3, ptr null, align 1
72+
ret void
73+
}
74+
75+
define void @check63(ptr %1) {
76+
; CHECK-LABEL: check63:
77+
; CHECK-NEXT: %bb.0
78+
; CHECK-NEXT: adiw r24, 63
79+
; CHECK-NEXT: mov r30, r24
80+
; CHECK-NEXT: mov r31, r25
81+
; CHECK-NEXT: ld r24, Z
82+
; CHECK-NEXT: ldd r25, Z+1
83+
; CHECK-NEXT: ldd r18, Z+2
84+
; CHECK-NEXT: ldd r19, Z+3
85+
; CHECK-NEXT: sts 3, r19
86+
; CHECK-NEXT: sts 2, r18
87+
; CHECK-NEXT: sts 1, r25
88+
; CHECK-NEXT: sts 0, r24
89+
; CHECK-NEXT: ret
90+
91+
bb0:
92+
%2 = getelementptr i8, ptr %1, i16 63
93+
%3 = load i32, ptr %2, align 1
94+
store i32 %3, ptr null, align 1
95+
ret void
96+
}
97+
98+
define void @check64(ptr %1) {
99+
; CHECK-LABEL: check64:
100+
; CHECK-NEXT: %bb.0
101+
; CHECK-NEXT: subi r24, 192
102+
; CHECK-NEXT: sbci r25, 255
103+
; CHECK-NEXT: mov r30, r24
104+
; CHECK-NEXT: mov r31, r25
105+
; CHECK-NEXT: ld r24, Z
106+
; CHECK-NEXT: ldd r25, Z+1
107+
; CHECK-NEXT: ldd r18, Z+2
108+
; CHECK-NEXT: ldd r19, Z+3
109+
; CHECK-NEXT: sts 3, r19
110+
; CHECK-NEXT: sts 2, r18
111+
; CHECK-NEXT: sts 1, r25
112+
; CHECK-NEXT: sts 0, r24
113+
; CHECK-NEXT: ret
114+
115+
bb0:
116+
%2 = getelementptr i8, ptr %1, i16 64
117+
%3 = load i32, ptr %2, align 1
118+
store i32 %3, ptr null, align 1
119+
ret void
120+
}
121+
122+
define void @check65(ptr %1) {
123+
; CHECK-LABEL: check65:
124+
; CHECK-NEXT: %bb.0
125+
; CHECK-NEXT: subi r24, 191
126+
; CHECK-NEXT: sbci r25, 255
127+
; CHECK-NEXT: mov r30, r24
128+
; CHECK-NEXT: mov r31, r25
129+
; CHECK-NEXT: ld r24, Z
130+
; CHECK-NEXT: ldd r25, Z+1
131+
; CHECK-NEXT: ldd r18, Z+2
132+
; CHECK-NEXT: ldd r19, Z+3
133+
; CHECK-NEXT: sts 3, r19
134+
; CHECK-NEXT: sts 2, r18
135+
; CHECK-NEXT: sts 1, r25
136+
; CHECK-NEXT: sts 0, r24
137+
; CHECK-NEXT: ret
138+
139+
bb0:
140+
%2 = getelementptr i8, ptr %1, i16 65
141+
%3 = load i32, ptr %2, align 1
142+
store i32 %3, ptr null, align 1
143+
ret void
144+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
; RUN: llc -march=avr -filetype=asm -O1 < %s | FileCheck %s
2+
3+
define void @check60(ptr %1) {
4+
; CHECK-LABEL: check60:
5+
; CHECK-NEXT: %bb.0
6+
; CHECK-NEXT: ldi r18, 0
7+
; CHECK-NEXT: ldi r19, 0
8+
; CHECK-NEXT: mov r30, r24
9+
; CHECK-NEXT: mov r31, r25
10+
; CHECK-NEXT: std Z+63, r19
11+
; CHECK-NEXT: std Z+62, r18
12+
; CHECK-NEXT: ldi r24, 210
13+
; CHECK-NEXT: ldi r25, 4
14+
; CHECK-NEXT: std Z+61, r25
15+
; CHECK-NEXT: std Z+60, r24
16+
; CHECK-NEXT: ret
17+
18+
bb0:
19+
%2 = getelementptr i8, ptr %1, i8 60
20+
store i32 1234, ptr %2
21+
ret void
22+
}
23+
24+
define void @check61(ptr %1) {
25+
; CHECK-LABEL: check61:
26+
; CHECK-NEXT: %bb.0
27+
; CHECK-NEXT: ldi r18, 210
28+
; CHECK-NEXT: ldi r19, 4
29+
; CHECK-NEXT: mov r30, r24
30+
; CHECK-NEXT: mov r31, r25
31+
; CHECK-NEXT: std Z+62, r19
32+
; CHECK-NEXT: std Z+61, r18
33+
; CHECK-NEXT: adiw r24, 63
34+
; CHECK-NEXT: ldi r18, 0
35+
; CHECK-NEXT: ldi r19, 0
36+
; CHECK-NEXT: mov r30, r24
37+
; CHECK-NEXT: mov r31, r25
38+
; CHECK-NEXT: std Z+1, r19
39+
; CHECK-NEXT: st Z, r18
40+
41+
bb0:
42+
%2 = getelementptr i8, ptr %1, i8 61
43+
store i32 1234, ptr %2
44+
ret void
45+
}
46+
47+
define void @check62(ptr %1) {
48+
; CHECK-LABEL: check62:
49+
; CHECK-NEXT: %bb.0
50+
; CHECK-NEXT: ldi r18, 210
51+
; CHECK-NEXT: ldi r19, 4
52+
; CHECK-NEXT: mov r30, r24
53+
; CHECK-NEXT: mov r31, r25
54+
; CHECK-NEXT: std Z+63, r19
55+
; CHECK-NEXT: std Z+62, r18
56+
; CHECK-NEXT: adiw r24, 62
57+
; CHECK-NEXT: ldi r18, 0
58+
; CHECK-NEXT: ldi r19, 0
59+
; CHECK-NEXT: mov r30, r24
60+
; CHECK-NEXT: mov r31, r25
61+
; CHECK-NEXT: std Z+3, r19
62+
; CHECK-NEXT: std Z+2, r18
63+
; CHECK-NEXT: ret
64+
65+
bb0:
66+
%2 = getelementptr i8, ptr %1, i8 62
67+
store i32 1234, ptr %2
68+
ret void
69+
}
70+
71+
define void @check63(ptr %1) {
72+
; CHECK-LABEL: check63:
73+
; CHECK-NEXT: %bb.0
74+
; CHECK-NEXT: adiw r24, 63
75+
; CHECK-NEXT: ldi r18, 0
76+
; CHECK-NEXT: ldi r19, 0
77+
; CHECK-NEXT: mov r30, r24
78+
; CHECK-NEXT: mov r31, r25
79+
; CHECK-NEXT: std Z+3, r19
80+
; CHECK-NEXT: std Z+2, r18
81+
; CHECK-NEXT: ldi r24, 210
82+
; CHECK-NEXT: ldi r25, 4
83+
; CHECK-NEXT: std Z+1, r25
84+
; CHECK-NEXT: st Z, r24
85+
; CHECK-NEXT: ret
86+
87+
bb0:
88+
%2 = getelementptr i8, ptr %1, i8 63
89+
store i32 1234, ptr %2
90+
ret void
91+
}
92+
93+
define void @check64(ptr %1) {
94+
; CHECK-LABEL: check64:
95+
; CHECK-NEXT: %bb.0
96+
; CHECK-NEXT: subi r24, 192
97+
; CHECK-NEXT: sbci r25, 255
98+
; CHECK-NEXT: ldi r18, 0
99+
; CHECK-NEXT: ldi r19, 0
100+
; CHECK-NEXT: mov r30, r24
101+
; CHECK-NEXT: mov r31, r25
102+
; CHECK-NEXT: std Z+3, r19
103+
; CHECK-NEXT: std Z+2, r18
104+
; CHECK-NEXT: ldi r24, 210
105+
; CHECK-NEXT: ldi r25, 4
106+
; CHECK-NEXT: std Z+1, r25
107+
; CHECK-NEXT: st Z, r24
108+
; CHECK-NEXT: ret
109+
110+
bb0:
111+
%2 = getelementptr i8, ptr %1, i8 64
112+
store i32 1234, ptr %2
113+
ret void
114+
}
115+
116+
define void @check65(ptr %1) {
117+
; CHECK-LABEL: check65:
118+
; CHECK-NEXT: %bb.0
119+
; CHECK-NEXT: subi r24, 191
120+
; CHECK-NEXT: sbci r25, 255
121+
; CHECK-NEXT: ldi r18, 0
122+
; CHECK-NEXT: ldi r19, 0
123+
; CHECK-NEXT: mov r30, r24
124+
; CHECK-NEXT: mov r31, r25
125+
; CHECK-NEXT: std Z+3, r19
126+
; CHECK-NEXT: std Z+2, r18
127+
; CHECK-NEXT: ldi r24, 210
128+
; CHECK-NEXT: ldi r25, 4
129+
; CHECK-NEXT: std Z+1, r25
130+
; CHECK-NEXT: st Z, r24
131+
; CHECK-NEXT: ret
132+
133+
bb0:
134+
%2 = getelementptr i8, ptr %1, i8 65
135+
store i32 1234, ptr %2
136+
ret void
137+
}

0 commit comments

Comments
 (0)