<div dir="ltr">This should be fixed as of r287180, thanks for letting me know!</div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Nov 17, 2016 at 1:16 PM, Dylan McKay <span dir="ltr"><<a href="mailto:dylanmckay34@gmail.com" target="_blank">dylanmckay34@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">You're right, I'll fix that up now.</div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Nov 17, 2016 at 1:13 PM, Yung, Douglas <span dir="ltr"><<a href="mailto:douglas.yung@sony.com" target="_blank">douglas.yung@sony.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Dylan,<br>
<br>
I believe your change caused the Windows hosted PS4 bot to start failing during testing. Can you take a look?<br>
<br>
<a href="http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/1261" rel="noreferrer" target="_blank">http://lab.llvm.org:8011/build<wbr>ers/llvm-clang-lld-x86_64-<wbr>scei-ps4-windows10pro-fast/bui<wbr>lds/1261</a><br>
<br>
Douglas Yung<br>
<br>
> -----Original Message-----<br>
> From: llvm-commits [mailto:<a href="mailto:llvm-commits-bounces@lists.llvm.org" target="_blank">llvm-commits-bounces@l<wbr>ists.llvm.org</a>] On<br>
> Behalf Of Dylan McKay via llvm-commits<br>
> Sent: Wednesday, November 16, 2016 13:58<br>
> To: <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
> Subject: [llvm] r287162 - [AVR] Add the pseudo instruction expansion<br>
> pass<br>
><br>
> Author: dylanmckay<br>
> Date: Wed Nov 16 15:58:04 2016<br>
> New Revision: 287162<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=287162&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=287162&view=rev</a><br>
> Log:<br>
> [AVR] Add the pseudo instruction expansion pass<br>
><br>
> Summary:<br>
> A lot of the pseudo instructions are required because LLVM assumes that<br>
> all integers of the same size as the pointer size are legal. This means<br>
> that it will not currently expand 16-bit instructions to their 8-bit<br>
> variants because it thinks 16-bit types are legal for the operations.<br>
><br>
> This also adds all of the CodeGen tests that required the pass to run.<br>
><br>
> Reviewers: arsenm, kparzysz<br>
><br>
> Subscribers: wdng, mgorny, modocache, llvm-commits<br>
><br>
> Differential Revision: <a href="https://reviews.llvm.org/D26577" rel="noreferrer" target="_blank">https://reviews.llvm.org/D2657<wbr>7</a><br>
><br>
> Added:<br>
>     llvm/trunk/lib/Target/AVR/AVR<wbr>ExpandPseudoInsts.cpp<br>
>     llvm/trunk/test/CodeGen/AVR/a<wbr>dd.ll<br>
>     llvm/trunk/test/CodeGen/AVR/a<wbr>lloca.ll<br>
>     llvm/trunk/test/CodeGen/AVR/a<wbr>nd.ll<br>
>     llvm/trunk/test/CodeGen/AVR/a<wbr>tomics/fence.ll<br>
>     llvm/trunk/test/CodeGen/AVR/a<wbr>tomics/load16.ll<br>
>     llvm/trunk/test/CodeGen/AVR/a<wbr>tomics/load8.ll<br>
>     llvm/trunk/test/CodeGen/AVR/a<wbr>tomics/store.ll<br>
>     llvm/trunk/test/CodeGen/AVR/a<wbr>tomics/store16.ll<br>
>     llvm/trunk/test/CodeGen/AVR/b<wbr>rind.ll<br>
>     llvm/trunk/test/CodeGen/AVR/c<wbr>all.ll<br>
>     llvm/trunk/test/CodeGen/AVR/c<wbr>mp.ll<br>
>     llvm/trunk/test/CodeGen/AVR/c<wbr>om.ll<br>
>     llvm/trunk/test/CodeGen/AVR/d<wbr>irectmem.ll<br>
>     llvm/trunk/test/CodeGen/AVR/d<wbr>ynalloca.ll<br>
>     llvm/trunk/test/CodeGen/AVR/e<wbr>or.ll<br>
>     llvm/trunk/test/CodeGen/AVR/e<wbr>rror-srcreg-destreg-same.ll<br>
>     llvm/trunk/test/CodeGen/AVR/e<wbr>xpand-integer-failure.ll<br>
>     llvm/trunk/test/CodeGen/AVR/f<wbr>rame.ll<br>
>     llvm/trunk/test/CodeGen/AVR/i<wbr>nline-asm.ll<br>
>     llvm/trunk/test/CodeGen/AVR/i<wbr>nterrupts.ll<br>
>     llvm/trunk/test/CodeGen/AVR/i<wbr>o.ll<br>
>     llvm/trunk/test/CodeGen/AVR/l<wbr>oad.ll<br>
>     llvm/trunk/test/CodeGen/AVR/o<wbr>r.ll<br>
>     llvm/trunk/test/CodeGen/AVR/p<wbr>rogmem.ll<br>
>     llvm/trunk/test/CodeGen/AVR/r<wbr>eturn.ll<br>
>     llvm/trunk/test/CodeGen/AVR/s<wbr>ext.ll<br>
>     llvm/trunk/test/CodeGen/AVR/s<wbr>tore.ll<br>
>     llvm/trunk/test/CodeGen/AVR/s<wbr>ub.ll<br>
>     llvm/trunk/test/CodeGen/AVR/v<wbr>arargs.ll<br>
>     llvm/trunk/test/CodeGen/AVR/x<wbr>or.ll<br>
>     llvm/trunk/test/CodeGen/AVR/z<wbr>ext.ll<br>
> Modified:<br>
>     llvm/trunk/lib/Target/AVR/AVR<wbr>TargetMachine.cpp<br>
>     llvm/trunk/lib/Target/AVR/CMa<wbr>keLists.txt<br>
>     llvm/trunk/test/CodeGen/AVR/h<wbr>igh-pressure-on-ptrregs.ll<br>
>     llvm/trunk/test/CodeGen/AVR/l<wbr>it.local.cfg<br>
><br>
> Added: llvm/trunk/lib/Target/AVR/AVRE<wbr>xpandPseudoInsts.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/lib/Target/<wbr>AVR/AVRExpandPseudoInsts.cpp?r<wbr>ev=287162&v<br>
> iew=auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/lib/Target/AVR/AVRE<wbr>xpandPseudoInsts.cpp (added)<br>
> +++ llvm/trunk/lib/Target/AVR/AVRE<wbr>xpandPseudoInsts.cpp Wed Nov 16<br>
> 15:58:04 2016<br>
> @@ -0,0 +1,1431 @@<br>
> +//===-- AVRExpandPseudoInsts.cpp - Expand pseudo instructions --------<br>
> -----===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open<br>
> Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===------------------------<wbr>------------------------------<wbr>-----------<br>
> -----===//<br>
> +//<br>
> +// This file contains a pass that expands pseudo instructions into<br>
> target<br>
> +// instructions. This pass should be run after register allocation but<br>
> before<br>
> +// the post-regalloc scheduling pass.<br>
> +//<br>
> +//===------------------------<wbr>------------------------------<wbr>-----------<br>
> -----===//<br>
> +<br>
> +#include "AVR.h"<br>
> +#include "AVRInstrInfo.h"<br>
> +#include "AVRTargetMachine.h"<br>
> +#include "MCTargetDesc/AVRMCTargetDesc.<wbr>h"<br>
> +<br>
> +#include "llvm/CodeGen/MachineFunctionP<wbr>ass.h"<br>
> +#include "llvm/CodeGen/MachineInstrBuil<wbr>der.h"<br>
> +#include "llvm/CodeGen/MachineRegisterI<wbr>nfo.h"<br>
> +#include "llvm/Target/TargetRegisterInf<wbr>o.h"<br>
> +<br>
> +using namespace llvm;<br>
> +<br>
> +namespace {<br>
> +<br>
> +/// Expands "placeholder" instructions marked as pseudo into<br>
> +/// actual AVR instructions.<br>
> +class AVRExpandPseudo : public MachineFunctionPass {<br>
> +public:<br>
> +  static char ID;<br>
> +<br>
> +  AVRExpandPseudo() : MachineFunctionPass(ID) {}<br>
> +<br>
> +  bool runOnMachineFunction(MachineFu<wbr>nction &MF) override;<br>
> +<br>
> +  StringRef getPassName() const override {<br>
> +    return "AVR pseudo instruction expansion pass";<br>
> +  }<br>
> +<br>
> +private:<br>
> +  typedef MachineBasicBlock Block;<br>
> +  typedef Block::iterator BlockIt;<br>
> +<br>
> +  const AVRRegisterInfo *TRI;<br>
> +  const TargetInstrInfo *TII;<br>
> +<br>
> +  /// The register to be used for temporary storage.<br>
> +  const unsigned SCRATCH_REGISTER = AVR::R0;<br>
> +  /// The IO address of the status register.<br>
> +  const unsigned SREG_ADDR = 0x3f;<br>
> +<br>
> +  bool expandMBB(Block &MBB);<br>
> +  bool expandMI(Block &MBB, BlockIt MBBI);<br>
> +  template <unsigned OP> bool expand(Block &MBB, BlockIt MBBI);<br>
> +<br>
> +  MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned<br>
> Opcode) {<br>
> +    return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode));<br>
> +  }<br>
> +<br>
> +  MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned<br>
> Opcode,<br>
> +                              unsigned DstReg) {<br>
> +    return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode),<br>
> DstReg);<br>
> +  }<br>
> +<br>
> +  MachineRegisterInfo &getRegInfo(Block &MBB) { return<br>
> MBB.getParent()->getRegInfo(); }<br>
> +<br>
> +  bool expandArith(unsigned OpLo, unsigned OpHi, Block &MBB, BlockIt<br>
> MBBI);<br>
> +  bool expandLogic(unsigned Op, Block &MBB, BlockIt MBBI);<br>
> +  bool expandLogicImm(unsigned Op, Block &MBB, BlockIt MBBI);<br>
> +<br>
> +  template<typename Func><br>
> +  bool expandAtomic(Block &MBB, BlockIt MBBI, Func f);<br>
> +<br>
> +  template<typename Func><br>
> +  bool expandAtomicBinaryOp(unsigned Opcode, Block &MBB, BlockIt MBBI,<br>
> Func f);<br>
> +<br>
> +  bool expandAtomicBinaryOp(unsigned Opcode, Block &MBB, BlockIt<br>
> MBBI);<br>
> +<br>
> +  bool expandAtomicArithmeticOp(unsig<wbr>ned MemOpcode,<br>
> +                                unsigned ArithOpcode,<br>
> +                                Block &MBB,<br>
> +                                BlockIt MBBI);<br>
> +};<br>
> +<br>
> +char AVRExpandPseudo::ID = 0;<br>
> +<br>
> +} // end of anonymous namespace<br>
> +<br>
> +bool AVRExpandPseudo::expandMBB(Mac<wbr>hineBasicBlock &MBB) {<br>
> +  bool Modified = false;<br>
> +<br>
> +  BlockIt MBBI = MBB.begin(), E = MBB.end();<br>
> +  while (MBBI != E) {<br>
> +    BlockIt NMBBI = std::next(MBBI);<br>
> +    Modified |= expandMI(MBB, MBBI);<br>
> +    MBBI = NMBBI;<br>
> +  }<br>
> +<br>
> +  return Modified;<br>
> +}<br>
> +<br>
> +bool AVRExpandPseudo::runOnMachineF<wbr>unction(MachineFunction &MF) {<br>
> +  bool Modified = false;<br>
> +<br>
> +  const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>(<wbr>);<br>
> +  TRI = STI.getRegisterInfo();<br>
> +  TII = STI.getInstrInfo();<br>
> +<br>
> +  for (Block &MBB : MF) {<br>
> +    bool ContinueExpanding = true;<br>
> +    unsigned ExpandCount = 0;<br>
> +<br>
> +    // Continue expanding the block until all pseudos are expanded.<br>
> +    do {<br>
> +      assert(ExpandCount < 10 && "pseudo expand limit reached");<br>
> +<br>
> +      bool BlockModified = expandMBB(MBB);<br>
> +      Modified |= BlockModified;<br>
> +      ExpandCount++;<br>
> +<br>
> +      ContinueExpanding = BlockModified;<br>
> +    } while (ContinueExpanding);<br>
> +  }<br>
> +<br>
> +  return Modified;<br>
> +}<br>
> +<br>
> +bool AVRExpandPseudo::<br>
> +expandArith(unsigned OpLo, unsigned OpHi, Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  unsigned SrcReg = MI.getOperand(2).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool DstIsKill = MI.getOperand(1).isKill();<br>
> +  bool SrcIsKill = MI.getOperand(2).isKill();<br>
> +  bool ImpIsDead = MI.getOperand(3).isDead();<br>
> +  TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstLoReg, getKillRegState(DstIsKill))<br>
> +    .addReg(SrcLoReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstHiReg, getKillRegState(DstIsKill))<br>
> +    .addReg(SrcHiReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  if (ImpIsDead)<br>
> +    MIBHI->getOperand(3).setIsDead<wbr>();<br>
> +<br>
> +  // SREG is always implicitly killed<br>
> +  MIBHI->getOperand(4).setIsKill<wbr>();<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +bool AVRExpandPseudo::<br>
> +expandLogic(unsigned Op, Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  unsigned SrcReg = MI.getOperand(2).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool DstIsKill = MI.getOperand(1).isKill();<br>
> +  bool SrcIsKill = MI.getOperand(2).isKill();<br>
> +  bool ImpIsDead = MI.getOperand(3).isDead();<br>
> +  TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, Op)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstLoReg, getKillRegState(DstIsKill))<br>
> +    .addReg(SrcLoReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  // SREG is always implicitly dead<br>
> +  MIBLO->getOperand(3).setIsDead<wbr>();<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, Op)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstHiReg, getKillRegState(DstIsKill))<br>
> +    .addReg(SrcHiReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  if (ImpIsDead)<br>
> +    MIBHI->getOperand(3).setIsDead<wbr>();<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +bool AVRExpandPseudo::<br>
> +expandLogicImm(unsigned Op, Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool SrcIsKill = MI.getOperand(1).isKill();<br>
> +  bool ImpIsDead = MI.getOperand(3).isDead();<br>
> +  unsigned Imm = MI.getOperand(2).getImm();<br>
> +  unsigned Lo8 = Imm & 0xff;<br>
> +  unsigned Hi8 = (Imm >> 8) & 0xff;<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, Op)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstLoReg, getKillRegState(SrcIsKill))<br>
> +    .addImm(Lo8);<br>
> +<br>
> +  // SREG is always implicitly dead<br>
> +  MIBLO->getOperand(3).setIsDead<wbr>();<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, Op)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstHiReg, getKillRegState(SrcIsKill))<br>
> +    .addImm(Hi8);<br>
> +<br>
> +  if (ImpIsDead)<br>
> +    MIBHI->getOperand(3).setIsDead<wbr>();<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>DDWRdRr>(Block &MBB, BlockIt MBBI)<br>
> {<br>
> +  return expandArith(AVR::ADDRdRr, AVR::ADCRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>DCWRdRr>(Block &MBB, BlockIt MBBI)<br>
> {<br>
> +  return expandArith(AVR::ADCRdRr, AVR::ADCRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::S<wbr>UBWRdRr>(Block &MBB, BlockIt MBBI)<br>
> {<br>
> +  return expandArith(AVR::SUBRdRr, AVR::SBCRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::S<wbr>UBIWRdK>(Block &MBB, BlockIt MBBI)<br>
> {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool SrcIsKill = MI.getOperand(1).isKill();<br>
> +  bool ImpIsDead = MI.getOperand(3).isDead();<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, AVR::SUBIRdK)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstLoReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, AVR::SBCIRdK)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstHiReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  switch (MI.getOperand(2).getType()) {<br>
> +  case MachineOperand::MO_GlobalAddre<wbr>ss: {<br>
> +    const GlobalValue *GV = MI.getOperand(2).getGlobal();<br>
> +    int64_t Offs = MI.getOperand(2).getOffset();<br>
> +    unsigned TF = MI.getOperand(2).getTargetFlag<wbr>s();<br>
> +    MIBLO.addGlobalAddress(GV, Offs, TF | AVRII::MO_NEG |<br>
> AVRII::MO_LO);<br>
> +    MIBHI.addGlobalAddress(GV, Offs, TF | AVRII::MO_NEG |<br>
> AVRII::MO_HI);<br>
> +    break;<br>
> +  }<br>
> +  case MachineOperand::MO_Immediate: {<br>
> +    unsigned Imm = MI.getOperand(2).getImm();<br>
> +    MIBLO.addImm(Imm & 0xff);<br>
> +    MIBHI.addImm((Imm >> 8) & 0xff);<br>
> +    break;<br>
> +  }<br>
> +  default:<br>
> +    llvm_unreachable("Unknown operand type!");<br>
> +  }<br>
> +<br>
> +  if (ImpIsDead)<br>
> +    MIBHI->getOperand(3).setIsDead<wbr>();<br>
> +<br>
> +  // SREG is always implicitly killed<br>
> +  MIBHI->getOperand(4).setIsKill<wbr>();<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::S<wbr>BCWRdRr>(Block &MBB, BlockIt MBBI)<br>
> {<br>
> +  return expandArith(AVR::SBCRdRr, AVR::SBCRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::S<wbr>BCIWRdK>(Block &MBB, BlockIt MBBI)<br>
> {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool SrcIsKill = MI.getOperand(1).isKill();<br>
> +  bool ImpIsDead = MI.getOperand(3).isDead();<br>
> +  unsigned Imm = MI.getOperand(2).getImm();<br>
> +  unsigned Lo8 = Imm & 0xff;<br>
> +  unsigned Hi8 = (Imm >> 8) & 0xff;<br>
> +  OpLo = AVR::SBCIRdK;<br>
> +  OpHi = AVR::SBCIRdK;<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstLoReg, getKillRegState(SrcIsKill))<br>
> +    .addImm(Lo8);<br>
> +<br>
> +  // SREG is always implicitly killed<br>
> +  MIBLO->getOperand(4).setIsKill<wbr>();<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstHiReg, getKillRegState(SrcIsKill))<br>
> +    .addImm(Hi8);<br>
> +<br>
> +  if (ImpIsDead)<br>
> +    MIBHI->getOperand(3).setIsDead<wbr>();<br>
> +<br>
> +  // SREG is always implicitly killed<br>
> +  MIBHI->getOperand(4).setIsKill<wbr>();<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>NDWRdRr>(Block &MBB, BlockIt MBBI)<br>
> {<br>
> +  return expandLogic(AVR::ANDRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>NDIWRdK>(Block &MBB, BlockIt MBBI)<br>
> {<br>
> +  return expandLogicImm(AVR::ANDIRdK, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::O<wbr>RWRdRr>(Block &MBB, BlockIt MBBI) {<br>
> +  return expandLogic(AVR::ORRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::O<wbr>RIWRdK>(Block &MBB, BlockIt MBBI) {<br>
> +  return expandLogicImm(AVR::ORIRdK, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::E<wbr>ORWRdRr>(Block &MBB, BlockIt MBBI)<br>
> {<br>
> +  return expandLogic(AVR::EORRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::C<wbr>OMWRd>(Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool DstIsKill = MI.getOperand(1).isKill();<br>
> +  bool ImpIsDead = MI.getOperand(2).isDead();<br>
> +  OpLo = AVR::COMRd;<br>
> +  OpHi = AVR::COMRd;<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstLoReg, getKillRegState(DstIsKill));<br>
> +<br>
> +  // SREG is always implicitly dead<br>
> +  MIBLO->getOperand(2).setIsDead<wbr>();<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstHiReg, getKillRegState(DstIsKill));<br>
> +<br>
> +  if (ImpIsDead)<br>
> +    MIBHI->getOperand(2).setIsDead<wbr>();<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::C<wbr>PWRdRr>(Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  unsigned SrcReg = MI.getOperand(1).getReg();<br>
> +  bool DstIsKill = MI.getOperand(0).isKill();<br>
> +  bool SrcIsKill = MI.getOperand(1).isKill();<br>
> +  bool ImpIsDead = MI.getOperand(2).isDead();<br>
> +  OpLo = AVR::CPRdRr;<br>
> +  OpHi = AVR::CPCRdRr;<br>
> +  TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  // Low part<br>
> +  buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, getKillRegState(DstIsKill))<br>
> +    .addReg(SrcLoReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, getKillRegState(DstIsKill))<br>
> +    .addReg(SrcHiReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  if (ImpIsDead)<br>
> +    MIBHI->getOperand(2).setIsDead<wbr>();<br>
> +<br>
> +  // SREG is always implicitly killed<br>
> +  MIBHI->getOperand(3).setIsKill<wbr>();<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::C<wbr>PCWRdRr>(Block &MBB, BlockIt MBBI)<br>
> {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  unsigned SrcReg = MI.getOperand(1).getReg();<br>
> +  bool DstIsKill = MI.getOperand(0).isKill();<br>
> +  bool SrcIsKill = MI.getOperand(1).isKill();<br>
> +  bool ImpIsDead = MI.getOperand(2).isDead();<br>
> +  OpLo = AVR::CPCRdRr;<br>
> +  OpHi = AVR::CPCRdRr;<br>
> +  TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, getKillRegState(DstIsKill))<br>
> +    .addReg(SrcLoReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  // SREG is always implicitly killed<br>
> +  MIBLO->getOperand(3).setIsKill<wbr>();<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, getKillRegState(DstIsKill))<br>
> +    .addReg(SrcHiReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  if (ImpIsDead)<br>
> +    MIBHI->getOperand(2).setIsDead<wbr>();<br>
> +<br>
> +  // SREG is always implicitly killed<br>
> +  MIBHI->getOperand(3).setIsKill<wbr>();<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::L<wbr>DIWRdK>(Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  OpLo = AVR::LDIRdK;<br>
> +  OpHi = AVR::LDIRdK;<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead));<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead));<br>
> +<br>
> +  switch (MI.getOperand(1).getType()) {<br>
> +  case MachineOperand::MO_GlobalAddre<wbr>ss: {<br>
> +    const GlobalValue *GV = MI.getOperand(1).getGlobal();<br>
> +    int64_t Offs = MI.getOperand(1).getOffset();<br>
> +    unsigned TF = MI.getOperand(1).getTargetFlag<wbr>s();<br>
> +<br>
> +    MIBLO.addGlobalAddress(GV, Offs, TF | AVRII::MO_LO);<br>
> +    MIBHI.addGlobalAddress(GV, Offs, TF | AVRII::MO_HI);<br>
> +    break;<br>
> +  }<br>
> +  case MachineOperand::MO_BlockAddres<wbr>s: {<br>
> +    const BlockAddress *BA = MI.getOperand(1).getBlockAddre<wbr>ss();<br>
> +    unsigned TF = MI.getOperand(1).getTargetFlag<wbr>s();<br>
> +<br>
> +    MIBLO.addOperand(MachineOperan<wbr>d::CreateBA(BA, TF | AVRII::MO_LO));<br>
> +    MIBHI.addOperand(MachineOperan<wbr>d::CreateBA(BA, TF | AVRII::MO_HI));<br>
> +    break;<br>
> +  }<br>
> +  case MachineOperand::MO_Immediate: {<br>
> +    unsigned Imm = MI.getOperand(1).getImm();<br>
> +<br>
> +    MIBLO.addImm(Imm & 0xff);<br>
> +    MIBHI.addImm((Imm >> 8) & 0xff);<br>
> +    break;<br>
> +  }<br>
> +  default:<br>
> +    llvm_unreachable("Unknown operand type!");<br>
> +  }<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::L<wbr>DSWRdK>(Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  OpLo = AVR::LDSRdK;<br>
> +  OpHi = AVR::LDSRdK;<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead));<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead));<br>
> +<br>
> +  switch (MI.getOperand(1).getType()) {<br>
> +  case MachineOperand::MO_GlobalAddre<wbr>ss: {<br>
> +    const GlobalValue *GV = MI.getOperand(1).getGlobal();<br>
> +    int64_t Offs = MI.getOperand(1).getOffset();<br>
> +    unsigned TF = MI.getOperand(1).getTargetFlag<wbr>s();<br>
> +<br>
> +    MIBLO.addGlobalAddress(GV, Offs, TF);<br>
> +    MIBHI.addGlobalAddress(GV, Offs + 1, TF);<br>
> +    break;<br>
> +  }<br>
> +  case MachineOperand::MO_Immediate: {<br>
> +    unsigned Imm = MI.getOperand(1).getImm();<br>
> +<br>
> +    MIBLO.addImm(Imm);<br>
> +    MIBHI.addImm(Imm + 1);<br>
> +    break;<br>
> +  }<br>
> +  default:<br>
> +    llvm_unreachable("Unknown operand type!");<br>
> +  }<br>
> +<br>
> +  MIBLO->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +  MIBHI->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::L<wbr>DWRdPtr>(Block &MBB, BlockIt MBBI)<br>
> {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  unsigned SrcReg = MI.getOperand(1).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool SrcIsKill = MI.getOperand(1).isKill();<br>
> +  OpLo = AVR::LDRdPtr;<br>
> +  OpHi = AVR::LDDRdPtrQ;<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(SrcReg);<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(SrcReg, getKillRegState(SrcIsKill))<br>
> +    .addImm(1);<br>
> +<br>
> +  MIBLO->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +  MIBHI->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::L<wbr>DWRdPtrPi>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  unsigned SrcReg = MI.getOperand(1).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool SrcIsDead = MI.getOperand(1).isKill();<br>
> +  OpLo = AVR::LDRdPtrPi;<br>
> +  OpHi = AVR::LDRdPtrPi;<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(SrcReg, RegState::Define)<br>
> +    .addReg(SrcReg, RegState::Kill);<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(SrcReg, RegState::Define | getDeadRegState(SrcIsDead))<br>
> +    .addReg(SrcReg, RegState::Kill);<br>
> +<br>
> +  MIBLO->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +  MIBHI->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::L<wbr>DWRdPtrPd>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  unsigned SrcReg = MI.getOperand(1).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool SrcIsDead = MI.getOperand(1).isKill();<br>
> +  OpLo = AVR::LDRdPtrPd;<br>
> +  OpHi = AVR::LDRdPtrPd;<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(SrcReg, RegState::Define)<br>
> +    .addReg(SrcReg, RegState::Kill);<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(SrcReg, RegState::Define | getDeadRegState(SrcIsDead))<br>
> +    .addReg(SrcReg, RegState::Kill);<br>
> +<br>
> +  MIBLO->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +  MIBHI->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::L<wbr>DDWRdPtrQ>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  unsigned SrcReg = MI.getOperand(1).getReg();<br>
> +  unsigned Imm = MI.getOperand(2).getImm();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool SrcIsKill = MI.getOperand(1).isKill();<br>
> +  OpLo = AVR::LDDRdPtrQ;<br>
> +  OpHi = AVR::LDDRdPtrQ;<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  assert(Imm < 63 && "Offset is out of range");<br>
> +  assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(SrcReg)<br>
> +    .addImm(Imm);<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(SrcReg, getKillRegState(SrcIsKill))<br>
> +    .addImm(Imm + 1);<br>
> +<br>
> +  MIBLO->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +  MIBHI->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template<typename Func><br>
> +bool AVRExpandPseudo::expandAtomic(<wbr>Block &MBB, BlockIt MBBI, Func f) {<br>
> +  // Remove the pseudo instruction.<br>
> +  MachineInstr &MI = *MBBI;<br>
> +<br>
> +  // Store the SREG.<br>
> +  buildMI(MBB, MBBI, AVR::INRdA)<br>
> +    .addReg(SCRATCH_REGISTER, RegState::Define)<br>
> +    .addImm(SREG_ADDR);<br>
> +<br>
> +  // Disable exceptions.<br>
> +  buildMI(MBB, MBBI, AVR::BCLRs).addImm(7); // CLI<br>
> +<br>
> +  f(MI);<br>
> +<br>
> +  // Restore the status reg.<br>
> +  buildMI(MBB, MBBI, AVR::OUTARr)<br>
> +    .addImm(SREG_ADDR)<br>
> +    .addReg(SCRATCH_REGISTER);<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template<typename Func><br>
> +bool AVRExpandPseudo::expandAtomicB<wbr>inaryOp(unsigned Opcode,<br>
> +                                           Block &MBB,<br>
> +                                           BlockIt MBBI,<br>
> +                                           Func f) {<br>
> +  return expandAtomic(MBB, MBBI, [&](MachineInstr &MI) {<br>
> +      auto Op1 = MI.getOperand(0);<br>
> +      auto Op2 = MI.getOperand(1);<br>
> +<br>
> +      MachineInstr &NewInst = *buildMI(MBB, MBBI, Opcode)<br>
> +        .addOperand(Op1).addOperand(Op<wbr>2)<br>
> +        .getInstr();<br>
> +      f(NewInst);<br>
> +  });<br>
> +}<br>
> +<br>
> +bool AVRExpandPseudo::expandAtomicB<wbr>inaryOp(unsigned Opcode,<br>
> +                                           Block &MBB,<br>
> +                                           BlockIt MBBI) {<br>
> +  return expandAtomicBinaryOp(Opcode, MBB, MBBI, [](MachineInstr &MI)<br>
> {});<br>
> +}<br>
> +<br>
> +bool AVRExpandPseudo::expandAtomicA<wbr>rithmeticOp(unsigned Width,<br>
> +                                               unsigned ArithOpcode,<br>
> +                                               Block &MBB,<br>
> +                                               BlockIt MBBI) {<br>
> +  return expandAtomic(MBB, MBBI, [&](MachineInstr &MI) {<br>
> +      auto Op1 = MI.getOperand(0);<br>
> +      auto Op2 = MI.getOperand(1);<br>
> +<br>
> +      unsigned LoadOpcode = (Width == 8) ? AVR::LDRdPtr :<br>
> AVR::LDWRdPtr;<br>
> +      unsigned StoreOpcode = (Width == 8) ? AVR::STPtrRr :<br>
> AVR::STWPtrRr;<br>
> +<br>
> +      // Create the load<br>
> +      buildMI(MBB, MBBI, LoadOpcode).addOperand(Op1).ad<wbr>dOperand(Op2);<br>
> +<br>
> +      // Create the arithmetic op<br>
> +      buildMI(MBB, MBBI, ArithOpcode)<br>
> +        .addOperand(Op1).addOperand(Op<wbr>1)<br>
> +        .addOperand(Op2);<br>
> +<br>
> +      // Create the store<br>
> +      buildMI(MBB, MBBI, StoreOpcode).addOperand(Op2).a<wbr>ddOperand(Op1);<br>
> +  });<br>
> +}<br>
> +<br>
> +template<><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>tomicLoad8>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  return expandAtomicBinaryOp(AVR::LDRd<wbr>Ptr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template<><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>tomicLoad16>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  return expandAtomicBinaryOp(AVR::LDWR<wbr>dPtr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template<><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>tomicStore8>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  return expandAtomicBinaryOp(AVR::STPt<wbr>rRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template<><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>tomicStore16>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  return expandAtomicBinaryOp(AVR::STWP<wbr>trRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template<><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>tomicLoadAdd8>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  return expandAtomicArithmeticOp(8, AVR::ADDRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template<><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>tomicLoadAdd16>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  return expandAtomicArithmeticOp(16, AVR::ADDWRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template<><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>tomicLoadSub8>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  return expandAtomicArithmeticOp(8, AVR::SUBRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template<><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>tomicLoadSub16>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  return expandAtomicArithmeticOp(16, AVR::SUBWRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template<><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>tomicLoadAnd8>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  return expandAtomicArithmeticOp(8, AVR::ANDRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template<><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>tomicLoadAnd16>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  return expandAtomicArithmeticOp(16, AVR::ANDWRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template<><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>tomicLoadOr8>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  return expandAtomicArithmeticOp(8, AVR::ORRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template<><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>tomicLoadOr16>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  return expandAtomicArithmeticOp(16, AVR::ORWRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template<><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>tomicLoadXor8>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  return expandAtomicArithmeticOp(8, AVR::EORRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template<><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>tomicLoadXor16>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  return expandAtomicArithmeticOp(16, AVR::EORWRdRr, MBB, MBBI);<br>
> +}<br>
> +<br>
> +template<><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>tomicFence>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  // On AVR, there is only one core and so atomic fences do nothing.<br>
> +  MBBI->eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::S<wbr>TSWKRr>(Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;<br>
> +  unsigned SrcReg = MI.getOperand(1).getReg();<br>
> +  bool SrcIsKill = MI.getOperand(1).isKill();<br>
> +  OpLo = AVR::STSKRr;<br>
> +  OpHi = AVR::STSKRr;<br>
> +  TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);<br>
> +<br>
> +  // Write the high byte first in case this address belongs to a<br>
> special<br>
> +  // I/O address with a special temporary register.<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi);<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo);<br>
> +<br>
> +  switch (MI.getOperand(0).getType()) {<br>
> +  case MachineOperand::MO_GlobalAddre<wbr>ss: {<br>
> +    const GlobalValue *GV = MI.getOperand(0).getGlobal();<br>
> +    int64_t Offs = MI.getOperand(0).getOffset();<br>
> +    unsigned TF = MI.getOperand(0).getTargetFlag<wbr>s();<br>
> +<br>
> +    MIBLO.addGlobalAddress(GV, Offs, TF);<br>
> +    MIBHI.addGlobalAddress(GV, Offs + 1, TF);<br>
> +    break;<br>
> +  }<br>
> +  case MachineOperand::MO_Immediate: {<br>
> +    unsigned Imm = MI.getOperand(0).getImm();<br>
> +<br>
> +    MIBLO.addImm(Imm);<br>
> +    MIBHI.addImm(Imm + 1);<br>
> +    break;<br>
> +  }<br>
> +  default:<br>
> +    llvm_unreachable("Unknown operand type!");<br>
> +  }<br>
> +<br>
> +  MIBLO.addReg(SrcLoReg, getKillRegState(SrcIsKill));<br>
> +  MIBHI.addReg(SrcHiReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  MIBLO->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +  MIBHI->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::S<wbr>TWPtrRr>(Block &MBB, BlockIt MBBI)<br>
> {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  unsigned SrcReg = MI.getOperand(1).getReg();<br>
> +  bool DstIsKill = MI.getOperand(0).isKill();<br>
> +  bool SrcIsKill = MI.getOperand(1).isKill();<br>
> +  OpLo = AVR::STPtrRr;<br>
> +  OpHi = AVR::STDPtrQRr;<br>
> +  TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);<br>
> +<br>
> +  //:TODO: need to reverse this order like inw and stsw?<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstReg)<br>
> +    .addReg(SrcLoReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstReg, getKillRegState(DstIsKill))<br>
> +    .addImm(1)<br>
> +    .addReg(SrcHiReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  MIBLO->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +  MIBHI->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::S<wbr>TWPtrPiRr>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  unsigned SrcReg = MI.getOperand(2).getReg();<br>
> +  unsigned Imm = MI.getOperand(3).getImm();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool SrcIsKill = MI.getOperand(2).isKill();<br>
> +  OpLo = AVR::STPtrPiRr;<br>
> +  OpHi = AVR::STPtrPiRr;<br>
> +  TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);<br>
> +<br>
> +  assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstReg, RegState::Define)<br>
> +    .addReg(DstReg, RegState::Kill)<br>
> +    .addReg(SrcLoReg, getKillRegState(SrcIsKill))<br>
> +    .addImm(Imm);<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstReg, RegState::Kill)<br>
> +    .addReg(SrcHiReg, getKillRegState(SrcIsKill))<br>
> +    .addImm(Imm);<br>
> +<br>
> +  MIBLO->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +  MIBHI->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::S<wbr>TWPtrPdRr>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  unsigned SrcReg = MI.getOperand(2).getReg();<br>
> +  unsigned Imm = MI.getOperand(3).getImm();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool SrcIsKill = MI.getOperand(2).isKill();<br>
> +  OpLo = AVR::STPtrPdRr;<br>
> +  OpHi = AVR::STPtrPdRr;<br>
> +  TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);<br>
> +<br>
> +  assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstReg, RegState::Define)<br>
> +    .addReg(DstReg, RegState::Kill)<br>
> +    .addReg(SrcHiReg, getKillRegState(SrcIsKill))<br>
> +    .addImm(Imm);<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstReg, RegState::Kill)<br>
> +    .addReg(SrcLoReg, getKillRegState(SrcIsKill))<br>
> +    .addImm(Imm);<br>
> +<br>
> +  MIBLO->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +  MIBHI->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::S<wbr>TDWPtrQRr>(Block &MBB, BlockIt<br>
> MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  unsigned SrcReg = MI.getOperand(2).getReg();<br>
> +  unsigned Imm = MI.getOperand(1).getImm();<br>
> +  bool DstIsKill = MI.getOperand(0).isKill();<br>
> +  bool SrcIsKill = MI.getOperand(2).isKill();<br>
> +  OpLo = AVR::STDPtrQRr;<br>
> +  OpHi = AVR::STDPtrQRr;<br>
> +  TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);<br>
> +<br>
> +  assert(Imm < 63 && "Offset is out of range");<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstReg)<br>
> +    .addImm(Imm)<br>
> +    .addReg(SrcLoReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstReg, getKillRegState(DstIsKill))<br>
> +    .addImm(Imm + 1)<br>
> +    .addReg(SrcHiReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  MIBLO->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +  MIBHI->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::I<wbr>NWRdA>(Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, DstLoReg, DstHiReg;<br>
> +  unsigned Imm = MI.getOperand(1).getImm();<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  OpLo = AVR::INRdA;<br>
> +  OpHi = AVR::INRdA;<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  assert(Imm < 63 && "Address is out of range");<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addImm(Imm);<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addImm(Imm + 1);<br>
> +<br>
> +  MIBLO->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +  MIBHI->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::O<wbr>UTWARr>(Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;<br>
> +  unsigned Imm = MI.getOperand(0).getImm();<br>
> +  unsigned SrcReg = MI.getOperand(1).getReg();<br>
> +  bool SrcIsKill = MI.getOperand(1).isKill();<br>
> +  OpLo = AVR::OUTARr;<br>
> +  OpHi = AVR::OUTARr;<br>
> +  TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);<br>
> +<br>
> +  assert(Imm < 63 && "Address is out of range");<br>
> +<br>
> +  // 16 bit I/O writes need the high byte first<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addImm(Imm + 1)<br>
> +    .addReg(SrcHiReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addImm(Imm)<br>
> +    .addReg(SrcLoReg, getKillRegState(SrcIsKill));<br>
> +<br>
> +  MIBLO->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +  MIBHI->setMemRefs(MI.memoperan<wbr>ds_begin(), MI.memoperands_end());<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::P<wbr>USHWRr>(Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;<br>
> +  unsigned SrcReg = MI.getOperand(0).getReg();<br>
> +  bool SrcIsKill = MI.getOperand(0).isKill();<br>
> +  unsigned Flags = MI.getFlags();<br>
> +  OpLo = AVR::PUSHRr;<br>
> +  OpHi = AVR::PUSHRr;<br>
> +  TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);<br>
> +<br>
> +  // Low part<br>
> +  buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(SrcLoReg, getKillRegState(SrcIsKill))<br>
> +    .setMIFlags(Flags);<br>
> +<br>
> +  // High part<br>
> +  buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(SrcHiReg, getKillRegState(SrcIsKill))<br>
> +    .setMIFlags(Flags);<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::P<wbr>OPWRd>(Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  unsigned Flags = MI.getFlags();<br>
> +  OpLo = AVR::POPRd;<br>
> +  OpHi = AVR::POPRd;<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  buildMI(MBB, MBBI, OpHi, DstHiReg).setMIFlags(Flags); // High<br>
> +  buildMI(MBB, MBBI, OpLo, DstLoReg).setMIFlags(Flags); // Low<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::L<wbr>SLWRd>(Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool DstIsKill = MI.getOperand(1).isKill();<br>
> +  bool ImpIsDead = MI.getOperand(2).isDead();<br>
> +  OpLo = AVR::LSLRd;<br>
> +  OpHi = AVR::ROLRd;<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  // Low part<br>
> +  buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstLoReg, getKillRegState(DstIsKill));<br>
> +<br>
> +  auto MIBHI = buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstHiReg, getKillRegState(DstIsKill));<br>
> +<br>
> +  if (ImpIsDead)<br>
> +    MIBHI->getOperand(2).setIsDead<wbr>();<br>
> +<br>
> +  // SREG is always implicitly killed<br>
> +  MIBHI->getOperand(3).setIsKill<wbr>();<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::L<wbr>SRWRd>(Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool DstIsKill = MI.getOperand(1).isKill();<br>
> +  bool ImpIsDead = MI.getOperand(2).isDead();<br>
> +  OpLo = AVR::RORRd;<br>
> +  OpHi = AVR::LSRRd;<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  // High part<br>
> +  buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstHiReg, getKillRegState(DstIsKill));<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstLoReg, getKillRegState(DstIsKill));<br>
> +<br>
> +  if (ImpIsDead)<br>
> +    MIBLO->getOperand(2).setIsDead<wbr>();<br>
> +<br>
> +  // SREG is always implicitly killed<br>
> +  MIBLO->getOperand(3).setIsKill<wbr>();<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::R<wbr>ORWRd>(Block &MBB, BlockIt MBBI) {<br>
> +  llvm_unreachable("RORW unimplemented");<br>
> +  return false;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::R<wbr>OLWRd>(Block &MBB, BlockIt MBBI) {<br>
> +  llvm_unreachable("ROLW unimplemented");<br>
> +  return false;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::A<wbr>SRWRd>(Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool DstIsKill = MI.getOperand(1).isKill();<br>
> +  bool ImpIsDead = MI.getOperand(2).isDead();<br>
> +  OpLo = AVR::RORRd;<br>
> +  OpHi = AVR::ASRRd;<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  // High part<br>
> +  buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstHiReg, getKillRegState(DstIsKill));<br>
> +<br>
> +  auto MIBLO = buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstLoReg, getKillRegState(DstIsKill));<br>
> +<br>
> +  if (ImpIsDead)<br>
> +    MIBLO->getOperand(2).setIsDead<wbr>();<br>
> +<br>
> +  // SREG is always implicitly killed<br>
> +  MIBLO->getOperand(3).setIsKill<wbr>();<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <> bool AVRExpandPseudo::expand<AVR::S<wbr>EXT>(Block &MBB,<br>
> BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned DstLoReg, DstHiReg;<br>
> +  // sext R17:R16, R17<br>
> +  // mov     r16, r17<br>
> +  // lsl     r17<br>
> +  // sbc     r17, r17<br>
> +  // sext R17:R16, R13<br>
> +  // mov     r16, r13<br>
> +  // mov     r17, r13<br>
> +  // lsl     r17<br>
> +  // sbc     r17, r17<br>
> +  // sext R17:R16, R16<br>
> +  // mov     r17, r16<br>
> +  // lsl     r17<br>
> +  // sbc     r17, r17<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  unsigned SrcReg = MI.getOperand(1).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool SrcIsKill = MI.getOperand(1).isKill();<br>
> +  bool ImpIsDead = MI.getOperand(2).isDead();<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  if (SrcReg != DstLoReg) {<br>
> +    auto MOV = buildMI(MBB, MBBI, AVR::MOVRdRr)<br>
> +      .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +      .addReg(SrcReg);<br>
> +<br>
> +    if (SrcReg == DstHiReg) {<br>
> +      MOV->getOperand(1).setIsKill()<wbr>;<br>
> +    }<br>
> +  }<br>
> +<br>
> +  if (SrcReg != DstHiReg) {<br>
> +    buildMI(MBB, MBBI, AVR::MOVRdRr)<br>
> +      .addReg(DstHiReg, RegState::Define)<br>
> +      .addReg(SrcReg, getKillRegState(SrcIsKill));<br>
> +  }<br>
> +<br>
> +  buildMI(MBB, MBBI, AVR::LSLRd)<br>
> +    .addReg(DstHiReg, RegState::Define)<br>
> +    .addReg(DstHiReg, RegState::Kill);<br>
> +<br>
> +  auto SBC = buildMI(MBB, MBBI, AVR::SBCRdRr)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstHiReg, RegState::Kill)<br>
> +    .addReg(DstHiReg, RegState::Kill);<br>
> +<br>
> +  if (ImpIsDead)<br>
> +    SBC->getOperand(3).setIsDead()<wbr>;<br>
> +<br>
> +  // SREG is always implicitly killed<br>
> +  SBC->getOperand(4).setIsKill()<wbr>;<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <> bool AVRExpandPseudo::expand<AVR::Z<wbr>EXT>(Block &MBB,<br>
> BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned DstLoReg, DstHiReg;<br>
> +  // zext R25:R24, R20<br>
> +  // mov      R24, R20<br>
> +  // eor      R25, R25<br>
> +  // zext R25:R24, R24<br>
> +  // eor      R25, R25<br>
> +  // zext R25:R24, R25<br>
> +  // mov      R24, R25<br>
> +  // eor      R25, R25<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  unsigned SrcReg = MI.getOperand(1).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  bool SrcIsKill = MI.getOperand(1).isKill();<br>
> +  bool ImpIsDead = MI.getOperand(2).isDead();<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  if (SrcReg != DstLoReg) {<br>
> +    buildMI(MBB, MBBI, AVR::MOVRdRr)<br>
> +      .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +      .addReg(SrcReg, getKillRegState(SrcIsKill));<br>
> +  }<br>
> +<br>
> +  auto EOR = buildMI(MBB, MBBI, AVR::EORRdRr)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addReg(DstHiReg, RegState::Kill)<br>
> +    .addReg(DstHiReg, RegState::Kill);<br>
> +<br>
> +  if (ImpIsDead)<br>
> +    EOR->getOperand(3).setIsDead()<wbr>;<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::S<wbr>PREAD>(Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned OpLo, OpHi, DstLoReg, DstHiReg;<br>
> +  unsigned DstReg = MI.getOperand(0).getReg();<br>
> +  bool DstIsDead = MI.getOperand(0).isDead();<br>
> +  unsigned Flags = MI.getFlags();<br>
> +  OpLo = AVR::INRdA;<br>
> +  OpHi = AVR::INRdA;<br>
> +  TRI->splitReg(DstReg, DstLoReg, DstHiReg);<br>
> +<br>
> +  // Low part<br>
> +  buildMI(MBB, MBBI, OpLo)<br>
> +    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addImm(0x3d)<br>
> +    .setMIFlags(Flags);<br>
> +<br>
> +  // High part<br>
> +  buildMI(MBB, MBBI, OpHi)<br>
> +    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))<br>
> +    .addImm(0x3e)<br>
> +    .setMIFlags(Flags);<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +template <><br>
> +bool AVRExpandPseudo::expand<AVR::S<wbr>PWRITE>(Block &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  unsigned SrcLoReg, SrcHiReg;<br>
> +  unsigned SrcReg = MI.getOperand(1).getReg();<br>
> +  bool SrcIsKill = MI.getOperand(1).isKill();<br>
> +  unsigned Flags = MI.getFlags();<br>
> +  TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);<br>
> +<br>
> +  buildMI(MBB, MBBI, AVR::INRdA)<br>
> +    .addReg(AVR::R0, RegState::Define)<br>
> +    .addImm(SREG_ADDR)<br>
> +    .setMIFlags(Flags);<br>
> +<br>
> +  buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMI<wbr>Flags(Flags);<br>
> +<br>
> +  buildMI(MBB, MBBI, AVR::OUTARr)<br>
> +    .addImm(0x3e)<br>
> +    .addReg(SrcHiReg, getKillRegState(SrcIsKill))<br>
> +    .setMIFlags(Flags);<br>
> +<br>
> +  buildMI(MBB, MBBI, AVR::OUTARr)<br>
> +    .addImm(SREG_ADDR)<br>
> +    .addReg(AVR::R0, RegState::Kill)<br>
> +    .setMIFlags(Flags);<br>
> +<br>
> +  buildMI(MBB, MBBI, AVR::OUTARr)<br>
> +    .addImm(0x3d)<br>
> +    .addReg(SrcLoReg, getKillRegState(SrcIsKill))<br>
> +    .setMIFlags(Flags);<br>
> +<br>
> +  MI.eraseFromParent();<br>
> +  return true;<br>
> +}<br>
> +<br>
> +bool AVRExpandPseudo::expandMI(Bloc<wbr>k &MBB, BlockIt MBBI) {<br>
> +  MachineInstr &MI = *MBBI;<br>
> +  int Opcode = MBBI->getOpcode();<br>
> +<br>
> +#define EXPAND(Op)               \<br>
> +  case Op:                       \<br>
> +    return expand<Op>(MBB, MI)<br>
> +<br>
> +  switch (Opcode) {<br>
> +    EXPAND(AVR::ADDWRdRr);<br>
> +    EXPAND(AVR::ADCWRdRr);<br>
> +    EXPAND(AVR::SUBWRdRr);<br>
> +    EXPAND(AVR::SUBIWRdK);<br>
> +    EXPAND(AVR::SBCWRdRr);<br>
> +    EXPAND(AVR::SBCIWRdK);<br>
> +    EXPAND(AVR::ANDWRdRr);<br>
> +    EXPAND(AVR::ANDIWRdK);<br>
> +    EXPAND(AVR::ORWRdRr);<br>
> +    EXPAND(AVR::ORIWRdK);<br>
> +    EXPAND(AVR::EORWRdRr);<br>
> +    EXPAND(AVR::COMWRd);<br>
> +    EXPAND(AVR::CPWRdRr);<br>
> +    EXPAND(AVR::CPCWRdRr);<br>
> +    EXPAND(AVR::LDIWRdK);<br>
> +    EXPAND(AVR::LDSWRdK);<br>
> +    EXPAND(AVR::LDWRdPtr);<br>
> +    EXPAND(AVR::LDWRdPtrPi);<br>
> +    EXPAND(AVR::LDWRdPtrPd);<br>
> +  case AVR::LDDWRdYQ: //:FIXME: remove this once PR13375 gets fixed<br>
> +    EXPAND(AVR::LDDWRdPtrQ);<br>
> +    EXPAND(AVR::AtomicLoad8);<br>
> +    EXPAND(AVR::AtomicLoad16);<br>
> +    EXPAND(AVR::AtomicStore8);<br>
> +    EXPAND(AVR::AtomicStore16);<br>
> +    EXPAND(AVR::AtomicLoadAdd8);<br>
> +    EXPAND(AVR::AtomicLoadAdd16);<br>
> +    EXPAND(AVR::AtomicLoadSub8);<br>
> +    EXPAND(AVR::AtomicLoadSub16);<br>
> +    EXPAND(AVR::AtomicLoadAnd8);<br>
> +    EXPAND(AVR::AtomicLoadAnd16);<br>
> +    EXPAND(AVR::AtomicLoadOr8);<br>
> +    EXPAND(AVR::AtomicLoadOr16);<br>
> +    EXPAND(AVR::AtomicLoadXor8);<br>
> +    EXPAND(AVR::AtomicLoadXor16);<br>
> +    EXPAND(AVR::AtomicFence);<br>
> +    EXPAND(AVR::STSWKRr);<br>
> +    EXPAND(AVR::STWPtrRr);<br>
> +    EXPAND(AVR::STWPtrPiRr);<br>
> +    EXPAND(AVR::STWPtrPdRr);<br>
> +    EXPAND(AVR::STDWPtrQRr);<br>
> +    EXPAND(AVR::INWRdA);<br>
> +    EXPAND(AVR::OUTWARr);<br>
> +    EXPAND(AVR::PUSHWRr);<br>
> +    EXPAND(AVR::POPWRd);<br>
> +    EXPAND(AVR::LSLWRd);<br>
> +    EXPAND(AVR::LSRWRd);<br>
> +    EXPAND(AVR::RORWRd);<br>
> +    EXPAND(AVR::ROLWRd);<br>
> +    EXPAND(AVR::ASRWRd);<br>
> +    EXPAND(AVR::SEXT);<br>
> +    EXPAND(AVR::ZEXT);<br>
> +    EXPAND(AVR::SPREAD);<br>
> +    EXPAND(AVR::SPWRITE);<br>
> +  }<br>
> +#undef EXPAND<br>
> +  return false;<br>
> +}<br>
> +<br>
> +namespace llvm {<br>
> +<br>
> +FunctionPass *createAVRExpandPseudoPass() { return new<br>
> AVRExpandPseudo(); }<br>
> +<br>
> +} // end of namespace llvm<br>
><br>
> Modified: llvm/trunk/lib/Target/AVR/AVRT<wbr>argetMachine.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/lib/Target/<wbr>AVR/AVRTargetMachine.cpp?rev=2<wbr>87162&r1=28<br>
> 7161&r2=287162&view=diff<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/lib/Target/AVR/AVRT<wbr>argetMachine.cpp (original)<br>
> +++ llvm/trunk/lib/Target/AVR/AVRT<wbr>argetMachine.cpp Wed Nov 16 15:58:04<br>
> 2016<br>
> @@ -106,7 +106,7 @@ void AVRPassConfig::addPreRegAlloc(<wbr>) {<br>
>    addPass(createAVRDynAllocaSRPa<wbr>ss());<br>
>  }<br>
><br>
> -void AVRPassConfig::addPreSched2() { }<br>
> +void AVRPassConfig::addPreSched2() {<br>
> addPass(createAVRExpandPseudoP<wbr>ass()); }<br>
><br>
>  void AVRPassConfig::addPreEmitPass(<wbr>) { }<br>
><br>
><br>
> Modified: llvm/trunk/lib/Target/AVR/CMak<wbr>eLists.txt<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/lib/Target/<wbr>AVR/CMakeLists.txt?rev=287162&<wbr>r1=287161&r<br>
> 2=287162&view=diff<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/lib/Target/AVR/CMak<wbr>eLists.txt (original)<br>
> +++ llvm/trunk/lib/Target/AVR/CMak<wbr>eLists.txt Wed Nov 16 15:58:04 2016<br>
> @@ -18,6 +18,7 @@ add_public_tablegen_target(AVR<wbr>CommonTabl<br>
><br>
>  add_llvm_target(AVRCodeGen<br>
>    AVRAsmPrinter.cpp<br>
> +  AVRExpandPseudoInsts.cpp<br>
>    AVRFrameLowering.cpp<br>
>    AVRInstrInfo.cpp<br>
>    AVRISelDAGToDAG.cpp<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/ad<wbr>d.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/add.ll?rev=287162&view=<wbr>auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/ad<wbr>d.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/ad<wbr>d.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,93 @@<br>
> +; RUN: llc -mattr=addsubiw < %s -march=avr | FileCheck %s<br>
> +<br>
> +define i8 @add8_reg_reg(i8 %a, i8 %b) {<br>
> +; CHECK-LABEL: add8_reg_reg:<br>
> +; CHECK: add r24, r22<br>
> +    %result = add i8 %a, %b<br>
> +    ret i8 %result<br>
> +}<br>
> +<br>
> +define i8 @add8_reg_imm(i8 %a) {<br>
> +; CHECK-LABEL: add8_reg_imm:<br>
> +; CHECK: subi r24, -5<br>
> +    %result = add i8 %a, 5<br>
> +    ret i8 %result<br>
> +}<br>
> +<br>
> +define i8 @add8_reg_increment(i8 %a) {<br>
> +; CHECK-LABEL: add8_reg_increment:<br>
> +; CHECK: inc r24<br>
> +    %result = add i8 %a, 1<br>
> +    ret i8 %result<br>
> +}<br>
> +<br>
> +<br>
> +define i16 @add16_reg_reg(i16 %a, i16 %b) {<br>
> +; CHECK-LABEL: add16_reg_reg:<br>
> +; CHECK: add r24, r22<br>
> +; CHECK: adc r25, r23<br>
> +    %result = add i16 %a, %b<br>
> +    ret i16 %result<br>
> +}<br>
> +<br>
> +define i16 @add16_reg_imm(i16 %a) {<br>
> +; CHECK-LABEL: add16_reg_imm:<br>
> +; CHECK: adiw r24, 63<br>
> +    %result = add i16 %a, 63<br>
> +    ret i16 %result<br>
> +}<br>
> +<br>
> +define i16 @add16_reg_imm_subi(i16 %a) {<br>
> +; CHECK-LABEL: add16_reg_imm_subi:<br>
> +; CHECK: subi r24, 133<br>
> +; CHECK: sbci r25, 255<br>
> +    %result = add i16 %a, 123<br>
> +    ret i16 %result<br>
> +}<br>
> +<br>
> +define i32 @add32_reg_reg(i32 %a, i32 %b) {<br>
> +; CHECK-LABEL: add32_reg_reg:<br>
> +; CHECK: add r22, r18<br>
> +; CHECK: adc r23, r19<br>
> +; CHECK: adc r24, r20<br>
> +; CHECK: adc r25, r21<br>
> +    %result = add i32 %a, %b<br>
> +    ret i32 %result<br>
> +}<br>
> +<br>
> +define i32 @add32_reg_imm(i32 %a) {<br>
> +; CHECK-LABEL: add32_reg_imm:<br>
> +; CHECK: subi r22, 251<br>
> +; CHECK: sbci r23, 255<br>
> +; CHECK: sbci r24, 255<br>
> +; CHECK: sbci r25, 255<br>
> +    %result = add i32 %a, 5<br>
> +    ret i32 %result<br>
> +}<br>
> +<br>
> +define i64 @add64_reg_reg(i64 %a, i64 %b) {<br>
> +; CHECK-LABEL: add64_reg_reg:<br>
> +; CHECK: add r18, r10<br>
> +; CHECK: adc r20, r12<br>
> +; CHECK: adc r21, r13<br>
> +; CHECK: adc r22, r14<br>
> +; CHECK: adc r23, r15<br>
> +; CHECK: adc r24, r16<br>
> +; CHECK: adc r25, r17<br>
> +    %result = add i64 %a, %b<br>
> +    ret i64 %result<br>
> +}<br>
> +<br>
> +define i64 @add64_reg_imm(i64 %a) {<br>
> +; CHECK-LABEL: add64_reg_imm:<br>
> +; CHECK: subi r18, 251<br>
> +; CHECK: sbci r19, 255<br>
> +; CHECK: sbci r20, 255<br>
> +; CHECK: sbci r21, 255<br>
> +; CHECK: sbci r22, 255<br>
> +; CHECK: sbci r23, 255<br>
> +; CHECK: sbci r24, 255<br>
> +; CHECK: sbci r25, 255<br>
> +    %result = add i64 %a, 5<br>
> +    ret i64 %result<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/al<wbr>loca.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/alloca.ll?rev=287162&<wbr>view=auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/al<wbr>loca.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/al<wbr>loca.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,84 @@<br>
> +; RUN: llc < %s -march=avr -mattr=avr6 | FileCheck %s<br>
> +<br>
> +declare i16 @allocate(i16*, i16*)<br>
> +<br>
> +; Test taking an address of an alloca with a small offset (adiw)<br>
> +define i16 @alloca_addressof_small() {<br>
> +entry:<br>
> +; CHECK-LABEL: alloca_addressof_small:<br>
> +; Test that Y is saved<br>
> +; CHECK: push r28<br>
> +; CHECK: push r29<br>
> +; CHECK: movw r24, r28<br>
> +; CHECK: adiw r24, 17<br>
> +; CHECK: movw {{.*}}, r28<br>
> +; CHECK: adiw {{.*}}, 39<br>
> +; CHECK: movw r22, {{.*}}<br>
> +; CHECK: pop r29<br>
> +; CHECK: pop r28<br>
> +  %p = alloca [18 x i16]<br>
> +  %k = alloca [14 x i16]<br>
> +  %arrayidx = getelementptr inbounds [14 x i16], [14 x i16]* %k, i16<br>
> 0, i16 8<br>
> +  %arrayidx1 = getelementptr inbounds [18 x i16], [18 x i16]* %p, i16<br>
> 0, i16 5<br>
> +  %call = call i16 @allocate(i16* %arrayidx, i16* %arrayidx1)<br>
> +  ret i16 %call<br>
> +}<br>
> +<br>
> +; Test taking an address of an alloca with a big offset (subi/sbci<br>
> pair)<br>
> +define i16 @alloca_addressof_big() {<br>
> +entry:<br>
> +; CHECK-LABEL: alloca_addressof_big:<br>
> +; CHECK: movw r24, r28<br>
> +; CHECK: adiw r24, 17<br>
> +; CHECK: movw r22, r28<br>
> +; CHECK: subi r22, 145<br>
> +; CHECK: sbci r23, 255<br>
> +  %p = alloca [55 x i16]<br>
> +  %k = alloca [14 x i16]<br>
> +  %arrayidx = getelementptr inbounds [14 x i16], [14 x i16]* %k, i16<br>
> 0, i16 8<br>
> +  %arrayidx1 = getelementptr inbounds [55 x i16], [55 x i16]* %p, i16<br>
> 0, i16 41<br>
> +  %call = call i16 @allocate(i16* %arrayidx, i16* %arrayidx1)<br>
> +  ret i16 %call<br>
> +}<br>
> +<br>
> +; Test writing to an allocated variable with a small and a big offset<br>
> +define i16 @alloca_write(i16 %x) {<br>
> +entry:<br>
> +; CHECK-LABEL: alloca_write:<br>
> +; Big offset here<br>
> +; CHECK: adiw r28, 57<br>
> +; CHECK: std Y+62, {{.*}}<br>
> +; CHECK: std Y+63, {{.*}}<br>
> +; CHECK: sbiw r28, 57<br>
> +; Small offset here<br>
> +; CHECK: std Y+23, {{.*}}<br>
> +; CHECK: std Y+24, {{.*}}<br>
> +  %p = alloca [15 x i16]<br>
> +  %k = alloca [14 x i16]<br>
> +  %arrayidx = getelementptr inbounds [15 x i16], [15 x i16]* %p, i16<br>
> 0, i16 45<br>
> +  store i16 22, i16* %arrayidx<br>
> +  %arrayidx1 = getelementptr inbounds [14 x i16], [14 x i16]* %k, i16<br>
> 0, i16 11<br>
> +  store i16 42, i16* %arrayidx1<br>
> +  %arrayidx2 = getelementptr inbounds [14 x i16], [14 x i16]* %k, i16<br>
> 0, i16 0<br>
> +  %arrayidx3 = getelementptr inbounds [15 x i16], [15 x i16]* %p, i16<br>
> 0, i16 0<br>
> +  %call = call i16 @allocate(i16* %arrayidx2, i16* %arrayidx3)<br>
> +  ret i16 %call<br>
> +}<br>
> +<br>
> +; Test writing to an allocated variable with a huge offset that cant<br>
> be<br>
> +; materialized with adiw/sbiw but with a subi/sbci pair.<br>
> +define void @alloca_write_huge() {<br>
> +; CHECK-LABEL: alloca_write_huge:<br>
> +; CHECK: subi r28, 41<br>
> +; CHECK: sbci r29, 255<br>
> +; CHECK: std Y+62, {{.*}}<br>
> +; CHECK: std Y+63, {{.*}}<br>
> +; CHECK: subi r28, 215<br>
> +; CHECK: sbci r29, 0<br>
> +  %k = alloca [140 x i16]<br>
> +  %arrayidx = getelementptr inbounds [140 x i16], [140 x i16]* %k, i16<br>
> 0, i16 138<br>
> +  store i16 22, i16* %arrayidx<br>
> +  %arraydecay = getelementptr inbounds [140 x i16], [140 x i16]* %k,<br>
> i16 0, i16 0<br>
> +  call i16 @allocate(i16* %arraydecay, i16* null)<br>
> +  ret void<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/an<wbr>d.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/and.ll?rev=287162&view=<wbr>auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/an<wbr>d.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/an<wbr>d.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,80 @@<br>
> +; RUN: llc < %s -march=avr | FileCheck %s<br>
> +<br>
> +define i8 @and8_reg_reg(i8 %a, i8 %b) {<br>
> +; CHECK-LABEL: and8_reg_reg:<br>
> +; CHECK: and r24, r22<br>
> +    %result = and i8 %a, %b<br>
> +    ret i8 %result<br>
> +}<br>
> +<br>
> +define i8 @and8_reg_imm(i8 %a) {<br>
> +; CHECK-LABEL: and8_reg_imm:<br>
> +; CHECK: andi r24, 5<br>
> +    %result = and i8 %a, 5<br>
> +    ret i8 %result<br>
> +}<br>
> +<br>
> +define i16 @and16_reg_reg(i16 %a, i16 %b) {<br>
> +; CHECK-LABEL: and16_reg_reg:<br>
> +; CHECK: and r24, r22<br>
> +; CHECK: and r25, r23<br>
> +    %result = and i16 %a, %b<br>
> +    ret i16 %result<br>
> +}<br>
> +<br>
> +define i16 @and16_reg_imm(i16 %a) {<br>
> +; CHECK-LABEL: and16_reg_imm:<br>
> +; CHECK: andi r24, 210<br>
> +; CHECK: andi r25, 4<br>
> +    %result = and i16 %a, 1234<br>
> +    ret i16 %result<br>
> +}<br>
> +<br>
> +define i32 @and32_reg_reg(i32 %a, i32 %b) {<br>
> +; CHECK-LABEL: and32_reg_reg:<br>
> +; CHECK: and r22, r18<br>
> +; CHECK: and r23, r19<br>
> +; CHECK: and r24, r20<br>
> +; CHECK: and r25, r21<br>
> +    %result = and i32 %a, %b<br>
> +    ret i32 %result<br>
> +}<br>
> +<br>
> +define i32 @and32_reg_imm(i32 %a) {<br>
> +; CHECK-LABEL: and32_reg_imm:<br>
> +; CHECK: andi r22, 21<br>
> +; CHECK: andi r23, 205<br>
> +; CHECK: andi r24, 91<br>
> +; CHECK: andi r25, 7<br>
> +    %result = and i32 %a, 123456789<br>
> +    ret i32 %result<br>
> +}<br>
> +<br>
> +define i64 @and64_reg_reg(i64 %a, i64 %b) {<br>
> +; CHECK-LABEL: and64_reg_reg:<br>
> +; CHECK: and r18, r10<br>
> +; CHECK: and r19, r11<br>
> +; CHECK: and r20, r12<br>
> +; CHECK: and r21, r13<br>
> +; CHECK: and r22, r14<br>
> +; CHECK: and r23, r15<br>
> +; CHECK: and r24, r16<br>
> +; CHECK: and r25, r17<br>
> +    %result = and i64 %a, %b<br>
> +    ret i64 %result<br>
> +}<br>
> +<br>
> +define i64 @and64_reg_imm(i64 %a) {<br>
> +; CHECK-LABEL: and64_reg_imm:<br>
> +; CHECK: andi r18, 253<br>
> +; CHECK: andi r19, 255<br>
> +; CHECK: andi r20, 155<br>
> +; CHECK: andi r21, 88<br>
> +; CHECK: andi r22, 76<br>
> +; CHECK: andi r23, 73<br>
> +; CHECK: andi r24, 31<br>
> +; CHECK: andi r25, 242<br>
> +    %result = and i64 %a, 17446744073709551613<br>
> +    ret i64 %result<br>
> +}<br>
> +<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/at<wbr>omics/fence.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/atomics/fence.ll?rev=<wbr>287162&view=au<br>
> to<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/at<wbr>omics/fence.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/at<wbr>omics/fence.ll Wed Nov 16 15:58:04<br>
> 2016<br>
> @@ -0,0 +1,13 @@<br>
> +; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s<br>
> +<br>
> +; Checks that atomic fences are simply removed from IR.<br>
> +; AVR is always singlethreaded so fences do nothing.<br>
> +<br>
> +; CHECK_LABEL: atomic_fence8<br>
> +; CHECK:      ; BB#0:<br>
> +; CHECK-NEXT:   ret<br>
> +define void @atomic_fence8() {<br>
> +  fence acquire<br>
> +  ret void<br>
> +}<br>
> +<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/at<wbr>omics/load16.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/atomics/load16.ll?rev=<wbr>287162&view=a<br>
> uto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/at<wbr>omics/load16.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/at<wbr>omics/load16.ll Wed Nov 16 15:58:04<br>
> 2016<br>
> @@ -0,0 +1,137 @@<br>
> +; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s<br>
> +<br>
> +; CHECK-LABEL: atomic_load16<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: ld [[RR:r[0-9]+]], [[RD:(X|Y|Z)]]<br>
> +; CHECK-NEXT: ldd [[RR:r[0-9]+]], [[RD:(X|Y|Z)]]+<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define i16 @atomic_load16(i16* %foo) {<br>
> +  %val = load atomic i16, i16* %foo unordered, align 2<br>
> +  ret i16 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_swap16<br>
> +; CHECK: call __sync_lock_test_and_set_2<br>
> +define i16 @atomic_load_swap16(i16* %foo) {<br>
> +  %val = atomicrmw xchg i16* %foo, i16 13 seq_cst<br>
> +  ret i16 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_cmp_swap16<br>
> +; CHECK: call __sync_val_compare_and_swap_2<br>
> +define i16 @atomic_load_cmp_swap16(i16* %foo) {<br>
> +  %val = cmpxchg i16* %foo, i16 5, i16 10 acq_rel monotonic<br>
> +  %value_loaded = extractvalue { i16, i1 } %val, 0<br>
> +  ret i16 %value_loaded<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_add16<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]<br>
> +; CHECK-NEXT: ldd [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]+<br>
> +; CHECK-NEXT: add [[RR1]], [[TMP:r[0-9]+]]<br>
> +; CHECK-NEXT: adc [[RR2]], [[TMP:r[0-9]+]]<br>
> +; CHECK-NEXT: st [[RD1]], [[RR1]]<br>
> +; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define i16 @atomic_load_add16(i16* %foo) {<br>
> +  %val = atomicrmw add i16* %foo, i16 13 seq_cst<br>
> +  ret i16 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_sub16<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]<br>
> +; CHECK-NEXT: ldd [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]+<br>
> +; CHECK-NEXT: sub [[RR1]], [[TMP:r[0-9]+]]<br>
> +; CHECK-NEXT: sbc [[RR2]], [[TMP:r[0-9]+]]<br>
> +; CHECK-NEXT: st [[RD1]], [[RR1]]<br>
> +; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define i16 @atomic_load_sub16(i16* %foo) {<br>
> +  %val = atomicrmw sub i16* %foo, i16 13 seq_cst<br>
> +  ret i16 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_and16<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]<br>
> +; CHECK-NEXT: ldd [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]+<br>
> +; CHECK-NEXT: and [[RR1]], [[TMP:r[0-9]+]]<br>
> +; CHECK-NEXT: and [[RR2]], [[TMP:r[0-9]+]]<br>
> +; CHECK-NEXT: st [[RD1]], [[RR1]]<br>
> +; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define i16 @atomic_load_and16(i16* %foo) {<br>
> +  %val = atomicrmw and i16* %foo, i16 13 seq_cst<br>
> +  ret i16 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_or16<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]<br>
> +; CHECK-NEXT: ldd [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]+<br>
> +; CHECK-NEXT: or [[RR1]], [[TMP:r[0-9]+]]<br>
> +; CHECK-NEXT: or [[RR2]], [[TMP:r[0-9]+]]<br>
> +; CHECK-NEXT: st [[RD1]], [[RR1]]<br>
> +; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define i16 @atomic_load_or16(i16* %foo) {<br>
> +  %val = atomicrmw or i16* %foo, i16 13 seq_cst<br>
> +  ret i16 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_xor16<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]<br>
> +; CHECK-NEXT: ldd [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]+<br>
> +; CHECK-NEXT: eor [[RR1]], [[TMP:r[0-9]+]]<br>
> +; CHECK-NEXT: eor [[RR2]], [[TMP:r[0-9]+]]<br>
> +; CHECK-NEXT: st [[RD1]], [[RR1]]<br>
> +; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define i16 @atomic_load_xor16(i16* %foo) {<br>
> +  %val = atomicrmw xor i16* %foo, i16 13 seq_cst<br>
> +  ret i16 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_nand16<br>
> +; CHECK: call __sync_fetch_and_nand_2<br>
> +define i16 @atomic_load_nand16(i16* %foo) {<br>
> +  %val = atomicrmw nand i16* %foo, i16 13 seq_cst<br>
> +  ret i16 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_max16<br>
> +; CHECK: call __sync_fetch_and_max_2<br>
> +define i16 @atomic_load_max16(i16* %foo) {<br>
> +  %val = atomicrmw max i16* %foo, i16 13 seq_cst<br>
> +  ret i16 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_min16<br>
> +; CHECK: call __sync_fetch_and_min_2<br>
> +define i16 @atomic_load_min16(i16* %foo) {<br>
> +  %val = atomicrmw min i16* %foo, i16 13 seq_cst<br>
> +  ret i16 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_umax16<br>
> +; CHECK: call __sync_fetch_and_umax_2<br>
> +define i16 @atomic_load_umax16(i16* %foo) {<br>
> +  %val = atomicrmw umax i16* %foo, i16 13 seq_cst<br>
> +  ret i16 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_umin16<br>
> +; CHECK: call __sync_fetch_and_umin_2<br>
> +define i16 @atomic_load_umin16(i16* %foo) {<br>
> +  %val = atomicrmw umin i16* %foo, i16 13 seq_cst<br>
> +  ret i16 %val<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/at<wbr>omics/load8.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/atomics/load8.ll?rev=<wbr>287162&view=au<br>
> to<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/at<wbr>omics/load8.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/at<wbr>omics/load8.ll Wed Nov 16 15:58:04<br>
> 2016<br>
> @@ -0,0 +1,124 @@<br>
> +; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s<br>
> +<br>
> +; Tests atomic operations on AVR<br>
> +<br>
> +; CHECK-LABEL: atomic_load8<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: ld [[RR:r[0-9]+]], [[RD:(X|Y|Z)]]<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define i8 @atomic_load8(i8* %foo) {<br>
> +  %val = load atomic i8, i8* %foo unordered, align 1<br>
> +  ret i8 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_swap8<br>
> +; CHECK: call __sync_lock_test_and_set_1<br>
> +define i8 @atomic_load_swap8(i8* %foo) {<br>
> +  %val = atomicrmw xchg i8* %foo, i8 13 seq_cst<br>
> +  ret i8 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_cmp_swap8<br>
> +; CHECK: call __sync_val_compare_and_swap_1<br>
> +define i8 @atomic_load_cmp_swap8(i8* %foo) {<br>
> +  %val = cmpxchg i8* %foo, i8 5, i8 10 acq_rel monotonic<br>
> +  %value_loaded = extractvalue { i8, i1 } %val, 0<br>
> +  ret i8 %value_loaded<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_add8<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: ld [[RD:r[0-9]+]], [[RR:(X|Y|Z)]]<br>
> +; CHECK-NEXT: add [[RD]], [[RR1:r[0-9]+]]<br>
> +; CHECK-NEXT: st [[RR]], [[RD]]<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define i8 @atomic_load_add8(i8* %foo) {<br>
> +  %val = atomicrmw add i8* %foo, i8 13 seq_cst<br>
> +  ret i8 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_sub8<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: ld [[RD:r[0-9]+]], [[RR:(X|Y|Z)]]<br>
> +; CHECK-NEXT: sub [[RD]], [[RR1:r[0-9]+]]<br>
> +; CHECK-NEXT: st [[RR]], [[RD]]<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define i8 @atomic_load_sub8(i8* %foo) {<br>
> +  %val = atomicrmw sub i8* %foo, i8 13 seq_cst<br>
> +  ret i8 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_and8<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: ld [[RD:r[0-9]+]], [[RR:(X|Y|Z)]]<br>
> +; CHECK-NEXT: and [[RD]], [[RR1:r[0-9]+]]<br>
> +; CHECK-NEXT: st [[RR]], [[RD]]<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define i8 @atomic_load_and8(i8* %foo) {<br>
> +  %val = atomicrmw and i8* %foo, i8 13 seq_cst<br>
> +  ret i8 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_or8<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: ld [[RD:r[0-9]+]], [[RR:(X|Y|Z)]]<br>
> +; CHECK-NEXT: or [[RD]], [[RR1:r[0-9]+]]<br>
> +; CHECK-NEXT: st [[RR]], [[RD]]<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define i8 @atomic_load_or8(i8* %foo) {<br>
> +  %val = atomicrmw or i8* %foo, i8 13 seq_cst<br>
> +  ret i8 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_xor8<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: ld [[RD:r[0-9]+]], [[RR:(X|Y|Z)]]<br>
> +; CHECK-NEXT: eor [[RD]], [[RR1:r[0-9]+]]<br>
> +; CHECK-NEXT: st [[RR]], [[RD]]<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define i8 @atomic_load_xor8(i8* %foo) {<br>
> +  %val = atomicrmw xor i8* %foo, i8 13 seq_cst<br>
> +  ret i8 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_nand8<br>
> +; CHECK: call __sync_fetch_and_nand_1<br>
> +define i8 @atomic_load_nand8(i8* %foo) {<br>
> +  %val = atomicrmw nand i8* %foo, i8 13 seq_cst<br>
> +  ret i8 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_max8<br>
> +; CHECK: call __sync_fetch_and_max_1<br>
> +define i8 @atomic_load_max8(i8* %foo) {<br>
> +  %val = atomicrmw max i8* %foo, i8 13 seq_cst<br>
> +  ret i8 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_min8<br>
> +; CHECK: call __sync_fetch_and_min_1<br>
> +define i8 @atomic_load_min8(i8* %foo) {<br>
> +  %val = atomicrmw min i8* %foo, i8 13 seq_cst<br>
> +  ret i8 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_umax8<br>
> +; CHECK: call __sync_fetch_and_umax_1<br>
> +define i8 @atomic_load_umax8(i8* %foo) {<br>
> +  %val = atomicrmw umax i8* %foo, i8 13 seq_cst<br>
> +  ret i8 %val<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_load_umin8<br>
> +; CHECK: call __sync_fetch_and_umin_1<br>
> +define i8 @atomic_load_umin8(i8* %foo) {<br>
> +  %val = atomicrmw umin i8* %foo, i8 13 seq_cst<br>
> +  ret i8 %val<br>
> +}<br>
> +<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/at<wbr>omics/store.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/atomics/store.ll?rev=<wbr>287162&view=au<br>
> to<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/at<wbr>omics/store.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/at<wbr>omics/store.ll Wed Nov 16 15:58:04<br>
> 2016<br>
> @@ -0,0 +1,37 @@<br>
> +; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s<br>
> +<br>
> +; CHECK-LABEL: atomic_store8<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: st [[RD:(X|Y|Z)]], [[RR:r[0-9]+]]<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define void @atomic_store8(i8* %foo) {<br>
> +  store atomic i8 1, i8* %foo unordered, align 1<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_store16<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: st [[RD:(X|Y|Z)]], [[RR:r[0-9]+]]<br>
> +; CHECK-NEXT: std [[RD]]+1, [[RR:r[0-9]+]]<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define void @atomic_store16(i16* %foo) {<br>
> +  store atomic i16 1, i16* %foo unordered, align 2<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_store32<br>
> +; CHECK: call __sync_lock_test_and_set_4<br>
> +define void @atomic_store32(i32* %foo) {<br>
> +  store atomic i32 1, i32* %foo unordered, align 4<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: atomic_store64<br>
> +; CHECK: call __sync_lock_test_and_set_8<br>
> +define void @atomic_store64(i64* %foo) {<br>
> +  store atomic i64 1, i64* %foo unordered, align 8<br>
> +  ret void<br>
> +}<br>
> +<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/at<wbr>omics/store16.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/atomics/store16.ll?rev=<wbr>287162&view=<br>
> auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/at<wbr>omics/store16.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/at<wbr>omics/store16.ll Wed Nov 16 15:58:04<br>
> 2016<br>
> @@ -0,0 +1,25 @@<br>
> +; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s<br>
> +<br>
> +; CHECK-LABEL: atomic_store16<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: st [[RD:(X|Y|Z)]], [[RR:r[0-9]+]]<br>
> +; CHECK-NEXT: std [[RD:(X|Y|Z)]]+1, [[RR:r[0-9]+]]<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define void @atomic_store16(i16* %foo) {<br>
> +  store atomic i16 1, i16* %foo unordered, align 2<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: monotonic<br>
> +; CHECK:      in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: st Z, r24<br>
> +; CHECK-NEXT: std Z+1, r25<br>
> +; CHECK-NEXT: out 63, r0<br>
> +define void @monotonic(i16) {<br>
> +entry-block:<br>
> +  store atomic i16 %0, i16* undef monotonic, align 2<br>
> +  ret void<br>
> +}<br>
> +<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/br<wbr>ind.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/brind.ll?rev=287162&<wbr>view=auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/br<wbr>ind.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/br<wbr>ind.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,20 @@<br>
> +; RUN: llc -mattr=sram,eijmpcall < %s -march=avr | FileCheck %s<br>
> +<br>
> +@brind.k = private unnamed_addr constant [2 x i8*] [i8*<br>
> blockaddress(@brind, %return), i8* blockaddress(@brind, %b)], align 1<br>
> +<br>
> +define i8 @brind(i8 %p) {<br>
> +; CHECK-LABEL: brind:<br>
> +; CHECK: ld r30<br>
> +; CHECK: ldd r31<br>
> +; CHECK: ijmp<br>
> +entry:<br>
> +  %idxprom = sext i8 %p to i16<br>
> +  %arrayidx = getelementptr inbounds [2 x i8*], [2 x i8*]* @brind.k,<br>
> i16 0, i16 %idxprom<br>
> +  %s = load i8*, i8** %arrayidx<br>
> +  indirectbr i8* %s, [label %return, label %b]<br>
> +b:<br>
> +  br label %return<br>
> +return:<br>
> +  %retval.0 = phi i8 [ 4, %b ], [ 2, %entry ]<br>
> +  ret i8 %retval.0<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/ca<wbr>ll.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/call.ll?rev=287162&view=<wbr>auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/ca<wbr>ll.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/ca<wbr>ll.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,211 @@<br>
> +; RUN: llc < %s -march=avr -mattr=avr6 | FileCheck %s<br>
> +<br>
> +; TODO: test returning byval structs<br>
> +<br>
> +declare i8 @foo8_1(i8)<br>
> +declare i8 @foo8_2(i8, i8, i8)<br>
> +declare i8 @foo8_3(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8)<br>
> +<br>
> +declare i16 @foo16_1(i16, i16)<br>
> +declare i16 @foo16_2(i16, i16, i16, i16, i16, i16, i16, i16, i16, i16,<br>
> i16)<br>
> +<br>
> +declare i32 @foo32_1(i32, i32)<br>
> +declare i32 @foo32_2(i32, i32, i32, i32, i32)<br>
> +<br>
> +declare i64 @foo64_1(i64)<br>
> +declare i64 @foo64_2(i64, i64, i64)<br>
> +<br>
> +define i8 @calli8_reg() {<br>
> +; CHECK-LABEL: calli8_reg:<br>
> +; CHECK: ldi r24, 12<br>
> +; CHECK: call foo8_1<br>
> +; CHECK: ldi r24, 12<br>
> +; CHECK: ldi r22, 13<br>
> +; CHECK: ldi r20, 14<br>
> +; CHECK: call foo8_2<br>
> +    %result1 = call i8 @foo8_1(i8 12)<br>
> +    %result2 = call i8 @foo8_2(i8 12, i8 13, i8 14)<br>
> +    ret i8 %result2<br>
> +}<br>
> +<br>
> +define i8 @calli8_stack() {<br>
> +; CHECK-LABEL: calli8_stack:<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 11<br>
> +; CHECK: push [[REG1]]<br>
> +; CHECK: ldi [[REG1]], 10<br>
> +; CHECK: push [[REG1]]<br>
> +; CHECK: call foo8_3<br>
> +    %result1 = call i8 @foo8_3(i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8<br>
> 7, i8 8, i8 9, i8 10, i8 11)<br>
> +    ret i8 %result1<br>
> +}<br>
> +<br>
> +define i16 @calli16_reg() {<br>
> +; CHECK-LABEL: calli16_reg:<br>
> +; CHECK: ldi r24, 1<br>
> +; CHECK: ldi r25, 2<br>
> +; CHECK: ldi r22, 2<br>
> +; CHECK: ldi r23, 2<br>
> +; CHECK: call foo16_1<br>
> +    %result1 = call i16 @foo16_1(i16 513, i16 514)<br>
> +    ret i16 %result1<br>
> +}<br>
> +<br>
> +define i16 @calli16_stack() {<br>
> +; CHECK-LABEL: calli16_stack:<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 10<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 2<br>
> +; CHECK: push [[REG2]]<br>
> +; CHECK: push [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 9<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 2<br>
> +; CHECK: push [[REG2]]<br>
> +; CHECK: push [[REG1]]<br>
> +; CHECK: call foo16_2<br>
> +    %result1 = call i16 @foo16_2(i16 512, i16 513, i16 514, i16 515,<br>
> i16 516, i16 517, i16 518, i16 519, i16 520, i16 521, i16 522)<br>
> +    ret i16 %result1<br>
> +}<br>
> +<br>
> +define i32 @calli32_reg() {<br>
> +; CHECK-LABEL: calli32_reg:<br>
> +; CHECK: ldi r22, 64<br>
> +; CHECK: ldi r23, 66<br>
> +; CHECK: ldi r24, 15<br>
> +; CHECK: ldi r25, 2<br>
> +; CHECK: ldi r18, 128<br>
> +; CHECK: ldi r19, 132<br>
> +; CHECK: ldi r20, 30<br>
> +; CHECK: ldi r21, 2<br>
> +; CHECK: call foo32_1<br>
> +    %result1 = call i32 @foo32_1(i32 34554432, i32 35554432)<br>
> +    ret i32 %result1<br>
> +}<br>
> +<br>
> +define i32 @calli32_stack() {<br>
> +; CHECK-LABEL: calli32_stack:<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 15<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 2<br>
> +; CHECK: push [[REG2]]<br>
> +; CHECK: push [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 64<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 66<br>
> +; CHECK: push [[REG2]]<br>
> +; CHECK: push [[REG1]]<br>
> +; CHECK: call foo32_2<br>
> +    %result1 = call i32 @foo32_2(i32 1, i32 2, i32 3, i32 4, i32<br>
> 34554432)<br>
> +    ret i32 %result1<br>
> +}<br>
> +<br>
> +define i64 @calli64_reg() {<br>
> +; CHECK-LABEL: calli64_reg:<br>
> +; CHECK: ldi r18, 255<br>
> +; CHECK: ldi r19, 255<br>
> +; CHECK: ldi r20, 155<br>
> +; CHECK: ldi r21, 88<br>
> +; CHECK: ldi r22, 76<br>
> +; CHECK: ldi r23, 73<br>
> +; CHECK: ldi r24, 31<br>
> +; CHECK: ldi r25, 242<br>
> +; CHECK: call foo64_1<br>
> +    %result1 = call i64 @foo64_1(i64 17446744073709551615)<br>
> +    ret i64 %result1<br>
> +}<br>
> +<br>
> +define i64 @calli64_stack() {<br>
> +; CHECK-LABEL: calli64_stack:<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 31<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 242<br>
> +; CHECK: push [[REG2]]<br>
> +; CHECK: push [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 76<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 73<br>
> +; CHECK: push [[REG2]]<br>
> +; CHECK: push [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 155<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 88<br>
> +; CHECK: push [[REG2]]<br>
> +; CHECK: push [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 255<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 255<br>
> +; CHECK: push [[REG2]]<br>
> +; CHECK: push [[REG1]]<br>
> +; CHECK: call foo64_2<br>
> +    %result1 = call i64 @foo64_2(i64 1, i64 2, i64<br>
> 17446744073709551615)<br>
> +    ret i64 %result1<br>
> +}<br>
> +<br>
> +; Test passing arguments through the stack when the call frame is<br>
> allocated<br>
> +; in the prologue.<br>
> +declare void @foo64_3(i64, i64, i64, i8, i16*)<br>
> +<br>
> +define void @testcallprologue() {<br>
> +; CHECK-LABEL: testcallprologue:<br>
> +; CHECK: push r28<br>
> +; CHECK: push r29<br>
> +; CHECK: sbiw r28, 28<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 88<br>
> +; CHECK: std Y+9, [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 11<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 10<br>
> +; CHECK: std Y+7, [[REG1]]<br>
> +; CHECK: std Y+8, [[REG2]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 13<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 12<br>
> +; CHECK: std Y+5, [[REG1]]<br>
> +; CHECK: std Y+6, [[REG2]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 15<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 14<br>
> +; CHECK: std Y+3, [[REG1]]<br>
> +; CHECK: std Y+4, [[REG2]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 8<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 9<br>
> +; CHECK: std Y+1, [[REG1]]<br>
> +; CHECK: std Y+2, [[REG2]]<br>
> +; CHECK: pop r29<br>
> +; CHECK: pop r28<br>
> +  %p = alloca [8 x i16]<br>
> +  %arraydecay = getelementptr inbounds [8 x i16], [8 x i16]* %p, i16<br>
> 0, i16 0<br>
> +  call void @foo64_3(i64 723685415333071112, i64 723685415333071112,<br>
> i64 723685415333071112, i8 88, i16* %arraydecay)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define i32 @icall(i32 (i32)* %foo) {<br>
> +; CHECK-LABEL: icall:<br>
> +; CHECK: movw [[REG:r[0-9]+]], r24<br>
> +; CHECK: ldi r22, 147<br>
> +; CHECK: ldi r23, 248<br>
> +; CHECK: ldi r24, 214<br>
> +; CHECK: ldi r25, 198<br>
> +; CHECK: movw r30, [[REG]]<br>
> +; CHECK: icall<br>
> +; CHECK: subi r22, 251<br>
> +; CHECK: sbci r23, 255<br>
> +; CHECK: sbci r24, 255<br>
> +; CHECK: sbci r25, 255<br>
> +  %1 = call i32 %foo(i32 3335977107)<br>
> +  %2 = add nsw i32 %1, 5<br>
> +  ret i32 %2<br>
> +}<br>
> +<br>
> +; Calling external functions (like __divsf3) require extra processing<br>
> for<br>
> +; arguments and return values in the LowerCall function.<br>
> +declare i32 @foofloat(float)<br>
> +<br>
> +define i32 @externcall(float %a, float %b) {<br>
> +; CHECK-LABEL: externcall:<br>
> +; CHECK: movw [[REG1:(r[0-9]+|[XYZ])]], r24<br>
> +; CHECK: movw [[REG2:(r[0-9]+|[XYZ])]], r22<br>
> +; CHECK: movw r22, r18<br>
> +; CHECK: movw r24, r20<br>
> +; CHECK: movw r18, [[REG2]]<br>
> +; CHECK: movw r20, [[REG1]]<br>
> +; CHECK: call __divsf3<br>
> +; CHECK: call foofloat<br>
> +; CHECK: subi r22, 251<br>
> +; CHECK: sbci r23, 255<br>
> +; CHECK: sbci r24, 255<br>
> +; CHECK: sbci r25, 255<br>
> +  %1 = fdiv float %b, %a<br>
> +  %2 = call i32 @foofloat(float %1)<br>
> +  %3 = add nsw i32 %2, 5<br>
> +  ret i32 %3<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/cm<wbr>p.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/cmp.ll?rev=287162&view=<wbr>auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/cm<wbr>p.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/cm<wbr>p.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,148 @@<br>
> +; RUN: llc < %s -march=avr | FileCheck %s<br>
> +<br>
> +declare void @f1(i8)<br>
> +declare void @f2(i8)<br>
> +define void @cmp8(i8 %a, i8 %b) {<br>
> +; CHECK-LABEL: cmp8:<br>
> +; CHECK: cp<br>
> +; CHECK-NOT: cpc<br>
> +  %cmp = icmp eq i8 %a, %b<br>
> +  br i1 %cmp, label %if.then, label %if.else<br>
> +if.then:<br>
> +  tail call void @f1(i8 %a)<br>
> +  br label %if.end<br>
> +if.else:<br>
> +  tail call void @f2(i8 %b)<br>
> +  br label %if.end<br>
> +if.end:<br>
> +  ret void<br>
> +}<br>
> +<br>
> +declare void @f3(i16)<br>
> +declare void @f4(i16)<br>
> +define void @cmp16(i16 %a, i16 %b) {<br>
> +; CHECK-LABEL: cmp16:<br>
> +; CHECK: cp<br>
> +; CHECK-NEXT: cpc<br>
> +  %cmp = icmp eq i16 %a, %b<br>
> +  br i1 %cmp, label %if.then, label %if.else<br>
> +if.then:<br>
> +  tail call void @f3(i16 %a)<br>
> +  br label %if.end<br>
> +if.else:<br>
> +  tail call void @f4(i16 %b)<br>
> +  br label %if.end<br>
> +if.end:<br>
> +  ret void<br>
> +}<br>
> +<br>
> +declare void @f5(i32)<br>
> +declare void @f6(i32)<br>
> +define void @cmp32(i32 %a, i32 %b) {<br>
> +; CHECK-LABEL: cmp32:<br>
> +; CHECK: cp<br>
> +; CHECK-NEXT: cpc<br>
> +; CHECK-NEXT: cpc<br>
> +; CHECK-NEXT: cpc<br>
> +  %cmp = icmp eq i32 %a, %b<br>
> +  br i1 %cmp, label %if.then, label %if.else<br>
> +if.then:<br>
> +  tail call void @f5(i32 %a)<br>
> +  br label %if.end<br>
> +if.else:<br>
> +  tail call void @f6(i32 %b)<br>
> +  br label %if.end<br>
> +if.end:<br>
> +  ret void<br>
> +}<br>
> +<br>
> +declare void @f7(i64)<br>
> +declare void @f8(i64)<br>
> +define void @cmp64(i64 %a, i64 %b) {<br>
> +; CHECK-LABEL: cmp64:<br>
> +; CHECK: cp<br>
> +; CHECK-NEXT: cpc<br>
> +; CHECK-NEXT: cpc<br>
> +; CHECK-NEXT: cpc<br>
> +; CHECK-NEXT: cpc<br>
> +; CHECK-NEXT: cpc<br>
> +; CHECK-NEXT: cpc<br>
> +; CHECK-NEXT: cpc<br>
> +  %cmp = icmp eq i64 %a, %b<br>
> +  br i1 %cmp, label %if.then, label %if.else<br>
> +if.then:<br>
> +  tail call void @f7(i64 %a)<br>
> +  br label %if.end<br>
> +if.else:<br>
> +  tail call void @f8(i64 %b)<br>
> +  br label %if.end<br>
> +if.end:<br>
> +  ret void<br>
> +}<br>
> +<br>
> +declare void @f9()<br>
> +declare void @f10()<br>
> +<br>
> +define void @tst8(i8 %a) {<br>
> +; CHECK-LABEL: tst8:<br>
> +; CHECK: tst r24<br>
> +; CHECK-NEXT: brmi<br>
> +  %cmp = icmp sgt i8 %a, -1<br>
> +  br i1 %cmp, label %if.then, label %if.else<br>
> +if.then:<br>
> +  tail call void @f9()<br>
> +  br label %if.end<br>
> +if.else:<br>
> +  tail call void @f10()<br>
> +  br label %if.end<br>
> +if.end:<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @tst16(i16 %a) {<br>
> +; CHECK-LABEL: tst16:<br>
> +; CHECK: tst r25<br>
> +; CHECK-NEXT: brmi<br>
> +  %cmp = icmp sgt i16 %a, -1<br>
> +  br i1 %cmp, label %if.then, label %if.else<br>
> +if.then:<br>
> +  tail call void @f9()<br>
> +  br label %if.end<br>
> +if.else:<br>
> +  tail call void @f10()<br>
> +  br label %if.end<br>
> +if.end:<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @tst32(i32 %a) {<br>
> +; CHECK-LABEL: tst32:<br>
> +; CHECK: tst r25<br>
> +; CHECK-NEXT: brmi<br>
> +  %cmp = icmp sgt i32 %a, -1<br>
> +  br i1 %cmp, label %if.then, label %if.else<br>
> +if.then:<br>
> +  tail call void @f9()<br>
> +  br label %if.end<br>
> +if.else:<br>
> +  tail call void @f10()<br>
> +  br label %if.end<br>
> +if.end:<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @tst64(i64 %a) {<br>
> +; CHECK-LABEL: tst64:<br>
> +; CHECK: tst r25<br>
> +; CHECK-NEXT: brmi<br>
> +  %cmp = icmp sgt i64 %a, -1<br>
> +  br i1 %cmp, label %if.then, label %if.else<br>
> +if.then:<br>
> +  tail call void @f9()<br>
> +  br label %if.end<br>
> +if.else:<br>
> +  tail call void @f10()<br>
> +  br label %if.end<br>
> +if.end:<br>
> +  ret void<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/co<wbr>m.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/com.ll?rev=287162&view=<wbr>auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/co<wbr>m.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/co<wbr>m.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,40 @@<br>
> +; RUN: llc < %s -march=avr | FileCheck %s<br>
> +<br>
> +define i8 @com8(i8 %x) {<br>
> +; CHECK-LABEL: com8:<br>
> +; CHECK: com r24<br>
> +  %neg = xor i8 %x, -1<br>
> +  ret i8 %neg<br>
> +}<br>
> +<br>
> +define i16 @com16(i16 %x) {<br>
> +; CHECK-LABEL: com16:<br>
> +; CHECK: com r24<br>
> +; CHECK: com r25<br>
> +  %neg = xor i16 %x, -1<br>
> +  ret i16 %neg<br>
> +}<br>
> +<br>
> +define i32 @com32(i32 %x) {<br>
> +; CHECK-LABEL: com32:<br>
> +; CHECK: com r22<br>
> +; CHECK: com r23<br>
> +; CHECK: com r24<br>
> +; CHECK: com r25<br>
> +  %neg = xor i32 %x, -1<br>
> +  ret i32 %neg<br>
> +}<br>
> +<br>
> +define i64 @com64(i64 %x) {<br>
> +; CHECK-LABEL: com64:<br>
> +; CHECK: com r18<br>
> +; CHECK: com r19<br>
> +; CHECK: com r20<br>
> +; CHECK: com r21<br>
> +; CHECK: com r22<br>
> +; CHECK: com r23<br>
> +; CHECK: com r24<br>
> +; CHECK: com r25<br>
> +  %neg = xor i64 %x, -1<br>
> +  ret i64 %neg<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/di<wbr>rectmem.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/directmem.ll?rev=287162&<wbr>view=auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/di<wbr>rectmem.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/di<wbr>rectmem.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,345 @@<br>
> +; RUN: llc -mattr=sram,addsubiw < %s -march=avr | FileCheck %s<br>
> +<br>
> +@char = common global i8 0<br>
> +@char.array = common global [3 x i8] zeroinitializer<br>
> +@char.static = internal global i8 0<br>
> +<br>
> +@int = common global i16 0<br>
> +@int.array = common global [3 x i16] zeroinitializer<br>
> +@int.static = internal global i16 0<br>
> +<br>
> +@long = common global i32 0<br>
> +@long.array = common global [3 x i32] zeroinitializer<br>
> +@long.static = internal global i32 0<br>
> +<br>
> +@longlong = common global i64 0<br>
> +@longlong.array = common global [3 x i64] zeroinitializer<br>
> +@longlong.static = internal global i64 0<br>
> +<br>
> +define void @global8_store() {<br>
> +; CHECK-LABEL: global8_store:<br>
> +; CHECK: ldi [[REG:r[0-9]+]], 6<br>
> +; CHECK: sts char, [[REG]]<br>
> +  store i8 6, i8* @char<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define i8 @global8_load() {<br>
> +; CHECK-LABEL: global8_load:<br>
> +; CHECK: lds r24, char<br>
> +  %result = load i8, i8* @char<br>
> +  ret i8 %result<br>
> +}<br>
> +<br>
> +define void @array8_store() {<br>
> +; CHECK-LABEL: array8_store:<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 1<br>
> +; CHECK: sts char.array, [[REG1]]<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 2<br>
> +; CHECK: sts char.array+1, [[REG2]]<br>
> +; CHECK: ldi [[REG:r[0-9]+]], 3<br>
> +; CHECK: sts char.array+2, [[REG]]<br>
> +  store i8 1, i8* getelementptr inbounds ([3 x i8], [3 x i8]*<br>
> @char.array, i32 0, i64 0)<br>
> +  store i8 2, i8* getelementptr inbounds ([3 x i8], [3 x i8]*<br>
> @char.array, i32 0, i64 1)<br>
> +  store i8 3, i8* getelementptr inbounds ([3 x i8], [3 x i8]*<br>
> @char.array, i32 0, i64 2)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define i8 @array8_load() {<br>
> +; CHECK-LABEL: array8_load:<br>
> +; CHECK: lds r24, char.array+2<br>
> +  %result = load i8, i8* getelementptr inbounds ([3 x i8], [3 x i8]*<br>
> @char.array, i32 0, i64 2)<br>
> +  ret i8 %result<br>
> +}<br>
> +<br>
> +define i8 @static8_inc() {<br>
> +; CHECK-LABEL: static8_inc:<br>
> +; CHECK: lds r24, char.static<br>
> +; CHECK: inc r24<br>
> +; CHECK: sts char.static, r24<br>
> +  %1 = load i8, i8* @char.static<br>
> +  %inc = add nsw i8 %1, 1<br>
> +  store i8 %inc, i8* @char.static<br>
> +  ret i8 %inc<br>
> +}<br>
> +<br>
> +define void @global16_store() {<br>
> +; CHECK-LABEL: global16_store:<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 187<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 170<br>
> +; CHECK: sts int+1, [[REG2]]<br>
> +; CHECK: sts int, [[REG1]]<br>
> +  store i16 43707, i16* @int<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define i16 @global16_load() {<br>
> +; CHECK-LABEL: global16_load:<br>
> +; CHECK: lds r24, int<br>
> +; CHECK: lds r25, int+1<br>
> +  %result = load i16, i16* @int<br>
> +  ret i16 %result<br>
> +}<br>
> +<br>
> +define void @array16_store() {<br>
> +; CHECK-LABEL: array16_store:<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 187<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 170<br>
> +; CHECK: sts int.array+1, [[REG2]]<br>
> +; CHECK: sts int.array, [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 204<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 170<br>
> +; CHECK: sts int.array+3, [[REG2]]<br>
> +; CHECK: sts int.array+2, [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 221<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 170<br>
> +; CHECK: sts int.array+5, [[REG2]]<br>
> +; CHECK: sts int.array+4, [[REG1]]<br>
> +  store i16 43707, i16* getelementptr inbounds ([3 x i16], [3 x i16]*<br>
> @int.array, i32 0, i64 0)<br>
> +  store i16 43724, i16* getelementptr inbounds ([3 x i16], [3 x i16]*<br>
> @int.array, i32 0, i64 1)<br>
> +  store i16 43741, i16* getelementptr inbounds ([3 x i16], [3 x i16]*<br>
> @int.array, i32 0, i64 2)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define i16 @array16_load() {<br>
> +; CHECK-LABEL: array16_load:<br>
> +; CHECK: lds r24, int.array+4<br>
> +; CHECK: lds r25, int.array+5<br>
> +  %result = load i16, i16* getelementptr inbounds ([3 x i16], [3 x<br>
> i16]* @int.array, i32 0, i64 2)<br>
> +  ret i16 %result<br>
> +}<br>
> +<br>
> +define i16 @static16_inc() {<br>
> +; CHECK-LABEL: static16_inc:<br>
> +; CHECK: lds r24, int.static<br>
> +; CHECK: lds r25, int.static+1<br>
> +; CHECK: adiw r24, 1<br>
> +; CHECK: sts int.static+1, r25<br>
> +; CHECK: sts int.static, r24<br>
> +  %1 = load i16, i16* @int.static<br>
> +  %inc = add nsw i16 %1, 1<br>
> +  store i16 %inc, i16* @int.static<br>
> +  ret i16 %inc<br>
> +}<br>
> +<br>
> +define void @global32_store() {<br>
> +; CHECK-LABEL: global32_store:<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 187<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 170<br>
> +; CHECK: sts long+3, [[REG2]]<br>
> +; CHECK: sts long+2, [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 221<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 204<br>
> +; CHECK: sts long+1, [[REG2]]<br>
> +; CHECK: sts long, [[REG1]]<br>
> +  store i32 2864434397, i32* @long<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define i32 @global32_load() {<br>
> +; CHECK-LABEL: global32_load:<br>
> +; CHECK: lds r22, long<br>
> +; CHECK: lds r23, long+1<br>
> +; CHECK: lds r24, long+2<br>
> +; CHECK: lds r25, long+3<br>
> +  %result = load i32, i32* @long<br>
> +  ret i32 %result<br>
> +}<br>
> +<br>
> +define void @array32_store() {<br>
> +; CHECK-LABEL: array32_store:<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 27<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 172<br>
> +; CHECK: sts long.array+3, [[REG2]]<br>
> +; CHECK: sts long.array+2, [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 68<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 13<br>
> +; CHECK: sts long.array+1, [[REG2]]<br>
> +; CHECK: sts long.array, [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 102<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 85<br>
> +; CHECK: sts long.array+7, [[REG2]]<br>
> +; CHECK: sts long.array+6, [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 136<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 119<br>
> +; CHECK: sts long.array+5, [[REG2]]<br>
> +; CHECK: sts long.array+4, [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 170<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 153<br>
> +; CHECK: sts long.array+11, [[REG2]]<br>
> +; CHECK: sts long.array+10, [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 204<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 187<br>
> +; CHECK: sts long.array+9, [[REG2]]<br>
> +; CHECK: sts long.array+8, [[REG1]]<br>
> +  store i32 2887454020, i32* getelementptr inbounds ([3 x i32], [3 x<br>
> i32]* @long.array, i32 0, i64 0)<br>
> +  store i32 1432778632, i32* getelementptr inbounds ([3 x i32], [3 x<br>
> i32]* @long.array, i32 0, i64 1)<br>
> +  store i32 2578103244, i32* getelementptr inbounds ([3 x i32], [3 x<br>
> i32]* @long.array, i32 0, i64 2)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define i32 @array32_load() {<br>
> +; CHECK-LABEL: array32_load:<br>
> +; CHECK: lds r22, long.array+8<br>
> +; CHECK: lds r23, long.array+9<br>
> +; CHECK: lds r24, long.array+10<br>
> +; CHECK: lds r25, long.array+11<br>
> +  %result = load i32, i32* getelementptr inbounds ([3 x i32], [3 x<br>
> i32]* @long.array, i32 0, i64 2)<br>
> +  ret i32 %result<br>
> +}<br>
> +<br>
> +define i32 @static32_inc() {<br>
> +; CHECK-LABEL: static32_inc:<br>
> +; CHECK: lds r22, long.static<br>
> +; CHECK: lds r23, long.static+1<br>
> +; CHECK: lds r24, long.static+2<br>
> +; CHECK: lds r25, long.static+3<br>
> +; CHECK: subi r22, 255<br>
> +; CHECK: sbci r23, 255<br>
> +; CHECK: sbci r24, 255<br>
> +; CHECK: sbci r25, 255<br>
> +; CHECK: sts long.static+3, r25<br>
> +; CHECK: sts long.static+2, r24<br>
> +; CHECK: sts long.static+1, r23<br>
> +; CHECK: sts long.static, r22<br>
> +  %1 = load i32, i32* @long.static<br>
> +  %inc = add nsw i32 %1, 1<br>
> +  store i32 %inc, i32* @long.static<br>
> +  ret i32 %inc<br>
> +}<br>
> +<br>
> +define void @global64_store() {<br>
> +; CHECK-LABEL: global64_store:<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 34<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 17<br>
> +; CHECK: sts longlong+7, [[REG2]]<br>
> +; CHECK: sts longlong+6, [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 68<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 51<br>
> +; CHECK: sts longlong+5, [[REG2]]<br>
> +; CHECK: sts longlong+4, [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 102<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 85<br>
> +; CHECK: sts longlong+3, [[REG2]]<br>
> +; CHECK: sts longlong+2, [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 136<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 119<br>
> +; CHECK: sts longlong+1, [[REG2]]<br>
> +; CHECK: sts longlong, [[REG1]]<br>
> +  store i64 1234605616436508552, i64* @longlong<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define i64 @global64_load() {<br>
> +; CHECK-LABEL: global64_load:<br>
> +; CHECK: lds r18, longlong<br>
> +; CHECK: lds r19, longlong+1<br>
> +; CHECK: lds r20, longlong+2<br>
> +; CHECK: lds r21, longlong+3<br>
> +; CHECK: lds r22, longlong+4<br>
> +; CHECK: lds r23, longlong+5<br>
> +; CHECK: lds r24, longlong+6<br>
> +; CHECK: lds r25, longlong+7<br>
> +  %result = load i64, i64* @longlong<br>
> +  ret i64 %result<br>
> +}<br>
> +<br>
> +define void @array64_store() {<br>
> +; CHECK-LABEL: array64_store:<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 34<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 17<br>
> +; CHECK: sts longlong.array+7, [[REG2]]<br>
> +; CHECK: sts longlong.array+6, [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 68<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 51<br>
> +; CHECK: sts longlong.array+5, [[REG2]]<br>
> +; CHECK: sts longlong.array+4, [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 102<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 85<br>
> +; CHECK: sts longlong.array+3, [[REG2]]<br>
> +; CHECK: sts longlong.array+2, [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 136<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 119<br>
> +; CHECK: sts longlong.array+1, [[REG2]]<br>
> +; CHECK: sts longlong.array, [[REG1]]<br>
> +  store i64 1234605616436508552, i64* getelementptr inbounds ([3 x<br>
> i64], [3 x i64]* @longlong.array, i64 0, i64 0)<br>
> +  store i64 81985529216486895, i64* getelementptr inbounds ([3 x i64],<br>
> [3 x i64]* @longlong.array, i64 0, i64 1)<br>
> +  store i64 1836475854449306472, i64* getelementptr inbounds ([3 x<br>
> i64], [3 x i64]* @longlong.array, i64 0, i64 2)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define i64 @array64_load() {<br>
> +; CHECK-LABEL: array64_load:<br>
> +; CHECK: lds r18, longlong.array+16<br>
> +; CHECK: lds r19, longlong.array+17<br>
> +; CHECK: lds r20, longlong.array+18<br>
> +; CHECK: lds r21, longlong.array+19<br>
> +; CHECK: lds r22, longlong.array+20<br>
> +; CHECK: lds r23, longlong.array+21<br>
> +; CHECK: lds r24, longlong.array+22<br>
> +; CHECK: lds r25, longlong.array+23<br>
> +  %result = load i64, i64* getelementptr inbounds ([3 x i64], [3 x<br>
> i64]* @longlong.array, i64 0, i64 2)<br>
> +  ret i64 %result<br>
> +}<br>
> +<br>
> +define i64 @static64_inc() {<br>
> +; CHECK-LABEL: static64_inc:<br>
> +; CHECK: lds r18, longlong.static<br>
> +; CHECK: lds r19, longlong.static+1<br>
> +; CHECK: lds r20, longlong.static+2<br>
> +; CHECK: lds r21, longlong.static+3<br>
> +; CHECK: lds r22, longlong.static+4<br>
> +; CHECK: lds r23, longlong.static+5<br>
> +; CHECK: lds r24, longlong.static+6<br>
> +; CHECK: lds r25, longlong.static+7<br>
> +; CHECK: subi r18, 255<br>
> +; CHECK: sbci r19, 255<br>
> +; CHECK: sbci r20, 255<br>
> +; CHECK: sbci r21, 255<br>
> +; CHECK: sbci r22, 255<br>
> +; CHECK: sbci r23, 255<br>
> +; CHECK: sbci r24, 255<br>
> +; CHECK: sbci r25, 255<br>
> +; CHECK: sts longlong.static+7, r25<br>
> +; CHECK: sts longlong.static+6, r24<br>
> +; CHECK: sts longlong.static+5, r23<br>
> +; CHECK: sts longlong.static+4, r22<br>
> +; CHECK: sts longlong.static+3, r21<br>
> +; CHECK: sts longlong.static+2, r20<br>
> +; CHECK: sts longlong.static+1, r19<br>
> +; CHECK: sts longlong.static, r18<br>
> +  %1 = load i64, i64* @longlong.static<br>
> +  %inc = add nsw i64 %1, 1<br>
> +  store i64 %inc, i64* @longlong.static<br>
> +  ret i64 %inc<br>
> +}<br>
> +<br>
> +define i8 @constantaddr_read8() {<br>
> +; CHECK-LABEL: constantaddr_read8:<br>
> +; CHECK: lds r24, 1234<br>
> +  %1 = load i8, i8* inttoptr (i16 1234 to i8*)<br>
> +  ret i8 %1<br>
> +}<br>
> +<br>
> +define i16 @constantaddr_read16() {<br>
> +; CHECK-LABEL: constantaddr_read16:<br>
> +; CHECK: lds r24, 1234<br>
> +; CHECK: lds r25, 1235<br>
> +  %1 = load i16, i16* inttoptr (i16 1234 to i16*)<br>
> +  ret i16 %1<br>
> +}<br>
> +<br>
> +define void @constantaddr_write8() {<br>
> +; CHECK-LABEL: constantaddr_write8:<br>
> +; CHECK: sts 1234<br>
> +  store i8 22, i8* inttoptr (i16 1234 to i8*)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @constantaddr_write16() {<br>
> +; CHECK-LABEL: constantaddr_write16:<br>
> +; CHECK: sts 1235<br>
> +; CHECK: sts 1234<br>
> +  store i16 2222, i16* inttoptr (i16 1234 to i16*)<br>
> +  ret void<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/dy<wbr>nalloca.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/dynalloca.ll?rev=287162&<wbr>view=auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/dy<wbr>nalloca.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/dy<wbr>nalloca.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,78 @@<br>
> +; RUN: llc < %s -march=avr | FileCheck %s<br>
> +<br>
> +declare void @foo(i16*, i16*, i8*)<br>
> +<br>
> +define void @test1(i16 %x) {<br>
> +; CHECK-LABEL: test1:<br>
> +; CHECK: out 61, r28<br>
> +; SP copy<br>
> +; CHECK-NEXT: in [[SPCOPY1:r[0-9]+]], 61<br>
> +; CHECK-NEXT: in [[SPCOPY2:r[0-9]+]], 62<br>
> +; allocate first dynalloca<br>
> +; CHECK: in {{.*}}, 61<br>
> +; CHECK: in {{.*}}, 62<br>
> +; CHECK: sub<br>
> +; CHECK: sbc<br>
> +; CHECK: in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: out 62, {{.*}}<br>
> +; CHECK-NEXT: out 63, r0<br>
> +; CHECK-NEXT: out 61, {{.*}}<br>
> +; Test writes<br>
> +; CHECK: std Z+12, {{.*}}<br>
> +; CHECK: std Z+13, {{.*}}<br>
> +; CHECK: std Z+7, {{.*}}<br>
> +; CHECK-NOT: std<br>
> +; Test SP restore<br>
> +; CHECK: in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: out 62, [[SPCOPY2]]<br>
> +; CHECK-NEXT: out 63, r0<br>
> +; CHECK-NEXT: out 61, [[SPCOPY1]]<br>
> +  %a = alloca [8 x i16]<br>
> +  %vla = alloca i16, i16 %x<br>
> +  %add = shl nsw i16 %x, 1<br>
> +  %vla1 = alloca i8, i16 %add<br>
> +  %arrayidx = getelementptr inbounds [8 x i16], [8 x i16]* %a, i16 0,<br>
> i16 2<br>
> +  store i16 3, i16* %arrayidx<br>
> +  %arrayidx2 = getelementptr inbounds i16, i16* %vla, i16 6<br>
> +  store i16 4, i16* %arrayidx2<br>
> +  %arrayidx3 = getelementptr inbounds i8, i8* %vla1, i16 7<br>
> +  store i8 44, i8* %arrayidx3<br>
> +  %arraydecay = getelementptr inbounds [8 x i16], [8 x i16]* %a, i16<br>
> 0, i16 0<br>
> +  call void @foo(i16* %arraydecay, i16* %vla, i8* %vla1)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +declare void @foo2(i16*, i64, i64, i64)<br>
> +<br>
> +; Test that arguments are passed through pushes into the call instead<br>
> of<br>
> +; allocating the call frame space in the prologue. Also test that SP<br>
> is restored<br>
> +; after the call frame is restored and not before.<br>
> +define void @dynalloca2(i16 %x) {<br>
> +; CHECK-LABEL: dynalloca2:<br>
> +; CHECK: in [[SPCOPY1:r[0-9]+]], 61<br>
> +; CHECK: in [[SPCOPY2:r[0-9]+]], 62<br>
> +; CHECK: push<br>
> +; CHECK-NOT: st<br>
> +; CHECK-NOT: std<br>
> +; CHECK: call<br>
> +; Call frame restore<br>
> +; CHECK-NEXT: in r30, 61<br>
> +; CHECK-NEXT: in r31, 62<br>
> +; CHECK-NEXT: adiw r30, 8<br>
> +; CHECK-NEXT: in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: out 62, r31<br>
> +; CHECK-NEXT: out 63, r0<br>
> +; CHECK-NEXT: out 61, r30<br>
> +; SP restore<br>
> +; CHECK: in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: out 62, r29<br>
> +; CHECK-NEXT: out 63, r0<br>
> +; CHECK-NEXT: out 61, r28<br>
> +  %vla = alloca i16, i16 %x<br>
> +  call void @foo2(i16* %vla, i64 0, i64 0, i64 0)<br>
> +  ret void<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/eo<wbr>r.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/eor.ll?rev=287162&view=<wbr>auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/eo<wbr>r.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/eo<wbr>r.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,92 @@<br>
> +; RUN: llc < %s -march=avr | FileCheck %s<br>
> +<br>
> +; Tests for the exclusive OR operation.<br>
> +<br>
> +define i8 @eor8_reg_reg(i8 %a, i8 %b) {<br>
> +; CHECK-LABEL: eor8_reg_reg:<br>
> +; CHECK: eor r24, r22<br>
> +    %result = xor i8 %a, %b<br>
> +    ret i8 %result<br>
> +}<br>
> +<br>
> +define i8 @eor8_reg_imm(i8 %a) {<br>
> +; CHECK-LABEL: eor8_reg_imm:<br>
> +; CHECK: ldi r25, 5<br>
> +; CHECK: eor r24, r25<br>
> +    %result = xor i8 %a, 5<br>
> +    ret i8 %result<br>
> +}<br>
> +<br>
> +define i16 @eor16_reg_reg(i16 %a, i16 %b) {<br>
> +; CHECK-LABEL: eor16_reg_reg:<br>
> +; CHECK: eor r24, r22<br>
> +; CHECK: eor r25, r23<br>
> +    %result = xor i16 %a, %b<br>
> +    ret i16 %result<br>
> +}<br>
> +<br>
> +define i16 @eor16_reg_imm(i16 %a) {<br>
> +; CHECK-LABEL: eor16_reg_imm:<br>
> +; CHECK: ldi r18, 210<br>
> +; CHECK: ldi r19, 4<br>
> +; CHECK: eor r24, r18<br>
> +; CHECK: eor r25, r19<br>
> +    %result = xor i16 %a, 1234<br>
> +    ret i16 %result<br>
> +}<br>
> +<br>
> +define i32 @eor32_reg_reg(i32 %a, i32 %b) {<br>
> +; CHECK-LABEL: eor32_reg_reg:<br>
> +; CHECK: eor r22, r18<br>
> +; CHECK: eor r23, r19<br>
> +; CHECK: eor r24, r20<br>
> +; CHECK: eor r25, r21<br>
> +    %result = xor i32 %a, %b<br>
> +    ret i32 %result<br>
> +}<br>
> +<br>
> +define i32 @eor32_reg_imm(i32 %a) {<br>
> +; CHECK-LABEL: eor32_reg_imm:<br>
> +; CHECK: ldi r18, 210<br>
> +; CHECK: ldi r19, 4<br>
> +; CHECK: eor r22, r18<br>
> +; CHECK: eor r23, r19<br>
> +    %result = xor i32 %a, 1234<br>
> +    ret i32 %result<br>
> +}<br>
> +<br>
> +define i64 @eor64_reg_reg(i64 %a, i64 %b) {<br>
> +; CHECK-LABEL: eor64_reg_reg:<br>
> +; CHECK: eor r18, r10<br>
> +; CHECK: eor r19, r11<br>
> +; CHECK: eor r20, r12<br>
> +; CHECK: eor r21, r13<br>
> +; CHECK: eor r22, r14<br>
> +; CHECK: eor r23, r15<br>
> +; CHECK: eor r24, r16<br>
> +; CHECK: eor r25, r17<br>
> +    %result = xor i64 %a, %b<br>
> +    ret i64 %result<br>
> +}<br>
> +<br>
> +define i64 @eor64_reg_imm(i64 %a) {<br>
> +; CHECK-LABEL: eor64_reg_imm:<br>
> +; CHECK: ldi r30, 253<br>
> +; CHECK: ldi r31, 255<br>
> +; CHECK: eor r18, r30<br>
> +; CHECK: eor r19, r31<br>
> +; CHECK: ldi r30, 155<br>
> +; CHECK: ldi r31, 88<br>
> +; CHECK: eor r20, r30<br>
> +; CHECK: eor r21, r31<br>
> +; CHECK: ldi r30, 76<br>
> +; CHECK: ldi r31, 73<br>
> +; CHECK: eor r22, r30<br>
> +; CHECK: eor r23, r31<br>
> +; CHECK: ldi r30, 31<br>
> +; CHECK: ldi r31, 242<br>
> +; CHECK: eor r24, r30<br>
> +; CHECK: eor r25, r31<br>
> +    %result = xor i64 %a, 17446744073709551613<br>
> +    ret i64 %result<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/er<wbr>ror-srcreg-destreg-same.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/error-srcreg-destreg-<br>
> same.ll?rev=287162&view=auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/er<wbr>ror-srcreg-destreg-same.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/er<wbr>ror-srcreg-destreg-same.ll Wed Nov 16<br>
> 15:58:04 2016<br>
> @@ -0,0 +1,56 @@<br>
> +; RUN: llc < %s -march=avr | FileCheck %s<br>
> +; XFAIL: *<br>
> +<br>
> +; This occurs when compiling Rust libcore.<br>
> +;<br>
> +; Assertion failed:<br>
> +; (DstReg != SrcReg && "SrcReg and DstReg cannot be the same")<br>
> +;   lib/Target/AVR/AVRExpandPseud<wbr>oInsts.cpp, line 817<br>
> +;<br>
> +; <a href="https://github.com/avr-llvm/llvm/issues/229" rel="noreferrer" target="_blank">https://github.com/avr-llvm/ll<wbr>vm/issues/229</a><br>
> +<br>
> +; CHECK-LABEL: rust_eh_personality<br>
> +declare void @rust_eh_personality()<br>
> +<br>
> +; CHECK-LABEL: __udivmoddi4<br>
> +define void @__udivmoddi4(i64 %arg, i64 %arg1) personality i32 (...)*<br>
> bitcast (void ()* @rust_eh_personality to i32 (...)*) {<br>
> +entry-block:<br>
> +  %tmp = lshr i64 %arg, 32<br>
> +  %tmp2 = trunc i64 %tmp to i32<br>
> +  %tmp3 = trunc i64 %arg to i32<br>
> +  %tmp4 = add i64 %arg1, -1<br>
> +  br label %bb135<br>
> +<br>
> +bb133.loopexit:<br>
> +  ret void<br>
> +<br>
> +bb135:<br>
> +  %carry.0120 = phi i64 [ 0, %entry-block ], [ %phitmp, %bb135 ]<br>
> +  %q.sroa.12.1119 = phi i32 [ %tmp3, %entry-block ], [<br>
> %q.sroa.12.0.extract.trunc, %bb135 ]<br>
> +  %q.sroa.0.1118 = phi i32 [ 0, %entry-block ], [<br>
> %q.sroa.0.0.extract.trunc, %bb135 ]<br>
> +  %r.sroa.0.1116 = phi i32 [ %tmp2, %entry-block ], [ undef, %bb135 ]<br>
> +  %r.sroa.0.0.insert.ext62 = zext i32 %r.sroa.0.1116 to i64<br>
> +  %r.sroa.0.0.insert.insert64 = or i64 0, %r.sroa.0.0.insert.ext62<br>
> +  %tmp5 = shl nuw nsw i64 %r.sroa.0.0.insert.ext62, 1<br>
> +  %q.sroa.12.0.insert.ext101 = zext i32 %q.sroa.12.1119 to i64<br>
> +  %q.sroa.12.0.insert.shift102 = shl nuw i64<br>
> %q.sroa.12.0.insert.ext101, 32<br>
> +  %q.sroa.0.0.insert.ext87 = zext i32 %q.sroa.0.1118 to i64<br>
> +  %q.sroa.0.0.insert.insert89 = or i64 %q.sroa.12.0.insert.shift102,<br>
> %q.sroa.0.0.insert.ext87<br>
> +  %tmp6 = lshr i64 %q.sroa.12.0.insert.ext101, 31<br>
> +  %tmp7 = lshr i64 %r.sroa.0.0.insert.insert64, 31<br>
> +  %tmp8 = shl nuw nsw i64 %q.sroa.0.0.insert.ext87, 1<br>
> +  %tmp9 = or i64 %tmp8, %carry.0120<br>
> +  %q.sroa.0.0.extract.trunc = trunc i64 %tmp9 to i32<br>
> +  %tmp10 = lshr i64 %q.sroa.0.0.insert.insert89, 31<br>
> +  %q.sroa.12.0.extract.trunc = trunc i64 %tmp10 to i32<br>
> +  %r.sroa.13.0.insert.shift72 = shl i64 %tmp7, 32<br>
> +  %.masked114 = and i64 %tmp5, 4294967294<br>
> +  %r.sroa.0.0.insert.ext57 = or i64 %tmp6, %.masked114<br>
> +  %r.sroa.0.0.insert.insert59 = or i64 %r.sroa.0.0.insert.ext57,<br>
> %r.sroa.13.0.insert.shift72<br>
> +  %tmp11 = sub i64 %tmp4, %r.sroa.0.0.insert.insert59<br>
> +  %tmp12 = ashr i64 %tmp11, 63<br>
> +  %phitmp = and i64 %tmp12, 1<br>
> +  %tmp13 = icmp ult i32 undef, 32<br>
> +  br i1 %tmp13, label %bb135, label %bb133.loopexit<br>
> +}<br>
> +<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/ex<wbr>pand-integer-failure.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/expand-integer-<br>
> failure.ll?rev=287162&view=aut<wbr>o<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/ex<wbr>pand-integer-failure.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/ex<wbr>pand-integer-failure.ll Wed Nov 16<br>
> 15:58:04 2016<br>
> @@ -0,0 +1,23 @@<br>
> +; RUN: llc < %s -march=avr | FileCheck %s<br>
> +; XFAIL: *<br>
> +<br>
> +; Causes an assertion error<br>
> +; Assertion failed: (Lo.getValueType() ==<br>
> TLI.getTypeToTransformTo(*DAG.<wbr>getContext(), Op.getValueType()) &&<br>
> +;   Hi.getValueType() == Lo.getValueType() &&<br>
> +;   "Invalid type for expanded integer"),<br>
> +; function SetExpandedInteger<br>
> +; file lib/CodeGen/SelectionDAG/Legal<wbr>izeTypes.cpp<br>
> +<br>
> +; CHECK-LABEL: foo<br>
> +define void @foo(i16 %a) {<br>
> +ifcont:<br>
> +  %cmp_result = icmp eq i16 %a, 255<br>
> +  %bool_result = uitofp i1 %cmp_result to double<br>
> +  %result = fcmp one double 0.000000e+00, %bool_result<br>
> +  br i1 %result, label %then, label %else<br>
> +then:<br>
> +  ret void<br>
> +else:<br>
> +  ret void<br>
> +}<br>
> +<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/fr<wbr>ame.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/frame.ll?rev=287162&<wbr>view=auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/fr<wbr>ame.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/fr<wbr>ame.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,65 @@<br>
> +; RUN: llc -mattr=mul < %s -march=avr | FileCheck %s<br>
> +<br>
> +declare float @dsin(float)<br>
> +declare float @dcos(float)<br>
> +declare float @dasin(float)<br>
> +<br>
> +; Test prologue and epilogue insertion<br>
> +define float @f3(float %days) {<br>
> +entry:<br>
> +; CHECK-LABEL: f3:<br>
> +; prologue code:<br>
> +; CHECK: push r28<br>
> +; CHECK: push r29<br>
> +; CHECK: in r28, 61<br>
> +; CHECK-NEXT: in r29, 62<br>
> +; CHECK-NEXT: sbiw r28, [[SIZE:[0-9]+]]<br>
> +; CHECK-NEXT: in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: out 62, r29<br>
> +; CHECK-NEXT: out 63, r0<br>
> +; CHECK-NEXT: out 61, r28<br>
> +; epilogue code:<br>
> +; CHECK: adiw r28, [[SIZE]]<br>
> +; CHECK-NEXT: in r0, 63<br>
> +; CHECK-NEXT: cli<br>
> +; CHECK-NEXT: out 62, r29<br>
> +; CHECK-NEXT: out 63, r0<br>
> +; CHECK-NEXT: out 61, r28<br>
> +; CHECK: pop r29<br>
> +; CHECK: pop r28<br>
> +  %mul = fmul float %days, 0x3FEF8A6C60000000<br>
> +  %add = fadd float %mul, 0x40718776A0000000<br>
> +  %mul1 = fmul float %days, 0x3FEF8A09A0000000<br>
> +  %add2 = fadd float %mul1, 0x4076587740000000<br>
> +  %mul3 = fmul float %days, 0x3E81B35CC0000000<br>
> +  %sub = fsub float 0x3FFEA235C0000000, %mul3<br>
> +  %call = call float @dsin(float %add2)<br>
> +  %mul4 = fmul float %sub, %call<br>
> +  %mul5 = fmul float %days, 0x3E27C04CA0000000<br>
> +  %sub6 = fsub float 0x3F94790B80000000, %mul5<br>
> +  %mul7 = fmul float %add2, 2.000000e+00<br>
> +  %call8 = call float @dsin(float %mul7)<br>
> +  %mul9 = fmul float %sub6, %call8<br>
> +  %add10 = fadd float %mul4, %mul9<br>
> +  %add11 = fadd float %add, %add10<br>
> +  %mul12 = fmul float %days, 0x3E13C5B640000000<br>
> +  %sub13 = fsub float 0x3F911C1180000000, %mul12<br>
> +  %mul14 = fmul float %add, 2.000000e+00<br>
> +  %call15 = call float @dsin(float %mul14)<br>
> +  %mul16 = fmul float %call15, 0x3FF1F736C0000000<br>
> +  %mul17 = fmul float %sub13, 2.000000e+00<br>
> +  %mul19 = fmul float %mul17, %call<br>
> +  %sub20 = fsub float %mul16, %mul19<br>
> +  %mul21 = fmul float %sub13, 4.000000e+00<br>
> +  %mul22 = fmul float %mul21, 0x3FF1F736C0000000<br>
> +  %mul24 = fmul float %mul22, %call<br>
> +  %call26 = call float @dcos(float %mul14)<br>
> +  %mul27 = fmul float %mul24, %call26<br>
> +  %add28 = fadd float %sub20, %mul27<br>
> +  %call29 = call float @dsin(float %add11)<br>
> +  %mul30 = fmul float %call29, 0x3FF0AB6960000000<br>
> +  %call31 = call float @dasin(float %mul30)<br>
> +  %add32 = fadd float %call31, %add28<br>
> +  ret float %add32<br>
> +}<br>
><br>
> Modified: llvm/trunk/test/CodeGen/AVR/hi<wbr>gh-pressure-on-ptrregs.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/high-pressure-on-<br>
> ptrregs.ll?rev=287162&r1=28716<wbr>1&r2=287162&view=diff<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/hi<wbr>gh-pressure-on-ptrregs.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/AVR/hi<wbr>gh-pressure-on-ptrregs.ll Wed Nov 16<br>
> 15:58:04 2016<br>
> @@ -1,4 +1,5 @@<br>
>  ; RUN: llc < %s -march=avr | FileCheck %s<br>
> +; XFAIL: *<br>
><br>
>  ; This tests how LLVM handles IR which puts very high<br>
>  ; presure on the PTRREGS class for the register allocator.<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/in<wbr>line-asm.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/inline-asm.ll?rev=287162<wbr>&view=auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/in<wbr>line-asm.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/in<wbr>line-asm.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,337 @@<br>
> +; RUN: llc < %s -march=avr | FileCheck %s<br>
> +; XFAIL: *<br>
> +<br>
> +;CHECK-LABEL: no_operands:<br>
> +define void @no_operands() {<br>
> +  ;CHECK: add r24, r22<br>
> +  call void asm sideeffect "add r24, r22", ""() nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: input_operand:<br>
> +define void @input_operand(i8 %a) {<br>
> +  ;CHECK: add r24, r24<br>
> +  call void asm sideeffect "add $0, $0", "r"(i8 %a) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: simple_upper_regs:<br>
> +define void @simple_upper_regs(i8 %p0, i8 %p1, i8 %p2, i8 %p3,<br>
> +                               i8 %p4, i8 %p5, i8 %p6, i8 %p7) {<br>
> +  ;CHECK: some_instr r17, r22, r20, r18, r16, r19, r21, r23<br>
> +  call void asm sideeffect "some_instr $0, $1, $2, $3, $4, $5, $6,<br>
> $7",<br>
> +                           "a,a,a,a,a,a,a,a" (i8 %p0, i8 %p1, i8 %p2,<br>
> i8 %p3,<br>
> +                                              i8 %p4, i8 %p5, i8 %p6,<br>
> i8 %p7) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: upper_regs:<br>
> +define void @upper_regs(i8 %p0) {<br>
> +  ;CHECK: some_instr r24<br>
> +  call void asm sideeffect "some_instr $0", "d" (i8 %p0) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: lower_regs:<br>
> +define void @lower_regs(i8 %p0) {<br>
> +  ;CHECK: some_instr r15<br>
> +  call void asm sideeffect "some_instr $0", "l" (i8 %p0) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: special_upper_regs:<br>
> +define void @special_upper_regs(i8 %p0, i8 %p1, i8 %p2, i8 %p3) {<br>
> +  ;CHECK: some_instr r24,r28,r26,r30<br>
> +  call void asm sideeffect "some_instr $0,$1,$2,$3", "w,w,w,w" (i8<br>
> %p0, i8 %p1, i8 %p2, i8 %p3) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: xyz_reg:<br>
> +define void @xyz_reg(i16 %var) {<br>
> +  ;CHECK: some_instr r26, r28, r30<br>
> +  call void asm sideeffect "some_instr $0, $1, $2", "x,y,z" (i16 %var,<br>
> i16 %var, i16 %var) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;TODO<br>
> +; How to use SP reg properly in inline asm??<br>
> +; define void @sp_reg(i16 %var)<br>
> +<br>
> +;CHECK-LABEL: ptr_reg:<br>
> +define void @ptr_reg(i16 %var0, i16 %var1, i16 %var2) {<br>
> +  ;CHECK: some_instr r28, r26, r30<br>
> +  call void asm sideeffect "some_instr $0, $1, $2", "e,e,e" (i16<br>
> %var0, i16 %var1, i16 %var2) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: base_ptr_reg:<br>
> +define void @base_ptr_reg(i16 %var0, i16 %var1) {<br>
> +  ;CHECK: some_instr r28, r30<br>
> +  call void asm sideeffect "some_instr $0, $1", "b,b" (i16 %var0, i16<br>
> %var1) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: input_output_operand:<br>
> +define i8 @input_output_operand(i8 %a, i8 %b) {<br>
> +  ;CHECK: add r24, r24<br>
> +  %1 = call i8 asm "add $0, $1", "=r,r"(i8 %a) nounwind<br>
> +  ret i8 %1<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: temp_reg:<br>
> +define void @temp_reg(i8 %a) {<br>
> +  ;CHECK: some_instr r0<br>
> +  call void asm sideeffect "some_instr $0", "t" (i8 %a) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: int_0_63:<br>
> +define void @int_0_63() {<br>
> +  ;CHECK: some_instr 5<br>
> +  call void asm sideeffect "some_instr $0", "I" (i8 5) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: int_minus63_0:<br>
> +define void @int_minus63_0() {<br>
> +  ;CHECK: some_instr -5<br>
> +  call void asm sideeffect "some_instr $0", "J" (i8 -5) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: int_2_2:<br>
> +define void @int_2_2() {<br>
> +  ;CHECK: some_instr 2<br>
> +  call void asm sideeffect "some_instr $0", "K" (i8 2) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: int_0_0:<br>
> +define void @int_0_0() {<br>
> +  ;CHECK: some_instr 0<br>
> +  call void asm sideeffect "some_instr $0", "L" (i8 0) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: int_0_255:<br>
> +define void @int_0_255() {<br>
> +  ;CHECK: some_instr 254<br>
> +  call void asm sideeffect "some_instr $0", "M" (i8 254) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: int_minus1_minus1:<br>
> +define void @int_minus1_minus1() {<br>
> +  ;CHECK: some_instr -1<br>
> +  call void asm sideeffect "some_instr $0", "N" (i8 -1) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: int_8_or_16_or_24:<br>
> +define void @int_8_or_16_or_24() {<br>
> +  ;CHECK: some_instr 8, 16, 24<br>
> +  call void asm sideeffect "some_instr $0, $1, $2", "O,O,O" (i8 8, i8<br>
> 16, i8 24) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: int_1_1:<br>
> +define void @int_1_1() {<br>
> +  ;CHECK: some_instr 1<br>
> +  call void asm sideeffect "some_instr $0", "P" (i8 1) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: int_minus6_5:<br>
> +define void @int_minus6_5() {<br>
> +  ;CHECK: some_instr -6<br>
> +  call void asm sideeffect "some_instr $0", "R" (i8 -6) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +;CHECK-LABEL: float_0_0:<br>
> +define void @float_0_0() {<br>
> +  ;CHECK: some_instr 0<br>
> +  call void asm sideeffect "some_instr $0", "G" (float 0.0) nounwind<br>
> +  ret void<br>
> +}<br>
> +<br>
> +<br>
> +; Memory constraint<br>
> +<br>
> +@a = internal global i16 0, align 4<br>
> +@b = internal global i16 0, align 4<br>
> +<br>
> +; CHECK-LABEL: mem_global:<br>
> +define void @mem_global() {<br>
> +  ;CHECK: some_instr Y, Z<br>
> +  call void asm "some_instr $0, $1", "=*Q,=*Q"(i16* @a, i16* @b)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: mem_params:<br>
> +define void @mem_params(i16* %a, i16* %b) {<br>
> +  ;CHECK: some_instr Y, Z<br>
> +  call void asm "some_instr $0, $1", "=*Q,=*Q"(i16* %a, i16* %b)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: mem_local:<br>
> +define void @mem_local() {<br>
> +  %a = alloca i16<br>
> +  %b = alloca i16<br>
> +  ;CHECK: some_instr Y+3, Y+1<br>
> +  call void asm "some_instr $0, $1", "=*Q,=*Q"(i16* %a, i16* %b)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: mem_mixed:<br>
> +define void @mem_mixed() {<br>
> +  %a = alloca i16<br>
> +  %b = alloca i16<br>
> +  ;CHECK: some_instr Z, Y+3, Y+1<br>
> +  call void asm "some_instr $0, $1, $2", "=*Q,=*Q,=*Q"(i16* @a, i16*<br>
> %a, i16* %b)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: mem_gep:<br>
> +define i8 @mem_gep(i8* %p) {<br>
> +entry:<br>
> +; CHECK: movw r30, r24<br>
> +  %arrayidx = getelementptr inbounds i8, i8* %p, i16 1<br>
> +; CHECK: ld r24, Z+1<br>
> +  %0 = tail call i8 asm sideeffect "ld $0, $1\0A\09", "=r,*Q"(i8*<br>
> %arrayidx)<br>
> +  ret i8 %0<br>
> +}<br>
> +<br>
> +; Multibyte references<br>
> +<br>
> +; CHECK-LABEL: multibyte_i16<br>
> +define void @multibyte_i16(i16 %a) {<br>
> +entry:<br>
> +; CHECK: instr r24 r25<br>
> +  call void asm sideeffect "instr ${0:A} ${0:B}", "r"(i16 %a)<br>
> +; CHECK: instr r25 r24<br>
> +  call void asm sideeffect "instr ${0:B} ${0:A}", "r"(i16 %a)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: multibyte_i32<br>
> +define void @multibyte_i32(i32 %a) {<br>
> +entry:<br>
> +; CHECK: instr r22 r23 r24 r25<br>
> +  call void asm sideeffect "instr ${0:A} ${0:B} ${0:C} ${0:D}",<br>
> "r"(i32 %a)<br>
> +; CHECK: instr r25 r24 r23 r22<br>
> +  call void asm sideeffect "instr ${0:D} ${0:C} ${0:B} ${0:A}",<br>
> "r"(i32 %a)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: multibyte_alternative_name<br>
> +define void @multibyte_alternative_name(i1<wbr>6* %p) {<br>
> +entry:<br>
> +; CHECK: instr Z<br>
> +  call void asm sideeffect "instr ${0:a}", "e" (i16* %p)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: multibyte_a_i32<br>
> +define void @multibyte_a_i32() {<br>
> +entry:<br>
> +  %a = alloca i32<br>
> +  %0 = load i32, i32* %a<br>
> +; CHECK: instr r20 r21 r22 r23<br>
> +  call void asm sideeffect "instr ${0:A} ${0:B} ${0:C} ${0:D}",<br>
> "a"(i32 %0)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +@c = internal global i32 0<br>
> +<br>
> +; CHECK-LABEL: multibyte_b_i32<br>
> +define void @multibyte_b_i32() {<br>
> +entry:<br>
> +  %0 = load i32, i32* @c<br>
> +; CHECK: instr r28 r29 r30 r31<br>
> +  call void asm sideeffect "instr ${0:A} ${0:B} ${0:C} ${0:D}",<br>
> "b"(i32 %0)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: multibyte_d_i32<br>
> +define void @multibyte_d_i32() {<br>
> +entry:<br>
> +  %a = alloca i32<br>
> +  %0 = load i32, i32* %a<br>
> +; CHECK: instr r18 r19 r24 r25<br>
> +  call void asm sideeffect "instr ${0:A} ${0:B} ${0:C} ${0:D}",<br>
> "d"(i32 %0)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: multibyte_e_i32<br>
> +define void @multibyte_e_i32() {<br>
> +entry:<br>
> +  %a = alloca i32<br>
> +  %0 = load i32, i32* %a<br>
> +; CHECK: instr r26 r27 r30 r31<br>
> +  call void asm sideeffect "instr ${0:A} ${0:B} ${0:C} ${0:D}",<br>
> "e"(i32 %0)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: multibyte_l_i32<br>
> +define void @multibyte_l_i32() {<br>
> +entry:<br>
> +  %a = alloca i32<br>
> +  %0 = load i32, i32* %a<br>
> +; CHECK: instr r12 r13 r14 r15<br>
> +  call void asm sideeffect "instr ${0:A} ${0:B} ${0:C} ${0:D}",<br>
> "l"(i32 %0)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: multibyte_a_i16<br>
> +define void @multibyte_a_i16() {<br>
> +entry:<br>
> +  %a = alloca i16<br>
> +  %0 = load i16, i16* %a<br>
> +; CHECK: instr r22 r23<br>
> +  call void asm sideeffect "instr ${0:A} ${0:B}", "a"(i16 %0)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: multibyte_b_i16<br>
> +define void @multibyte_b_i16() {<br>
> +entry:<br>
> +  %a = alloca i16<br>
> +  %0 = load i16, i16* %a<br>
> +; CHECK: instr r30 r31<br>
> +  call void asm sideeffect "instr ${0:A} ${0:B}", "b"(i16 %0)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: multibyte_d_i16<br>
> +define void @multibyte_d_i16() {<br>
> +entry:<br>
> +  %a = alloca i16<br>
> +  %0 = load i16, i16* %a<br>
> +; CHECK: instr r24 r25<br>
> +  call void asm sideeffect "instr ${0:A} ${0:B}", "d"(i16 %0)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: multibyte_e_i16<br>
> +define void @multibyte_e_i16() {<br>
> +entry:<br>
> +  %a = alloca i16<br>
> +  %0 = load i16, i16* %a<br>
> +; CHECK: instr r30 r31<br>
> +  call void asm sideeffect "instr ${0:A} ${0:B}", "e"(i16 %0)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: multibyte_l_i16<br>
> +define void @multibyte_l_i16() {<br>
> +entry:<br>
> +  %a = alloca i16<br>
> +  %0 = load i16, i16* %a<br>
> +; CHECK: instr r14 r15<br>
> +  call void asm sideeffect "instr ${0:A} ${0:B}", "l"(i16 %0)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/in<wbr>terrupts.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/interrupts.ll?rev=287162<wbr>&view=auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/in<wbr>terrupts.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/in<wbr>terrupts.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,33 @@<br>
> +; RUN: llc < %s -march=avr | FileCheck %s<br>
> +<br>
> +define avr_intrcc void @interrupt_handler() {<br>
> +; CHECK-LABEL: interrupt_handler:<br>
> +; CHECK: sei<br>
> +; CHECK-NEXT: push r0<br>
> +; CHECK-NEXT: push r1<br>
> +; CHECK-NEXT: in r0, 63<br>
> +; CHECK-NEXT: push r0<br>
> +; CHECK: eor r0, r0<br>
> +; CHECK: pop r0<br>
> +; CHECK-NEXT: out 63, r0<br>
> +; CHECK-NEXT: pop r1<br>
> +; CHECK-NEXT: pop r0<br>
> +; CHECK-NEXT: reti<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define avr_signalcc void @signal_handler() {<br>
> +; CHECK-LABEL: signal_handler:<br>
> +; CHECK-NOT: sei<br>
> +; CHECK: push r0<br>
> +; CHECK-NEXT: push r1<br>
> +; CHECK-NEXT: in r0, 63<br>
> +; CHECK-NEXT: push r0<br>
> +; CHECK: eor r0, r0<br>
> +; CHECK: pop r0<br>
> +; CHECK-NEXT: out 63, r0<br>
> +; CHECK-NEXT: pop r1<br>
> +; CHECK-NEXT: pop r0<br>
> +; CHECK-NEXT: reti<br>
> +  ret void<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/io<wbr>.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/io.ll?rev=287162&view=<wbr>auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/io<wbr>.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/io<wbr>.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,97 @@<br>
> +; RUN: llc < %s -march=avr | FileCheck %s<br>
> +<br>
> +define i8 @read8() {<br>
> +; CHECK-LABEL: read8<br>
> +; CHECK: in r24, 8<br>
> +  %1 = load i8, i8* inttoptr (i16 40 to i8*)<br>
> +  ret i8 %1<br>
> +}<br>
> +<br>
> +define i16 @read16() {<br>
> +; CHECK-LABEL: read16<br>
> +; CHECK: in r24, 8<br>
> +; CHECK: in r25, 9<br>
> +  %1 = load i16, i16* inttoptr (i16 40 to i16*)<br>
> +  ret i16 %1<br>
> +}<br>
> +<br>
> +define i32 @read32() {<br>
> +; CHECK-LABEL: read32<br>
> +; CHECK: in r22, 8<br>
> +; CHECK: in r23, 9<br>
> +; CHECK: in r24, 10<br>
> +; CHECK: in r25, 11<br>
> +  %1 = load i32, i32* inttoptr (i16 40 to i32*)<br>
> +  ret i32 %1<br>
> +}<br>
> +<br>
> +define i64 @read64() {<br>
> +; CHECK-LABEL: read64<br>
> +; CHECK: in r18, 8<br>
> +; CHECK: in r19, 9<br>
> +; CHECK: in r20, 10<br>
> +; CHECK: in r21, 11<br>
> +; CHECK: in r22, 12<br>
> +; CHECK: in r23, 13<br>
> +; CHECK: in r24, 14<br>
> +; CHECK: in r25, 15<br>
> +  %1 = load i64, i64* inttoptr (i16 40 to i64*)<br>
> +  ret i64 %1<br>
> +}<br>
> +<br>
> +define void @write8() {<br>
> +; CHECK-LABEL: write8<br>
> +; CHECK: out 8<br>
> +  store i8 22, i8* inttoptr (i16 40 to i8*)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @write16() {<br>
> +; CHECK-LABEL: write16<br>
> +; CHECK: out 9<br>
> +; CHECK: out 8<br>
> +  store i16 1234, i16* inttoptr (i16 40 to i16*)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @write32() {<br>
> +; CHECK-LABEL: write32<br>
> +; CHECK: out 11<br>
> +; CHECK: out 10<br>
> +; CHECK: out 9<br>
> +; CHECK: out 8<br>
> +  store i32 12345678, i32* inttoptr (i16 40 to i32*)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @write64() {<br>
> +; CHECK-LABEL: write64<br>
> +; CHECK: out 15<br>
> +; CHECK: out 14<br>
> +; CHECK: out 13<br>
> +; CHECK: out 12<br>
> +; CHECK: out 11<br>
> +; CHECK: out 10<br>
> +; CHECK: out 9<br>
> +; CHECK: out 8<br>
> +  store i64 1234567891234567, i64* inttoptr (i16 40 to i64*)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @sbi8() {<br>
> +; CHECK-LABEL: sbi8<br>
> +; CHECK: sbi 8, 5<br>
> +  %1 = load i8, i8* inttoptr (i16 40 to i8*)<br>
> +  %or = or i8 %1, 32<br>
> +  store i8 %or, i8* inttoptr (i16 40 to i8*)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @cbi8() {<br>
> +; CHECK-LABEL: cbi8<br>
> +; CHECK: cbi 8, 5<br>
> +  %1 = load volatile i8, i8* inttoptr (i16 40 to i8*)<br>
> +  %and = and i8 %1, -33<br>
> +  store volatile i8 %and, i8* inttoptr (i16 40 to i8*)<br>
> +  ret void<br>
> +}<br>
><br>
> Modified: llvm/trunk/test/CodeGen/AVR/li<wbr>t.local.cfg<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/lit.local.cfg?rev=287162<wbr>&r1=287161&<br>
> r2=287162&view=diff<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/li<wbr>t.local.cfg (original)<br>
> +++ llvm/trunk/test/CodeGen/AVR/li<wbr>t.local.cfg Wed Nov 16 15:58:04 2016<br>
> @@ -1,3 +1,27 @@<br>
>  if not 'AVR' in config.root.targets:<br>
>      config.unsupported = True<br>
><br>
> +config.suffixes = ['.ll', '.cpp']<br>
> +<br>
> +import os, lit.TestRunner<br>
> +from lit.formats import ShTest<br>
> +<br>
> +targets = set(config.root.targets_to_bui<wbr>ld.split())<br>
> +if not 'AVR' in targets:<br>
> +  config.unsupported = True<br>
> +<br>
> +if 'AVRLIT_PORT' in os.environ:<br>
> +  config.environment['AVRLIT_POR<wbr>T'] = os.environ['AVRLIT_PORT']<br>
> +<br>
> +class AVRCodeGenTest(ShTest):<br>
> +  def __init__(self):<br>
> +    ShTest.__init__(self)<br>
> +<br>
> +  def execute(self, test, litConfig):<br>
> +    if test.getSourcePath().endswith(<wbr>'.cpp') and not 'AVRLIT_PORT' in<br>
> os.environ:<br>
> +      return (lit.Test.UNSUPPORTED, 'AVRLIT_PORT environment variable<br>
> is not set')<br>
> +<br>
> +    return ShTest.execute(self, test, litConfig)<br>
> +<br>
> +<br>
> +config.test_format = AVRCodeGenTest()<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/lo<wbr>ad.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/load.ll?rev=287162&view=<wbr>auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/lo<wbr>ad.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/lo<wbr>ad.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,142 @@<br>
> +; RUN: llc -mattr=avr6,sram < %s -march=avr | FileCheck %s<br>
> +<br>
> +define i8 @load8(i8* %x) {<br>
> +; CHECK-LABEL: load8:<br>
> +; CHECK: ld r24, {{[XYZ]}}<br>
> +  %1 = load i8, i8* %x<br>
> +  ret i8 %1<br>
> +}<br>
> +<br>
> +define i16 @load16(i16* %x) {<br>
> +; CHECK-LABEL: load16:<br>
> +; CHECK: ld r24, {{[YZ]}}<br>
> +; CHECK: ldd r25, {{[YZ]}}+1<br>
> +  %1 = load i16, i16* %x<br>
> +  ret i16 %1<br>
> +}<br>
> +<br>
> +define i8 @load8disp(i8* %x) {<br>
> +; CHECK-LABEL: load8disp:<br>
> +; CHECK: ldd r24, {{[YZ]}}+63<br>
> +  %1 = getelementptr inbounds i8, i8* %x, i64 63<br>
> +  %2 = load i8, i8* %1<br>
> +  ret i8 %2<br>
> +}<br>
> +<br>
> +define i8 @load8nodisp(i8* %x) {<br>
> +; CHECK-LABEL: load8nodisp:<br>
> +; CHECK: movw r26, r24<br>
> +; CHECK: subi r26, 192<br>
> +; CHECK: sbci r27, 255<br>
> +; CHECK: ld r24, {{[XYZ]}}<br>
> +  %1 = getelementptr inbounds i8, i8* %x, i64 64<br>
> +  %2 = load i8, i8* %1<br>
> +  ret i8 %2<br>
> +}<br>
> +<br>
> +define i16 @load16disp(i16* %x) {<br>
> +; CHECK-LABEL: load16disp:<br>
> +; CHECK: ldd r24, {{[YZ]}}+62<br>
> +; CHECK: ldd r25, {{[YZ]}}+63<br>
> +  %1 = getelementptr inbounds i16, i16* %x, i64 31<br>
> +  %2 = load i16, i16* %1<br>
> +  ret i16 %2<br>
> +}<br>
> +<br>
> +define i16 @load16nodisp(i16* %x) {<br>
> +; CHECK-LABEL: load16nodisp:<br>
> +; CHECK: movw r30, r24<br>
> +; CHECK: subi r30, 192<br>
> +; CHECK: sbci r31, 255<br>
> +; CHECK: ld r24, {{[YZ]}}<br>
> +; CHECK: ldd r25, {{[YZ]}}+1<br>
> +  %1 = getelementptr inbounds i16, i16* %x, i64 32<br>
> +  %2 = load i16, i16* %1<br>
> +  ret i16 %2<br>
> +}<br>
> +<br>
> +define i8 @load8postinc(i8* %x, i8 %y) {<br>
> +; CHECK-LABEL: load8postinc:<br>
> +; CHECK: ld {{.*}}, {{[XYZ]}}+<br>
> +entry:<br>
> +  %tobool6 = icmp eq i8 %y, 0<br>
> +  br i1 %tobool6, label %while.end, label %while.body<br>
> +while.body:                                       ; preds = %entry,<br>
> %while.body<br>
> +  %r.09 = phi i8 [ %add, %while.body ], [ 0, %entry ]<br>
> +  %y.addr.08 = phi i8 [ %dec, %while.body ], [ %y, %entry ]<br>
> +  %x.addr.07 = phi i8* [ %incdec.ptr, %while.body ], [ %x, %entry ]<br>
> +  %dec = add i8 %y.addr.08, -1<br>
> +  %incdec.ptr = getelementptr inbounds i8, i8* %x.addr.07, i16 1<br>
> +  %0 = load i8, i8* %x.addr.07<br>
> +  %add = add i8 %0, %r.09<br>
> +  %tobool = icmp eq i8 %dec, 0<br>
> +  br i1 %tobool, label %while.end, label %while.body<br>
> +while.end:                                        ; preds =<br>
> %while.body, %entry<br>
> +  %r.0.lcssa = phi i8 [ 0, %entry ], [ %add, %while.body ]<br>
> +  ret i8 %r.0.lcssa<br>
> +}<br>
> +<br>
> +define i16 @load16postinc(i16* %x, i16 %y) {<br>
> +; CHECK-LABEL: load16postinc:<br>
> +; CHECK: ld {{.*}}, {{[XYZ]}}+<br>
> +; CHECK: ld {{.*}}, {{[XYZ]}}+<br>
> +entry:<br>
> +  %tobool2 = icmp eq i16 %y, 0<br>
> +  br i1 %tobool2, label %while.end, label %while.body<br>
> +while.body:                                       ; preds = %entry,<br>
> %while.body<br>
> +  %r.05 = phi i16 [ %add, %while.body ], [ 0, %entry ]<br>
> +  %y.addr.04 = phi i16 [ %dec, %while.body ], [ %y, %entry ]<br>
> +  %x.addr.03 = phi i16* [ %incdec.ptr, %while.body ], [ %x, %entry ]<br>
> +  %dec = add nsw i16 %y.addr.04, -1<br>
> +  %incdec.ptr = getelementptr inbounds i16, i16* %x.addr.03, i16 1<br>
> +  %0 = load i16, i16* %x.addr.03<br>
> +  %add = add nsw i16 %0, %r.05<br>
> +  %tobool = icmp eq i16 %dec, 0<br>
> +  br i1 %tobool, label %while.end, label %while.body<br>
> +while.end:                                        ; preds =<br>
> %while.body, %entry<br>
> +  %r.0.lcssa = phi i16 [ 0, %entry ], [ %add, %while.body ]<br>
> +  ret i16 %r.0.lcssa<br>
> +}<br>
> +<br>
> +define i8 @load8predec(i8* %x, i8 %y) {<br>
> +; CHECK-LABEL: load8predec:<br>
> +; CHECK: ld {{.*}}, -{{[XYZ]}}<br>
> +entry:<br>
> +  %tobool6 = icmp eq i8 %y, 0<br>
> +  br i1 %tobool6, label %while.end, label %while.body<br>
> +while.body:                                       ; preds = %entry,<br>
> %while.body<br>
> +  %r.09 = phi i8 [ %add, %while.body ], [ 0, %entry ]<br>
> +  %y.addr.08 = phi i8 [ %dec, %while.body ], [ %y, %entry ]<br>
> +  %x.addr.07 = phi i8* [ %incdec.ptr, %while.body ], [ %x, %entry ]<br>
> +  %dec = add i8 %y.addr.08, -1<br>
> +  %incdec.ptr = getelementptr inbounds i8, i8* %x.addr.07, i16 -1<br>
> +  %0 = load i8, i8* %incdec.ptr<br>
> +  %add = add i8 %0, %r.09<br>
> +  %tobool = icmp eq i8 %dec, 0<br>
> +  br i1 %tobool, label %while.end, label %while.body<br>
> +while.end:                                        ; preds =<br>
> %while.body, %entry<br>
> +  %r.0.lcssa = phi i8 [ 0, %entry ], [ %add, %while.body ]<br>
> +  ret i8 %r.0.lcssa<br>
> +}<br>
> +<br>
> +define i16 @load16predec(i16* %x, i16 %y) {<br>
> +; CHECK-LABEL: load16predec:<br>
> +; CHECK: ld {{.*}}, -{{[XYZ]}}<br>
> +; CHECK: ld {{.*}}, -{{[XYZ]}}<br>
> +entry:<br>
> +  %tobool2 = icmp eq i16 %y, 0<br>
> +  br i1 %tobool2, label %while.end, label %while.body<br>
> +while.body:                                       ; preds = %entry,<br>
> %while.body<br>
> +  %r.05 = phi i16 [ %add, %while.body ], [ 0, %entry ]<br>
> +  %y.addr.04 = phi i16 [ %dec, %while.body ], [ %y, %entry ]<br>
> +  %x.addr.03 = phi i16* [ %incdec.ptr, %while.body ], [ %x, %entry ]<br>
> +  %dec = add nsw i16 %y.addr.04, -1<br>
> +  %incdec.ptr = getelementptr inbounds i16, i16* %x.addr.03, i16 -1<br>
> +  %0 = load i16, i16* %incdec.ptr<br>
> +  %add = add nsw i16 %0, %r.05<br>
> +  %tobool = icmp eq i16 %dec, 0<br>
> +  br i1 %tobool, label %while.end, label %while.body<br>
> +while.end:                                        ; preds =<br>
> %while.body, %entry<br>
> +  %r.0.lcssa = phi i16 [ 0, %entry ], [ %add, %while.body ]<br>
> +  ret i16 %r.0.lcssa<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/or<wbr>.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/or.ll?rev=287162&view=<wbr>auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/or<wbr>.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/or<wbr>.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,80 @@<br>
> +; RUN: llc < %s -march=avr | FileCheck %s<br>
> +<br>
> +define i8 @or8_reg_reg(i8 %a, i8 %b) {<br>
> +; CHECK-LABEL: or8_reg_reg:<br>
> +; CHECK: or r24, r22<br>
> +    %result = or i8 %a, %b<br>
> +    ret i8 %result<br>
> +}<br>
> +<br>
> +define i8 @or8_reg_imm(i8 %a) {<br>
> +; CHECK-LABEL: or8_reg_imm:<br>
> +; CHECK: ori r24, 5<br>
> +    %result = or i8 %a, 5<br>
> +    ret i8 %result<br>
> +}<br>
> +<br>
> +define i16 @or16_reg_reg(i16 %a, i16 %b) {<br>
> +; CHECK-LABEL: or16_reg_reg:<br>
> +; CHECK: or r24, r22<br>
> +; CHECK: or r25, r23<br>
> +    %result = or i16 %a, %b<br>
> +    ret i16 %result<br>
> +}<br>
> +<br>
> +define i16 @or16_reg_imm(i16 %a) {<br>
> +; CHECK-LABEL: or16_reg_imm:<br>
> +; CHECK: ori r24, 210<br>
> +; CHECK: ori r25, 4<br>
> +    %result = or i16 %a, 1234<br>
> +    ret i16 %result<br>
> +}<br>
> +<br>
> +define i32 @or32_reg_reg(i32 %a, i32 %b) {<br>
> +; CHECK-LABEL: or32_reg_reg:<br>
> +; CHECK: or r22, r18<br>
> +; CHECK: or r23, r19<br>
> +; CHECK: or r24, r20<br>
> +; CHECK: or r25, r21<br>
> +    %result = or i32 %a, %b<br>
> +    ret i32 %result<br>
> +}<br>
> +<br>
> +define i32 @or32_reg_imm(i32 %a) {<br>
> +; CHECK-LABEL: or32_reg_imm:<br>
> +; CHECK: ori r22, 21<br>
> +; CHECK: ori r23, 205<br>
> +; CHECK: ori r24, 91<br>
> +; CHECK: ori r25, 7<br>
> +    %result = or i32 %a, 123456789<br>
> +    ret i32 %result<br>
> +}<br>
> +<br>
> +define i64 @or64_reg_reg(i64 %a, i64 %b) {<br>
> +; CHECK-LABEL: or64_reg_reg:<br>
> +; CHECK: or r18, r10<br>
> +; CHECK: or r19, r11<br>
> +; CHECK: or r20, r12<br>
> +; CHECK: or r21, r13<br>
> +; CHECK: or r22, r14<br>
> +; CHECK: or r23, r15<br>
> +; CHECK: or r24, r16<br>
> +; CHECK: or r25, r17<br>
> +    %result = or i64 %a, %b<br>
> +    ret i64 %result<br>
> +}<br>
> +<br>
> +define i64 @or64_reg_imm(i64 %a) {<br>
> +; CHECK-LABEL: or64_reg_imm:<br>
> +; CHECK: ori r18, 204<br>
> +; CHECK: ori r19, 204<br>
> +; CHECK: ori r20, 204<br>
> +; CHECK: ori r21, 204<br>
> +; CHECK: ori r22, 204<br>
> +; CHECK: ori r23, 204<br>
> +; CHECK: ori r24, 204<br>
> +; CHECK: ori r25, 204<br>
> +    %result = or i64 %a, 14757395258967641292<br>
> +    ret i64 %result<br>
> +}<br>
> +<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/pr<wbr>ogmem.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/progmem.ll?rev=287162&<wbr>view=auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/pr<wbr>ogmem.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/pr<wbr>ogmem.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,70 @@<br>
> +; RUN: llc < %s -march=avr -mattr=movw,lpm | FileCheck %s<br>
> +; XFAIL: *<br>
> +<br>
> +; Tests the standard LPM instruction<br>
> +<br>
> +define i8 @test8(i8 addrspace(1)* %p) {<br>
> +; CHECK-LABEL: test8:<br>
> +; CHECK: movw r30, r24<br>
> +; CHECK: lpm r24, Z<br>
> +  %1 = load i8, i8 addrspace(1)* %p<br>
> +  ret i8 %1<br>
> +}<br>
> +<br>
> +define i16 @test16(i16 addrspace(1)* %p) {<br>
> +; CHECK-LABEL: test16:<br>
> +; CHECK: movw r30, r24<br>
> +; CHECK: lpm r24, Z+<br>
> +; CHECK: lpm r25, Z+<br>
> +  %1 = load i16, i16 addrspace(1)* %p<br>
> +  ret i16 %1<br>
> +}<br>
> +<br>
> +define i8 @test8postinc(i8 addrspace(1)* %x, i8 %y) {<br>
> +; CHECK-LABEL: test8postinc:<br>
> +; CHECK: movw r30, r24<br>
> +; CHECK: lpm {{.*}}, Z+<br>
> +entry:<br>
> +  %cmp10 = icmp sgt i8 %y, 0<br>
> +  br i1 %cmp10, label %for.body, label %for.end<br>
> +<br>
> +for.body:                                         ; preds = %entry,<br>
> %for.body<br>
> +  %ret.013 = phi i8 [ %add, %for.body ], [ 0, %entry ]<br>
> +  %i.012 = phi i8 [ %inc, %for.body ], [ 0, %entry ]<br>
> +  %x.addr.011 = phi i8 addrspace(1)* [ %incdec.ptr, %for.body ], [ %x,<br>
> %entry ]<br>
> +  %incdec.ptr = getelementptr inbounds i8, i8 addrspace(1)*<br>
> %x.addr.011, i16 1<br>
> +  %0 = load i8, i8 addrspace(1)* %x.addr.011<br>
> +  %add = add i8 %0, %ret.013<br>
> +  %inc = add i8 %i.012, 1<br>
> +  %exitcond = icmp eq i8 %inc, %y<br>
> +  br i1 %exitcond, label %for.end, label %for.body<br>
> +<br>
> +for.end:                                          ; preds = %for.body,<br>
> %entry<br>
> +  %ret.0.lcssa = phi i8 [ 0, %entry ], [ %add, %for.body ]<br>
> +  ret i8 %ret.0.lcssa<br>
> +}<br>
> +<br>
> +define i16 @test16postinc(i16 addrspace(1)* %x, i8 %y) {<br>
> +; CHECK-LABEL: test16postinc:<br>
> +; CHECK: movw r30, r24<br>
> +; CHECK: lpm {{.*}}, Z+<br>
> +; CHECK: lpm {{.*}}, Z+<br>
> +entry:<br>
> +  %cmp5 = icmp sgt i8 %y, 0<br>
> +  br i1 %cmp5, label %for.body, label %for.end<br>
> +<br>
> +for.body:                                         ; preds = %entry,<br>
> %for.body<br>
> +  %ret.08 = phi i16 [ %add, %for.body ], [ 0, %entry ]<br>
> +  %i.07 = phi i8 [ %inc, %for.body ], [ 0, %entry ]<br>
> +  %x.addr.06 = phi i16 addrspace(1)* [ %incdec.ptr, %for.body ], [ %x,<br>
> %entry ]<br>
> +  %incdec.ptr = getelementptr inbounds i16, i16 addrspace(1)*<br>
> %x.addr.06, i16 1<br>
> +  %0 = load i16, i16 addrspace(1)* %x.addr.06<br>
> +  %add = add nsw i16 %0, %ret.08<br>
> +  %inc = add i8 %i.07, 1<br>
> +  %exitcond = icmp eq i8 %inc, %y<br>
> +  br i1 %exitcond, label %for.end, label %for.body<br>
> +<br>
> +for.end:                                          ; preds = %for.body,<br>
> %entry<br>
> +  %ret.0.lcssa = phi i16 [ 0, %entry ], [ %add, %for.body ]<br>
> +  ret i16 %ret.0.lcssa<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/re<wbr>turn.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/return.ll?rev=287162&<wbr>view=auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/re<wbr>turn.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/re<wbr>turn.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,142 @@<br>
> +; RUN: llc -mattr=avr6,sram < %s -march=avr | FileCheck %s<br>
> +<br>
> +;TODO: test returning byval structs<br>
> +; TODO: test naked functions<br>
> +<br>
> +define void @return_void() {<br>
> +; CHECK: return_void:{{[a-zA-Z0-9 #@]*}}<br>
> +; CHECK-NEXT: #{{[a-zA-Z0-9 #@]*}}<br>
> +; CHECK-NEXT: ret<br>
> +    ret void<br>
> +}<br>
> +<br>
> +define i8 @return8_imm() {<br>
> +; CHECK-LABEL: return8_imm:<br>
> +; CHECK: ldi r24, 5<br>
> +    ret i8 5<br>
> +}<br>
> +<br>
> +define i8 @return8_arg(i8 %x) {<br>
> +; CHECK: return8_arg:{{[a-zA-Z0-9 #@]*}}<br>
> +; CHECK-NEXT: #{{[a-zA-Z0-9 #@]*}}<br>
> +; CHECK-NEXT: ret<br>
> +    ret i8 %x<br>
> +}<br>
> +<br>
> +define i8 @return8_arg2(i8 %x, i8 %y, i8 %z) {<br>
> +; CHECK-LABEL: return8_arg2:<br>
> +; CHECK: mov r24, r20<br>
> +    ret i8 %z<br>
> +}<br>
> +<br>
> +define i16 @return16_imm() {<br>
> +; CHECK-LABEL: return16_imm:<br>
> +; CHECK: ldi r24, 57<br>
> +; CHECK: ldi r25, 48<br>
> +    ret i16 12345<br>
> +}<br>
> +<br>
> +define i16 @return16_arg(i16 %x) {<br>
> +; CHECK: return16_arg:{{[a-zA-Z0-9 #@]*}}<br>
> +; CHECK-NEXT: #{{[a-zA-Z0-9 #@]*}}<br>
> +; CHECK-NEXT: ret<br>
> +    ret i16 %x<br>
> +}<br>
> +<br>
> +define i16 @return16_arg2(i16 %x, i16 %y, i16 %z) {<br>
> +; CHECK-LABEL: return16_arg2:<br>
> +; CHECK: movw r24, r20<br>
> +    ret i16 %z<br>
> +}<br>
> +<br>
> +define i32 @return32_imm() {<br>
> +; CHECK-LABEL: return32_imm:<br>
> +; CHECK: ldi r22, 21<br>
> +; CHECK: ldi r23, 205<br>
> +; CHECK: ldi r24, 91<br>
> +; CHECK: ldi r25, 7<br>
> +    ret i32 123456789<br>
> +}<br>
> +<br>
> +define i32 @return32_arg(i32 %x) {<br>
> +; CHECK: return32_arg:{{[a-zA-Z0-9 #@]*}}<br>
> +; CHECK-NEXT: #{{[a-zA-Z0-9 #@]*}}<br>
> +; CHECK-NEXT: ret<br>
> +    ret i32 %x<br>
> +}<br>
> +<br>
> +define i32 @return32_arg2(i32 %x, i32 %y, i32 %z) {<br>
> +; CHECK-LABEL: return32_arg2:<br>
> +; CHECK: movw r22, r14<br>
> +; CHECK: movw r24, r16<br>
> +    ret i32 %z<br>
> +}<br>
> +<br>
> +define i64 @return64_imm() {<br>
> +; CHECK-LABEL: return64_imm:<br>
> +; CHECK: ldi r18, 204<br>
> +; CHECK: ldi r19, 204<br>
> +; CHECK: ldi r20, 104<br>
> +; CHECK: ldi r21, 37<br>
> +; CHECK: ldi r22, 25<br>
> +; CHECK: ldi r23, 22<br>
> +; CHECK: ldi r24, 236<br>
> +; CHECK: ldi r25, 190<br>
> +    ret i64 13757395258967641292<br>
> +}<br>
> +<br>
> +define i64 @return64_arg(i64 %x) {<br>
> +; CHECK: return64_arg:{{[a-zA-Z0-9 #@]*}}<br>
> +; CHECK-NEXT: #{{[a-zA-Z0-9 #@]*}}<br>
> +; CHECK-NEXT: ret<br>
> +    ret i64 %x<br>
> +}<br>
> +<br>
> +define i64 @return64_arg2(i64 %x, i64 %y, i64 %z) {<br>
> +; CHECK-LABEL: return64_arg2:<br>
> +; CHECK: push r28<br>
> +; CHECK: push r29<br>
> +; CHECK: ldd r18, Y+5<br>
> +; CHECK: ldd r19, Y+6<br>
> +; CHECK: ldd r20, Y+7<br>
> +; CHECK: ldd r21, Y+8<br>
> +; CHECK: ldd r22, Y+9<br>
> +; CHECK: ldd r23, Y+10<br>
> +; CHECK: ldd r24, Y+11<br>
> +; CHECK: ldd r25, Y+12<br>
> +; CHECK: pop r29<br>
> +; CHECK: pop r28<br>
> +    ret i64 %z<br>
> +}<br>
> +<br>
> +define i32 @return64_trunc(i32 %a, i32 %b, i32 %c, i64 %d) {<br>
> +; CHECK-LABEL: return64_trunc:<br>
> +; CHECK: push r28<br>
> +; CHECK: push r29<br>
> +; CHECK: ldd r22, Y+5<br>
> +; CHECK: ldd r23, Y+6<br>
> +; CHECK: ldd r24, Y+7<br>
> +; CHECK: ldd r25, Y+8<br>
> +; CHECK: pop r29<br>
> +; CHECK: pop r28<br>
> +  %result = trunc i64 %d to i32<br>
> +  ret i32 %result<br>
> +}<br>
> +<br>
> +define i32 @naked(i32 %x) naked {<br>
> +; CHECK-LABEL: naked:<br>
> +; CHECK-NOT: ret<br>
> +  ret i32 %x<br>
> +}<br>
> +<br>
> +define avr_intrcc void @interrupt_handler() {<br>
> +; CHECK-LABEL: interrupt_handler:<br>
> +; CHECK: reti<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define avr_signalcc void @signal_handler() {<br>
> +; CHECK-LABEL: signal_handler:<br>
> +; CHECK: reti<br>
> +  ret void<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/se<wbr>xt.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/sext.ll?rev=287162&view=<wbr>auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/se<wbr>xt.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/se<wbr>xt.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,29 @@<br>
> +; RUN: llc < %s -march=avr | FileCheck %s<br>
> +<br>
> +; sext R17:R16, R13<br>
> +; mov r16, r13<br>
> +; mov r17, r13<br>
> +; lsl r17<br>
> +; sbc r17, r17<br>
> +define i16 @sext1(i8 %x, i8 %y) {<br>
> +; CHECK-LABEL: sext1:<br>
> +; CHECK: mov r24, r22<br>
> +; CHECK: mov r25, r22<br>
> +; CHECK: lsl r25<br>
> +; CHECK: sbc r25, r25<br>
> +  %1 = sext i8 %y to i16<br>
> +  ret i16 %1<br>
> +}<br>
> +<br>
> +; sext R17:R16, R16<br>
> +; mov r17, r16<br>
> +; lsl r17<br>
> +; sbc r17, r17<br>
> +define i16 @sext2(i8 %x) {<br>
> +; CHECK-LABEL: sext2:<br>
> +; CHECK: mov r25, r24<br>
> +; CHECK: lsl r25<br>
> +; CHECK: sbc r25, r25<br>
> +  %1 = sext i8 %x to i16<br>
> +  ret i16 %1<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/st<wbr>ore.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/store.ll?rev=287162&<wbr>view=auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/st<wbr>ore.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/st<wbr>ore.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,130 @@<br>
> +; RUN: llc -mattr=avr6,sram < %s -march=avr | FileCheck %s<br>
> +<br>
> +define void @store8(i8* %x, i8 %y) {<br>
> +; CHECK-LABEL: store8:<br>
> +; CHECK: st {{[XYZ]}}, r22<br>
> +  store i8 %y, i8* %x<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @store16(i16* %x, i16 %y) {<br>
> +; CHECK-LABEL: store16:<br>
> +; CHECK: st {{[YZ]}}, r22<br>
> +; CHECK: std {{[YZ]}}+1, r23<br>
> +  store i16 %y, i16* %x<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @store8disp(i8* %x, i8 %y) {<br>
> +; CHECK-LABEL: store8disp:<br>
> +; CHECK: std {{[YZ]}}+63, r22<br>
> +  %arrayidx = getelementptr inbounds i8, i8* %x, i16 63<br>
> +  store i8 %y, i8* %arrayidx<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @store8nodisp(i8* %x, i8 %y) {<br>
> +; CHECK-LABEL: store8nodisp:<br>
> +; CHECK: movw r26, r24<br>
> +; CHECK: subi r26, 192<br>
> +; CHECK: sbci r27, 255<br>
> +; CHECK: st {{[XYZ]}}, r22<br>
> +  %arrayidx = getelementptr inbounds i8, i8* %x, i16 64<br>
> +  store i8 %y, i8* %arrayidx<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @store16disp(i16* %x, i16 %y) {<br>
> +; CHECK-LABEL: store16disp:<br>
> +; CHECK: std {{[YZ]}}+62, r22<br>
> +; CHECK: std {{[YZ]}}+63, r23<br>
> +  %arrayidx = getelementptr inbounds i16, i16* %x, i16 31<br>
> +  store i16 %y, i16* %arrayidx<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @store16nodisp(i16* %x, i16 %y) {<br>
> +; CHECK-LABEL: store16nodisp:<br>
> +; CHECK: movw r30, r24<br>
> +; CHECK: subi r30, 192<br>
> +; CHECK: sbci r31, 255<br>
> +; CHECK: st {{[YZ]}}, r22<br>
> +; CHECK: std {{[YZ]}}+1, r23<br>
> +  %arrayidx = getelementptr inbounds i16, i16* %x, i16 32<br>
> +  store i16 %y, i16* %arrayidx<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @store8postinc(i8* %x, i8 %y) {<br>
> +; CHECK-LABEL: store8postinc:<br>
> +; CHECK: st {{[XYZ]}}+, {{.*}}<br>
> +entry:<br>
> +  %tobool3 = icmp eq i8 %y, 0<br>
> +  br i1 %tobool3, label %while.end, label %while.body<br>
> +while.body:                                       ; preds = %entry,<br>
> %while.body<br>
> +  %<a href="http://dec5.in" rel="noreferrer" target="_blank">dec5.in</a> = phi i8 [ %dec5, %while.body ], [ %y, %entry ]<br>
> +  %x.addr.04 = phi i8* [ %incdec.ptr, %while.body ], [ %x, %entry ]<br>
> +  %dec5 = add i8 %<a href="http://dec5.in" rel="noreferrer" target="_blank">dec5.in</a>, -1<br>
> +  %incdec.ptr = getelementptr inbounds i8, i8* %x.addr.04, i16 1<br>
> +  store i8 %dec5, i8* %x.addr.04<br>
> +  %tobool = icmp eq i8 %dec5, 0<br>
> +  br i1 %tobool, label %while.end, label %while.body<br>
> +while.end:                                        ; preds =<br>
> %while.body, %entry<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @store16postinc(i16* %x, i16 %y) {<br>
> +; CHECK-LABEL: store16postinc:<br>
> +; CHECK: st {{[XYZ]}}+, {{.*}}<br>
> +; CHECK: st {{[XYZ]}}+, {{.*}}<br>
> +entry:<br>
> +  %tobool3 = icmp eq i16 %y, 0<br>
> +  br i1 %tobool3, label %while.end, label %while.body<br>
> +while.body:                                       ; preds = %entry,<br>
> %while.body<br>
> +  %<a href="http://dec5.in" rel="noreferrer" target="_blank">dec5.in</a> = phi i16 [ %dec5, %while.body ], [ %y, %entry ]<br>
> +  %x.addr.04 = phi i16* [ %incdec.ptr, %while.body ], [ %x, %entry ]<br>
> +  %dec5 = add nsw i16 %<a href="http://dec5.in" rel="noreferrer" target="_blank">dec5.in</a>, -1<br>
> +  %incdec.ptr = getelementptr inbounds i16, i16* %x.addr.04, i16 1<br>
> +  store i16 %dec5, i16* %x.addr.04<br>
> +  %tobool = icmp eq i16 %dec5, 0<br>
> +  br i1 %tobool, label %while.end, label %while.body<br>
> +while.end:                                        ; preds =<br>
> %while.body, %entry<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @store8predec(i8* %x, i8 %y) {<br>
> +; CHECK-LABEL: store8predec:<br>
> +; CHECK: st -{{[XYZ]}}, {{.*}}<br>
> +entry:<br>
> +  %tobool3 = icmp eq i8 %y, 0<br>
> +  br i1 %tobool3, label %while.end, label %while.body<br>
> +while.body:                                       ; preds = %entry,<br>
> %while.body<br>
> +  %<a href="http://dec5.in" rel="noreferrer" target="_blank">dec5.in</a> = phi i8 [ %dec5, %while.body ], [ %y, %entry ]<br>
> +  %x.addr.04 = phi i8* [ %incdec.ptr, %while.body ], [ %x, %entry ]<br>
> +  %dec5 = add i8 %<a href="http://dec5.in" rel="noreferrer" target="_blank">dec5.in</a>, -1<br>
> +  %incdec.ptr = getelementptr inbounds i8, i8* %x.addr.04, i16 -1<br>
> +  store i8 %dec5, i8* %incdec.ptr<br>
> +  %tobool = icmp eq i8 %dec5, 0<br>
> +  br i1 %tobool, label %while.end, label %while.body<br>
> +while.end:                                        ; preds =<br>
> %while.body, %entry<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @store16predec(i16* %x, i16 %y) {<br>
> +; CHECK-LABEL: store16predec:<br>
> +; CHECK: st -{{[XYZ]}}, {{.*}}<br>
> +; CHECK: st -{{[XYZ]}}, {{.*}}<br>
> +entry:<br>
> +  %tobool3 = icmp eq i16 %y, 0<br>
> +  br i1 %tobool3, label %while.end, label %while.body<br>
> +while.body:                                       ; preds = %entry,<br>
> %while.body<br>
> +  %<a href="http://dec5.in" rel="noreferrer" target="_blank">dec5.in</a> = phi i16 [ %dec5, %while.body ], [ %y, %entry ]<br>
> +  %x.addr.04 = phi i16* [ %incdec.ptr, %while.body ], [ %x, %entry ]<br>
> +  %dec5 = add nsw i16 %<a href="http://dec5.in" rel="noreferrer" target="_blank">dec5.in</a>, -1<br>
> +  %incdec.ptr = getelementptr inbounds i16, i16* %x.addr.04, i16 -1<br>
> +  store i16 %dec5, i16* %incdec.ptr<br>
> +  %tobool = icmp eq i16 %dec5, 0<br>
> +  br i1 %tobool, label %while.end, label %while.body<br>
> +while.end:                                        ; preds =<br>
> %while.body, %entry<br>
> +  ret void<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/su<wbr>b.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/sub.ll?rev=287162&view=<wbr>auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/su<wbr>b.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/su<wbr>b.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,92 @@<br>
> +; RUN: llc < %s -march=avr | FileCheck %s<br>
> +<br>
> +define i8 @sub8_reg_reg(i8 %a, i8 %b) {<br>
> +; CHECK-LABEL: sub8_reg_reg:<br>
> +; CHECK: sub r24, r22<br>
> +    %result = sub i8 %a, %b<br>
> +    ret i8 %result<br>
> +}<br>
> +<br>
> +define i8 @sub8_reg_imm(i8 %a) {<br>
> +; CHECK-LABEL: sub8_reg_imm:<br>
> +; CHECK: subi r24, 5<br>
> +    %result = sub i8 %a, 5<br>
> +    ret i8 %result<br>
> +}<br>
> +<br>
> +define i8 @sub8_reg_decrement(i8 %a) {<br>
> +; CHECK-LABEL: sub8_reg_decrement:<br>
> +; CHECK: dec r24<br>
> +    %result = sub i8 %a, 1<br>
> +    ret i8 %result<br>
> +}<br>
> +<br>
> +define i16 @sub16_reg_reg(i16 %a, i16 %b) {<br>
> +; CHECK-LABEL: sub16_reg_reg:<br>
> +; CHECK: sub r24, r22<br>
> +; CHECK: sbc r25, r23<br>
> +    %result = sub i16 %a, %b<br>
> +    ret i16 %result<br>
> +}<br>
> +<br>
> +define i16 @sub16_reg_imm(i16 %a) {<br>
> +; CHECK-LABEL: sub16_reg_imm:<br>
> +; CHECK: sbiw r24, 63<br>
> +    %result = sub i16 %a, 63<br>
> +    ret i16 %result<br>
> +}<br>
> +<br>
> +define i16 @sub16_reg_imm_subi(i16 %a) {<br>
> +; CHECK-LABEL: sub16_reg_imm_subi:<br>
> +; CHECK: subi r24, 210<br>
> +; CHECK: sbci r25, 4<br>
> +    %result = sub i16 %a, 1234<br>
> +    ret i16 %result<br>
> +}<br>
> +<br>
> +define i32 @sub32_reg_reg(i32 %a, i32 %b) {<br>
> +; CHECK-LABEL: sub32_reg_reg:<br>
> +; CHECK: sub r22, r18<br>
> +; CHECK: sbc r23, r19<br>
> +; CHECK: sbc r24, r20<br>
> +; CHECK: sbc r25, r21<br>
> +    %result = sub i32 %a, %b<br>
> +    ret i32 %result<br>
> +}<br>
> +<br>
> +define i32 @sub32_reg_imm(i32 %a) {<br>
> +; CHECK-LABEL: sub32_reg_imm:<br>
> +; CHECK: subi r22, 21<br>
> +; CHECK: sbci r23, 205<br>
> +; CHECK: sbci r24, 91<br>
> +; CHECK: sbci r25, 7<br>
> +    %result = sub i32 %a, 123456789<br>
> +    ret i32 %result<br>
> +}<br>
> +<br>
> +define i64 @sub64_reg_reg(i64 %a, i64 %b) {<br>
> +; CHECK-LABEL: sub64_reg_reg:<br>
> +; CHECK: sub r18, r10<br>
> +; CHECK: sbc r20, r12<br>
> +; CHECK: sbc r21, r13<br>
> +; CHECK: sbc r22, r14<br>
> +; CHECK: sbc r23, r15<br>
> +; CHECK: sbc r24, r16<br>
> +; CHECK: sbc r25, r17<br>
> +    %result = sub i64 %a, %b<br>
> +    ret i64 %result<br>
> +}<br>
> +<br>
> +define i64 @sub64_reg_imm(i64 %a) {<br>
> +; CHECK-LABEL: sub64_reg_imm:<br>
> +; CHECK: subi r18, 204<br>
> +; CHECK: sbci r19, 204<br>
> +; CHECK: sbci r20, 104<br>
> +; CHECK: sbci r21, 37<br>
> +; CHECK: sbci r22, 25<br>
> +; CHECK: sbci r23, 22<br>
> +; CHECK: sbci r24, 236<br>
> +; CHECK: sbci r25, 190<br>
> +    %result = sub i64 %a, 13757395258967641292<br>
> +    ret i64 %result<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/va<wbr>rargs.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/varargs.ll?rev=287162&<wbr>view=auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/va<wbr>rargs.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/va<wbr>rargs.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,59 @@<br>
> +; RUN: llc -mattr=sram,movw,addsubiw < %s -march=avr | FileCheck %s<br>
> +<br>
> +declare void @llvm.va_start(i8*)<br>
> +declare i16 @vsprintf(i8* nocapture, i8* nocapture, i8*)<br>
> +declare void @llvm.va_end(i8*)<br>
> +<br>
> +define i16 @varargs1(i8* nocapture %x, ...) {<br>
> +; CHECK-LABEL: varargs1:<br>
> +; CHECK: movw r20, r28<br>
> +; CHECK: subi r20, 215<br>
> +; CHECK: sbci r21, 255<br>
> +; CHECK: movw r24, r28<br>
> +; CHECK: adiw r24, 3<br>
> +; CHECK: ldd r22, Y+39<br>
> +; CHECK: ldd r23, Y+40<br>
> +; CHECK: call<br>
> +  %buffer = alloca [32 x i8]<br>
> +  %ap = alloca i8*<br>
> +  %ap1 = bitcast i8** %ap to i8*<br>
> +  call void @llvm.va_start(i8* %ap1)<br>
> +  %arraydecay = getelementptr inbounds [32 x i8], [32 x i8]* %buffer,<br>
> i16 0, i16 0<br>
> +  %1 = load i8*, i8** %ap<br>
> +  %call = call i16 @vsprintf(i8* %arraydecay, i8* %x, i8* %1)<br>
> +  call void @llvm.va_end(i8* %ap1)<br>
> +  ret i16 0<br>
> +}<br>
> +<br>
> +define i16 @varargs2(i8* nocapture %x, ...) {<br>
> +; CHECK-LABEL: varargs2:<br>
> +; CHECK: ld r24, Z<br>
> +; CHECK: ldd r25, Z+1<br>
> +  %ap = alloca i8*<br>
> +  %ap1 = bitcast i8** %ap to i8*<br>
> +  call void @llvm.va_start(i8* %ap1)<br>
> +  %1 = va_arg i8** %ap, i16<br>
> +  call void @llvm.va_end(i8* %ap1)<br>
> +  ret i16 %1<br>
> +}<br>
> +<br>
> +declare void @var1223(i16, ...)<br>
> +define void @varargcall() {<br>
> +; CHECK-LABEL: varargcall:<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 191<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 223<br>
> +; CHECK: push [[REG2]]<br>
> +; CHECK: push [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 189<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 205<br>
> +; CHECK: push [[REG2]]<br>
> +; CHECK: push [[REG1]]<br>
> +; CHECK: ldi [[REG1:r[0-9]+]], 205<br>
> +; CHECK: ldi [[REG2:r[0-9]+]], 171<br>
> +; CHECK: push [[REG2]]<br>
> +; CHECK: push [[REG1]]<br>
> +; CHECK: call<br>
> +; CHECK: adiw r30, 6<br>
> +  tail call void (i16, ...) @var1223(i16 -21555, i16 -12867, i16 -<br>
> 8257)<br>
> +  ret void<br>
> +}<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/xo<wbr>r.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/xor.ll?rev=287162&view=<wbr>auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/xo<wbr>r.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/xo<wbr>r.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,41 @@<br>
> +; RUN: llc < %s -march=avr | FileCheck %s<br>
> +<br>
> +define i8 @xor8_reg_reg(i8 %a, i8 %b) {<br>
> +; CHECK-LABEL: xor8_reg_reg:<br>
> +; CHECK: eor r24, r22<br>
> +    %result = xor i8 %a, %b<br>
> +    ret i8 %result<br>
> +}<br>
> +<br>
> +define i16 @xor16_reg_reg(i16 %a, i16 %b) {<br>
> +; CHECK-LABEL: xor16_reg_reg:<br>
> +; CHECK: eor r24, r22<br>
> +; CHECK: eor r25, r23<br>
> +    %result = xor i16 %a, %b<br>
> +    ret i16 %result<br>
> +}<br>
> +<br>
> +define i32 @xor32_reg_reg(i32 %a, i32 %b) {<br>
> +; CHECK-LABEL: xor32_reg_reg:<br>
> +; CHECK: eor r22, r18<br>
> +; CHECK: eor r23, r19<br>
> +; CHECK: eor r24, r20<br>
> +; CHECK: eor r25, r21<br>
> +    %result = xor i32 %a, %b<br>
> +    ret i32 %result<br>
> +}<br>
> +<br>
> +define i64 @xor64_reg_reg(i64 %a, i64 %b) {<br>
> +; CHECK-LABEL: xor64_reg_reg:<br>
> +; CHECK: eor r18, r10<br>
> +; CHECK: eor r19, r11<br>
> +; CHECK: eor r20, r12<br>
> +; CHECK: eor r21, r13<br>
> +; CHECK: eor r22, r14<br>
> +; CHECK: eor r23, r15<br>
> +; CHECK: eor r24, r16<br>
> +; CHECK: eor r25, r17<br>
> +    %result = xor i64 %a, %b<br>
> +    ret i64 %result<br>
> +}<br>
> +<br>
><br>
> Added: llvm/trunk/test/CodeGen/AVR/ze<wbr>xt.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-</a><br>
> project/llvm/trunk/test/CodeGe<wbr>n/AVR/zext.ll?rev=287162&view=<wbr>auto<br>
> ==============================<wbr>==============================<wbr>===========<br>
> =======<br>
> --- llvm/trunk/test/CodeGen/AVR/ze<wbr>xt.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AVR/ze<wbr>xt.ll Wed Nov 16 15:58:04 2016<br>
> @@ -0,0 +1,31 @@<br>
> +; RUN: llc < %s -march=avr | FileCheck %s<br>
> +<br>
> +; zext R25:R24, R24<br>
> +; eor R25, R25<br>
> +define i16 @zext1(i8 %x) {<br>
> +; CHECK-LABEL: zext1:<br>
> +; CHECK: eor r25, r25<br>
> +  %1 = zext i8 %x to i16<br>
> +  ret i16 %1<br>
> +}<br>
> +<br>
> +; zext R25:R24, R20<br>
> +; mov R24, R20<br>
> +; eor R25, R25<br>
> +define i16 @zext2(i8 %x, i8 %y) {<br>
> +; CHECK-LABEL: zext2:<br>
> +; CHECK: mov r24, r22<br>
> +; CHECK: eor r25, r25<br>
> +  %1 = zext i8 %y to i16<br>
> +  ret i16 %1<br>
> +}<br>
> +<br>
> +; zext R25:R24, R24<br>
> +; eor R25, R25<br>
> +define i16 @zext_i1(i1 %x) {<br>
> +; CHECK-LABEL: zext_i1:<br>
> +; CHECK: eor r25, r25<br>
> +  %1 = zext i1 %x to i16<br>
> +  ret i16 %1<br>
> +}<br>
> +<br>
><br>
><br>
> ______________________________<wbr>_________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>
</blockquote></div><br></div>