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 @@ -2103,6 +2103,30 @@ return true; } +template <> +bool AVRExpandPseudo::expand(Block &MBB, BlockIt MBBI) { + MachineInstr &MI = *MBBI; + MachineFunction &MF = *MI.getParent()->getParent(); + const AVRSubtarget &STI = MF.getSubtarget(); + + MI.setDesc(TII->get(AVR::STDPtrQRr)); + MI.getOperand(0).setReg(STI.getFrameLowering()->hasReservedCallFrame(MF) ? AVR::R29R28 : AVR::R31R30); + + return true; +} + +template <> +bool AVRExpandPseudo::expand(Block &MBB, BlockIt MBBI) { + MachineInstr &MI = *MBBI; + MachineFunction &MF = *MI.getParent()->getParent(); + const AVRSubtarget &STI = MF.getSubtarget(); + + MI.setDesc(TII->get(AVR::STDWPtrQRr)); + MI.getOperand(0).setReg(STI.getFrameLowering()->hasReservedCallFrame(MF) ? AVR::R29R28 : AVR::R31R30); + + return true; +} + bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) { MachineInstr &MI = *MBBI; int Opcode = MBBI->getOpcode(); @@ -2177,6 +2201,8 @@ EXPAND(AVR::ZEXT); EXPAND(AVR::SPREAD); EXPAND(AVR::SPWRITE); + EXPAND(AVR::STDSPQRr); + EXPAND(AVR::STDWSPQRr); } #undef EXPAND return false; diff --git a/llvm/lib/Target/AVR/AVRFrameLowering.cpp b/llvm/lib/Target/AVR/AVRFrameLowering.cpp --- a/llvm/lib/Target/AVR/AVRFrameLowering.cpp +++ b/llvm/lib/Target/AVR/AVRFrameLowering.cpp @@ -298,107 +298,70 @@ return true; } -/// Replace pseudo store instructions that pass arguments through the stack with -/// real instructions. -static void fixStackStores(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const TargetInstrInfo &TII, Register FP) { - // Iterate through the BB until we hit a call instruction or we reach the end. - for (auto I = MI, E = MBB.end(); I != E && !I->isCall();) { - MachineBasicBlock::iterator NextMI = std::next(I); - MachineInstr &MI = *I; - unsigned Opcode = I->getOpcode(); - - // Only care of pseudo store instructions where SP is the base pointer. - if (Opcode != AVR::STDSPQRr && Opcode != AVR::STDWSPQRr) { - I = NextMI; - continue; - } - - assert(MI.getOperand(0).getReg() == AVR::SP && - "Invalid register, should be SP!"); - - // Replace this instruction with a regular store. Use Y as the base - // pointer since it is guaranteed to contain a copy of SP. - unsigned STOpc = - (Opcode == AVR::STDWSPQRr) ? AVR::STDWPtrQRr : AVR::STDPtrQRr; - - MI.setDesc(TII.get(STOpc)); - MI.getOperand(0).setReg(FP); - - I = NextMI; - } -} - MachineBasicBlock::iterator AVRFrameLowering::eliminateCallFramePseudoInstr( MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const { const AVRSubtarget &STI = MF.getSubtarget(); const AVRInstrInfo &TII = *STI.getInstrInfo(); - // There is nothing to insert when the call frame memory is allocated during - // function entry. Delete the call frame pseudo and replace all pseudo stores - // with real store instructions. if (hasReservedCallFrame(MF)) { - fixStackStores(MBB, MI, TII, AVR::R29R28); + return MBB.erase(MI); + } + + int Amount = TII.getFrameSize(*MI); + + if (Amount == 0) { return MBB.erase(MI); } DebugLoc DL = MI->getDebugLoc(); unsigned int Opcode = MI->getOpcode(); - int Amount = TII.getFrameSize(*MI); + + assert(getStackAlign() == Align(1) && "Unsupported stack alignment"); // ADJCALLSTACKUP and ADJCALLSTACKDOWN are converted to adiw/subi // instructions to read and write the stack pointer in I/O space. - if (Amount != 0) { - assert(getStackAlign() == Align(1) && "Unsupported stack alignment"); - - if (Opcode == TII.getCallFrameSetupOpcode()) { - // Update the stack pointer. - // In many cases this can be done far more efficiently by pushing the - // relevant values directly to the stack. However, doing that correctly - // (in the right order, possibly skipping some empty space for undef - // values, etc) is tricky and thus left to be optimized in the future. - BuildMI(MBB, MI, DL, TII.get(AVR::SPREAD), AVR::R31R30).addReg(AVR::SP); - - MachineInstr *New = BuildMI(MBB, MI, DL, TII.get(AVR::SUBIWRdK), AVR::R31R30) - .addReg(AVR::R31R30, RegState::Kill) - .addImm(Amount); - New->getOperand(3).setIsDead(); - - BuildMI(MBB, MI, DL, TII.get(AVR::SPWRITE), AVR::SP) - .addReg(AVR::R31R30); - - // Make sure the remaining stack stores are converted to real store - // instructions. - fixStackStores(MBB, MI, TII, AVR::R31R30); + if (Opcode == TII.getCallFrameSetupOpcode()) { + // Update the stack pointer. + // In many cases this can be done far more efficiently by pushing the + // relevant values directly to the stack. However, doing that correctly + // (in the right order, possibly skipping some empty space for undef + // values, etc) is tricky and thus left to be optimized in the future. + BuildMI(MBB, MI, DL, TII.get(AVR::SPREAD), AVR::R31R30).addReg(AVR::SP); + + MachineInstr *New = + BuildMI(MBB, MI, DL, TII.get(AVR::SUBIWRdK), AVR::R31R30) + .addReg(AVR::R31R30, RegState::Kill) + .addImm(Amount); + New->getOperand(3).setIsDead(); + + BuildMI(MBB, MI, DL, TII.get(AVR::SPWRITE), AVR::SP).addReg(AVR::R31R30); + } else { + assert(Opcode == TII.getCallFrameDestroyOpcode()); + + // Note that small stack changes could be implemented more efficiently + // with a few pop instructions instead of the 8-9 instructions now + // required. + + // Select the best opcode to adjust SP based on the offset size. + unsigned addOpcode; + if (isUInt<6>(Amount)) { + addOpcode = AVR::ADIWRdK; } else { - assert(Opcode == TII.getCallFrameDestroyOpcode()); - - // Note that small stack changes could be implemented more efficiently - // with a few pop instructions instead of the 8-9 instructions now - // required. - - // Select the best opcode to adjust SP based on the offset size. - unsigned addOpcode; - if (isUInt<6>(Amount)) { - addOpcode = AVR::ADIWRdK; - } else { - addOpcode = AVR::SUBIWRdK; - Amount = -Amount; - } + addOpcode = AVR::SUBIWRdK; + Amount = -Amount; + } - // Build the instruction sequence. - BuildMI(MBB, MI, DL, TII.get(AVR::SPREAD), AVR::R31R30).addReg(AVR::SP); + // Build the instruction sequence. + BuildMI(MBB, MI, DL, TII.get(AVR::SPREAD), AVR::R31R30).addReg(AVR::SP); - MachineInstr *New = BuildMI(MBB, MI, DL, TII.get(addOpcode), AVR::R31R30) - .addReg(AVR::R31R30, RegState::Kill) - .addImm(Amount); - New->getOperand(3).setIsDead(); + MachineInstr *New = BuildMI(MBB, MI, DL, TII.get(addOpcode), AVR::R31R30) + .addReg(AVR::R31R30, RegState::Kill) + .addImm(Amount); + New->getOperand(3).setIsDead(); - BuildMI(MBB, MI, DL, TII.get(AVR::SPWRITE), AVR::SP) - .addReg(AVR::R31R30, RegState::Kill); - } + BuildMI(MBB, MI, DL, TII.get(AVR::SPWRITE), AVR::SP) + .addReg(AVR::R31R30, RegState::Kill); } return MBB.erase(MI); @@ -415,6 +378,7 @@ SavedRegs.set(AVR::R28); } } + /// The frame analyzer pass. /// /// Scans the function for allocas and used arguments @@ -425,7 +389,7 @@ bool runOnMachineFunction(MachineFunction &MF) override { const MachineFrameInfo &MFI = MF.getFrameInfo(); - AVRMachineFunctionInfo *FuncInfo = MF.getInfo(); + AVRMachineFunctionInfo *AFI = MF.getInfo(); // If there are no fixed frame indexes during this stage it means there // are allocas present in the function. @@ -436,7 +400,7 @@ for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) { // Variable sized objects have size 0. if (MFI.getObjectSize(i)) { - FuncInfo->setHasAllocas(true); + AFI->setHasAllocas(true); break; } } @@ -465,7 +429,7 @@ } if (MFI.isFixedObjectIndex(MO.getIndex())) { - FuncInfo->setHasStackArgs(true); + AFI->setHasStackArgs(true); return false; } } @@ -480,7 +444,6 @@ char AVRFrameAnalyzer::ID = 0; -/// Creates instance of the frame analyzer pass. FunctionPass *createAVRFrameAnalyzerPass() { return new AVRFrameAnalyzer(); } /// Create the Dynalloca Stack Pointer Save/Restore pass. @@ -531,9 +494,6 @@ char AVRDynAllocaSR::ID = 0; -/// createAVRDynAllocaSRPass - returns an instance of the dynalloca stack -/// pointer save/restore pass. FunctionPass *createAVRDynAllocaSRPass() { return new AVRDynAllocaSR(); } } // end of namespace llvm - diff --git a/llvm/lib/Target/AVR/AVRRegisterInfo.cpp b/llvm/lib/Target/AVR/AVRRegisterInfo.cpp --- a/llvm/lib/Target/AVR/AVRRegisterInfo.cpp +++ b/llvm/lib/Target/AVR/AVRRegisterInfo.cpp @@ -66,7 +66,7 @@ Reserved.set(AVR::SPH); Reserved.set(AVR::SP); - // We tenatively reserve the frame pointer register r29:r28 because the + // We tentatively reserve the frame pointer register r29:r28 because the // function may require one, but we cannot tell until register allocation // is complete, which can be too late. // 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 @@ -79,7 +79,7 @@ /// of an ELF object file. unsigned getELFArch() const { assert(ELFArch != 0 && - "every device must have an associate ELF architecture"); + "every device must have an associated ELF architecture"); return ELFArch; } diff --git a/llvm/test/CodeGen/AVR/pseudo/STDWSPQRr.ll b/llvm/test/CodeGen/AVR/pseudo/STDWSPQRr.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AVR/pseudo/STDWSPQRr.ll @@ -0,0 +1,14 @@ +; RUN: llc < %s -march=avr | FileCheck %s + +declare { } @foo(i128, i128) addrspace(1) + +define i128 @bar(i128 %a, i128 %b) addrspace(1) { +; CHECK-LABEL: LBB0_6: +; CHECK-NEXT: std Y+13, r18 +; CHECK-NEXT: std Y+14, r19 + %b_neg = icmp slt i128 %b, 0 + %divisor = select i1 %b_neg, i128 0, i128 %b + %result = tail call fastcc addrspace(1) { } @foo(i128 undef, i128 %divisor) + + ret i128 0 +} diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -356,6 +356,7 @@ def get_triple_from_march(march): triples = { 'amdgcn': 'amdgcn', + 'avr': 'avr', 'r600': 'r600', 'mips': 'mips', 'sparc': 'sparc',