diff --git a/llvm/lib/Target/AVR/AVRDevices.td b/llvm/lib/Target/AVR/AVRDevices.td --- a/llvm/lib/Target/AVR/AVRDevices.td +++ b/llvm/lib/Target/AVR/AVRDevices.td @@ -120,6 +120,12 @@ "The device has Tiny core specific " "instruction encodings">; +// When writing a 16-bit port or storing a 16-bit word, do the low byte first. +def FeatureLowByteFirst + : SubtargetFeature<"lowbytefirst", "m_hasLowByteFirst", "true", + "Do the low byte first when writing a 16-bit port or " + "storing a 16-bit word">; + // The device has CPU registers mapped in data address space def FeatureMMR : SubtargetFeature<"memmappedregs", "m_hasMemMappedGPR", "true", "The device has CPU registers " @@ -195,14 +201,15 @@ [FamilyAVR0, FeatureLPM, FeatureIJMPCALL, FeatureADDSUBIW, FeatureSRAM, FeatureJMPCALL, FeatureMultiplication, FeatureMOVW, FeatureLPMX, - FeatureBREAK]>; + FeatureBREAK, FeatureLowByteFirst]>; def FamilyXMEGA : Family<"xmega", [FamilyAVR0, FeatureLPM, FeatureIJMPCALL, FeatureADDSUBIW, FeatureSRAM, FeatureJMPCALL, FeatureMultiplication, FeatureMOVW, FeatureLPMX, FeatureSPM, FeatureBREAK, FeatureEIJMPCALL, - FeatureSPMX, FeatureDES, FeatureELPM, FeatureELPMX]>; + FeatureSPMX, FeatureDES, FeatureELPM, FeatureELPMX, + FeatureLowByteFirst]>; def FamilyXMEGAU : Family<"xmegau", [FamilyXMEGA, FeatureRMW]>; diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp --- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp +++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp @@ -1057,18 +1057,15 @@ template <> bool AVRExpandPseudo::expand(Block &MBB, BlockIt MBBI) { + const AVRSubtarget &STI = MBB.getParent()->getSubtarget(); MachineInstr &MI = *MBBI; Register SrcLoReg, SrcHiReg; Register SrcReg = MI.getOperand(1).getReg(); bool SrcIsKill = MI.getOperand(1).isKill(); - unsigned OpLo = AVR::STSKRr; - unsigned OpHi = AVR::STSKRr; TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg); - // Write the high byte first in case this address belongs to a special - // I/O address with a special temporary register. - auto MIBHI = buildMI(MBB, MBBI, OpHi); - auto MIBLO = buildMI(MBB, MBBI, OpLo); + auto MIB0 = buildMI(MBB, MBBI, AVR::STSKRr); + auto MIB1 = buildMI(MBB, MBBI, AVR::STSKRr); switch (MI.getOperand(0).getType()) { case MachineOperand::MO_GlobalAddress: { @@ -1076,26 +1073,50 @@ int64_t Offs = MI.getOperand(0).getOffset(); unsigned TF = MI.getOperand(0).getTargetFlags(); - MIBLO.addGlobalAddress(GV, Offs, TF); - MIBHI.addGlobalAddress(GV, Offs + 1, TF); + if (STI.hasLowByteFirst()) { + // Write the low byte first for XMEGA devices. + MIB0.addGlobalAddress(GV, Offs, TF); + MIB1.addGlobalAddress(GV, Offs + 1, TF); + } else { + // Write the high byte first for traditional devices. + MIB0.addGlobalAddress(GV, Offs + 1, TF); + MIB1.addGlobalAddress(GV, Offs, TF); + } + break; } case MachineOperand::MO_Immediate: { unsigned Imm = MI.getOperand(0).getImm(); - MIBLO.addImm(Imm); - MIBHI.addImm(Imm + 1); + if (STI.hasLowByteFirst()) { + // Write the low byte first for XMEGA devices. + MIB0.addImm(Imm); + MIB1.addImm(Imm + 1); + } else { + // Write the high byte first for traditional devices. + MIB0.addImm(Imm + 1); + MIB1.addImm(Imm); + } + break; } default: llvm_unreachable("Unknown operand type!"); } - MIBLO.addReg(SrcLoReg, getKillRegState(SrcIsKill)); - MIBHI.addReg(SrcHiReg, getKillRegState(SrcIsKill)); - - MIBLO.setMemRefs(MI.memoperands()); - MIBHI.setMemRefs(MI.memoperands()); + if (STI.hasLowByteFirst()) { + // Write the low byte first for XMEGA devices. + MIB0.addReg(SrcLoReg, getKillRegState(SrcIsKill)) + .setMemRefs(MI.memoperands()); + MIB1.addReg(SrcHiReg, getKillRegState(SrcIsKill)) + .setMemRefs(MI.memoperands()); + } else { + // Write the high byte first for traditional devices. + MIB0.addReg(SrcHiReg, getKillRegState(SrcIsKill)) + .setMemRefs(MI.memoperands()); + MIB1.addReg(SrcLoReg, getKillRegState(SrcIsKill)) + .setMemRefs(MI.memoperands()); + } MI.eraseFromParent(); return true; @@ -1126,16 +1147,27 @@ } else { Register SrcLoReg, SrcHiReg; TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg); - buildMI(MBB, MBBI, AVR::STPtrRr) - .addReg(DstReg, getUndefRegState(DstIsUndef)) - .addReg(SrcLoReg, getKillRegState(SrcIsKill)) - .setMemRefs(MI.memoperands()); - - buildMI(MBB, MBBI, AVR::STDPtrQRr) - .addReg(DstReg, getUndefRegState(DstIsUndef)) - .addImm(1) - .addReg(SrcHiReg, getKillRegState(SrcIsKill)) - .setMemRefs(MI.memoperands()); + if (STI.hasLowByteFirst()) { + buildMI(MBB, MBBI, AVR::STPtrRr) + .addReg(DstReg, getUndefRegState(DstIsUndef)) + .addReg(SrcLoReg, getKillRegState(SrcIsKill)) + .setMemRefs(MI.memoperands()); + buildMI(MBB, MBBI, AVR::STDPtrQRr) + .addReg(DstReg, getUndefRegState(DstIsUndef)) + .addImm(1) + .addReg(SrcHiReg, getKillRegState(SrcIsKill)) + .setMemRefs(MI.memoperands()); + } else { + buildMI(MBB, MBBI, AVR::STDPtrQRr) + .addReg(DstReg, getUndefRegState(DstIsUndef)) + .addImm(1) + .addReg(SrcHiReg, getKillRegState(SrcIsKill)) + .setMemRefs(MI.memoperands()); + buildMI(MBB, MBBI, AVR::STPtrRr) + .addReg(DstReg, getUndefRegState(DstIsUndef)) + .addReg(SrcLoReg, getKillRegState(SrcIsKill)) + .setMemRefs(MI.memoperands()); + } } MI.eraseFromParent(); @@ -1252,23 +1284,32 @@ .addImm(Imm + 2); } } else { - unsigned OpLo = AVR::STDPtrQRr; - unsigned OpHi = AVR::STDPtrQRr; Register SrcLoReg, SrcHiReg; TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg); - auto MIBLO = buildMI(MBB, MBBI, OpLo) - .addReg(DstReg) - .addImm(Imm) - .addReg(SrcLoReg, getKillRegState(SrcIsKill)); - - auto MIBHI = buildMI(MBB, MBBI, OpHi) - .addReg(DstReg, getKillRegState(DstIsKill)) - .addImm(Imm + 1) - .addReg(SrcHiReg, getKillRegState(SrcIsKill)); - - MIBLO.setMemRefs(MI.memoperands()); - MIBHI.setMemRefs(MI.memoperands()); + if (STI.hasLowByteFirst()) { + buildMI(MBB, MBBI, AVR::STDPtrQRr) + .addReg(DstReg) + .addImm(Imm) + .addReg(SrcLoReg, getKillRegState(SrcIsKill)) + .setMemRefs(MI.memoperands()); + buildMI(MBB, MBBI, AVR::STDPtrQRr) + .addReg(DstReg, getKillRegState(DstIsKill)) + .addImm(Imm + 1) + .addReg(SrcHiReg, getKillRegState(SrcIsKill)) + .setMemRefs(MI.memoperands()); + } else { + buildMI(MBB, MBBI, AVR::STDPtrQRr) + .addReg(DstReg) + .addImm(Imm + 1) + .addReg(SrcHiReg, getKillRegState(SrcIsKill)) + .setMemRefs(MI.memoperands()); + buildMI(MBB, MBBI, AVR::STDPtrQRr) + .addReg(DstReg, getKillRegState(DstIsKill)) + .addImm(Imm) + .addReg(SrcLoReg, getKillRegState(SrcIsKill)) + .setMemRefs(MI.memoperands()); + } } MI.eraseFromParent(); @@ -1347,27 +1388,28 @@ template <> bool AVRExpandPseudo::expand(Block &MBB, BlockIt MBBI) { + const AVRSubtarget &STI = MBB.getParent()->getSubtarget(); MachineInstr &MI = *MBBI; Register SrcLoReg, SrcHiReg; unsigned Imm = MI.getOperand(0).getImm(); Register SrcReg = MI.getOperand(1).getReg(); bool SrcIsKill = MI.getOperand(1).isKill(); - unsigned OpLo = AVR::OUTARr; - unsigned OpHi = AVR::OUTARr; TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg); // Since we add 1 to the Imm value for the high byte below, and 63 is the // highest Imm value allowed for the instruction, 62 is the limit here. assert(Imm <= 62 && "Address is out of range"); - // 16 bit I/O writes need the high byte first - auto MIBHI = buildMI(MBB, MBBI, OpHi) - .addImm(Imm + 1) - .addReg(SrcHiReg, getKillRegState(SrcIsKill)); - - auto MIBLO = buildMI(MBB, MBBI, OpLo) - .addImm(Imm) - .addReg(SrcLoReg, getKillRegState(SrcIsKill)); + // 16 bit I/O writes need the high byte first on normal AVR devices, + // and in reverse order for the XMEGA/XMEGA3/XMEGAU families. + auto MIBHI = buildMI(MBB, MBBI, AVR::OUTARr) + .addImm(STI.hasLowByteFirst() ? Imm : Imm + 1) + .addReg(STI.hasLowByteFirst() ? SrcLoReg : SrcHiReg, + getKillRegState(SrcIsKill)); + auto MIBLO = buildMI(MBB, MBBI, AVR::OUTARr) + .addImm(STI.hasLowByteFirst() ? Imm + 1 : Imm) + .addReg(STI.hasLowByteFirst() ? SrcHiReg : SrcLoReg, + getKillRegState(SrcIsKill)); MIBLO.setMemRefs(MI.memoperands()); MIBHI.setMemRefs(MI.memoperands()); diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp --- a/llvm/lib/Target/AVR/AVRISelLowering.cpp +++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp @@ -1128,9 +1128,15 @@ return false; } else if (const StoreSDNode *ST = dyn_cast(N)) { VT = ST->getMemoryVT(); - if (AVR::isProgramMemoryAccess(ST)) { + // We can not store to program memory. + if (AVR::isProgramMemoryAccess(ST)) + return false; + // Since the high byte need to be stored first, we can not emit + // i16 post increment store like: + // st X+, r24 + // st X+, r25 + if (VT == MVT::i16 && !Subtarget.hasLowByteFirst()) return false; - } } else { return false; } diff --git a/llvm/lib/Target/AVR/AVRSubtarget.h b/llvm/lib/Target/AVR/AVRSubtarget.h --- a/llvm/lib/Target/AVR/AVRSubtarget.h +++ b/llvm/lib/Target/AVR/AVRSubtarget.h @@ -81,6 +81,7 @@ bool hasBREAK() const { return m_hasBREAK; } bool hasTinyEncoding() const { return m_hasTinyEncoding; } bool hasMemMappedGPR() const { return m_hasMemMappedGPR; } + bool hasLowByteFirst() const { return m_hasLowByteFirst; } uint8_t getIORegisterOffset() const { return hasMemMappedGPR() ? 0x20 : 0x0; } @@ -134,6 +135,7 @@ bool m_supportsMultiplication = false; bool m_hasBREAK = false; bool m_hasTinyEncoding = false; + bool m_hasLowByteFirst = false; bool m_hasMemMappedGPR = false; // Dummy member, used by FeatureSet's. We cannot have a SubtargetFeature with diff --git a/llvm/test/CodeGen/AVR/PR37143.ll b/llvm/test/CodeGen/AVR/PR37143.ll --- a/llvm/test/CodeGen/AVR/PR37143.ll +++ b/llvm/test/CodeGen/AVR/PR37143.ll @@ -2,8 +2,8 @@ ; CHECK: ld {{r[0-9]+}}, [[PTR:[XYZ]]] ; CHECK: ldd {{r[0-9]+}}, [[PTR]]+1 -; CHECK: st [[PTR2:[XYZ]]], {{r[0-9]+}} -; CHECK: std [[PTR2]]+1, {{r[0-9]+}} +; CHECK: std [[PTR2:[XYZ]]]+1, {{r[0-9]+}} +; CHECK: st [[PTR2]], {{r[0-9]+}} define void @load_store_16(i16* nocapture %ptr) local_unnamed_addr #1 { entry: %0 = load i16, i16* %ptr, align 2 diff --git a/llvm/test/CodeGen/AVR/alloca.ll b/llvm/test/CodeGen/AVR/alloca.ll --- a/llvm/test/CodeGen/AVR/alloca.ll +++ b/llvm/test/CodeGen/AVR/alloca.ll @@ -46,12 +46,12 @@ entry: ; CHECK-LABEL: alloca_write: ; Small offset here -; CHECK: std Y+23, {{.*}} ; CHECK: std Y+24, {{.*}} +; CHECK: std Y+23, {{.*}} ; Big offset here ; CHECK: adiw r28, 57 -; CHECK: std Y+62, {{.*}} ; CHECK: std Y+63, {{.*}} +; CHECK: std Y+62, {{.*}} ; CHECK: sbiw r28, 57 %p = alloca [15 x i16] %k = alloca [14 x i16] @@ -71,8 +71,8 @@ ; CHECK-LABEL: alloca_write_huge: ; CHECK: subi r28, 41 ; CHECK: sbci r29, 255 -; CHECK: std Y+62, {{.*}} ; CHECK: std Y+63, {{.*}} +; CHECK: std Y+62, {{.*}} ; CHECK: subi r28, 215 ; CHECK: sbci r29, 0 %k = alloca [140 x i16] diff --git a/llvm/test/CodeGen/AVR/atomics/load16.ll b/llvm/test/CodeGen/AVR/atomics/load16.ll --- a/llvm/test/CodeGen/AVR/atomics/load16.ll +++ b/llvm/test/CodeGen/AVR/atomics/load16.ll @@ -33,8 +33,8 @@ ; CHECK-NEXT: ldd [[RDH:r[0-9]+]], [[RR]]+1 ; CHECK-NEXT: add [[RR1L:r[0-9]+]], [[RDL]] ; CHECK-NEXT: adc [[RR1H:r[0-9]+]], [[RDH]] -; CHECK-NEXT: st [[RR]], [[RR1L]] ; CHECK-NEXT: std [[RR]]+1, [[RR1H]] +; CHECK-NEXT: st [[RR]], [[RR1L]] ; CHECK-NEXT: out 63, r0 define i16 @atomic_load_add16(i16* %foo) { %val = atomicrmw add i16* %foo, i16 13 seq_cst @@ -49,8 +49,8 @@ ; CHECK-NEXT: movw [[TMPL:r[0-9]+]], [[RDL]] ; CHECK-NEXT: sub [[TMPL]], [[RR1L:r[0-9]+]] ; CHECK-NEXT: sbc [[TMPH:r[0-9]+]], [[RR1H:r[0-9]+]] -; CHECK-NEXT: st [[RR]], [[TMPL]] ; CHECK-NEXT: std [[RR]]+1, [[TMPH]] +; CHECK-NEXT: st [[RR]], [[TMPL]] ; CHECK-NEXT: out 63, r0 define i16 @atomic_load_sub16(i16* %foo) { %val = atomicrmw sub i16* %foo, i16 13 seq_cst @@ -64,8 +64,8 @@ ; CHECK-NEXT: ldd [[RDH:r[0-9]+]], [[RR]]+1 ; CHECK-NEXT: and [[RD1L:r[0-9]+]], [[RDL]] ; CHECK-NEXT: and [[RD1H:r[0-9]+]], [[RDH]] -; CHECK-NEXT: st [[RR]], [[RD1L]] ; CHECK-NEXT: std [[RR]]+1, [[RD1H]] +; CHECK-NEXT: st [[RR]], [[RD1L]] ; CHECK-NEXT: out 63, r0 define i16 @atomic_load_and16(i16* %foo) { %val = atomicrmw and i16* %foo, i16 13 seq_cst @@ -79,8 +79,8 @@ ; CHECK-NEXT: ldd [[RDH:r[0-9]+]], [[RR]]+1 ; CHECK-NEXT: or [[RD1L:r[0-9]+]], [[RDL]] ; CHECK-NEXT: or [[RD1H:r[0-9]+]], [[RDH]] -; CHECK-NEXT: st [[RR]], [[RD1L]] ; CHECK-NEXT: std [[RR]]+1, [[RD1H]] +; CHECK-NEXT: st [[RR]], [[RD1L]] ; CHECK-NEXT: out 63, r0 define i16 @atomic_load_or16(i16* %foo) { %val = atomicrmw or i16* %foo, i16 13 seq_cst @@ -94,8 +94,8 @@ ; CHECK-NEXT: ldd [[RDH:r[0-9]+]], [[RR]]+1 ; CHECK-NEXT: eor [[RD1L:r[0-9]+]], [[RDL]] ; CHECK-NEXT: eor [[RD1H:r[0-9]+]], [[RDH]] -; CHECK-NEXT: st [[RR]], [[RD1L]] ; CHECK-NEXT: std [[RR]]+1, [[RD1H]] +; CHECK-NEXT: st [[RR]], [[RD1L]] ; CHECK-NEXT: out 63, r0 define i16 @atomic_load_xor16(i16* %foo) { %val = atomicrmw xor i16* %foo, i16 13 seq_cst diff --git a/llvm/test/CodeGen/AVR/atomics/store.ll b/llvm/test/CodeGen/AVR/atomics/store.ll --- a/llvm/test/CodeGen/AVR/atomics/store.ll +++ b/llvm/test/CodeGen/AVR/atomics/store.ll @@ -13,8 +13,8 @@ ; CHECK-LABEL: atomic_store16 ; CHECK: in r0, 63 ; CHECK-NEXT: cli -; CHECK-NEXT: st [[RD:(X|Y|Z)]], [[RR:r[0-9]+]] -; CHECK-NEXT: std [[RD]]+1, [[RR:r[0-9]+]] +; CHECK-NEXT: std [[RD:(X|Y|Z)]]+1, [[RR:r[0-9]+]] +; CHECK-NEXT: st [[RD]], [[RR:r[0-9]+]] ; CHECK-NEXT: out 63, r0 define void @atomic_store16(i16* %foo) { store atomic i16 1, i16* %foo unordered, align 2 diff --git a/llvm/test/CodeGen/AVR/atomics/store16.ll b/llvm/test/CodeGen/AVR/atomics/store16.ll --- a/llvm/test/CodeGen/AVR/atomics/store16.ll +++ b/llvm/test/CodeGen/AVR/atomics/store16.ll @@ -3,8 +3,8 @@ ; CHECK-LABEL: atomic_store16 ; CHECK: in r0, 63 ; CHECK-NEXT: cli -; CHECK-NEXT: st [[RD:(X|Y|Z)]], [[RR:r[0-9]+]] ; CHECK-NEXT: std [[RD:(X|Y|Z)]]+1, [[RR:r[0-9]+]] +; CHECK-NEXT: st [[RD:(X|Y|Z)]], [[RR:r[0-9]+]] ; CHECK-NEXT: out 63, r0 define void @atomic_store16(i16* %foo) { store atomic i16 1, i16* %foo unordered, align 2 @@ -14,8 +14,8 @@ ; CHECK-LABEL: monotonic ; CHECK: in r0, 63 ; CHECK-NEXT: cli -; CHECK-NEXT: st Z, r24 ; CHECK-NEXT: std Z+1, r25 +; CHECK-NEXT: st Z, r24 ; CHECK-NEXT: out 63, r0 define void @monotonic(i16) { entry-block: diff --git a/llvm/test/CodeGen/AVR/call.ll b/llvm/test/CodeGen/AVR/call.ll --- a/llvm/test/CodeGen/AVR/call.ll +++ b/llvm/test/CodeGen/AVR/call.ll @@ -35,8 +35,8 @@ ; CHECK-LABEL: calli8_stack: ; CHECK: ldi [[REG1:r[0-9]+]], 10 ; CHECK: ldi [[REG2:r[0-9]+]], 11 -; CHECK: std Z+1, [[REG1]] ; CHECK: std Z+2, [[REG2]] +; CHECK: std Z+1, [[REG1]] ; AVR6: call foo8_3 ; AVR2: rcall foo8_3 %result1 = call i8 @foo8_3(i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 9, i8 10, i8 11) @@ -59,12 +59,12 @@ ; CHECK-LABEL: calli16_stack: ; CHECK: ldi [[REG1:r[0-9]+]], 10 ; CHECK: ldi [[REG2:r[0-9]+]], 2 -; CHECK: std Z+3, [[REG1]] ; CHECK: std Z+4, [[REG2]] +; CHECK: std Z+3, [[REG1]] ; CHECK: ldi [[REG1:r[0-9]+]], 9 ; CHECK: ldi [[REG2:r[0-9]+]], 2 -; CHECK: std Z+1, [[REG1]] ; CHECK: std Z+2, [[REG2]] +; CHECK: std Z+1, [[REG1]] ; AVR6: call foo16_2 ; AVR2: rcall foo16_2 %result1 = call i16 @foo16_2(i16 512, i16 513, i16 514, i16 515, i16 516, i16 517, i16 518, i16 519, i16 520, i16 521, i16 522) @@ -91,12 +91,12 @@ ; CHECK-LABEL: calli32_stack: ; CHECK: ldi [[REG1:r[0-9]+]], 15 ; CHECK: ldi [[REG2:r[0-9]+]], 2 -; CHECK: std Z+3, [[REG1]] ; CHECK: std Z+4, [[REG2]] +; CHECK: std Z+3, [[REG1]] ; CHECK: ldi [[REG1:r[0-9]+]], 64 ; CHECK: ldi [[REG2:r[0-9]+]], 66 -; CHECK: std Z+1, [[REG1]] ; CHECK: std Z+2, [[REG2]] +; CHECK: std Z+1, [[REG1]] ; AVR6: call foo32_2 ; AVR2: rcall foo32_2 %result1 = call i32 @foo32_2(i32 1, i32 2, i32 3, i32 4, i32 34554432) @@ -124,20 +124,20 @@ ; CHECK: ldi [[REG1:r[0-9]+]], 31 ; CHECK: ldi [[REG2:r[0-9]+]], 242 -; CHECK: std Z+7, [[REG1]] ; CHECK: std Z+8, [[REG2]] +; CHECK: std Z+7, [[REG1]] ; CHECK: ldi [[REG1:r[0-9]+]], 76 ; CHECK: ldi [[REG2:r[0-9]+]], 73 -; CHECK: std Z+5, [[REG1]] ; CHECK: std Z+6, [[REG2]] +; CHECK: std Z+5, [[REG1]] ; CHECK: ldi [[REG1:r[0-9]+]], 155 ; CHECK: ldi [[REG2:r[0-9]+]], 88 -; CHECK: std Z+3, [[REG1]] ; CHECK: std Z+4, [[REG2]] +; CHECK: std Z+3, [[REG1]] ; CHECK: ldi [[REG1:r[0-9]+]], 255 ; CHECK: ldi [[REG2:r[0-9]+]], 255 -; CHECK: std Z+1, [[REG1]] ; CHECK: std Z+2, [[REG2]] +; CHECK: std Z+1, [[REG1]] ; AVR6: call foo64_2 ; AVR2: rcall foo64_2 %result1 = call i64 @foo64_2(i64 1, i64 2, i64 17446744073709551615) @@ -157,20 +157,20 @@ ; CHECK: std Y+9, [[REG1]] ; CHECK: ldi [[REG1:r[0-9]+]], 11 ; CHECK: ldi [[REG2:r[0-9]+]], 10 -; CHECK: std Y+7, [[REG1]] ; CHECK: std Y+8, [[REG2]] +; CHECK: std Y+7, [[REG1]] ; CHECK: ldi [[REG1:r[0-9]+]], 13 ; CHECK: ldi [[REG2:r[0-9]+]], 12 -; CHECK: std Y+5, [[REG1]] ; CHECK: std Y+6, [[REG2]] +; CHECK: std Y+5, [[REG1]] ; CHECK: ldi [[REG1:r[0-9]+]], 15 ; CHECK: ldi [[REG2:r[0-9]+]], 14 -; CHECK: std Y+3, [[REG1]] ; CHECK: std Y+4, [[REG2]] +; CHECK: std Y+3, [[REG1]] ; CHECK: ldi [[REG1:r[0-9]+]], 8 ; CHECK: ldi [[REG2:r[0-9]+]], 9 -; CHECK: std Y+1, [[REG1]] ; CHECK: std Y+2, [[REG2]] +; CHECK: std Y+1, [[REG1]] ; CHECK: pop r29 ; CHECK: pop r28 %p = alloca [8 x i16] diff --git a/llvm/test/CodeGen/AVR/dynalloca.ll b/llvm/test/CodeGen/AVR/dynalloca.ll --- a/llvm/test/CodeGen/AVR/dynalloca.ll +++ b/llvm/test/CodeGen/AVR/dynalloca.ll @@ -19,8 +19,8 @@ ; CHECK-NEXT: out 63, r0 ; CHECK-NEXT: out 61, {{.*}} ; Test writes -; CHECK: std Z+12, {{.*}} ; CHECK: std Z+13, {{.*}} +; CHECK: std Z+12, {{.*}} ; CHECK: std Z+7, {{.*}} ; CHECK-NOT: std ; Test SP restore @@ -66,14 +66,14 @@ ; Store values on the stack ; CHECK: ldi r16, 0 ; CHECK: ldi r17, 0 -; CHECK: std Z+7, r16 ; CHECK: std Z+8, r17 -; CHECK: std Z+5, r16 +; CHECK: std Z+7, r16 ; CHECK: std Z+6, r17 -; CHECK: std Z+3, r16 +; CHECK: std Z+5, r16 ; CHECK: std Z+4, r17 -; CHECK: std Z+1, r16 +; CHECK: std Z+3, r16 ; CHECK: std Z+2, r17 +; CHECK: std Z+1, r16 ; CHECK: call ; Call frame restore ; CHECK-NEXT: in r30, 61 diff --git a/llvm/test/CodeGen/AVR/lpmx.ll b/llvm/test/CodeGen/AVR/lpmx.ll --- a/llvm/test/CodeGen/AVR/lpmx.ll +++ b/llvm/test/CodeGen/AVR/lpmx.ll @@ -20,8 +20,8 @@ ; CHECK-O0-NEXT: out 62, r29 ; CHECK-O0-NEXT: out 63, r0 ; CHECK-O0-NEXT: out 61, r28 -; CHECK-O0-NEXT: std Y+1, r24 ; CHECK-O0-NEXT: std Y+2, r25 +; CHECK-O0-NEXT: std Y+1, r24 ; CHECK-O0-NEXT: ldd r30, Y+1 ; CHECK-O0-NEXT: ldd r31, Y+2 ; CHECK-O0-NEXT: lsl r30 @@ -52,8 +52,8 @@ ; CHECK-O3-NEXT: out 62, r29 ; CHECK-O3-NEXT: out 63, r0 ; CHECK-O3-NEXT: out 61, r28 -; CHECK-O3-NEXT: std Y+1, r24 ; CHECK-O3-NEXT: std Y+2, r25 +; CHECK-O3-NEXT: std Y+1, r24 ; CHECK-O3-NEXT: lsl r24 ; CHECK-O3-NEXT: rol r25 ; CHECK-O3-NEXT: subi r24, lo8(-(arr0)) @@ -92,8 +92,8 @@ ; CHECK-O0-NEXT: out 62, r29 ; CHECK-O0-NEXT: out 63, r0 ; CHECK-O0-NEXT: out 61, r28 -; CHECK-O0-NEXT: std Y+1, r24 ; CHECK-O0-NEXT: std Y+2, r25 +; CHECK-O0-NEXT: std Y+1, r24 ; CHECK-O0-NEXT: ldd r30, Y+1 ; CHECK-O0-NEXT: ldd r31, Y+2 ; CHECK-O0-NEXT: subi r30, lo8(-(arr1)) @@ -121,8 +121,8 @@ ; CHECK-O3-NEXT: out 62, r29 ; CHECK-O3-NEXT: out 63, r0 ; CHECK-O3-NEXT: out 61, r28 -; CHECK-O3-NEXT: std Y+1, r24 ; CHECK-O3-NEXT: std Y+2, r25 +; CHECK-O3-NEXT: std Y+1, r24 ; CHECK-O3-NEXT: subi r24, lo8(-(arr1)) ; CHECK-O3-NEXT: sbci r25, hi8(-(arr1)) ; CHECK-O3-NEXT: movw r30, r24 diff --git a/llvm/test/CodeGen/AVR/pr43443-ctor-alias.ll b/llvm/test/CodeGen/AVR/pr43443-ctor-alias.ll --- a/llvm/test/CodeGen/AVR/pr43443-ctor-alias.ll +++ b/llvm/test/CodeGen/AVR/pr43443-ctor-alias.ll @@ -30,8 +30,8 @@ ; CHECK-NEXT: out 62, r29 ; CHECK-NEXT: out 63, r0 ; CHECK-NEXT: out 61, r28 -; CHECK-NEXT: std Y+1, r24 ; CHECK-NEXT: std Y+2, r25 +; CHECK-NEXT: std Y+1, r24 ; CHECK-NEXT: adiw r28, 2 ; CHECK-NEXT: in r0, 63 ; CHECK-NEXT: cli diff --git a/llvm/test/CodeGen/AVR/pseudo/OUTWARr.mir b/llvm/test/CodeGen/AVR/pseudo/OUTWARr.mir --- a/llvm/test/CodeGen/AVR/pseudo/OUTWARr.mir +++ b/llvm/test/CodeGen/AVR/pseudo/OUTWARr.mir @@ -1,4 +1,13 @@ -# RUN: llc -O0 -run-pass=avr-expand-pseudo %s -o - | FileCheck %s +# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=attiny11 %s -o - \ +# RUN: | FileCheck %s +# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=atmega328 %s -o - \ +# RUN: | FileCheck %s +# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=attiny817 %s -o - \ +# RUN: | FileCheck --check-prefix=XMEGA %s +# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=atxmega64a1 %s -o - \ +# RUN: | FileCheck --check-prefix=XMEGA %s +# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=atxmega256a3u %s -o - \ +# RUN: | FileCheck --check-prefix=XMEGA %s --- | target triple = "avr--" @@ -15,9 +24,12 @@ liveins: $r15r14 ; CHECK-LABEL: test + ; CHECK: OUTARr 32, $r15 + ; CHECK-NEXT: OUTARr 31, $r14 - ; CHECK: OUTARr 32, $r15 - ; CHECK-NEXT: OUTARr 31, $r14 + ; XMEGA-LABEL: test + ; XMEGA: OUTARr 31, $r14 + ; XMEGA-NEXT: OUTARr 32, $r15 OUTWARr 31, $r15r14 ... diff --git a/llvm/test/CodeGen/AVR/pseudo/STDWPtrQRr.mir b/llvm/test/CodeGen/AVR/pseudo/STDWPtrQRr.mir --- a/llvm/test/CodeGen/AVR/pseudo/STDWPtrQRr.mir +++ b/llvm/test/CodeGen/AVR/pseudo/STDWPtrQRr.mir @@ -1,5 +1,8 @@ # RUN: llc -O0 -run-pass=avr-expand-pseudo -verify-machineinstrs %s -o - | FileCheck %s -# RUN: llc -O0 -run-pass=avr-expand-pseudo -verify-machineinstrs -mattr=avrtiny %s -o - | FileCheck %s --check-prefix=CHECK-TINY +# RUN: llc -O0 -run-pass=avr-expand-pseudo -verify-machineinstrs -mattr=avrtiny %s -o - \ +# RUN: | FileCheck %s --check-prefix=CHECK-TINY +# RUN: llc -O0 -run-pass=avr-expand-pseudo -verify-machineinstrs -mattr=lowbytefirst %s -o - \ +# RUN: | FileCheck %s --check-prefix=CHECK-XMEGA --- | target triple = "avr--" @@ -17,29 +20,37 @@ ; CHECK-LABEL: test ; Small displacement (<63): - ; CHECK: STDPtrQRr $r29r28, 3, $r0 - ; CHECK-NEXT: STDPtrQRr $r29r28, 4, $r1 - ; CHECK-TINY: $r28 = SUBIRdK killed $r28, 253, implicit-def $sreg - ; CHECK-TINY-NEXT: $r29 = SBCIRdK killed $r29, 255, implicit-def $sreg, implicit killed $sreg - ; CHECK-TINY-NEXT: early-clobber $r29r28 = STPtrPiRr killed $r29r28, $r0, 0 - ; CHECK-TINY-NEXT: early-clobber $r29r28 = STPtrPiRr killed $r29r28, $r1, 0 - ; CHECK-TINY-NEXT: $r28 = SUBIRdK killed $r28, 5, implicit-def $sreg - ; CHECK-TINY-NEXT: $r29 = SBCIRdK killed $r29, 0, implicit-def $sreg, implicit killed $sreg + ; CHECK: STDPtrQRr $r29r28, 4, $r1 + ; CHECK-NEXT: STDPtrQRr $r29r28, 3, $r0 + ; CHECK-XMEGA: STDPtrQRr $r29r28, 3, $r0 + ; CHECK-XMEGA-NEXT: STDPtrQRr $r29r28, 4, $r1 + ; CHECK-TINY: $r28 = SUBIRdK killed $r28, 253, implicit-def $sreg + ; CHECK-TINY-NEXT: $r29 = SBCIRdK killed $r29, 255, implicit-def $sreg, implicit killed $sreg + ; CHECK-TINY-NEXT: early-clobber $r29r28 = STPtrPiRr killed $r29r28, $r0, 0 + ; CHECK-TINY-NEXT: early-clobber $r29r28 = STPtrPiRr killed $r29r28, $r1, 0 + ; CHECK-TINY-NEXT: $r28 = SUBIRdK killed $r28, 5, implicit-def $sreg + ; CHECK-TINY-NEXT: $r29 = SBCIRdK killed $r29, 0, implicit-def $sreg, implicit killed $sreg STDWPtrQRr $r29r28, 3, $r1r0 ; Small displacement where the destination register is killed: - ; CHECK: STDPtrQRr $r29r28, 3, $r0 - ; CHECK-NEXT: STDPtrQRr killed $r29r28, 4, $r1 + ; CHECK-NEXT: STDPtrQRr $r29r28, 4, $r1 + ; CHECK-NEXT: STDPtrQRr killed $r29r28, 3, $r0 + ; CHECK-XMEGA-NEXT: STDPtrQRr $r29r28, 3, $r0 + ; CHECK-XMEGA-NEXT: STDPtrQRr killed $r29r28, 4, $r1 STDWPtrQRr killed $r29r28, 3, $r1r0 ; Small displacement where the source register is killed: - ; CHECK: STDPtrQRr $r29r28, 3, killed $r0 - ; CHECK-NEXT: STDPtrQRr $r29r28, 4, killed $r1 + ; CHECK: STDPtrQRr $r29r28, 4, killed $r1 + ; CHECK-NEXT: STDPtrQRr $r29r28, 3, killed $r0 + ; CHECK-XMEGA: STDPtrQRr $r29r28, 3, killed $r0 + ; CHECK-XMEGA-NEXT: STDPtrQRr $r29r28, 4, killed $r1 STDWPtrQRr $r29r28, 3, killed $r1r0 ; Small displacement, near the limit (=62): - ; CHECK: STDPtrQRr $r29r28, 62, $r0 - ; CHECK-NEXT: STDPtrQRr $r29r28, 63, $r1 + ; CHECK: STDPtrQRr $r29r28, 63, $r1 + ; CHECK-NEXT: STDPtrQRr $r29r28, 62, $r0 + ; CHECK-XMEGA: STDPtrQRr $r29r28, 62, $r0 + ; CHECK-XMEGA-NEXT: STDPtrQRr $r29r28, 63, $r1 STDWPtrQRr $r29r28, 62, $r1r0 ; Large displacement (>=63): diff --git a/llvm/test/CodeGen/AVR/pseudo/STSWKRr.mir b/llvm/test/CodeGen/AVR/pseudo/STSWKRr.mir --- a/llvm/test/CodeGen/AVR/pseudo/STSWKRr.mir +++ b/llvm/test/CodeGen/AVR/pseudo/STSWKRr.mir @@ -1,4 +1,6 @@ # RUN: llc -O0 -run-pass=avr-expand-pseudo %s -o - | FileCheck %s +# RUN: llc -O0 -run-pass=avr-expand-pseudo -mcpu=atxmega64a1 %s -o - \ +# RUN: | FileCheck --check-prefix=XMEGA %s # This test checks the expansion of the 16-bit STSWRdK pseudo instruction. @@ -17,9 +19,12 @@ liveins: $r31r30 ; CHECK-LABEL: test_stswkrr + ; CHECK: STSKRr 2560, $r31 + ; CHECK-NEXT: STSKRr 2559, $r30 - ; CHECK: STSKRr 2560, $r31 - ; CHECK-NEXT: STSKRr 2559, $r30 + ; XMEGA-LABEL: test_stswkrr + ; XMEGA: STSKRr 2559, $r30 + ; XMEGA-NEXT: STSKRr 2560, $r31 STSWKRr 2559, $r31r30 ... diff --git a/llvm/test/CodeGen/AVR/pseudo/STWPtrRr.mir b/llvm/test/CodeGen/AVR/pseudo/STWPtrRr.mir --- a/llvm/test/CodeGen/AVR/pseudo/STWPtrRr.mir +++ b/llvm/test/CodeGen/AVR/pseudo/STWPtrRr.mir @@ -1,5 +1,8 @@ # RUN: llc -O0 -run-pass=avr-expand-pseudo %s -o - | FileCheck %s -# RUN: llc -O0 -run-pass=avr-expand-pseudo -mattr=avrtiny %s -o - | FileCheck %s --check-prefix=CHECK-TINY +# RUN: llc -O0 -run-pass=avr-expand-pseudo -mattr=avrtiny %s -o - \ +# RUN: | FileCheck %s --check-prefix=CHECK-TINY +# RUN: llc -O0 -run-pass=avr-expand-pseudo -mattr=lowbytefirst %s -o - \ +# RUN: | FileCheck %s --check-prefix=CHECK-XMEGA # This test checks the expansion of the 16-bit STSWRdK pseudo instruction. @@ -18,14 +21,18 @@ liveins: $r31r30, $r17r16 ; CHECK-LABEL: test_stwptrrr + ; CHECK: STDPtrQRr $r31r30, 1, $r17 + ; CHECK-NEXT: STPtrRr $r31r30, $r16 - ; CHECK: STPtrRr $r31r30, $r16 - ; CHECK-NEXT: STDPtrQRr $r31r30, 1, $r17 + ; CHECK-TINY-LABEL: test_stwptrrr + ; CHECK-TINY: $r31r30 = STPtrPiRr killed $r31r30, $r16, 0 + ; CHECK-TINY-NEXT: $r31r30 = STPtrPiRr killed $r31r30, $r17, 0 + ; CHECK-TINY-NEXT: $r30 = SUBIRdK killed $r30, 2, implicit-def $sreg + ; CHECK-TINY-NEXT: $r31 = SBCIRdK killed $r31, 0, implicit-def $sreg, implicit killed $sreg - ; CHECK-TINY: $r31r30 = STPtrPiRr killed $r31r30, $r16, 0 - ; CHECK-TINY-NEXT: $r31r30 = STPtrPiRr killed $r31r30, $r17, 0 - ; CHECK-TINY-NEXT: $r30 = SUBIRdK killed $r30, 2, implicit-def $sreg - ; CHECK-TINY-NEXT: $r31 = SBCIRdK killed $r31, 0, implicit-def $sreg, implicit killed $sreg + ; CHECK-XMEGA-LABEL: test_stwptrrr + ; CHECK-XMEGA: STPtrRr $r31r30, $r16 + ; CHECK-XMEGA-NEXT: STDPtrQRr $r31r30, 1, $r17 STWPtrRr $r31r30, $r17r16 ... diff --git a/llvm/test/CodeGen/AVR/shift32.ll b/llvm/test/CodeGen/AVR/shift32.ll --- a/llvm/test/CodeGen/AVR/shift32.ll +++ b/llvm/test/CodeGen/AVR/shift32.ll @@ -208,12 +208,12 @@ ; CHECK-LABEL: shl_i32_16_ptr: ; CHECK: ; %bb.0: ; CHECK-NEXT: movw r30, r20 -; CHECK-NEXT: std Z+2, r22 ; CHECK-NEXT: std Z+3, r23 +; CHECK-NEXT: std Z+2, r22 ; CHECK-NEXT: ldi r24, 0 ; CHECK-NEXT: ldi r25, 0 -; CHECK-NEXT: st Z, r24 ; CHECK-NEXT: std Z+1, r25 +; CHECK-NEXT: st Z, r24 ; CHECK-NEXT: ret %res = shl i32 %a, 16 store i32 %res, ptr %ptr diff --git a/llvm/test/CodeGen/AVR/store.ll b/llvm/test/CodeGen/AVR/store.ll --- a/llvm/test/CodeGen/AVR/store.ll +++ b/llvm/test/CodeGen/AVR/store.ll @@ -9,8 +9,8 @@ define void @store16(i16* %x, i16 %y) { ; CHECK-LABEL: store16: -; CHECK: st {{[YZ]}}, r22 ; CHECK: std {{[YZ]}}+1, r23 +; CHECK: st {{[YZ]}}, r22 store i16 %y, i16* %x ret void } @@ -36,8 +36,8 @@ define void @store16disp(i16* %x, i16 %y) { ; CHECK-LABEL: store16disp: -; CHECK: std {{[YZ]}}+62, r22 ; CHECK: std {{[YZ]}}+63, r23 +; CHECK: std {{[YZ]}}+62, r22 %arrayidx = getelementptr inbounds i16, i16* %x, i16 31 store i16 %y, i16* %arrayidx ret void @@ -48,8 +48,8 @@ ; CHECK: subi r24, 192 ; CHECK: sbci r25, 255 ; CHECK: movw r30, r24 -; CHECK: st {{[YZ]}}, r22 ; CHECK: std {{[YZ]}}+1, r23 +; CHECK: st {{[YZ]}}, r22 %arrayidx = getelementptr inbounds i16, i16* %x, i16 32 store i16 %y, i16* %arrayidx ret void @@ -75,8 +75,8 @@ define void @store16postinc(i16* %x, i16 %y) { ; CHECK-LABEL: store16postinc: -; CHECK: st {{[XYZ]}}+, {{.*}} -; CHECK: st {{[XYZ]}}+, {{.*}} +; CHECK: std {{[XYZ]}}+1, {{.*}} +; CHECK: st {{[XYZ]}}, {{.*}} entry: %tobool3 = icmp eq i16 %y, 0 br i1 %tobool3, label %while.end, label %while.body diff --git a/llvm/test/CodeGen/AVR/struct.ll b/llvm/test/CodeGen/AVR/struct.ll --- a/llvm/test/CodeGen/AVR/struct.ll +++ b/llvm/test/CodeGen/AVR/struct.ll @@ -11,23 +11,23 @@ ; CHECKA: ; %bb.0: ; CHECKA-NEXT: mov r30, r24 ; CHECKA-NEXT: mov r31, r25 -; CHECKA-NEXT: std Z+4, r22 ; CHECKA-NEXT: std Z+5, r23 -; CHECKA-NEXT: std Z+2, r20 +; CHECKA-NEXT: std Z+4, r22 ; CHECKA-NEXT: std Z+3, r21 -; CHECKA-NEXT: st Z, r18 +; CHECKA-NEXT: std Z+2, r20 ; CHECKA-NEXT: std Z+1, r19 +; CHECKA-NEXT: st Z, r18 ; CHECKA-NEXT: ret ; ; CHECKB-LABEL: foo10: ; CHECKB: ; %bb.0: ; CHECKB-NEXT: movw r30, r24 -; CHECKB-NEXT: std Z+4, r22 ; CHECKB-NEXT: std Z+5, r23 -; CHECKB-NEXT: std Z+2, r20 +; CHECKB-NEXT: std Z+4, r22 ; CHECKB-NEXT: std Z+3, r21 -; CHECKB-NEXT: st Z, r18 +; CHECKB-NEXT: std Z+2, r20 ; CHECKB-NEXT: std Z+1, r19 +; CHECKB-NEXT: st Z, r18 ; CHECKB-NEXT: ret %5 = getelementptr inbounds %struct.s10, %struct.s10* %0, i16 0, i32 0 store i16 %3, i16* %5 diff --git a/llvm/test/CodeGen/AVR/varargs.ll b/llvm/test/CodeGen/AVR/varargs.ll --- a/llvm/test/CodeGen/AVR/varargs.ll +++ b/llvm/test/CodeGen/AVR/varargs.ll @@ -42,16 +42,16 @@ ; CHECK-LABEL: varargcall: ; CHECK: ldi [[REG1:r[0-9]+]], 191 ; CHECK: ldi [[REG2:r[0-9]+]], 223 -; CHECK: std Z+5, [[REG1]] ; CHECK: std Z+6, [[REG2]] +; CHECK: std Z+5, [[REG1]] ; CHECK: ldi [[REG1:r[0-9]+]], 189 ; CHECK: ldi [[REG2:r[0-9]+]], 205 -; CHECK: std Z+3, [[REG1]] ; CHECK: std Z+4, [[REG2]] +; CHECK: std Z+3, [[REG1]] ; CHECK: ldi [[REG1:r[0-9]+]], 205 ; CHECK: ldi [[REG2:r[0-9]+]], 171 -; CHECK: std Z+1, [[REG1]] ; CHECK: std Z+2, [[REG2]] +; CHECK: std Z+1, [[REG1]] ; CHECK: call ; CHECK: adiw r30, 6 tail call void (i16, ...) @var1223(i16 -21555, i16 -12867, i16 -8257)