Skip to content

Commit 77364be

Browse files
committed
[AVR] Fix codegen bug in 16-bit loads
Prior to this patch, the AVR::LDWRdPtr instruction was always lowered to instructions of this pattern: ld $GPR8, [PTR:XYZ]+ ld $GPR8, [PTR]+1 This has a problem; the [PTR] is incremented in-place once, but never decremented. Future uses of the same pointer will use the now clobbered value, leading to the pointer being incorrect by an offset of one. This patch modifies the expansion code of the LDWRdPtr pseudo instruction so that the pointer variable is not silently clobbered in future uses in the same live range. Patch by Keshav Kini. llvm-svn: 351544
1 parent 845d329 commit 77364be

File tree

6 files changed

+50
-37
lines changed

6 files changed

+50
-37
lines changed

llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -583,8 +583,8 @@ bool AVRExpandPseudo::expand<AVR::LDWRdPtr>(Block &MBB, BlockIt MBBI) {
583583
unsigned TmpReg = 0; // 0 for no temporary register
584584
unsigned SrcReg = MI.getOperand(1).getReg();
585585
bool SrcIsKill = MI.getOperand(1).isKill();
586-
OpLo = AVR::LDRdPtrPi;
587-
OpHi = AVR::LDRdPtr;
586+
OpLo = AVR::LDRdPtr;
587+
OpHi = AVR::LDDRdPtrQ;
588588
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
589589

590590
// Use a temporary register if src and dst registers are the same.
@@ -597,8 +597,7 @@ bool AVRExpandPseudo::expand<AVR::LDWRdPtr>(Block &MBB, BlockIt MBBI) {
597597
// Load low byte.
598598
auto MIBLO = buildMI(MBB, MBBI, OpLo)
599599
.addReg(CurDstLoReg, RegState::Define)
600-
.addReg(SrcReg, RegState::Define)
601-
.addReg(SrcReg);
600+
.addReg(SrcReg, RegState::Define);
602601

603602
// Push low byte onto stack if necessary.
604603
if (TmpReg)
@@ -607,7 +606,8 @@ bool AVRExpandPseudo::expand<AVR::LDWRdPtr>(Block &MBB, BlockIt MBBI) {
607606
// Load high byte.
608607
auto MIBHI = buildMI(MBB, MBBI, OpHi)
609608
.addReg(CurDstHiReg, RegState::Define)
610-
.addReg(SrcReg, getKillRegState(SrcIsKill));
609+
.addReg(SrcReg, getKillRegState(SrcIsKill))
610+
.addImm(1);
611611

612612
if (TmpReg) {
613613
// Move the high byte into the final destination.

llvm/test/CodeGen/AVR/PR37143.ll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
; RUN: llc -mattr=avr6,sram < %s -march=avr | FileCheck %s
2+
3+
; CHECK: ld {{r[0-9]+}}, [[PTR:[YZ]]]
4+
; CHECK: ldd {{r[0-9]+}}, [[PTR]]+1
5+
; CHECK: st [[PTR]], {{r[0-9]+}}
6+
; CHECK: std [[PTR]]+1, {{r[0-9]+}}
7+
define void @load_store_16(i16* nocapture %ptr) local_unnamed_addr #1 {
8+
entry:
9+
%0 = load i16, i16* %ptr, align 2
10+
%add = add i16 %0, 5
11+
store i16 %add, i16* %ptr, align 2
12+
ret void
13+
}

llvm/test/CodeGen/AVR/atomics/load16.ll

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
; CHECK-LABEL: atomic_load16
44
; CHECK: in r0, 63
55
; CHECK-NEXT: cli
6-
; CHECK-NEXT: ld [[RR:r[0-9]+]], [[RD:(X|Y|Z)]]+
7-
; CHECK-NEXT: ld [[RR:r[0-9]+]], [[RD:(X|Y|Z)]]
6+
; CHECK-NEXT: ld [[RR:r[0-9]+]], [[RD:(X|Y|Z)]]
7+
; CHECK-NEXT: ldd [[RR:r[0-9]+]], [[RD]]+1
88
; CHECK-NEXT: out 63, r0
99
define i16 @atomic_load16(i16* %foo) {
1010
%val = load atomic i16, i16* %foo unordered, align 2
@@ -29,12 +29,12 @@ define i16 @atomic_load_cmp_swap16(i16* %foo) {
2929
; CHECK-LABEL: atomic_load_add16
3030
; CHECK: in r0, 63
3131
; CHECK-NEXT: cli
32-
; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]+
33-
; CHECK-NEXT: ld [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]
32+
; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD:(X|Y|Z)]]
33+
; CHECK-NEXT: ldd [[RR2:r[0-9]+]], [[RD]]+1
3434
; CHECK-NEXT: add [[RR1]], [[TMP:r[0-9]+]]
3535
; CHECK-NEXT: adc [[RR2]], [[TMP:r[0-9]+]]
36-
; CHECK-NEXT: st [[RD1]], [[RR1]]
37-
; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]
36+
; CHECK-NEXT: st [[RD]], [[RR1]]
37+
; CHECK-NEXT: std [[RD]]+1, [[A:r[0-9]+]]
3838
; CHECK-NEXT: out 63, r0
3939
define i16 @atomic_load_add16(i16* %foo) {
4040
%val = atomicrmw add i16* %foo, i16 13 seq_cst
@@ -44,12 +44,12 @@ define i16 @atomic_load_add16(i16* %foo) {
4444
; CHECK-LABEL: atomic_load_sub16
4545
; CHECK: in r0, 63
4646
; CHECK-NEXT: cli
47-
; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]+
48-
; CHECK-NEXT: ld [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]
47+
; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD:(X|Y|Z)]]
48+
; CHECK-NEXT: ldd [[RR2:r[0-9]+]], [[RD]]+1
4949
; CHECK-NEXT: sub [[RR1]], [[TMP:r[0-9]+]]
5050
; CHECK-NEXT: sbc [[RR2]], [[TMP:r[0-9]+]]
51-
; CHECK-NEXT: st [[RD1]], [[RR1]]
52-
; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]
51+
; CHECK-NEXT: st [[RD]], [[RR1]]
52+
; CHECK-NEXT: std [[RD]]+1, [[A:r[0-9]+]]
5353
; CHECK-NEXT: out 63, r0
5454
define i16 @atomic_load_sub16(i16* %foo) {
5555
%val = atomicrmw sub i16* %foo, i16 13 seq_cst
@@ -59,12 +59,12 @@ define i16 @atomic_load_sub16(i16* %foo) {
5959
; CHECK-LABEL: atomic_load_and16
6060
; CHECK: in r0, 63
6161
; CHECK-NEXT: cli
62-
; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]+
63-
; CHECK-NEXT: ld [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]
62+
; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD:(X|Y|Z)]]
63+
; CHECK-NEXT: ldd [[RR2:r[0-9]+]], [[RD]]+1
6464
; CHECK-NEXT: and [[RR1]], [[TMP:r[0-9]+]]
6565
; CHECK-NEXT: and [[RR2]], [[TMP:r[0-9]+]]
66-
; CHECK-NEXT: st [[RD1]], [[RR1]]
67-
; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]
66+
; CHECK-NEXT: st [[RD]], [[RR1]]
67+
; CHECK-NEXT: std [[RD]]+1, [[A:r[0-9]+]]
6868
; CHECK-NEXT: out 63, r0
6969
define i16 @atomic_load_and16(i16* %foo) {
7070
%val = atomicrmw and i16* %foo, i16 13 seq_cst
@@ -74,12 +74,12 @@ define i16 @atomic_load_and16(i16* %foo) {
7474
; CHECK-LABEL: atomic_load_or16
7575
; CHECK: in r0, 63
7676
; CHECK-NEXT: cli
77-
; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]+
78-
; CHECK-NEXT: ld [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]
77+
; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD:(X|Y|Z)]]
78+
; CHECK-NEXT: ldd [[RR2:r[0-9]+]], [[RD]]+1
7979
; CHECK-NEXT: or [[RR1]], [[TMP:r[0-9]+]]
8080
; CHECK-NEXT: or [[RR2]], [[TMP:r[0-9]+]]
81-
; CHECK-NEXT: st [[RD1]], [[RR1]]
82-
; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]
81+
; CHECK-NEXT: st [[RD]], [[RR1]]
82+
; CHECK-NEXT: std [[RD]]+1, [[A:r[0-9]+]]
8383
; CHECK-NEXT: out 63, r0
8484
define i16 @atomic_load_or16(i16* %foo) {
8585
%val = atomicrmw or i16* %foo, i16 13 seq_cst
@@ -89,12 +89,12 @@ define i16 @atomic_load_or16(i16* %foo) {
8989
; CHECK-LABEL: atomic_load_xor16
9090
; CHECK: in r0, 63
9191
; CHECK-NEXT: cli
92-
; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]+
93-
; CHECK-NEXT: ld [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]
92+
; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD:(X|Y|Z)]]
93+
; CHECK-NEXT: ldd [[RR2:r[0-9]+]], [[RD]]+1
9494
; CHECK-NEXT: eor [[RR1]], [[TMP:r[0-9]+]]
9595
; CHECK-NEXT: eor [[RR2]], [[TMP:r[0-9]+]]
96-
; CHECK-NEXT: st [[RD1]], [[RR1]]
97-
; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]
96+
; CHECK-NEXT: st [[RD]], [[RR1]]
97+
; CHECK-NEXT: std [[RD]]+1, [[A:r[0-9]+]]
9898
; CHECK-NEXT: out 63, r0
9999
define i16 @atomic_load_xor16(i16* %foo) {
100100
%val = atomicrmw xor i16* %foo, i16 13 seq_cst

llvm/test/CodeGen/AVR/load.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ define i8 @load8(i8* %x) {
99

1010
define i16 @load16(i16* %x) {
1111
; CHECK-LABEL: load16:
12-
; CHECK: ld r24, {{[XYZ]}}+
13-
; CHECK: ld r25, {{[XYZ]}}
12+
; CHECK: ld r24, [[PTR:[XYZ]]]
13+
; CHECK: ldd r25, [[PTR]]+1
1414
%1 = load i16, i16* %x
1515
ret i16 %1
1616
}
@@ -36,8 +36,8 @@ define i8 @load8nodisp(i8* %x) {
3636

3737
define i16 @load16disp(i16* %x) {
3838
; CHECK-LABEL: load16disp:
39-
; CHECK: ldd r24, {{[YZ]}}+62
40-
; CHECK: ldd r25, {{[YZ]}}+63
39+
; CHECK: ldd r24, [[PTR:[YZ]]]+62
40+
; CHECK: ldd r25, [[PTR]]+63
4141
%1 = getelementptr inbounds i16, i16* %x, i64 31
4242
%2 = load i16, i16* %1
4343
ret i16 %2
@@ -48,8 +48,8 @@ define i16 @load16nodisp(i16* %x) {
4848
; CHECK: movw r26, r24
4949
; CHECK: subi r26, 192
5050
; CHECK: sbci r27, 255
51-
; CHECK: ld r24, {{[XYZ]}}+
52-
; CHECK: ld r25, {{[XYZ]}}
51+
; CHECK: ld r24, [[PTR:[XYZ]]]
52+
; CHECK: ldd r25, [[PTR]]+1
5353
%1 = getelementptr inbounds i16, i16* %x, i64 32
5454
%2 = load i16, i16* %1
5555
ret i16 %2

llvm/test/CodeGen/AVR/pseudo/LDWRdPtr-same-src-dst.mir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ body: |
1818
1919
; CHECK-LABEL: test_ldwrdptr
2020
21-
; CHECK: ld [[SCRATCH:r[0-9]+]], Z+
21+
; CHECK: ld [[SCRATCH:r[0-9]+]], Z
2222
; CHECK-NEXT: push [[SCRATCH]]
23-
; CHECK-NEXT: ld [[SCRATCH]], Z
23+
; CHECK-NEXT: ldd [[SCRATCH]], Z+1
2424
; CHECK-NEXT: mov r31, [[SCRATCH]]
2525
; CHECK-NEXT: pop r30
2626

llvm/test/CodeGen/AVR/pseudo/LDWRdPtr.mir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ body: |
1717
1818
; CHECK-LABEL: test_ldwrdptr
1919
20-
; CHECK: $r0, $r31r30 = LDRdPtrPi $r31r30
21-
; CHECK-NEXT: $r1 = LDRdPtr $r31r30
20+
; CHECK: $r0, $r31r30 = LDRdPtr
21+
; CHECK-NEXT: $r1 = LDDRdPtrQ $r31r30, 1
2222
2323
$r1r0 = LDWRdPtr $r31r30
2424
...

0 commit comments

Comments
 (0)