<div dir="ltr">The code is in a half-migrated state, where it should mostly compile but there are a few problems. With regards to the eliminateCallFramePseudoInstr problem, a fix was made to the offline repo but hasn't been upstreamed yet.<div><br></div><div>There are also a few functions which don't have definitions (mostly the global createSomething() functions). I have left the definitions out so it compiles, but it doesn't link yet.</div><div><br></div><div>I will remove the unused variable AFI.</div><div><br></div><div>Will also change the signature of getTargetCPU, nice catch. I will be doing work on getting the backend to compile and link properly.</div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, May 11, 2016 at 11:03 AM, Justin Bogner <span dir="ltr"><<a href="mailto:mail@justinbogner.com" target="_blank">mail@justinbogner.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">Dylan McKay via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> writes:<br>
> Author: dylanmckay<br>
> Date: Fri May  6 05:12:31 2016<br>
> New Revision: 268722<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=268722&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=268722&view=rev</a><br>
> Log:<br>
> [AVR] Add a majority of the backend code<br>
><br>
> Summary: This adds the majority of the AVR backend.<br>
<br>
</span>Um, this doesn't seem to even compile. Am I missing something here? I<br>
tried to work around the compiler errors that popped up, but then there<br>
were a slew of linker errors I didn't have time to dig into.<br>
<div><div class="h5"><br>
> Reviewers: hfinkel, dsanders, vkalintiris, arsenm<br>
><br>
> Subscribers: dylanmckay<br>
><br>
> Differential Revision: <a href="http://reviews.llvm.org/D17906" rel="noreferrer" target="_blank">http://reviews.llvm.org/D17906</a><br>
><br>
> Added:<br>
>     llvm/trunk/lib/Target/AVR/AVRFrameLowering.h<br>
>     llvm/trunk/lib/Target/AVR/AVRISelLowering.h<br>
>     llvm/trunk/lib/Target/AVR/AVRInstrInfo.cpp<br>
>     llvm/trunk/lib/Target/AVR/AVRInstrInfo.h<br>
>     llvm/trunk/lib/Target/AVR/AVRRegisterInfo.cpp<br>
>     llvm/trunk/lib/Target/AVR/AVRRegisterInfo.h<br>
>     llvm/trunk/lib/Target/AVR/AVRSubtarget.cpp<br>
>     llvm/trunk/lib/Target/AVR/AVRSubtarget.h<br>
>     llvm/trunk/lib/Target/AVR/AVRTargetMachine.h<br>
>     llvm/trunk/lib/Target/AVR/MCTargetDesc/<br>
>     llvm/trunk/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h<br>
> Modified:<br>
>     llvm/trunk/lib/Target/AVR/AVRInstrInfo.td<br>
>     llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp<br>
>     llvm/trunk/lib/Target/AVR/CMakeLists.txt<br>
><br>
> Added: llvm/trunk/lib/Target/AVR/AVRFrameLowering.h<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRFrameLowering.h?rev=268722&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRFrameLowering.h?rev=268722&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Target/AVR/AVRFrameLowering.h (added)<br>
> +++ llvm/trunk/lib/Target/AVR/AVRFrameLowering.h Fri May  6 05:12:31 2016<br>
> @@ -0,0 +1,48 @@<br>
> +//===-- AVRFrameLowering.h - Define frame lowering for AVR ------*- C++ -*-===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#ifndef LLVM_AVR_FRAME_LOWERING_H<br>
> +#define LLVM_AVR_FRAME_LOWERING_H<br>
> +<br>
> +#include "AVRConfig.h"<br>
> +<br>
> +#include "llvm/Target/TargetFrameLowering.h"<br>
> +<br>
> +namespace llvm {<br>
> +<br>
> +/// Utilities for creating function call frames.<br>
> +class AVRFrameLowering : public TargetFrameLowering {<br>
> +public:<br>
> +  explicit AVRFrameLowering();<br>
> +<br>
> +public:<br>
> +  void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;<br>
> +  void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;<br>
> +  bool hasFP(const MachineFunction &MF) const override;<br>
> +  bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,<br>
> +                                 MachineBasicBlock::iterator MI,<br>
> +                                 const std::vector<CalleeSavedInfo> &CSI,<br>
> +                                 const TargetRegisterInfo *TRI) const override;<br>
> +  bool<br>
> +  restoreCalleeSavedRegisters(MachineBasicBlock &MBB,<br>
> +                              MachineBasicBlock::iterator MI,<br>
> +                              const std::vector<CalleeSavedInfo> &CSI,<br>
> +                              const TargetRegisterInfo *TRI) const override;<br>
> +  bool hasReservedCallFrame(const MachineFunction &MF) const override;<br>
> +  bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override;<br>
> +  void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,<br>
> +                            RegScavenger *RS = nullptr) const override;<br>
> +  void<br>
> +  eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,<br>
> +                                MachineBasicBlock::iterator MI) const override;<br>
<br>
</div></div>This isn't the correct signature for eliminateCallFramePseudoInstr. It<br>
was changed to return a MachineBasicBlock::iterator a couple of months<br>
ago.<br>
<br>
Also as far as I can tell none of these have definitions. They're<br>
declared and never defined.<br>
<div><div class="h5"><br>
> +};<br>
> +<br>
> +} // end namespace llvm<br>
> +<br>
> +#endif // LLVM_AVR_FRAME_LOWERING_H<br>
><br>
> Added: llvm/trunk/lib/Target/AVR/AVRISelLowering.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRISelLowering.h?rev=268722&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRISelLowering.h?rev=268722&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Target/AVR/AVRISelLowering.h (added)<br>
> +++ llvm/trunk/lib/Target/AVR/AVRISelLowering.h Fri May  6 05:12:31 2016<br>
> @@ -0,0 +1,154 @@<br>
> +//===-- AVRISelLowering.h - AVR DAG Lowering Interface ----------*- C++ -*-===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// This file defines the interfaces that AVR uses to lower LLVM code into a<br>
> +// selection DAG.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#ifndef LLVM_AVR_ISEL_LOWERING_H<br>
> +#define LLVM_AVR_ISEL_LOWERING_H<br>
> +<br>
> +#include "AVRConfig.h"<br>
> +<br>
> +#include "llvm/Target/TargetLowering.h"<br>
> +<br>
> +namespace llvm {<br>
> +<br>
> +namespace AVRISD {<br>
> +<br>
> +/// AVR Specific DAG Nodes<br>
> +enum NodeType {<br>
> +  /// Start the numbering where the builtin ops leave off.<br>
> +  FIRST_NUMBER = ISD::BUILTIN_OP_END,<br>
> +  /// Return from subroutine.<br>
> +  RET_FLAG,<br>
> +  /// Return from ISR.<br>
> +  RETI_FLAG,<br>
> +  /// Represents an abstract call instruction,<br>
> +  /// which includes a bunch of information.<br>
> +  CALL,<br>
> +  /// A wrapper node for TargetConstantPool,<br>
> +  /// TargetExternalSymbol, and TargetGlobalAddress.<br>
> +  WRAPPER,<br>
> +  LSL,     ///< Logical shift left.<br>
> +  LSR,     ///< Logical shift right.<br>
> +  ASR,     ///< Arithmetic shift right.<br>
> +  ROR,     ///< Bit rotate right.<br>
> +  ROL,     ///< Bit rotate left.<br>
> +  LSLLOOP, ///< A loop of single logical shift left instructions.<br>
> +  LSRLOOP, ///< A loop of single logical shift right instructions.<br>
> +  ASRLOOP, ///< A loop of single arithmetic shift right instructions.<br>
> +  /// AVR conditional branches. Operand 0 is the chain operand, operand 1<br>
> +  /// is the block to branch if condition is true, operand 2 is the<br>
> +  /// condition code, and operand 3 is the flag operand produced by a CMP<br>
> +  /// or TEST instruction.<br>
> +  BRCOND,<br>
> +  /// Compare instruction.<br>
> +  CMP,<br>
> +  /// Compare with carry instruction.<br>
> +  CMPC,<br>
> +  /// Test for zero or minus instruction.<br>
> +  TST,<br>
> +  /// Operand 0 and operand 1 are selection variable, operand 2<br>
> +  /// is condition code and operand 3 is flag operand.<br>
> +  SELECT_CC<br>
> +};<br>
> +<br>
> +} // end of namespace AVRISD<br>
> +<br>
> +class AVRTargetMachine;<br>
> +<br>
> +/// Performs target lowering for the AVR.<br>
> +class AVRTargetLowering : public TargetLowering {<br>
> +public:<br>
> +  explicit AVRTargetLowering(AVRTargetMachine &TM);<br>
> +<br>
> +public:<br>
> +  MVT getScalarShiftAmountTy(const DataLayout &, EVT LHSTy) const override {<br>
> +    return MVT::i8;<br>
> +  }<br>
> +  const char *getTargetNodeName(unsigned Opcode) const override;<br>
> +<br>
> +  SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;<br>
> +<br>
> +  void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,<br>
> +                          SelectionDAG &DAG) const override;<br>
> +<br>
> +  bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,<br>
> +                             unsigned AS) const override;<br>
> +<br>
> +  bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset,<br>
> +                                 ISD::MemIndexedMode &AM,<br>
> +                                 SelectionDAG &DAG) const override;<br>
> +<br>
> +  bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base,<br>
> +                                  SDValue &Offset, ISD::MemIndexedMode &AM,<br>
> +                                  SelectionDAG &DAG) const override;<br>
> +<br>
> +  bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;<br>
> +<br>
> +  MachineBasicBlock *<br>
> +  EmitInstrWithCustomInserter(MachineInstr *MI,<br>
> +                              MachineBasicBlock *MBB) const override;<br>
> +<br>
> +  ConstraintType getConstraintType(StringRef Constraint) const override;<br>
> +<br>
> +  ConstraintWeight<br>
> +  getSingleConstraintMatchWeight(AsmOperandInfo &info,<br>
> +                                 const char *constraint) const override;<br>
> +<br>
> +  std::pair<unsigned, const TargetRegisterClass *><br>
> +  getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,<br>
> +                               StringRef Constraint, MVT VT) const override;<br>
> +<br>
> +  unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const override;<br>
> +<br>
> +  void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint,<br>
> +                                    std::vector<SDValue> &Ops,<br>
> +                                    SelectionDAG &DAG) const override;<br>
> +<br>
> +private:<br>
> +  SDValue getAVRCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &AVRcc,<br>
> +                    SelectionDAG &DAG, SDLoc dl) const;<br>
> +  SDValue LowerShifts(SDValue Op, SelectionDAG &DAG) const;<br>
> +  SDValue LowerDivRem(SDValue Op, SelectionDAG &DAG) const;<br>
> +  SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;<br>
> +  SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;<br>
> +  SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;<br>
> +  SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const;<br>
> +  SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;<br>
> +  SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;<br>
> +  SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;<br>
> +<br>
> +  SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,<br>
> +                      const SmallVectorImpl<ISD::OutputArg> &Outs,<br>
> +                      const SmallVectorImpl<SDValue> &OutVals, SDLoc dl,<br>
> +                      SelectionDAG &DAG) const override;<br>
> +  SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,<br>
> +                               bool isVarArg,<br>
> +                               const SmallVectorImpl<ISD::InputArg> &Ins,<br>
> +                               SDLoc dl, SelectionDAG &DAG,<br>
> +                               SmallVectorImpl<SDValue> &InVals) const override;<br>
> +  SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,<br>
> +                    SmallVectorImpl<SDValue> &InVals) const override;<br>
> +  SDValue LowerCallResult(SDValue Chain, SDValue InFlag,<br>
> +                          CallingConv::ID CallConv, bool isVarArg,<br>
> +                          const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl,<br>
> +                          SelectionDAG &DAG,<br>
> +                          SmallVectorImpl<SDValue> &InVals) const;<br>
> +<br>
> +private:<br>
> +  MachineBasicBlock *insertShift(MachineInstr *MI, MachineBasicBlock *BB) const;<br>
> +  MachineBasicBlock *insertMul(MachineInstr *MI, MachineBasicBlock *BB) const;<br>
> +};<br>
> +<br>
> +} // end namespace llvm<br>
> +<br>
> +#endif // LLVM_AVR_ISEL_LOWERING_H<br>
><br>
> Added: llvm/trunk/lib/Target/AVR/AVRInstrInfo.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRInstrInfo.cpp?rev=268722&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRInstrInfo.cpp?rev=268722&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Target/AVR/AVRInstrInfo.cpp (added)<br>
> +++ llvm/trunk/lib/Target/AVR/AVRInstrInfo.cpp Fri May  6 05:12:31 2016<br>
> @@ -0,0 +1,467 @@<br>
> +//===-- AVRInstrInfo.cpp - AVR Instruction Information --------------------===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// This file contains the AVR implementation of the TargetInstrInfo class.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#include "AVRInstrInfo.h"<br>
> +<br>
> +#include "llvm/ADT/STLExtras.h"<br>
> +#include "llvm/CodeGen/MachineConstantPool.h"<br>
> +#include "llvm/CodeGen/MachineFrameInfo.h"<br>
> +#include "llvm/CodeGen/MachineInstrBuilder.h"<br>
> +#include "llvm/CodeGen/MachineMemOperand.h"<br>
> +#include "llvm/IR/Constants.h"<br>
> +#include "llvm/IR/Function.h"<br>
> +#include "llvm/MC/MCContext.h"<br>
> +#include "llvm/Support/Debug.h"<br>
> +#include "llvm/Support/ErrorHandling.h"<br>
> +#include "llvm/Support/TargetRegistry.h"<br>
> +<br>
> +#include "AVR.h"<br>
> +#include "AVRMachineFunctionInfo.h"<br>
> +#include "AVRTargetMachine.h"<br>
> +#include "MCTargetDesc/AVRMCTargetDesc.h"<br>
> +<br>
> +#define GET_INSTRINFO_CTOR_DTOR<br>
> +#include "AVRGenInstrInfo.inc"<br>
> +<br>
> +namespace llvm {<br>
> +<br>
> +AVRInstrInfo::AVRInstrInfo()<br>
> +    : AVRGenInstrInfo(AVR::ADJCALLSTACKDOWN, AVR::ADJCALLSTACKUP), RI() {}<br>
> +<br>
> +void AVRInstrInfo::copyPhysReg(MachineBasicBlock &MBB,<br>
> +                               MachineBasicBlock::iterator MI, DebugLoc DL,<br>
> +                               unsigned DestReg, unsigned SrcReg,<br>
> +                               bool KillSrc) const {<br>
> +  unsigned Opc;<br>
> +<br>
> +  if (AVR::GPR8RegClass.contains(DestReg, SrcReg)) {<br>
> +    Opc = AVR::MOVRdRr;<br>
> +  } else if (AVR::DREGSRegClass.contains(DestReg, SrcReg)) {<br>
> +    Opc = AVR::MOVWRdRr;<br>
> +  } else if (SrcReg == AVR::SP && AVR::DREGSRegClass.contains(DestReg)) {<br>
> +    Opc = AVR::SPREAD;<br>
> +  } else if (DestReg == AVR::SP && AVR::DREGSRegClass.contains(SrcReg)) {<br>
> +    Opc = AVR::SPWRITE;<br>
> +  } else {<br>
> +    llvm_unreachable("Impossible reg-to-reg copy");<br>
> +  }<br>
> +<br>
> +  BuildMI(MBB, MI, DL, get(Opc), DestReg)<br>
> +      .addReg(SrcReg, getKillRegState(KillSrc));<br>
> +}<br>
> +<br>
> +unsigned AVRInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,<br>
> +                                           int &FrameIndex) const {<br>
> +  switch (MI->getOpcode()) {<br>
> +  case AVR::LDDRdPtrQ:<br>
> +  case AVR::LDDWRdYQ: { //:FIXME: remove this once PR13375 gets fixed<br>
> +    if ((MI->getOperand(1).isFI()) && (MI->getOperand(2).isImm()) &&<br>
> +        (MI->getOperand(2).getImm() == 0)) {<br>
> +      FrameIndex = MI->getOperand(1).getIndex();<br>
> +      return MI->getOperand(0).getReg();<br>
> +    }<br>
> +    break;<br>
> +  }<br>
> +  default:<br>
> +    break;<br>
> +  }<br>
> +<br>
> +  return 0;<br>
> +}<br>
> +<br>
> +unsigned AVRInstrInfo::isStoreToStackSlot(const MachineInstr *MI,<br>
> +                                          int &FrameIndex) const {<br>
> +  switch (MI->getOpcode()) {<br>
> +  case AVR::STDPtrQRr:<br>
> +  case AVR::STDWPtrQRr: {<br>
> +    if ((MI->getOperand(0).isFI()) && (MI->getOperand(1).isImm()) &&<br>
> +        (MI->getOperand(1).getImm() == 0)) {<br>
> +      FrameIndex = MI->getOperand(0).getIndex();<br>
> +      return MI->getOperand(2).getReg();<br>
> +    }<br>
> +    break;<br>
> +  }<br>
> +  default:<br>
> +    break;<br>
> +  }<br>
> +<br>
> +  return 0;<br>
> +}<br>
> +<br>
> +void AVRInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,<br>
> +                                       MachineBasicBlock::iterator MI,<br>
> +                                       unsigned SrcReg, bool isKill,<br>
> +                                       int FrameIndex,<br>
> +                                       const TargetRegisterClass *RC,<br>
> +                                       const TargetRegisterInfo *TRI) const {<br>
> +  MachineFunction &MF = *MBB.getParent();<br>
> +  AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();<br>
<br>
</div></div>AFI isn't used.<br>
<div><div class="h5"><br>
> +<br>
> +  DebugLoc DL;<br>
> +  if (MI != MBB.end()) {<br>
> +    DL = MI->getDebugLoc();<br>
> +  }<br>
> +<br>
> +  const MachineFrameInfo &MFI = *MF.getFrameInfo();<br>
> +<br>
> +  MachineMemOperand *MMO = MF.getMachineMemOperand(<br>
> +      MachinePointerInfo::getFixedStack(MF, FrameIndex),<br>
> +      MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),<br>
> +      MFI.getObjectAlignment(FrameIndex));<br>
> +<br>
> +  unsigned Opcode = 0;<br>
> +  if (RC->hasType(MVT::i8)) {<br>
> +    Opcode = AVR::STDPtrQRr;<br>
> +  } else if (RC->hasType(MVT::i16)) {<br>
> +    Opcode = AVR::STDWPtrQRr;<br>
> +  } else {<br>
> +    llvm_unreachable("Cannot store this register into a stack slot!");<br>
> +  }<br>
> +<br>
> +  BuildMI(MBB, MI, DL, get(Opcode))<br>
> +      .addFrameIndex(FrameIndex)<br>
> +      .addImm(0)<br>
> +      .addReg(SrcReg, getKillRegState(isKill))<br>
> +      .addMemOperand(MMO);<br>
> +}<br>
> +<br>
> +void AVRInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,<br>
> +                                        MachineBasicBlock::iterator MI,<br>
> +                                        unsigned DestReg, int FrameIndex,<br>
> +                                        const TargetRegisterClass *RC,<br>
> +                                        const TargetRegisterInfo *TRI) const {<br>
> +  DebugLoc DL;<br>
> +  if (MI != MBB.end()) {<br>
> +    DL = MI->getDebugLoc();<br>
> +  }<br>
> +<br>
> +  MachineFunction &MF = *MBB.getParent();<br>
> +  const MachineFrameInfo &MFI = *MF.getFrameInfo();<br>
> +<br>
> +  MachineMemOperand *MMO = MF.getMachineMemOperand(<br>
> +      MachinePointerInfo::getFixedStack(MF, FrameIndex),<br>
> +      MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),<br>
> +      MFI.getObjectAlignment(FrameIndex));<br>
> +<br>
> +  unsigned Opcode = 0;<br>
> +  if (RC->hasType(MVT::i8)) {<br>
> +    Opcode = AVR::LDDRdPtrQ;<br>
> +  } else if (RC->hasType(MVT::i16)) {<br>
> +    // Opcode = AVR::LDDWRdPtrQ;<br>
> +    //:FIXME: remove this once PR13375 gets fixed<br>
> +    Opcode = AVR::LDDWRdYQ;<br>
> +  } else {<br>
> +    llvm_unreachable("Cannot load this register from a stack slot!");<br>
> +  }<br>
> +<br>
> +  BuildMI(MBB, MI, DL, get(Opcode), DestReg)<br>
> +      .addFrameIndex(FrameIndex)<br>
> +      .addImm(0)<br>
> +      .addMemOperand(MMO);<br>
> +}<br>
> +<br>
> +const MCInstrDesc &AVRInstrInfo::getBrCond(AVRCC::CondCodes CC) const {<br>
> +  switch (CC) {<br>
> +  default:<br>
> +    llvm_unreachable("Unknown condition code!");<br>
> +  case AVRCC::COND_EQ:<br>
> +    return get(AVR::BREQk);<br>
> +  case AVRCC::COND_NE:<br>
> +    return get(AVR::BRNEk);<br>
> +  case AVRCC::COND_GE:<br>
> +    return get(AVR::BRGEk);<br>
> +  case AVRCC::COND_LT:<br>
> +    return get(AVR::BRLTk);<br>
> +  case AVRCC::COND_SH:<br>
> +    return get(AVR::BRSHk);<br>
> +  case AVRCC::COND_LO:<br>
> +    return get(AVR::BRLOk);<br>
> +  case AVRCC::COND_MI:<br>
> +    return get(AVR::BRMIk);<br>
> +  case AVRCC::COND_PL:<br>
> +    return get(AVR::BRPLk);<br>
> +  }<br>
> +}<br>
> +<br>
> +AVRCC::CondCodes AVRInstrInfo::getCondFromBranchOpc(unsigned Opc) const {<br>
> +  switch (Opc) {<br>
> +  default:<br>
> +    return AVRCC::COND_INVALID;<br>
> +  case AVR::BREQk:<br>
> +    return AVRCC::COND_EQ;<br>
> +  case AVR::BRNEk:<br>
> +    return AVRCC::COND_NE;<br>
> +  case AVR::BRSHk:<br>
> +    return AVRCC::COND_SH;<br>
> +  case AVR::BRLOk:<br>
> +    return AVRCC::COND_LO;<br>
> +  case AVR::BRMIk:<br>
> +    return AVRCC::COND_MI;<br>
> +  case AVR::BRPLk:<br>
> +    return AVRCC::COND_PL;<br>
> +  case AVR::BRGEk:<br>
> +    return AVRCC::COND_GE;<br>
> +  case AVR::BRLTk:<br>
> +    return AVRCC::COND_LT;<br>
> +  }<br>
> +}<br>
> +<br>
> +AVRCC::CondCodes AVRInstrInfo::getOppositeCondition(AVRCC::CondCodes CC) const {<br>
> +  switch (CC) {<br>
> +  default:<br>
> +    llvm_unreachable("Invalid condition!");<br>
> +  case AVRCC::COND_EQ:<br>
> +    return AVRCC::COND_NE;<br>
> +  case AVRCC::COND_NE:<br>
> +    return AVRCC::COND_EQ;<br>
> +  case AVRCC::COND_SH:<br>
> +    return AVRCC::COND_LO;<br>
> +  case AVRCC::COND_LO:<br>
> +    return AVRCC::COND_SH;<br>
> +  case AVRCC::COND_GE:<br>
> +    return AVRCC::COND_LT;<br>
> +  case AVRCC::COND_LT:<br>
> +    return AVRCC::COND_GE;<br>
> +  case AVRCC::COND_MI:<br>
> +    return AVRCC::COND_PL;<br>
> +  case AVRCC::COND_PL:<br>
> +    return AVRCC::COND_MI;<br>
> +  }<br>
> +}<br>
> +<br>
> +bool AVRInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,<br>
> +                                 MachineBasicBlock *&TBB,<br>
> +                                 MachineBasicBlock *&FBB,<br>
> +                                 SmallVectorImpl<MachineOperand> &Cond,<br>
> +                                 bool AllowModify) const {<br>
> +  // Start from the bottom of the block and work up, examining the<br>
> +  // terminator instructions.<br>
> +  MachineBasicBlock::iterator I = MBB.end();<br>
> +  MachineBasicBlock::iterator UnCondBrIter = MBB.end();<br>
> +<br>
> +  while (I != MBB.begin()) {<br>
> +    --I;<br>
> +    if (I->isDebugValue()) {<br>
> +      continue;<br>
> +    }<br>
> +<br>
> +    // Working from the bottom, when we see a non-terminator<br>
> +    // instruction, we're done.<br>
> +    if (!isUnpredicatedTerminator(*I)) {<br>
> +      break;<br>
> +    }<br>
> +<br>
> +    // A terminator that isn't a branch can't easily be handled<br>
> +    // by this analysis.<br>
> +    if (!I->getDesc().isBranch()) {<br>
> +      return true;<br>
> +    }<br>
> +<br>
> +    // Handle unconditional branches.<br>
> +    //:TODO: add here jmp<br>
> +    if (I->getOpcode() == AVR::RJMPk) {<br>
> +      UnCondBrIter = I;<br>
> +<br>
> +      if (!AllowModify) {<br>
> +        TBB = I->getOperand(0).getMBB();<br>
> +        continue;<br>
> +      }<br>
> +<br>
> +      // If the block has any instructions after a JMP, delete them.<br>
> +      while (std::next(I) != MBB.end()) {<br>
> +        std::next(I)->eraseFromParent();<br>
> +      }<br>
> +<br>
> +      Cond.clear();<br>
> +      FBB = 0;<br>
> +<br>
> +      // Delete the JMP if it's equivalent to a fall-through.<br>
> +      if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {<br>
> +        TBB = 0;<br>
> +        I->eraseFromParent();<br>
> +        I = MBB.end();<br>
> +        UnCondBrIter = MBB.end();<br>
> +        continue;<br>
> +      }<br>
> +<br>
> +      // TBB is used to indicate the unconditinal destination.<br>
> +      TBB = I->getOperand(0).getMBB();<br>
> +      continue;<br>
> +    }<br>
> +<br>
> +    // Handle conditional branches.<br>
> +    AVRCC::CondCodes BranchCode = getCondFromBranchOpc(I->getOpcode());<br>
> +    if (BranchCode == AVRCC::COND_INVALID) {<br>
> +      return true; // Can't handle indirect branch.<br>
> +    }<br>
> +<br>
> +    // Working from the bottom, handle the first conditional branch.<br>
> +    if (Cond.empty()) {<br>
> +      MachineBasicBlock *TargetBB = I->getOperand(0).getMBB();<br>
> +      if (AllowModify && UnCondBrIter != MBB.end() &&<br>
> +          MBB.isLayoutSuccessor(TargetBB)) {<br>
> +        // If we can modify the code and it ends in something like:<br>
> +        //<br>
> +        //     jCC L1<br>
> +        //     jmp L2<br>
> +        //   L1:<br>
> +        //     ...<br>
> +        //   L2:<br>
> +        //<br>
> +        // Then we can change this to:<br>
> +        //<br>
> +        //     jnCC L2<br>
> +        //   L1:<br>
> +        //     ...<br>
> +        //   L2:<br>
> +        //<br>
> +        // Which is a bit more efficient.<br>
> +        // We conditionally jump to the fall-through block.<br>
> +        BranchCode = getOppositeCondition(BranchCode);<br>
> +        unsigned JNCC = getBrCond(BranchCode).getOpcode();<br>
> +        MachineBasicBlock::iterator OldInst = I;<br>
> +<br>
> +        BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(JNCC))<br>
> +            .addMBB(UnCondBrIter->getOperand(0).getMBB());<br>
> +        BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(AVR::RJMPk))<br>
> +            .addMBB(TargetBB);<br>
> +<br>
> +        OldInst->eraseFromParent();<br>
> +        UnCondBrIter->eraseFromParent();<br>
> +<br>
> +        // Restart the analysis.<br>
> +        UnCondBrIter = MBB.end();<br>
> +        I = MBB.end();<br>
> +        continue;<br>
> +      }<br>
> +<br>
> +      FBB = TBB;<br>
> +      TBB = I->getOperand(0).getMBB();<br>
> +      Cond.push_back(MachineOperand::CreateImm(BranchCode));<br>
> +      continue;<br>
> +    }<br>
> +<br>
> +    // Handle subsequent conditional branches. Only handle the case where all<br>
> +    // conditional branches branch to the same destination.<br>
> +    assert(Cond.size() == 1);<br>
> +    assert(TBB);<br>
> +<br>
> +    // Only handle the case where all conditional branches branch to<br>
> +    // the same destination.<br>
> +    if (TBB != I->getOperand(0).getMBB()) {<br>
> +      return true;<br>
> +    }<br>
> +<br>
> +    AVRCC::CondCodes OldBranchCode = (AVRCC::CondCodes)Cond[0].getImm();<br>
> +    // If the conditions are the same, we can leave them alone.<br>
> +    if (OldBranchCode == BranchCode) {<br>
> +      continue;<br>
> +    }<br>
> +<br>
> +    return true;<br>
> +  }<br>
> +<br>
> +  return false;<br>
> +}<br>
> +<br>
> +unsigned AVRInstrInfo::InsertBranch(MachineBasicBlock &MBB,<br>
> +                                    MachineBasicBlock *TBB,<br>
> +                                    MachineBasicBlock *FBB,<br>
> +                                    ArrayRef<MachineOperand> Cond,<br>
> +                                    DebugLoc DL) const {<br>
> +  // Shouldn't be a fall through.<br>
> +  assert(TBB && "InsertBranch must not be told to insert a fallthrough");<br>
> +  assert((Cond.size() == 1 || Cond.size() == 0) &&<br>
> +         "AVR branch conditions have one component!");<br>
> +<br>
> +  if (Cond.empty()) {<br>
> +    assert(!FBB && "Unconditional branch with multiple successors!");<br>
> +    BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(TBB);<br>
> +    return 1;<br>
> +  }<br>
> +<br>
> +  // Conditional branch.<br>
> +  unsigned Count = 0;<br>
> +  AVRCC::CondCodes CC = (AVRCC::CondCodes)Cond[0].getImm();<br>
> +  BuildMI(&MBB, DL, getBrCond(CC)).addMBB(TBB);<br>
> +  ++Count;<br>
> +<br>
> +  if (FBB) {<br>
> +    // Two-way Conditional branch. Insert the second branch.<br>
> +    BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(FBB);<br>
> +    ++Count;<br>
> +  }<br>
> +<br>
> +  return Count;<br>
> +}<br>
> +<br>
> +unsigned AVRInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {<br>
> +  MachineBasicBlock::iterator I = MBB.end();<br>
> +  unsigned Count = 0;<br>
> +<br>
> +  while (I != MBB.begin()) {<br>
> +    --I;<br>
> +    if (I->isDebugValue()) {<br>
> +      continue;<br>
> +    }<br>
> +    //:TODO: add here the missing jmp instructions once they are implemented<br>
> +    // like jmp, {e}ijmp, and other cond branches, ...<br>
> +    if (I->getOpcode() != AVR::RJMPk &&<br>
> +        getCondFromBranchOpc(I->getOpcode()) == AVRCC::COND_INVALID) {<br>
> +      break;<br>
> +    }<br>
> +<br>
> +    // Remove the branch.<br>
> +    I->eraseFromParent();<br>
> +    I = MBB.end();<br>
> +    ++Count;<br>
> +  }<br>
> +<br>
> +  return Count;<br>
> +}<br>
> +<br>
> +bool AVRInstrInfo::ReverseBranchCondition(<br>
> +    SmallVectorImpl<MachineOperand> &Cond) const {<br>
> +  assert(Cond.size() == 1 && "Invalid AVR branch condition!");<br>
> +<br>
> +  AVRCC::CondCodes CC = static_cast<AVRCC::CondCodes>(Cond[0].getImm());<br>
> +  Cond[0].setImm(getOppositeCondition(CC));<br>
> +<br>
> +  return false;<br>
> +}<br>
> +<br>
> +unsigned AVRInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {<br>
> +  unsigned Opcode = MI->getOpcode();<br>
> +<br>
> +  switch (Opcode) {<br>
> +  // A regular instruction<br>
> +  default: {<br>
> +    const MCInstrDesc &Desc = get(Opcode);<br>
> +    return Desc.getSize();<br>
> +  }<br>
> +  case TargetOpcode::EH_LABEL:<br>
> +  case TargetOpcode::IMPLICIT_DEF:<br>
> +  case TargetOpcode::KILL:<br>
> +  case TargetOpcode::DBG_VALUE:<br>
> +    return 0;<br>
> +  case TargetOpcode::INLINEASM: {<br>
> +    const MachineFunction *MF = MI->getParent()->getParent();<br>
> +    const AVRTargetMachine &TM = static_cast<const AVRTargetMachine&>(MF->getTarget());<br>
> +    const TargetInstrInfo &TII = *TM.getSubtargetImpl()->getInstrInfo();<br>
> +    return TII.getInlineAsmLength(MI->getOperand(0).getSymbolName(),<br>
> +                                  *TM.getMCAsmInfo());<br>
> +  }<br>
> +  }<br>
> +}<br>
> +<br>
> +} // end of namespace llvm<br>
><br>
> Added: llvm/trunk/lib/Target/AVR/AVRInstrInfo.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRInstrInfo.h?rev=268722&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRInstrInfo.h?rev=268722&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Target/AVR/AVRInstrInfo.h (added)<br>
> +++ llvm/trunk/lib/Target/AVR/AVRInstrInfo.h Fri May  6 05:12:31 2016<br>
> @@ -0,0 +1,112 @@<br>
> +//===-- AVRInstrInfo.h - AVR Instruction Information ------------*- C++ -*-===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// This file contains the AVR implementation of the TargetInstrInfo class.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#ifndef LLVM_AVR_INSTR_INFO_H<br>
> +#define LLVM_AVR_INSTR_INFO_H<br>
> +<br>
> +#include "llvm/Target/TargetInstrInfo.h"<br>
> +<br>
> +#include "AVRRegisterInfo.h"<br>
> +<br>
> +#define GET_INSTRINFO_HEADER<br>
> +#include "AVRGenInstrInfo.inc"<br>
> +#undef GET_INSTRINFO_HEADER<br>
> +<br>
> +namespace llvm {<br>
> +<br>
> +namespace AVRCC {<br>
> +<br>
> +/// AVR specific condition codes.<br>
> +/// These correspond to `AVR_*_COND` in `AVRInstrInfo.td`.<br>
> +/// They must be kept in synch.<br>
> +enum CondCodes {<br>
> +  COND_EQ, //!< Equal<br>
> +  COND_NE, //!< Not equal<br>
> +  COND_GE, //!< Greater than or equal<br>
> +  COND_LT, //!< Less than<br>
> +  COND_SH, //!< Unsigned same or higher<br>
> +  COND_LO, //!< Unsigned lower<br>
> +  COND_MI, //!< Minus<br>
> +  COND_PL, //!< Plus<br>
> +  COND_INVALID<br>
> +};<br>
> +<br>
> +} // end of namespace AVRCC<br>
> +<br>
> +namespace AVRII {<br>
> +<br>
> +/// Specifies a target operand flag.<br>
> +enum TOF {<br>
> +  MO_NO_FLAG,<br>
> +<br>
> +  /// On a symbol operand, this represents the lo part.<br>
> +  MO_LO = (1 << 1),<br>
> +<br>
> +  /// On a symbol operand, this represents the hi part.<br>
> +  MO_HI = (1 << 2),<br>
> +<br>
> +  /// On a symbol operand, this represents it has to be negated.<br>
> +  MO_NEG = (1 << 3)<br>
> +};<br>
> +<br>
> +} // end of namespace AVRII<br>
> +<br>
> +/**<br>
> + * Utilities related to the AVR instruction set.<br>
> + */<br>
> +class AVRInstrInfo : public AVRGenInstrInfo {<br>
> +public:<br>
> +  explicit AVRInstrInfo();<br>
> +<br>
> +  const AVRRegisterInfo &getRegisterInfo() const { return RI; }<br>
> +  const MCInstrDesc &getBrCond(AVRCC::CondCodes CC) const;<br>
> +  AVRCC::CondCodes getCondFromBranchOpc(unsigned Opc) const;<br>
> +  AVRCC::CondCodes getOppositeCondition(AVRCC::CondCodes CC) const;<br>
> +  unsigned GetInstSizeInBytes(const MachineInstr *MI) const;<br>
> +<br>
> +  void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,<br>
> +                   DebugLoc DL, unsigned DestReg, unsigned SrcReg,<br>
> +                   bool KillSrc) const override;<br>
> +  void storeRegToStackSlot(MachineBasicBlock &MBB,<br>
> +                           MachineBasicBlock::iterator MI, unsigned SrcReg,<br>
> +                           bool isKill, int FrameIndex,<br>
> +                           const TargetRegisterClass *RC,<br>
> +                           const TargetRegisterInfo *TRI) const override;<br>
> +  void loadRegFromStackSlot(MachineBasicBlock &MBB,<br>
> +                            MachineBasicBlock::iterator MI, unsigned DestReg,<br>
> +                            int FrameIndex, const TargetRegisterClass *RC,<br>
> +                            const TargetRegisterInfo *TRI) const override;<br>
> +  unsigned isLoadFromStackSlot(const MachineInstr *MI,<br>
> +                               int &FrameIndex) const override;<br>
> +  unsigned isStoreToStackSlot(const MachineInstr *MI,<br>
> +                              int &FrameIndex) const override;<br>
> +<br>
> +  // Branch analysis.<br>
> +  bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,<br>
> +                     MachineBasicBlock *&FBB,<br>
> +                     SmallVectorImpl<MachineOperand> &Cond,<br>
> +                     bool AllowModify = false) const override;<br>
> +  unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,<br>
> +                        MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,<br>
> +                        DebugLoc DL) const override;<br>
> +  unsigned RemoveBranch(MachineBasicBlock &MBB) const override;<br>
> +  bool<br>
> +  ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;<br>
> +<br>
> +private:<br>
> +  const AVRRegisterInfo RI;<br>
> +};<br>
> +<br>
> +} // end namespace llvm<br>
> +<br>
> +#endif // LLVM_AVR_INSTR_INFO_H<br>
><br>
> Modified: llvm/trunk/lib/Target/AVR/AVRInstrInfo.td<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRInstrInfo.td?rev=268722&r1=268721&r2=268722&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRInstrInfo.td?rev=268722&r1=268721&r2=268722&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Target/AVR/AVRInstrInfo.td (original)<br>
> +++ llvm/trunk/lib/Target/AVR/AVRInstrInfo.td Fri May  6 05:12:31 2016<br>
> @@ -45,7 +45,7 @@ def AVRcallseq_end : SDNode<"ISD::CALLSE<br>
>  def AVRcall : SDNode<"AVRISD::CALL", SDT_AVRCall,<br>
>                       [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, SDNPVariadic]>;<br>
><br>
> -def AVRWrapper : SDNode<"AVRISD::Wrapper", SDT_AVRWrapper>;<br>
> +def AVRWrapper : SDNode<"AVRISD::WRAPPER", SDT_AVRWrapper>;<br>
><br>
>  def AVRbrcond : SDNode<"AVRISD::BRCOND", SDT_AVRBrcond,<br>
>                         [SDNPHasChain, SDNPInGlue]>;<br>
><br>
> Added: llvm/trunk/lib/Target/AVR/AVRRegisterInfo.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRRegisterInfo.cpp?rev=268722&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRRegisterInfo.cpp?rev=268722&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Target/AVR/AVRRegisterInfo.cpp (added)<br>
> +++ llvm/trunk/lib/Target/AVR/AVRRegisterInfo.cpp Fri May  6 05:12:31 2016<br>
> @@ -0,0 +1,256 @@<br>
> +//===-- AVRRegisterInfo.cpp - AVR Register Information --------------------===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// This file contains the AVR implementation of the TargetRegisterInfo class.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#include "AVRRegisterInfo.h"<br>
> +<br>
> +#include "llvm/ADT/BitVector.h"<br>
> +#include "llvm/CodeGen/MachineFrameInfo.h"<br>
> +#include "llvm/CodeGen/MachineFunction.h"<br>
> +#include "llvm/CodeGen/MachineInstrBuilder.h"<br>
> +#include "llvm/IR/Function.h"<br>
> +#include "llvm/Target/TargetFrameLowering.h"<br>
> +<br>
> +#include "AVR.h"<br>
> +#include "AVRInstrInfo.h"<br>
> +#include "AVRTargetMachine.h"<br>
> +#include "MCTargetDesc/AVRMCTargetDesc.h"<br>
> +<br>
> +#define GET_REGINFO_TARGET_DESC<br>
> +#include "AVRGenRegisterInfo.inc"<br>
> +<br>
> +namespace llvm {<br>
> +<br>
> +AVRRegisterInfo::AVRRegisterInfo() : AVRGenRegisterInfo(0) {}<br>
> +<br>
> +const uint16_t *<br>
> +AVRRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {<br>
> +  CallingConv::ID CC = MF->getFunction()->getCallingConv();<br>
> +<br>
> +  return ((CC == CallingConv::AVR_INTR || CC == CallingConv::AVR_SIGNAL)<br>
> +              ? CSR_Interrupts_SaveList<br>
> +              : CSR_Normal_SaveList);<br>
> +}<br>
> +<br>
> +const uint32_t *<br>
> +AVRRegisterInfo::getCallPreservedMask(const MachineFunction &MF,<br>
> +                                      CallingConv::ID CC) const {<br>
> +  return ((CC == CallingConv::AVR_INTR || CC == CallingConv::AVR_SIGNAL)<br>
> +              ? CSR_Interrupts_RegMask<br>
> +              : CSR_Normal_RegMask);<br>
> +}<br>
> +<br>
> +BitVector AVRRegisterInfo::getReservedRegs(const MachineFunction &MF) const {<br>
> +  BitVector Reserved(getNumRegs());<br>
> +  const AVRTargetMachine &TM = static_cast<const AVRTargetMachine&>(MF.getTarget());<br>
> +  const TargetFrameLowering *TFI = TM.getSubtargetImpl()->getFrameLowering();<br>
> +<br>
> +  // Reserve the intermediate result registers r1 and r2<br>
> +  // The result of instructions like 'mul' is always stored here.<br>
> +  Reserved.set(AVR::R0);<br>
> +  Reserved.set(AVR::R1);<br>
> +  Reserved.set(AVR::R1R0);<br>
> +<br>
> +  //  Reserve the stack pointer.<br>
> +  Reserved.set(AVR::SPL);<br>
> +  Reserved.set(AVR::SPH);<br>
> +  Reserved.set(AVR::SP);<br>
> +<br>
> +  // Reserve the frame pointer registers r28 and r29 if the function requires one.<br>
> +  if (TFI->hasFP(MF)) {<br>
> +    Reserved.set(AVR::R28);<br>
> +    Reserved.set(AVR::R29);<br>
> +    Reserved.set(AVR::R29R28);<br>
> +  }<br>
> +<br>
> +  return Reserved;<br>
> +}<br>
> +<br>
> +const TargetRegisterClass *<br>
> +AVRRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,<br>
> +                                           const MachineFunction &MF) const {<br>
> +  if (RC->hasType(MVT::i16)) {<br>
> +    return &AVR::DREGSRegClass;<br>
> +  }<br>
> +<br>
> +  if (RC->hasType(MVT::i8)) {<br>
> +    return &AVR::GPR8RegClass;<br>
> +  }<br>
> +<br>
> +  llvm_unreachable("Invalid register size");<br>
> +}<br>
> +<br>
> +/// Fold a frame offset shared between two add instructions into a single one.<br>
> +static void foldFrameOffset(MachineInstr &MI, int &Offset, unsigned DstReg) {<br>
> +  int Opcode = MI.getOpcode();<br>
> +<br>
> +  // Don't bother trying if the next instruction is not an add or a sub.<br>
> +  if ((Opcode != AVR::SUBIWRdK) && (Opcode != AVR::ADIWRdK)) {<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  // Check that DstReg matches with next instruction, otherwise the instruction<br>
> +  // is not related to stack address manipulation.<br>
> +  if (DstReg != MI.getOperand(0).getReg()) {<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  // Add the offset in the next instruction to our offset.<br>
> +  switch (Opcode) {<br>
> +  case AVR::SUBIWRdK:<br>
> +    Offset += -MI.getOperand(2).getImm();<br>
> +    break;<br>
> +  case AVR::ADIWRdK:<br>
> +    Offset += MI.getOperand(2).getImm();<br>
> +    break;<br>
> +  }<br>
> +<br>
> +  // Finally remove the instruction.<br>
> +  MI.eraseFromParent();<br>
> +}<br>
> +<br>
> +void AVRRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,<br>
> +                                          int SPAdj, unsigned FIOperandNum,<br>
> +                                          RegScavenger *RS) const {<br>
> +  assert(SPAdj == 0 && "Unexpected SPAdj value");<br>
> +<br>
> +  MachineInstr &MI = *II;<br>
> +  DebugLoc dl = MI.getDebugLoc();<br>
> +  MachineBasicBlock &MBB = *MI.getParent();<br>
> +  const MachineFunction &MF = *MBB.getParent();<br>
> +  const AVRTargetMachine &TM = (const AVRTargetMachine &)MF.getTarget();<br>
> +  const TargetInstrInfo &TII = *TM.getSubtargetImpl()->getInstrInfo();<br>
> +  const MachineFrameInfo *MFI = MF.getFrameInfo();<br>
> +  const TargetFrameLowering *TFI = TM.getSubtargetImpl()->getFrameLowering();<br>
> +  int FrameIndex = MI.getOperand(FIOperandNum).getIndex();<br>
> +  int Offset = MFI->getObjectOffset(FrameIndex);<br>
> +<br>
> +  // Add one to the offset because SP points to an empty slot.<br>
> +  Offset += MFI->getStackSize() - TFI->getOffsetOfLocalArea() + 1;<br>
> +  // Fold incoming offset.<br>
> +  Offset += MI.getOperand(FIOperandNum + 1).getImm();<br>
> +<br>
> +  // This is actually "load effective address" of the stack slot<br>
> +  // instruction. We have only two-address instructions, thus we need to<br>
> +  // expand it into move + add.<br>
> +  if (MI.getOpcode() == AVR::FRMIDX) {<br>
> +    MI.setDesc(TII.get(AVR::MOVWRdRr));<br>
> +    MI.getOperand(FIOperandNum).ChangeToRegister(AVR::R29R28, false);<br>
> +<br>
> +    assert(Offset > 0 && "Invalid offset");<br>
> +<br>
> +    // We need to materialize the offset via an add instruction.<br>
> +    unsigned Opcode;<br>
> +    unsigned DstReg = MI.getOperand(0).getReg();<br>
> +    assert(DstReg != AVR::R29R28 && "Dest reg cannot be the frame pointer");<br>
> +<br>
> +    // Generally, to load a frame address two add instructions are emitted that<br>
> +    // could get folded into a single one:<br>
> +    //  movw    r31:r30, r29:r28<br>
> +    //  adiw    r31:r30, 29<br>
> +    //  adiw    r31:r30, 16<br>
> +    // to:<br>
> +    //  movw    r31:r30, r29:r28<br>
> +    //  adiw    r31:r30, 45<br>
> +    foldFrameOffset(*std::next(II), Offset, DstReg);<br>
> +<br>
> +    // Select the best opcode based on DstReg and the offset size.<br>
> +    switch (DstReg) {<br>
> +    case AVR::R25R24:<br>
> +    case AVR::R27R26:<br>
> +    case AVR::R31R30: {<br>
> +      if (isUInt<6>(Offset)) {<br>
> +        Opcode = AVR::ADIWRdK;<br>
> +        break;<br>
> +      }<br>
> +      // Fallthrough<br>
> +    }<br>
> +    default: {<br>
> +      // This opcode will get expanded into a pair of subi/sbci.<br>
> +      Opcode = AVR::SUBIWRdK;<br>
> +      Offset = -Offset;<br>
> +      break;<br>
> +    }<br>
> +    }<br>
> +<br>
> +    MachineInstr *New = BuildMI(MBB, std::next(II), dl, TII.get(Opcode), DstReg)<br>
> +                            .addReg(DstReg, RegState::Kill)<br>
> +                            .addImm(Offset);<br>
> +    New->getOperand(3).setIsDead();<br>
> +<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  // If the offset is too big we have to adjust and restore the frame pointer<br>
> +  // to materialize a valid load/store with displacement.<br>
> +  //:TODO: consider using only one adiw/sbiw chain for more than one frame index<br>
> +  if (Offset >= 63) {<br>
> +    unsigned AddOpc = AVR::ADIWRdK, SubOpc = AVR::SBIWRdK;<br>
> +    int AddOffset = Offset - 63 + 1;<br>
> +<br>
> +    // For huge offsets where adiw/sbiw cannot be used use a pair of subi/sbci.<br>
> +    if ((Offset - 63 + 1) > 63) {<br>
> +      AddOpc = AVR::SUBIWRdK;<br>
> +      SubOpc = AVR::SUBIWRdK;<br>
> +      AddOffset = -AddOffset;<br>
> +    }<br>
> +<br>
> +    // It is possible that the spiller places this frame instruction in between<br>
> +    // a compare and branch, invalidating the contents of SREG set by the<br>
> +    // compare instruction because of the add/sub pairs. Conservatively save and<br>
> +    // restore SREG before and after each add/sub pair.<br>
> +    BuildMI(MBB, II, dl, TII.get(AVR::INRdA), AVR::R0).addImm(0x3f);<br>
> +<br>
> +    MachineInstr *New = BuildMI(MBB, II, dl, TII.get(AddOpc), AVR::R29R28)<br>
> +                            .addReg(AVR::R29R28, RegState::Kill)<br>
> +                            .addImm(AddOffset);<br>
> +    New->getOperand(3).setIsDead();<br>
> +<br>
> +    // Restore SREG.<br>
> +    BuildMI(MBB, std::next(II), dl, TII.get(AVR::OUTARr))<br>
> +        .addImm(0x3f)<br>
> +        .addReg(AVR::R0, RegState::Kill);<br>
> +<br>
> +    // No need to set SREG as dead here otherwise if the next instruction is a<br>
> +    // cond branch it will be using a dead register.<br>
> +    New = BuildMI(MBB, std::next(II), dl, TII.get(SubOpc), AVR::R29R28)<br>
> +              .addReg(AVR::R29R28, RegState::Kill)<br>
> +              .addImm(Offset - 63 + 1);<br>
> +<br>
> +    Offset = 62;<br>
> +  }<br>
> +<br>
> +  MI.getOperand(FIOperandNum).ChangeToRegister(AVR::R29R28, false);<br>
> +  assert(isUInt<6>(Offset) && "Offset is out of range");<br>
> +  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);<br>
> +}<br>
> +<br>
> +unsigned AVRRegisterInfo::getFrameRegister(const MachineFunction &MF) const {<br>
> +  const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();<br>
> +  if (TFI->hasFP(MF)) {<br>
> +    // The Y pointer register<br>
> +    return AVR::R28;<br>
> +  }<br>
> +<br>
> +  return AVR::SP;<br>
> +}<br>
> +<br>
> +const TargetRegisterClass *<br>
> +AVRRegisterInfo::getPointerRegClass(const MachineFunction &MF,<br>
> +                                    unsigned Kind) const {<br>
> +  // FIXME: Currently we're using avr-gcc as reference, so we restrict<br>
> +  // ptrs to Y and Z regs. Though avr-gcc has buggy implementation<br>
> +  // of memory constraint, so we can fix it and bit avr-gcc here ;-)<br>
> +  return &AVR::PTRDISPREGSRegClass;<br>
> +}<br>
> +<br>
> +} // end of namespace llvm<br>
><br>
> Added: llvm/trunk/lib/Target/AVR/AVRRegisterInfo.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRRegisterInfo.h?rev=268722&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRRegisterInfo.h?rev=268722&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Target/AVR/AVRRegisterInfo.h (added)<br>
> +++ llvm/trunk/lib/Target/AVR/AVRRegisterInfo.h Fri May  6 05:12:31 2016<br>
> @@ -0,0 +1,56 @@<br>
> +//===-- AVRRegisterInfo.h - AVR Register Information Impl -------*- C++ -*-===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// This file contains the AVR implementation of the TargetRegisterInfo class.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#ifndef LLVM_AVR_REGISTER_INFO_H<br>
> +#define LLVM_AVR_REGISTER_INFO_H<br>
> +<br>
> +#include "llvm/Target/TargetRegisterInfo.h"<br>
> +<br>
> +#define GET_REGINFO_HEADER<br>
> +#include "AVRGenRegisterInfo.inc"<br>
> +<br>
> +namespace llvm {<br>
> +<br>
> +/// Utilities relating to AVR registers.<br>
> +class AVRRegisterInfo : public AVRGenRegisterInfo {<br>
> +public:<br>
> +  AVRRegisterInfo();<br>
> +<br>
> +public:<br>
> +  const uint16_t *<br>
> +  getCalleeSavedRegs(const MachineFunction *MF = 0) const override;<br>
> +  const uint32_t *getCallPreservedMask(const MachineFunction &MF,<br>
> +                                       CallingConv::ID CC) const override;<br>
> +  BitVector getReservedRegs(const MachineFunction &MF) const override;<br>
> +<br>
> +  const TargetRegisterClass *<br>
> +  getLargestLegalSuperClass(const TargetRegisterClass *RC,<br>
> +                            const MachineFunction &MF) const override;<br>
> +<br>
> +  /// Stack Frame Processing Methods<br>
> +  void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj,<br>
> +                           unsigned FIOperandNum,<br>
> +                           RegScavenger *RS = NULL) const override;<br>
> +<br>
> +  /// Debug information queries.<br>
> +  unsigned getFrameRegister(const MachineFunction &MF) const override;<br>
> +<br>
> +  /// Returns a TargetRegisterClass used for pointer values.<br>
> +  const TargetRegisterClass *<br>
> +  getPointerRegClass(const MachineFunction &MF,<br>
> +                     unsigned Kind = 0) const override;<br>
> +};<br>
> +<br>
> +} // end namespace llvm<br>
> +<br>
> +#endif // LLVM_AVR_REGISTER_INFO_H<br>
><br>
> Added: llvm/trunk/lib/Target/AVR/AVRSubtarget.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRSubtarget.cpp?rev=268722&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRSubtarget.cpp?rev=268722&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Target/AVR/AVRSubtarget.cpp (added)<br>
> +++ llvm/trunk/lib/Target/AVR/AVRSubtarget.cpp Fri May  6 05:12:31 2016<br>
> @@ -0,0 +1,47 @@<br>
> +//===-- AVRSubtarget.cpp - AVR Subtarget Information ----------------------===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// This file implements the AVR specific subclass of TargetSubtargetInfo.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#include "AVRSubtarget.h"<br>
> +<br>
> +#include "llvm/Support/ELF.h"<br>
> +#include "llvm/Support/TargetRegistry.h"<br>
> +<br>
> +#include "AVR.h"<br>
> +#include "AVRTargetMachine.h"<br>
> +#include "MCTargetDesc/AVRMCTargetDesc.h"<br>
> +<br>
> +#define DEBUG_TYPE "avr-subtarget"<br>
> +<br>
> +#define GET_SUBTARGETINFO_TARGET_DESC<br>
> +#define GET_SUBTARGETINFO_CTOR<br>
> +#include "AVRGenSubtargetInfo.inc"<br>
> +<br>
> +namespace llvm {<br>
> +<br>
> +AVRSubtarget::AVRSubtarget(const Triple &TT, const std::string &CPU,<br>
> +                           const std::string &FS, AVRTargetMachine &TM)<br>
> +    : AVRGenSubtargetInfo(TT, CPU, FS), InstrInfo(), FrameLowering(),<br>
> +      TLInfo(TM), TSInfo(),<br>
> +<br>
> +      // Subtarget features<br>
> +      m_hasSRAM(false), m_hasJMPCALL(false), m_hasIJMPCALL(false),<br>
> +      m_hasEIJMPCALL(false), m_hasADDSUBIW(false), m_hasSmallStack(false),<br>
> +      m_hasMOVW(false), m_hasLPM(false), m_hasLPMX(false),  m_hasELPM(false),<br>
> +      m_hasELPMX(false), m_hasSPM(false), m_hasSPMX(false), m_hasDES(false),<br>
> +      m_supportsRMW(false), m_supportsMultiplication(false), m_hasBREAK(false),<br>
> +      m_hasTinyEncoding(false), ELFArch(false), m_FeatureSetDummy(false) {<br>
> +  // Parse features string.<br>
> +  ParseSubtargetFeatures(CPU, FS);<br>
> +}<br>
> +<br>
> +} // end of namespace llvm<br>
><br>
> Added: llvm/trunk/lib/Target/AVR/AVRSubtarget.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRSubtarget.h?rev=268722&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRSubtarget.h?rev=268722&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Target/AVR/AVRSubtarget.h (added)<br>
> +++ llvm/trunk/lib/Target/AVR/AVRSubtarget.h Fri May  6 05:12:31 2016<br>
> @@ -0,0 +1,121 @@<br>
> +//===-- AVRSubtarget.h - Define Subtarget for the AVR -----------*- C++ -*-===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// This file declares the AVR specific subclass of TargetSubtargetInfo.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#ifndef LLVM_AVR_SUBTARGET_H<br>
> +#define LLVM_AVR_SUBTARGET_H<br>
> +<br>
> +#include "AVRConfig.h"<br>
> +<br>
> +#include "llvm/Target/TargetSubtargetInfo.h"<br>
> +#include "llvm/IR/DataLayout.h"<br>
> +#include "llvm/IR/DataLayout.h"<br>
> +#include "llvm/Target/TargetMachine.h"<br>
> +<br>
> +#include "AVRFrameLowering.h"<br>
> +#include "AVRISelLowering.h"<br>
> +#include "AVRInstrInfo.h"<br>
> +#include "AVRSelectionDAGInfo.h"<br>
> +<br>
> +#define GET_SUBTARGETINFO_HEADER<br>
> +#include "AVRGenSubtargetInfo.inc"<br>
> +<br>
> +namespace llvm {<br>
> +<br>
> +/// A specific AVR target MCU.<br>
> +class AVRSubtarget : public AVRGenSubtargetInfo {<br>
> +public:<br>
> +  //! Creates an AVR subtarget.<br>
> +  //! \param TT  The target triple.<br>
> +  //! \param CPU The CPU to target.<br>
> +  //! \param FS  The feature string.<br>
> +  //! \param TM  The target machine.<br>
> +  AVRSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS,<br>
> +               AVRTargetMachine &TM);<br>
> +<br>
> +  const AVRInstrInfo *getInstrInfo() const override { return &InstrInfo; }<br>
> +  const TargetFrameLowering *getFrameLowering() const override { return &FrameLowering; }<br>
> +  const AVRTargetLowering *getTargetLowering() const override { return &TLInfo; }<br>
> +  const AVRSelectionDAGInfo *getSelectionDAGInfo() const override { return &TSInfo; }<br>
> +  const AVRRegisterInfo *getRegisterInfo() const override { return &InstrInfo.getRegisterInfo(); }<br>
> +<br>
> +  /// Parses a subtarget feature string, setting appropriate options.<br>
> +  /// \note Definition of function is auto generated by `tblgen`.<br>
> +  void ParseSubtargetFeatures(StringRef CPU, StringRef FS);<br>
> +<br>
> +  // Subtarget feature getters.<br>
> +  // See AVR.td for details.<br>
> +  bool hasSRAM() const { return m_hasSRAM; }<br>
> +  bool hasJMPCALL() const { return m_hasJMPCALL; }<br>
> +  bool hasIJMPCALL() const { return m_hasIJMPCALL; }<br>
> +  bool hasEIJMPCALL() const { return m_hasEIJMPCALL; }<br>
> +  bool hasADDSUBIW() const { return m_hasADDSUBIW; }<br>
> +  bool hasSmallStack() const { return m_hasSmallStack; }<br>
> +  bool hasMOVW() const { return m_hasMOVW; }<br>
> +  bool hasLPM() const { return m_hasLPM; }<br>
> +  bool hasLPMX() const { return m_hasLPMX; }<br>
> +  bool hasELPM() const { return m_hasELPM; }<br>
> +  bool hasELPMX() const { return m_hasELPMX; }<br>
> +  bool hasSPM() const { return m_hasSPM; }<br>
> +  bool hasSPMX() const { return m_hasSPMX; }<br>
> +  bool hasDES() const { return m_hasDES; }<br>
> +  bool supportsRMW() const { return m_supportsRMW; }<br>
> +  bool supportsMultiplication() const { return m_supportsMultiplication; }<br>
> +  bool hasBREAK() const { return m_hasBREAK; }<br>
> +  bool hasTinyEncoding() const { return m_hasTinyEncoding; }<br>
> +<br>
> +  /// Gets the ELF architecture for the e_flags field<br>
> +  /// of an ELF object file.<br>
> +  unsigned getELFArch() const {<br>
> +    assert(ELFArch != 0 &&<br>
> +           "every device must have an associate ELF architecture");<br>
> +    return ELFArch;<br>
> +  }<br>
> +<br>
> +private:<br>
> +  AVRInstrInfo InstrInfo;<br>
> +  AVRFrameLowering FrameLowering;<br>
> +  AVRTargetLowering TLInfo;<br>
> +  AVRSelectionDAGInfo TSInfo;<br>
> +<br>
> +  // Subtarget feature settings<br>
> +  // See AVR.td for details.<br>
> +  bool m_hasSRAM;<br>
> +  bool m_hasJMPCALL;<br>
> +  bool m_hasIJMPCALL;<br>
> +  bool m_hasEIJMPCALL;<br>
> +  bool m_hasADDSUBIW;<br>
> +  bool m_hasSmallStack;<br>
> +  bool m_hasMOVW;<br>
> +  bool m_hasLPM;<br>
> +  bool m_hasLPMX;<br>
> +  bool m_hasELPM;<br>
> +  bool m_hasELPMX;<br>
> +  bool m_hasSPM;<br>
> +  bool m_hasSPMX;<br>
> +  bool m_hasDES;<br>
> +  bool m_supportsRMW;<br>
> +  bool m_supportsMultiplication;<br>
> +  bool m_hasBREAK;<br>
> +  bool m_hasTinyEncoding;<br>
> +<br>
> +  /// The ELF e_flags architecture.<br>
> +  unsigned ELFArch;<br>
> +<br>
> +  // Dummy member, used by FeatureSet's. We cannot have a SubtargetFeature with<br>
> +  // no variable, so we instead bind pseudo features to this variable.<br>
> +  bool m_FeatureSetDummy;<br>
> +};<br>
> +<br>
> +} // end namespace llvm<br>
> +<br>
> +#endif // LLVM_AVR_SUBTARGET_H<br>
><br>
> Modified: llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp?rev=268722&r1=268721&r2=268722&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp?rev=268722&r1=268721&r2=268722&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp (original)<br>
> +++ llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp Fri May  6 05:12:31 2016<br>
> @@ -1,4 +1,100 @@<br>
> +//===-- AVRTargetMachine.cpp - Define TargetMachine for AVR ---------------===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// This file defines the AVR specific subclass of TargetMachine.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#include "AVRTargetMachine.h"<br>
> +<br>
> +#include "llvm/CodeGen/Passes.h"<br>
> +#include "llvm/IR/Module.h"<br>
> +#include "llvm/IR/LegacyPassManager.h"<br>
> +#include "llvm/Support/TargetRegistry.h"<br>
> +<br>
> +#include "AVRTargetObjectFile.h"<br>
> +#include "AVR.h"<br>
> +#include "MCTargetDesc/AVRMCTargetDesc.h"<br>
> +<br>
> +namespace llvm {<br>
> +<br>
> +/// Processes a CPU name.<br>
> +static StringRef getTargetCPU(StringRef CPU) {<br>
> +  if (CPU.empty() || CPU == "generic") {<br>
> +    return "avr2";<br>
> +  }<br>
> +<br>
> +  return CPU;<br>
> +}<br>
> +<br>
> +AVRTargetMachine::AVRTargetMachine(const Target &T, const Triple &TT,<br>
> +                                   StringRef CPU, StringRef FS,<br>
> +                                   const TargetOptions &Options,<br>
> +                                   Reloc::Model RM, CodeModel::Model CM,<br>
> +                                   CodeGenOpt::Level OL)<br>
> +    : LLVMTargetMachine(<br>
> +          T, "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-i64:8:8-f32:8:8-f64:8:8-n8", TT,<br>
> +          getTargetCPU(CPU), FS, Options, RM, CM, OL),<br>
> +      SubTarget(TT, GetTargetCPU(CPU), FS, *this) {<br>
<br>
</div></div>There is no function called GetTargetCPU. I assume this is supposed to<br>
be calling getTargetCPU like above, but that doesn't really work either<br>
since TargetMachine has a member function called getTargetCPU that<br>
resolves first but doesn't match the signature.<br>
<div class="HOEnZb"><div class="h5"><br>
> +  this->TLOF = make_unique<AVRTargetObjectFile>();<br>
> +  initAsmInfo();<br>
> +}<br>
> +<br>
> +namespace {<br>
> +/// AVR Code Generator Pass Configuration Options.<br>
> +class AVRPassConfig : public TargetPassConfig {<br>
> +public:<br>
> +  AVRPassConfig(AVRTargetMachine *TM, PassManagerBase &PM)<br>
> +      : TargetPassConfig(TM, PM) {}<br>
> +<br>
> +  AVRTargetMachine &getAVRTargetMachine() const {<br>
> +    return getTM<AVRTargetMachine>();<br>
> +  }<br>
> +<br>
> +  bool addInstSelector() override;<br>
> +  void addPreSched2() override;<br>
> +  void addPreRegAlloc() override;<br>
> +  void addPreEmitPass() override;<br>
> +};<br>
> +} // namespace<br>
> +<br>
> +TargetPassConfig *AVRTargetMachine::createPassConfig(PassManagerBase &PM) {<br>
> +  return new AVRPassConfig(this, PM);<br>
> +}<br>
><br>
>  extern "C" void LLVMInitializeAVRTarget() {<br>
> +  // Register the target.<br>
> +  RegisterTargetMachine<AVRTargetMachine> X(TheAVRTarget);<br>
> +}<br>
> +<br>
> +const AVRSubtarget *AVRTargetMachine::getSubtargetImpl() const {<br>
> +  return &SubTarget;<br>
> +}<br>
> +<br>
> +const AVRSubtarget *AVRTargetMachine::getSubtargetImpl(const Function &) const {<br>
> +  return &SubTarget;<br>
> +}<br>
> +<br>
> +//===----------------------------------------------------------------------===//<br>
> +// Pass Pipeline Configuration<br>
> +//===----------------------------------------------------------------------===//<br>
><br>
> +bool AVRPassConfig::addInstSelector() {<br>
> +  return false;<br>
>  }<br>
> +<br>
> +void AVRPassConfig::addPreRegAlloc() {<br>
> +}<br>
> +<br>
> +void AVRPassConfig::addPreSched2() { }<br>
> +<br>
> +void AVRPassConfig::addPreEmitPass() {<br>
> +}<br>
> +<br>
> +} // end of namespace llvm<br>
><br>
> Added: llvm/trunk/lib/Target/AVR/AVRTargetMachine.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRTargetMachine.h?rev=268722&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRTargetMachine.h?rev=268722&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Target/AVR/AVRTargetMachine.h (added)<br>
> +++ llvm/trunk/lib/Target/AVR/AVRTargetMachine.h Fri May  6 05:12:31 2016<br>
> @@ -0,0 +1,56 @@<br>
> +//===-- AVRTargetMachine.h - Define TargetMachine for AVR -------*- C++ -*-===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// This file declares the AVR specific subclass of TargetMachine.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#ifndef LLVM_AVR_TARGET_MACHINE_H<br>
> +#define LLVM_AVR_TARGET_MACHINE_H<br>
> +<br>
> +#include "AVRConfig.h"<br>
> +<br>
> +#include "llvm/IR/DataLayout.h"<br>
> +#include "llvm/Target/TargetMachine.h"<br>
> +<br>
> +#include "AVRFrameLowering.h"<br>
> +#include "AVRISelLowering.h"<br>
> +#include "AVRInstrInfo.h"<br>
> +#include "AVRSelectionDAGInfo.h"<br>
> +#include "AVRSubtarget.h"<br>
> +<br>
> +namespace llvm {<br>
> +<br>
> +/**<br>
> + * A generic AVR implementation.<br>
> + */<br>
> +class AVRTargetMachine : public LLVMTargetMachine {<br>
> +public:<br>
> +  AVRTargetMachine(const Target &T, const Triple &TT, StringRef CPU,<br>
> +                   StringRef FS, const TargetOptions &Options, Reloc::Model RM,<br>
> +                   CodeModel::Model CM, CodeGenOpt::Level OL);<br>
> +<br>
> +  const AVRSubtarget *getSubtargetImpl() const;<br>
> +  const AVRSubtarget *getSubtargetImpl(const Function &) const override;<br>
> +<br>
> +  TargetLoweringObjectFile *getObjFileLowering() const override {<br>
> +    return this->TLOF.get();<br>
> +  }<br>
> +<br>
> +  // Pass Pipeline Configuration.<br>
> +  TargetPassConfig *createPassConfig(PassManagerBase &PM) override;<br>
> +<br>
> +private:<br>
> +  std::unique_ptr<TargetLoweringObjectFile> TLOF;<br>
> +  AVRSubtarget SubTarget;<br>
> +};<br>
> +<br>
> +} // end namespace llvm<br>
> +<br>
> +#endif // LLVM_AVR_TARGET_MACHINE_H<br>
><br>
> Modified: llvm/trunk/lib/Target/AVR/CMakeLists.txt<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/CMakeLists.txt?rev=268722&r1=268721&r2=268722&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/CMakeLists.txt?rev=268722&r1=268721&r2=268722&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Target/AVR/CMakeLists.txt (original)<br>
> +++ llvm/trunk/lib/Target/AVR/CMakeLists.txt Fri May  6 05:12:31 2016<br>
> @@ -3,11 +3,15 @@ set(LLVM_TARGET_DEFINITIONS AVR.td)<br>
>  tablegen(LLVM AVRGenRegisterInfo.inc -gen-register-info)<br>
>  tablegen(LLVM AVRGenInstrInfo.inc -gen-instr-info)<br>
>  tablegen(LLVM AVRGenCallingConv.inc -gen-callingconv)<br>
> +tablegen(LLVM AVRGenSubtargetInfo.inc -gen-subtarget)<br>
>  add_public_tablegen_target(AVRCommonTableGen)<br>
><br>
>  add_llvm_target(AVRCodeGen<br>
>      AVRTargetMachine.cpp<br>
>      AVRTargetObjectFile.cpp<br>
> +    AVRSubtarget.cpp<br>
> +    AVRInstrInfo.cpp<br>
> +    AVRRegisterInfo.cpp<br>
>    )<br>
><br>
>  add_dependencies(LLVMAVRCodeGen intrinsics_gen)<br>
><br>
> Added: llvm/trunk/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h?rev=268722&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h?rev=268722&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h (added)<br>
> +++ llvm/trunk/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h Fri May  6 05:12:31 2016<br>
> @@ -0,0 +1,65 @@<br>
> +//===-- AVRMCTargetDesc.h - AVR Target Descriptions -------------*- C++ -*-===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// This file provides AVR specific target descriptions.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#ifndef LLVM_AVR_MCTARGET_DESC_H<br>
> +#define LLVM_AVR_MCTARGET_DESC_H<br>
> +<br>
> +#include "AVRConfig.h"<br>
> +<br>
> +#include "llvm/Support/DataTypes.h"<br>
> +<br>
> +namespace llvm {<br>
> +<br>
> +class MCAsmBackend;<br>
> +class MCCodeEmitter;<br>
> +class MCContext;<br>
> +class MCInstrInfo;<br>
> +class MCObjectWriter;<br>
> +class MCRegisterInfo;<br>
> +class StringRef;<br>
> +class Target;<br>
> +class Triple;<br>
> +class raw_pwrite_stream;<br>
> +<br>
> +extern Target TheAVRTarget;<br>
> +<br>
> +/**<br>
> + * Creates a machine code emitter for AVR.<br>
> + */<br>
> +MCCodeEmitter *createAVRMCCodeEmitter(const MCInstrInfo &MCII,<br>
> +                                      const MCRegisterInfo &MRI,<br>
> +                                      MCContext &Ctx);<br>
> +<br>
> +/**<br>
> + * Creates an assembly backend for AVR.<br>
> + */<br>
> +MCAsmBackend *createAVRAsmBackend(const Target &T, const MCRegisterInfo &MRI,<br>
> +                                  const Triple &TT, StringRef CPU);<br>
> +<br>
> +/**<br>
> + * Creates an ELF object writer for AVR.<br>
> + */<br>
> +MCObjectWriter *createAVRELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI);<br>
> +<br>
> +} // end namespace llvm<br>
> +<br>
> +#define GET_REGINFO_ENUM<br>
> +#include "AVRGenRegisterInfo.inc"<br>
> +<br>
> +#define GET_INSTRINFO_ENUM<br>
> +#include "AVRGenInstrInfo.inc"<br>
> +<br>
> +#define GET_SUBTARGETINFO_ENUM<br>
> +#include "AVRGenSubtargetInfo.inc"<br>
> +<br>
> +#endif // LLVM_AVR_MCTARGET_DESC_H<br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org">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/mailman/listinfo/llvm-commits</a><br>
</div></div></blockquote></div><br></div>