llvm.org GIT mirror llvm / 31dcac0
[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. Bug first reported by Keshav Kini. Patch by Kaushik Phatak. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351673 91177308-0d34-0410-b5e6-96231b3b80d8 Dylan McKay 1 year, 10 months ago
7 changed file(s) with 50 addition(s) and 40 deletion(s). Raw diff Collapse all Expand all
581581 unsigned TmpReg = 0; // 0 for no temporary register
582582 unsigned SrcReg = MI.getOperand(1).getReg();
583583 bool SrcIsKill = MI.getOperand(1).isKill();
584 OpLo = AVR::LDRdPtrPi;
585 OpHi = AVR::LDRdPtr;
584 OpLo = AVR::LDRdPtr;
585 OpHi = AVR::LDDRdPtrQ;
586586 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
587587
588588 // Use a temporary register if src and dst registers are the same.
595595 // Load low byte.
596596 auto MIBLO = buildMI(MBB, MBBI, OpLo)
597597 .addReg(CurDstLoReg, RegState::Define)
598 .addReg(SrcReg, RegState::Define)
599 .addReg(SrcReg);
598 .addReg(SrcReg, RegState::Define);
600599
601600 // Push low byte onto stack if necessary.
602601 if (TmpReg)
605604 // Load high byte.
606605 auto MIBHI = buildMI(MBB, MBBI, OpHi)
607606 .addReg(CurDstHiReg, RegState::Define)
608 .addReg(SrcReg, getKillRegState(SrcIsKill));
607 .addReg(SrcReg, getKillRegState(SrcIsKill))
608 .addImm(1);
609609
610610 if (TmpReg) {
611611 // Move the high byte into the final destination.
12771277 }
12781278
12791279 // Add a register mask operand representing the call-preserved registers.
1280 const AVRTargetMachine &TM = (const AVRTargetMachine &)getTargetMachine();
12811280 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
12821281 const uint32_t *Mask =
12831282 TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);
14401439 bool HasRepeatedOperand = false;
14411440 MachineFunction *F = BB->getParent();
14421441 MachineRegisterInfo &RI = F->getRegInfo();
1443 const AVRTargetMachine &TM = (const AVRTargetMachine &)getTargetMachine();
14441442 const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
14451443 DebugLoc dl = MI.getDebugLoc();
14461444
15811579 // it, but it works for now.
15821580 MachineBasicBlock *AVRTargetLowering::insertMul(MachineInstr &MI,
15831581 MachineBasicBlock *BB) const {
1584 const AVRTargetMachine &TM = (const AVRTargetMachine &)getTargetMachine();
15851582 const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
15861583 MachineBasicBlock::iterator I(MI);
15871584 ++I; // in any case insert *after* the mul instruction
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 ...