llvm.org GIT mirror llvm / 912adb1
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351544 91177308-0d34-0410-b5e6-96231b3b80d8 Dylan McKay 1 year, 10 months ago
6 changed file(s) with 50 addition(s) and 37 deletion(s). Raw diff Collapse all Expand all
582582 unsigned TmpReg = 0; // 0 for no temporary register
583583 unsigned SrcReg = MI.getOperand(1).getReg();
584584 bool SrcIsKill = MI.getOperand(1).isKill();
585 OpLo = AVR::LDRdPtrPi;
586 OpHi = AVR::LDRdPtr;
585 OpLo = AVR::LDRdPtr;
586 OpHi = AVR::LDDRdPtrQ;
587587 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
588588
589589 // Use a temporary register if src and dst registers are the same.
596596 // Load low byte.
597597 auto MIBLO = buildMI(MBB, MBBI, OpLo)
598598 .addReg(CurDstLoReg, RegState::Define)
599 .addReg(SrcReg, RegState::Define)
600 .addReg(SrcReg);
599 .addReg(SrcReg, RegState::Define);
601600
602601 // Push low byte onto stack if necessary.
603602 if (TmpReg)
606605 // Load high byte.
607606 auto MIBHI = buildMI(MBB, MBBI, OpHi)
608607 .addReg(CurDstHiReg, RegState::Define)
609 .addReg(SrcReg, getKillRegState(SrcIsKill));
608 .addReg(SrcReg, getKillRegState(SrcIsKill))
609 .addImm(1);
610610
611611 if (TmpReg) {
612612 // Move the high byte into the final destination.
0 ; RUN: llc -mattr=avr6,sram < %s -march=avr | FileCheck %s
1
2 ; CHECK: ld {{r[0-9]+}}, [[PTR:[YZ]]]
3 ; CHECK: ldd {{r[0-9]+}}, [[PTR]]+1
4 ; CHECK: st [[PTR]], {{r[0-9]+}}
5 ; CHECK: std [[PTR]]+1, {{r[0-9]+}}
6 define void @load_store_16(i16* nocapture %ptr) local_unnamed_addr #1 {
7 entry:
8 %0 = load i16, i16* %ptr, align 2
9 %add = add i16 %0, 5
10 store i16 %add, i16* %ptr, align 2
11 ret void
12 }
22 ; CHECK-LABEL: atomic_load16
33 ; CHECK: in r0, 63
44 ; CHECK-NEXT: cli
5 ; CHECK-NEXT: ld [[RR:r[0-9]+]], [[RD:(X|Y|Z)]]+
6 ; CHECK-NEXT: ld [[RR:r[0-9]+]], [[RD:(X|Y|Z)]]
5 ; CHECK-NEXT: ld [[RR:r[0-9]+]], [[RD:(X|Y|Z)]]
6 ; CHECK-NEXT: ldd [[RR:r[0-9]+]], [[RD]]+1
77 ; CHECK-NEXT: out 63, r0
88 define i16 @atomic_load16(i16* %foo) {
99 %val = load atomic i16, i16* %foo unordered, align 2
2828 ; CHECK-LABEL: atomic_load_add16
2929 ; CHECK: in r0, 63
3030 ; CHECK-NEXT: cli
31 ; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]+
32 ; CHECK-NEXT: ld [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]
31 ; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD:(X|Y|Z)]]
32 ; CHECK-NEXT: ldd [[RR2:r[0-9]+]], [[RD]]+1
3333 ; CHECK-NEXT: add [[RR1]], [[TMP:r[0-9]+]]
3434 ; CHECK-NEXT: adc [[RR2]], [[TMP:r[0-9]+]]
35 ; CHECK-NEXT: st [[RD1]], [[RR1]]
36 ; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]
35 ; CHECK-NEXT: st [[RD]], [[RR1]]
36 ; CHECK-NEXT: std [[RD]]+1, [[A:r[0-9]+]]
3737 ; CHECK-NEXT: out 63, r0
3838 define i16 @atomic_load_add16(i16* %foo) {
3939 %val = atomicrmw add i16* %foo, i16 13 seq_cst
4343 ; CHECK-LABEL: atomic_load_sub16
4444 ; CHECK: in r0, 63
4545 ; CHECK-NEXT: cli
46 ; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]+
47 ; CHECK-NEXT: ld [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]
46 ; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD:(X|Y|Z)]]
47 ; CHECK-NEXT: ldd [[RR2:r[0-9]+]], [[RD]]+1
4848 ; CHECK-NEXT: sub [[RR1]], [[TMP:r[0-9]+]]
4949 ; CHECK-NEXT: sbc [[RR2]], [[TMP:r[0-9]+]]
50 ; CHECK-NEXT: st [[RD1]], [[RR1]]
51 ; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]
50 ; CHECK-NEXT: st [[RD]], [[RR1]]
51 ; CHECK-NEXT: std [[RD]]+1, [[A:r[0-9]+]]
5252 ; CHECK-NEXT: out 63, r0
5353 define i16 @atomic_load_sub16(i16* %foo) {
5454 %val = atomicrmw sub i16* %foo, i16 13 seq_cst
5858 ; CHECK-LABEL: atomic_load_and16
5959 ; CHECK: in r0, 63
6060 ; CHECK-NEXT: cli
61 ; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]+
62 ; CHECK-NEXT: ld [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]
61 ; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD:(X|Y|Z)]]
62 ; CHECK-NEXT: ldd [[RR2:r[0-9]+]], [[RD]]+1
6363 ; CHECK-NEXT: and [[RR1]], [[TMP:r[0-9]+]]
6464 ; CHECK-NEXT: and [[RR2]], [[TMP:r[0-9]+]]
65 ; CHECK-NEXT: st [[RD1]], [[RR1]]
66 ; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]
65 ; CHECK-NEXT: st [[RD]], [[RR1]]
66 ; CHECK-NEXT: std [[RD]]+1, [[A:r[0-9]+]]
6767 ; CHECK-NEXT: out 63, r0
6868 define i16 @atomic_load_and16(i16* %foo) {
6969 %val = atomicrmw and i16* %foo, i16 13 seq_cst
7373 ; CHECK-LABEL: atomic_load_or16
7474 ; CHECK: in r0, 63
7575 ; CHECK-NEXT: cli
76 ; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]+
77 ; CHECK-NEXT: ld [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]
76 ; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD:(X|Y|Z)]]
77 ; CHECK-NEXT: ldd [[RR2:r[0-9]+]], [[RD]]+1
7878 ; CHECK-NEXT: or [[RR1]], [[TMP:r[0-9]+]]
7979 ; CHECK-NEXT: or [[RR2]], [[TMP:r[0-9]+]]
80 ; CHECK-NEXT: st [[RD1]], [[RR1]]
81 ; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]
80 ; CHECK-NEXT: st [[RD]], [[RR1]]
81 ; CHECK-NEXT: std [[RD]]+1, [[A:r[0-9]+]]
8282 ; CHECK-NEXT: out 63, r0
8383 define i16 @atomic_load_or16(i16* %foo) {
8484 %val = atomicrmw or i16* %foo, i16 13 seq_cst
8888 ; CHECK-LABEL: atomic_load_xor16
8989 ; CHECK: in r0, 63
9090 ; CHECK-NEXT: cli
91 ; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]+
92 ; CHECK-NEXT: ld [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]
91 ; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD:(X|Y|Z)]]
92 ; CHECK-NEXT: ldd [[RR2:r[0-9]+]], [[RD]]+1
9393 ; CHECK-NEXT: eor [[RR1]], [[TMP:r[0-9]+]]
9494 ; CHECK-NEXT: eor [[RR2]], [[TMP:r[0-9]+]]
95 ; CHECK-NEXT: st [[RD1]], [[RR1]]
96 ; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]
95 ; CHECK-NEXT: st [[RD]], [[RR1]]
96 ; CHECK-NEXT: std [[RD]]+1, [[A:r[0-9]+]]
9797 ; CHECK-NEXT: out 63, r0
9898 define i16 @atomic_load_xor16(i16* %foo) {
9999 %val = atomicrmw xor i16* %foo, i16 13 seq_cst
88
99 define i16 @load16(i16* %x) {
1010 ; CHECK-LABEL: load16:
11 ; CHECK: ld r24, {{[XYZ]}}+
12 ; CHECK: ld r25, {{[XYZ]}}
11 ; CHECK: ld r24, [[PTR:[XYZ]]]
12 ; CHECK: ldd r25, [[PTR]]+1
1313 %1 = load i16, i16* %x
1414 ret i16 %1
1515 }
3535
3636 define i16 @load16disp(i16* %x) {
3737 ; CHECK-LABEL: load16disp:
38 ; CHECK: ldd r24, {{[YZ]}}+62
39 ; CHECK: ldd r25, {{[YZ]}}+63
38 ; CHECK: ldd r24, [[PTR:[YZ]]]+62
39 ; CHECK: ldd r25, [[PTR]]+63
4040 %1 = getelementptr inbounds i16, i16* %x, i64 31
4141 %2 = load i16, i16* %1
4242 ret i16 %2
4747 ; CHECK: movw r26, r24
4848 ; CHECK: subi r26, 192
4949 ; CHECK: sbci r27, 255
50 ; CHECK: ld r24, {{[XYZ]}}+
51 ; CHECK: ld r25, {{[XYZ]}}
50 ; CHECK: ld r24, [[PTR:[XYZ]]]
51 ; CHECK: ldd r25, [[PTR]]+1
5252 %1 = getelementptr inbounds i16, i16* %x, i64 32
5353 %2 = load i16, i16* %1
5454 ret i16 %2
1717
1818 ; CHECK-LABEL: test_ldwrdptr
1919
20 ; CHECK: ld [[SCRATCH:r[0-9]+]], Z+
20 ; CHECK: ld [[SCRATCH:r[0-9]+]], Z
2121 ; CHECK-NEXT: push [[SCRATCH]]
22 ; CHECK-NEXT: ld [[SCRATCH]], Z
22 ; CHECK-NEXT: ldd [[SCRATCH]], Z+1
2323 ; CHECK-NEXT: mov r31, [[SCRATCH]]
2424 ; CHECK-NEXT: pop r30
2525
1616
1717 ; CHECK-LABEL: test_ldwrdptr
1818
19 ; CHECK: $r0, $r31r30 = LDRdPtrPi $r31r30
20 ; CHECK-NEXT: $r1 = LDRdPtr $r31r30
19 ; CHECK: $r0, $r31r30 = LDRdPtr
20 ; CHECK-NEXT: $r1 = LDDRdPtrQ $r31r30, 1
2121
2222 $r1r0 = LDWRdPtr $r31r30
2323 ...