diff --git a/clang/docs/tools/clang-formatted-files.txt b/clang/docs/tools/clang-formatted-files.txt --- a/clang/docs/tools/clang-formatted-files.txt +++ b/clang/docs/tools/clang-formatted-files.txt @@ -5990,7 +5990,6 @@ llvm/lib/Target/AVR/AVRMCInstLower.h llvm/lib/Target/AVR/AVRRegisterInfo.cpp llvm/lib/Target/AVR/AVRRegisterInfo.h -llvm/lib/Target/AVR/AVRRelaxMemOperations.cpp llvm/lib/Target/AVR/AVRSelectionDAGInfo.h llvm/lib/Target/AVR/AVRShiftExpand.cpp llvm/lib/Target/AVR/AVRSubtarget.cpp diff --git a/llvm/lib/Target/AVR/AVR.h b/llvm/lib/Target/AVR/AVR.h --- a/llvm/lib/Target/AVR/AVR.h +++ b/llvm/lib/Target/AVR/AVR.h @@ -27,12 +27,10 @@ CodeGenOpt::Level OptLevel); FunctionPass *createAVRExpandPseudoPass(); FunctionPass *createAVRFrameAnalyzerPass(); -FunctionPass *createAVRRelaxMemPass(); FunctionPass *createAVRBranchSelectionPass(); void initializeAVRShiftExpandPass(PassRegistry &); void initializeAVRExpandPseudoPass(PassRegistry &); -void initializeAVRRelaxMemPass(PassRegistry &); /// Contains the AVR backend. namespace AVR { 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 @@ -1230,37 +1230,93 @@ template <> bool AVRExpandPseudo::expand(Block &MBB, BlockIt MBBI) { MachineInstr &MI = *MBBI; - Register SrcLoReg, SrcHiReg; - Register DstReg = MI.getOperand(0).getReg(); - Register SrcReg = MI.getOperand(2).getReg(); - unsigned Imm = MI.getOperand(1).getImm(); + + MachineOperand &Dst = MI.getOperand(0); + Register DstReg = Dst.getReg(); bool DstIsKill = MI.getOperand(0).isKill(); + + int64_t Imm = MI.getOperand(1).getImm(); + + MachineOperand &Src = MI.getOperand(2); + Register SrcReg = Src.getReg(); bool SrcIsKill = MI.getOperand(2).isKill(); - unsigned OpLo = AVR::STDPtrQRr; - unsigned OpHi = AVR::STDPtrQRr; - 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 && "Offset is out of range"); + // STD's maximum displacement is 63, so larger stores have to be split into a + // few operations + if (Imm >= 63) { + if (!DstIsKill) { + buildMI(MBB, MBBI, AVR::PUSHWRr).addReg(DstReg); + } - auto MIBLO = buildMI(MBB, MBBI, OpLo) - .addReg(DstReg) - .addImm(Imm) - .addReg(SrcLoReg, getKillRegState(SrcIsKill)); + buildMI(MBB, MBBI, AVR::SBCIWRdK) + .addReg(DstReg, RegState::Define) + .addReg(DstReg) + .addImm(-Imm); - auto MIBHI = buildMI(MBB, MBBI, OpHi) - .addReg(DstReg, getKillRegState(DstIsKill)) - .addImm(Imm + 1) - .addReg(SrcHiReg, getKillRegState(SrcIsKill)); + buildMI(MBB, MBBI, AVR::STWPtrRr) + .addReg(Dst.getReg()) + .addReg(Src.getReg(), getKillRegState(SrcIsKill)); - MIBLO.setMemRefs(MI.memoperands()); - MIBHI.setMemRefs(MI.memoperands()); + if (!DstIsKill) { + buildMI(MBB, MBBI, AVR::POPWRd).addDef(Dst.getReg()); + } + } else { + Register SrcLoReg, SrcHiReg; + TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg); + + unsigned OpLo = AVR::STDPtrQRr; + unsigned OpHi = AVR::STDPtrQRr; + + 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()); + } MI.eraseFromParent(); return true; } +template <> +bool AVRExpandPseudo::expand(Block &MBB, BlockIt MBBI) { + MachineInstr &MI = *MBBI; + const MachineFunction &MF = *MBB.getParent(); + const AVRSubtarget &STI = MF.getSubtarget(); + + assert(MI.getOperand(0).getReg() == AVR::SP && "Unexpected register"); + + 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; + const MachineFunction &MF = *MBB.getParent(); + const AVRSubtarget &STI = MF.getSubtarget(); + + assert(MI.getOperand(0).getReg() == AVR::SP && "Unexpected register"); + + MI.setDesc(TII->get(AVR::STDWPtrQRr)); + 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; @@ -2346,6 +2402,8 @@ EXPAND(AVR::STWPtrPiRr); EXPAND(AVR::STWPtrPdRr); EXPAND(AVR::STDWPtrQRr); + EXPAND(AVR::STDSPQRr); + EXPAND(AVR::STDWSPQRr); EXPAND(AVR::INWRdA); EXPAND(AVR::OUTWARr); EXPAND(AVR::PUSHWRr); 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 @@ -295,47 +295,13 @@ 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 (MachineInstr &MI : - llvm::make_early_inc_range(llvm::make_range(MI, MBB.end()))) { - if (MI.isCall()) - break; - - unsigned Opcode = MI.getOpcode(); - - // Only care of pseudo store instructions where SP is the base pointer. - if (Opcode != AVR::STDSPQRr && Opcode != AVR::STDWSPQRr) - 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); - } -} - 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); } @@ -343,57 +309,53 @@ unsigned int Opcode = MI->getOpcode(); int Amount = TII.getFrameSize(*MI); - // 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 (Amount == 0) { + return MBB.erase(MI); + } + + 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); + } 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); @@ -410,6 +372,7 @@ SavedRegs.set(AVR::R28); } } + /// The frame analyzer pass. /// /// Scans the function for allocas and used arguments @@ -420,7 +383,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. @@ -431,7 +394,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; } } @@ -460,7 +423,7 @@ } if (MFI.isFixedObjectIndex(MO.getIndex())) { - FuncInfo->setHasStackArgs(true); + AFI->setHasStackArgs(true); return false; } } @@ -475,7 +438,6 @@ char AVRFrameAnalyzer::ID = 0; -/// Creates instance of the frame analyzer pass. FunctionPass *createAVRFrameAnalyzerPass() { return new AVRFrameAnalyzer(); } } // 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 @@ -61,7 +61,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/AVRRelaxMemOperations.cpp b/llvm/lib/Target/AVR/AVRRelaxMemOperations.cpp deleted file mode 100644 --- a/llvm/lib/Target/AVR/AVRRelaxMemOperations.cpp +++ /dev/null @@ -1,144 +0,0 @@ -//===-- AVRRelaxMemOperations.cpp - Relax out of range loads/stores -------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains a pass which relaxes out of range memory operations into -// equivalent operations which handle bigger addresses. -// -//===----------------------------------------------------------------------===// - -#include "AVR.h" -#include "AVRInstrInfo.h" -#include "AVRTargetMachine.h" -#include "MCTargetDesc/AVRMCTargetDesc.h" - -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" - -using namespace llvm; - -#define AVR_RELAX_MEM_OPS_NAME "AVR memory operation relaxation pass" - -namespace { - -class AVRRelaxMem : public MachineFunctionPass { -public: - static char ID; - - AVRRelaxMem() : MachineFunctionPass(ID) { - initializeAVRRelaxMemPass(*PassRegistry::getPassRegistry()); - } - - bool runOnMachineFunction(MachineFunction &MF) override; - - StringRef getPassName() const override { return AVR_RELAX_MEM_OPS_NAME; } - -private: - typedef MachineBasicBlock Block; - typedef Block::iterator BlockIt; - - const TargetInstrInfo *TII; - - template bool relax(Block &MBB, BlockIt MBBI); - - bool runOnBasicBlock(Block &MBB); - bool runOnInstruction(Block &MBB, BlockIt MBBI); - - MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned Opcode) { - return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode)); - } -}; - -char AVRRelaxMem::ID = 0; - -bool AVRRelaxMem::runOnMachineFunction(MachineFunction &MF) { - bool Modified = false; - - const AVRSubtarget &STI = MF.getSubtarget(); - TII = STI.getInstrInfo(); - - for (Block &MBB : MF) { - bool BlockModified = runOnBasicBlock(MBB); - Modified |= BlockModified; - } - - return Modified; -} - -bool AVRRelaxMem::runOnBasicBlock(Block &MBB) { - bool Modified = false; - - BlockIt MBBI = MBB.begin(), E = MBB.end(); - while (MBBI != E) { - BlockIt NMBBI = std::next(MBBI); - Modified |= runOnInstruction(MBB, MBBI); - MBBI = NMBBI; - } - - return Modified; -} - -template <> bool AVRRelaxMem::relax(Block &MBB, BlockIt MBBI) { - MachineInstr &MI = *MBBI; - - MachineOperand &Ptr = MI.getOperand(0); - MachineOperand &Src = MI.getOperand(2); - int64_t Imm = MI.getOperand(1).getImm(); - - // We can definitely optimise this better. - if (Imm > 63) { - // Push the previous state of the pointer register. - // This instruction must preserve the value. - buildMI(MBB, MBBI, AVR::PUSHWRr).addReg(Ptr.getReg()); - - // Add the immediate to the pointer register. - buildMI(MBB, MBBI, AVR::SBCIWRdK) - .addReg(Ptr.getReg(), RegState::Define) - .addReg(Ptr.getReg()) - .addImm(-Imm); - - // Store the value in the source register to the address - // pointed to by the pointer register. - buildMI(MBB, MBBI, AVR::STWPtrRr) - .addReg(Ptr.getReg()) - .addReg(Src.getReg(), getKillRegState(Src.isKill())); - - // Pop the original state of the pointer register. - buildMI(MBB, MBBI, AVR::POPWRd) - .addDef(Ptr.getReg(), getKillRegState(Ptr.isKill())); - - MI.removeFromParent(); - } - - return false; -} - -bool AVRRelaxMem::runOnInstruction(Block &MBB, BlockIt MBBI) { - MachineInstr &MI = *MBBI; - int Opcode = MBBI->getOpcode(); - -#define RELAX(Op) \ - case Op: \ - return relax(MBB, MI) - - switch (Opcode) { RELAX(AVR::STDWPtrQRr); } -#undef RELAX - return false; -} - -} // end of anonymous namespace - -INITIALIZE_PASS(AVRRelaxMem, "avr-relax-mem", AVR_RELAX_MEM_OPS_NAME, false, - false) - -namespace llvm { - -FunctionPass *createAVRRelaxMemPass() { return new AVRRelaxMem(); } - -} // end of namespace llvm 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 @@ -87,7 +87,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/lib/Target/AVR/AVRTargetMachine.cpp b/llvm/lib/Target/AVR/AVRTargetMachine.cpp --- a/llvm/lib/Target/AVR/AVRTargetMachine.cpp +++ b/llvm/lib/Target/AVR/AVRTargetMachine.cpp @@ -28,7 +28,6 @@ static const char *AVRDataLayout = "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8"; -/// Processes a CPU name. static StringRef getCPU(StringRef CPU) { if (CPU.empty() || CPU == "generic") { return "avr2"; @@ -87,12 +86,10 @@ } extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRTarget() { - // Register the target. RegisterTargetMachine X(getTheAVRTarget()); auto &PR = *PassRegistry::getPassRegistry(); initializeAVRExpandPseudoPass(PR); - initializeAVRRelaxMemPass(PR); initializeAVRShiftExpandPass(PR); } @@ -117,10 +114,7 @@ return false; } -void AVRPassConfig::addPreSched2() { - addPass(createAVRRelaxMemPass()); - addPass(createAVRExpandPseudoPass()); -} +void AVRPassConfig::addPreSched2() { addPass(createAVRExpandPseudoPass()); } void AVRPassConfig::addPreEmitPass() { // Must run branch selection immediately preceding the asm printer. diff --git a/llvm/lib/Target/AVR/CMakeLists.txt b/llvm/lib/Target/AVR/CMakeLists.txt --- a/llvm/lib/Target/AVR/CMakeLists.txt +++ b/llvm/lib/Target/AVR/CMakeLists.txt @@ -22,7 +22,6 @@ AVRISelDAGToDAG.cpp AVRISelLowering.cpp AVRMCInstLower.cpp - AVRRelaxMemOperations.cpp AVRRegisterInfo.cpp AVRShiftExpand.cpp AVRSubtarget.cpp diff --git a/llvm/test/CodeGen/AVR/hardware-mul.ll b/llvm/test/CodeGen/AVR/mul-hardware.ll rename from llvm/test/CodeGen/AVR/hardware-mul.ll rename to llvm/test/CodeGen/AVR/mul-hardware.ll diff --git a/llvm/test/CodeGen/AVR/software-mul.ll b/llvm/test/CodeGen/AVR/mul-software.ll rename from llvm/test/CodeGen/AVR/software-mul.ll rename to llvm/test/CodeGen/AVR/mul-software.ll diff --git a/llvm/test/CodeGen/AVR/past-bugs/D114611.ll b/llvm/test/CodeGen/AVR/past-bugs/D114611.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AVR/past-bugs/D114611.ll @@ -0,0 +1,16 @@ +; RUN: llc < %s -march=avr | FileCheck %s + +declare { } @foo(i128, i128) addrspace(1) + +define i128 @bar(i128 %a, i128 %b) addrspace(1) { + call void asm "nop", "" () +; CHECK: nop +; CHECK-NEXT: ;NO_APP +; CHECK-NEXT: Y+15, r20 +; CHECK-NEXT: Y+16, r21 + %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/test/CodeGen/AVR/PR31344.ll b/llvm/test/CodeGen/AVR/past-bugs/PR31344.ll rename from llvm/test/CodeGen/AVR/PR31344.ll rename to llvm/test/CodeGen/AVR/past-bugs/PR31344.ll diff --git a/llvm/test/CodeGen/AVR/PR31345.ll b/llvm/test/CodeGen/AVR/past-bugs/PR31345.ll rename from llvm/test/CodeGen/AVR/PR31345.ll rename to llvm/test/CodeGen/AVR/past-bugs/PR31345.ll diff --git a/llvm/test/CodeGen/AVR/PR37143.ll b/llvm/test/CodeGen/AVR/past-bugs/PR37143.ll rename from llvm/test/CodeGen/AVR/PR37143.ll rename to llvm/test/CodeGen/AVR/past-bugs/PR37143.ll diff --git a/llvm/test/CodeGen/AVR/avr-rust-issue-123.ll b/llvm/test/CodeGen/AVR/past-bugs/avr-rust-issue-123.ll rename from llvm/test/CodeGen/AVR/avr-rust-issue-123.ll rename to llvm/test/CodeGen/AVR/past-bugs/avr-rust-issue-123.ll diff --git a/llvm/test/CodeGen/AVR/frmidx-iterator-bug.ll b/llvm/test/CodeGen/AVR/past-bugs/frmidx-iterator-bug.ll rename from llvm/test/CodeGen/AVR/frmidx-iterator-bug.ll rename to llvm/test/CodeGen/AVR/past-bugs/frmidx-iterator-bug.ll diff --git a/llvm/test/CodeGen/AVR/rust-avr-bug-112.ll b/llvm/test/CodeGen/AVR/past-bugs/rust-avr-bug-112.ll rename from llvm/test/CodeGen/AVR/rust-avr-bug-112.ll rename to llvm/test/CodeGen/AVR/past-bugs/rust-avr-bug-112.ll diff --git a/llvm/test/CodeGen/AVR/rust-avr-bug-37.ll b/llvm/test/CodeGen/AVR/past-bugs/rust-avr-bug-37.ll rename from llvm/test/CodeGen/AVR/rust-avr-bug-37.ll rename to llvm/test/CodeGen/AVR/past-bugs/rust-avr-bug-37.ll diff --git a/llvm/test/CodeGen/AVR/rust-avr-bug-95.ll b/llvm/test/CodeGen/AVR/past-bugs/rust-avr-bug-95.ll rename from llvm/test/CodeGen/AVR/rust-avr-bug-95.ll rename to llvm/test/CodeGen/AVR/past-bugs/rust-avr-bug-95.ll diff --git a/llvm/test/CodeGen/AVR/rust-avr-bug-99.ll b/llvm/test/CodeGen/AVR/past-bugs/rust-avr-bug-99.ll rename from llvm/test/CodeGen/AVR/rust-avr-bug-99.ll rename to llvm/test/CodeGen/AVR/past-bugs/rust-avr-bug-99.ll diff --git a/llvm/test/CodeGen/AVR/pseudo/STDSPQRr.mir b/llvm/test/CodeGen/AVR/pseudo/STDSPQRr.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AVR/pseudo/STDSPQRr.mir @@ -0,0 +1,19 @@ +# RUN: llc -O0 -run-pass=avr-expand-pseudo %s -o - | FileCheck %s + +--- | + target triple = "avr--" + define void @test() { + entry: + ret void + } +... + +--- +name: test +body: | + bb.0.entry: + + ; CHECK: STDPtrQRr $r31r30, 10, $r1, implicit-def $sp + + STDSPQRr $sp, 10, $r1, implicit-def $sp +... 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 @@ -15,8 +15,52 @@ ; CHECK-LABEL: test - ; CHECK: STDPtrQRr $r29r28, 10, $r0 - ; CHECK-NEXT: STDPtrQRr $r29r28, 11, $r1 + ; Small displacement (<63): + ; CHECK: STDPtrQRr $r29r28, 3, $r0 + ; CHECK-NEXT: STDPtrQRr $r29r28, 4, $r1 + STDWPtrQRr $r29r28, 3, $r1r0 - STDWPtrQRr $r29r28, 10, $r1r0 + ; Small displacement where the destination register is killed: + ; CHECK: STDPtrQRr $r29r28, 3, $r0 + ; CHECK-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 + STDWPtrQRr $r29r28, 3, killed $r1r0 + + ; Small displacement, near the limit: + ; CHECK: STDPtrQRr $r29r28, 62, $r0 + ; CHECK-NEXT: STDPtrQRr $r29r28, 63, $r1 + STDWPtrQRr $r29r28, 62, $r1r0 + + ; Large displacement: + ; CHECK: PUSHRr $r28, implicit-def $sp, implicit $sp + ; CHECK-NEXT: PUSHRr $r29, implicit-def $sp, implicit $sp + ; CHECK-NEXT: $r28 = SBCIRdK $r28, 193, implicit-def $sreg, implicit killed $sreg + ; CHECK-NEXT: $r29 = SBCIRdK $r29, 255, implicit-def $sreg, implicit killed $sreg + ; CHECK-NEXT: STPtrRr $r29r28, $r0 + ; CHECK-NEXT: STDPtrQRr $r29r28, 1, $r1 + ; CHECK-NEXT: $r29 = POPRd implicit-def $sp, implicit $sp + ; CHECK-NEXT: $r28 = POPRd implicit-def $sp, implicit $sp + STDWPtrQRr $r29r28, 63, $r1r0 + + ; Large displacement where the destination register is killed: + ; CHECK: $r28 = SBCIRdK $r28, 193, implicit-def $sreg, implicit killed $sreg + ; CHECK-NEXT: $r29 = SBCIRdK $r29, 255, implicit-def $sreg, implicit killed $sreg + ; CHECK-NEXT: STPtrRr $r29r28, $r0 + ; CHECK-NEXT: STDPtrQRr $r29r28, 1, $r1 + STDWPtrQRr killed $r29r28, 63, $r1r0 + + ; Large displacement where the source register is killed: + ; CHECK: PUSHRr $r28, implicit-def $sp, implicit $sp + ; CHECK-NEXT: PUSHRr $r29, implicit-def $sp, implicit $sp + ; CHECK-NEXT: $r28 = SBCIRdK $r28, 193, implicit-def $sreg, implicit killed $sreg + ; CHECK-NEXT: $r29 = SBCIRdK $r29, 255, implicit-def $sreg, implicit killed $sreg + ; CHECK-NEXT: STPtrRr $r29r28, killed $r0 + ; CHECK-NEXT: STDPtrQRr $r29r28, 1, killed $r1 + ; CHECK-NEXT: $r29 = POPRd implicit-def $sp, implicit $sp + ; CHECK-NEXT: $r28 = POPRd implicit-def $sp, implicit $sp + STDWPtrQRr $r29r28, 63, killed $r1r0 ... diff --git a/llvm/test/CodeGen/AVR/pseudo/STDWSPQRr.mir b/llvm/test/CodeGen/AVR/pseudo/STDWSPQRr.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AVR/pseudo/STDWSPQRr.mir @@ -0,0 +1,20 @@ +# RUN: llc -O0 -run-pass=avr-expand-pseudo %s -o - | FileCheck %s + +--- | + target triple = "avr--" + define void @test() { + entry: + ret void + } +... + +--- +name: test +body: | + bb.0.entry: + + ; CHECK: STDPtrQRr $r31r30, 10, $r9 + ; CHECK-NEXT: STDPtrQRr $r31r30, 11, $r10 + + STDWSPQRr $sp, 10, $r10r9, implicit-def $sp +... diff --git a/llvm/test/CodeGen/AVR/relax-mem/STDWPtrQRr.mir b/llvm/test/CodeGen/AVR/relax-mem/STDWPtrQRr.mir deleted file mode 100644 --- a/llvm/test/CodeGen/AVR/relax-mem/STDWPtrQRr.mir +++ /dev/null @@ -1,31 +0,0 @@ -# RUN: llc -O0 -run-pass=avr-relax-mem %s -o - | FileCheck %s - ---- | - target triple = "avr--" - define void @test() { - entry: - ret void - } -... - ---- -name: test -body: | - bb.0.entry: - - ; CHECK-LABEL: test - - ; We shouldn't expand things which already have 6-bit imms. - ; CHECK: STDWPtrQRr $r29r28, 63, $r1r0 - STDWPtrQRr $r29r28, 63, $r1r0 - - ; We shouldn't expand things which already have 6-bit imms. - ; CHECK-NEXT: STDWPtrQRr $r29r28, 0, $r1r0 - STDWPtrQRr $r29r28, 0, $r1r0 - - ; CHECK-NEXT: PUSHWRr $r29r28, implicit-def $sp, implicit $sp - ; CHECK-NEXT: $r29r28 = SBCIWRdK $r29r28, -64, implicit-def $sreg, implicit $sreg - ; CHECK-NEXT: STWPtrRr $r29r28, $r1r0 - ; CHECK-NEXT: $r29r28 = POPWRd implicit-def $sp, implicit $sp - STDWPtrQRr $r29r28, 64, $r1r0 -... 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 @@ -391,6 +391,7 @@ def get_triple_from_march(march): triples = { 'amdgcn': 'amdgcn', + 'avr': 'avr', 'r600': 'r600', 'mips': 'mips', 'sparc': 'sparc', diff --git a/llvm/utils/gn/secondary/llvm/lib/Target/AVR/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Target/AVR/BUILD.gn --- a/llvm/utils/gn/secondary/llvm/lib/Target/AVR/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Target/AVR/BUILD.gn @@ -37,7 +37,6 @@ "AVRInstrInfo.cpp", "AVRMCInstLower.cpp", "AVRRegisterInfo.cpp", - "AVRRelaxMemOperations.cpp", "AVRShiftExpand.cpp", "AVRSubtarget.cpp", "AVRTargetMachine.cpp",