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