-//===- XCoreInstrInfo.cpp - XCore Instruction Information -------*- C++ -*-===//
+//===-- XCoreInstrInfo.cpp - XCore Instruction Information ----------------===//
//
// The LLVM Compiler Infrastructure
//
//
//===----------------------------------------------------------------------===//
-#include "XCoreMachineFunctionInfo.h"
#include "XCoreInstrInfo.h"
#include "XCore.h"
+#include "XCoreMachineFunctionInfo.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineLocation.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "XCoreGenInstrInfo.inc"
+#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"
+
+#define GET_INSTRINFO_CTOR_DTOR
+#include "XCoreGenInstrInfo.inc"
namespace llvm {
namespace XCore {
using namespace llvm;
-XCoreInstrInfo::XCoreInstrInfo(void)
- : TargetInstrInfoImpl(XCoreInsts, array_lengthof(XCoreInsts)),
- RI(*this) {
+
+// Pin the vtable to this file.
+void XCoreInstrInfo::anchor() {}
+
+XCoreInstrInfo::XCoreInstrInfo()
+ : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP),
+ RI() {
}
static bool isZeroImm(const MachineOperand &op) {
return op.isImm() && op.getImm() == 0;
}
-/// Return true if the instruction is a register to register move and
-/// leave the source and dest operands in the passed parameters.
-///
-bool XCoreInstrInfo::isMoveInstr(const MachineInstr &MI,
- unsigned &SrcReg, unsigned &DstReg,
- unsigned &SrcSR, unsigned &DstSR) const {
- SrcSR = DstSR = 0; // No sub-registers.
-
- // We look for 4 kinds of patterns here:
- // add dst, src, 0
- // sub dst, src, 0
- // or dst, src, src
- // and dst, src, src
- if ((MI.getOpcode() == XCore::ADD_2rus || MI.getOpcode() == XCore::SUB_2rus)
- && isZeroImm(MI.getOperand(2))) {
- DstReg = MI.getOperand(0).getReg();
- SrcReg = MI.getOperand(1).getReg();
- return true;
- } else if ((MI.getOpcode() == XCore::OR_3r || MI.getOpcode() == XCore::AND_3r)
- && MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
- DstReg = MI.getOperand(0).getReg();
- SrcReg = MI.getOperand(1).getReg();
- return true;
- }
- return false;
-}
-
/// isLoadFromStackSlot - If the specified machine instruction is a direct
/// load from a stack slot, return the virtual or physical register number of
/// the destination along with the FrameIndex of the loaded stack slot. If
return 0;
}
-/// isInvariantLoad - Return true if the specified instruction (which is marked
-/// mayLoad) is loading from a location whose value is invariant across the
-/// function. For example, loading a value from the constant pool or from
-/// from the argument area of a function if it does not change. This should
-/// only return true of *all* loads the instruction does are invariant (if it
-/// does multiple loads).
-bool
-XCoreInstrInfo::isInvariantLoad(const MachineInstr *MI) const {
- // Loads from constants pools and loads from invariant argument slots are
- // invariant
- int Opcode = MI->getOpcode();
- if (Opcode == XCore::LDWCP_ru6 || Opcode == XCore::LDWCP_lru6) {
- return MI->getOperand(1).isCPI();
- }
- int FrameIndex;
- if (isLoadFromStackSlot(MI, FrameIndex)) {
- const MachineFrameInfo &MFI =
- *MI->getParent()->getParent()->getFrameInfo();
- return MFI.isFixedObjectIndex(FrameIndex) &&
- MFI.isImmutableObjectIndex(FrameIndex);
- }
- return false;
-}
-
//===----------------------------------------------------------------------===//
// Branch Analysis
//===----------------------------------------------------------------------===//
return IsBRF(BrOpc) || IsBRT(BrOpc);
}
+static inline bool IsBR_JT(unsigned BrOpc) {
+ return BrOpc == XCore::BR_JT
+ || BrOpc == XCore::BR_JT32;
+}
+
/// GetCondFromBranchOpc - Return the XCore CC that matches
/// the correspondent Branch instruction opcode.
static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc)
static inline unsigned GetCondBranchFromCond(XCore::CondCode CC)
{
switch (CC) {
- default: assert(0 && "Illegal condition code!");
+ default: llvm_unreachable("Illegal condition code!");
case XCore::COND_TRUE : return XCore::BRFT_lru6;
case XCore::COND_FALSE : return XCore::BRFF_lru6;
}
static inline XCore::CondCode GetOppositeBranchCondition(XCore::CondCode CC)
{
switch (CC) {
- default: assert(0 && "Illegal condition code!");
+ default: llvm_unreachable("Illegal condition code!");
case XCore::COND_TRUE : return XCore::COND_FALSE;
case XCore::COND_FALSE : return XCore::COND_TRUE;
}
bool AllowModify) const {
// If the block has no terminators, it just falls into the block after it.
MachineBasicBlock::iterator I = MBB.end();
- if (I == MBB.begin() || !isUnpredicatedTerminator(--I))
+ if (I == MBB.begin())
+ return false;
+ --I;
+ while (I->isDebugValue()) {
+ if (I == MBB.begin())
+ return false;
+ --I;
+ }
+ if (!isUnpredicatedTerminator(I))
return false;
// Get the last instruction in the block.
return false;
}
+ // Likewise if it ends with a branch table followed by an unconditional branch.
+ if (IsBR_JT(SecondLastInst->getOpcode()) && IsBRU(LastInst->getOpcode())) {
+ I = LastInst;
+ if (AllowModify)
+ I->eraseFromParent();
+ return true;
+ }
+
// Otherwise, can't handle this.
return true;
}
unsigned
XCoreInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB,
MachineBasicBlock *FBB,
- const SmallVectorImpl<MachineOperand> &Cond)const{
+ const SmallVectorImpl<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() == 2 || Cond.size() == 0) &&
if (FBB == 0) { // One way branch.
if (Cond.empty()) {
// Unconditional branch
- BuildMI(&MBB, get(XCore::BRFU_lu6)).addMBB(TBB);
+ BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(TBB);
} else {
// Conditional branch.
unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
- BuildMI(&MBB, get(Opc)).addReg(Cond[1].getReg())
+ BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
.addMBB(TBB);
}
return 1;
// Two-way Conditional branch.
assert(Cond.size() == 2 && "Unexpected number of components!");
unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
- BuildMI(&MBB, get(Opc)).addReg(Cond[1].getReg())
+ BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
.addMBB(TBB);
- BuildMI(&MBB, get(XCore::BRFU_lu6)).addMBB(FBB);
+ BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(FBB);
return 2;
}
MachineBasicBlock::iterator I = MBB.end();
if (I == MBB.begin()) return 0;
--I;
+ while (I->isDebugValue()) {
+ if (I == MBB.begin())
+ return 0;
+ --I;
+ }
if (!IsBRU(I->getOpcode()) && !IsCondBranch(I->getOpcode()))
return 0;
return 2;
}
-bool XCoreInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- unsigned DestReg, unsigned SrcReg,
- const TargetRegisterClass *DestRC,
- const TargetRegisterClass *SrcRC) const {
- if (DestRC == SrcRC) {
- if (DestRC == XCore::GRRegsRegisterClass) {
- BuildMI(MBB, I, get(XCore::ADD_2rus), DestReg).addReg(SrcReg).addImm(0);
- return true;
- } else {
- return false;
- }
+void XCoreInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I, DebugLoc DL,
+ unsigned DestReg, unsigned SrcReg,
+ bool KillSrc) const {
+ bool GRDest = XCore::GRRegsRegClass.contains(DestReg);
+ bool GRSrc = XCore::GRRegsRegClass.contains(SrcReg);
+
+ if (GRDest && GRSrc) {
+ BuildMI(MBB, I, DL, get(XCore::ADD_2rus), DestReg)
+ .addReg(SrcReg, getKillRegState(KillSrc))
+ .addImm(0);
+ return;
}
- if (SrcRC == XCore::RRegsRegisterClass && SrcReg == XCore::SP &&
- DestRC == XCore::GRRegsRegisterClass) {
- BuildMI(MBB, I, get(XCore::LDAWSP_ru6), DestReg).addImm(0);
- return true;
+ if (GRDest && SrcReg == XCore::SP) {
+ BuildMI(MBB, I, DL, get(XCore::LDAWSP_ru6), DestReg).addImm(0);
+ return;
}
- if (DestRC == XCore::RRegsRegisterClass && DestReg == XCore::SP &&
- SrcRC == XCore::GRRegsRegisterClass) {
- BuildMI(MBB, I, get(XCore::SETSP_1r)).addReg(SrcReg);
- return true;
+
+ if (DestReg == XCore::SP && GRSrc) {
+ BuildMI(MBB, I, DL, get(XCore::SETSP_1r))
+ .addReg(SrcReg, getKillRegState(KillSrc));
+ return;
}
- return false;
+ llvm_unreachable("Impossible reg-to-reg copy");
}
void XCoreInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- unsigned SrcReg, bool isKill, int FrameIndex,
- const TargetRegisterClass *RC) const
-{
- BuildMI(MBB, I, get(XCore::STWFI)).addReg(SrcReg, false, false, isKill)
- .addFrameIndex(FrameIndex).addImm(0);
-}
-
-void XCoreInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
- bool isKill, SmallVectorImpl<MachineOperand> &Addr,
- const TargetRegisterClass *RC,
- SmallVectorImpl<MachineInstr*> &NewMIs) const
+ MachineBasicBlock::iterator I,
+ unsigned SrcReg, bool isKill,
+ int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const
{
- assert(0 && "unimplemented\n");
+ DebugLoc DL;
+ if (I != MBB.end()) DL = I->getDebugLoc();
+ MachineFunction *MF = MBB.getParent();
+ const MachineFrameInfo &MFI = *MF->getFrameInfo();
+ MachineMemOperand *MMO =
+ MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIndex),
+ MachineMemOperand::MOStore,
+ MFI.getObjectSize(FrameIndex),
+ MFI.getObjectAlignment(FrameIndex));
+ BuildMI(MBB, I, DL, get(XCore::STWFI))
+ .addReg(SrcReg, getKillRegState(isKill))
+ .addFrameIndex(FrameIndex)
+ .addImm(0)
+ .addMemOperand(MMO);
}
void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- unsigned DestReg, int FrameIndex,
- const TargetRegisterClass *RC) const
-{
- BuildMI(MBB, I, get(XCore::LDWFI), DestReg).addFrameIndex(FrameIndex)
- .addImm(0);
-}
-
-void XCoreInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
- SmallVectorImpl<MachineOperand> &Addr,
- const TargetRegisterClass *RC,
- SmallVectorImpl<MachineInstr*> &NewMIs) const
-{
- assert(0 && "unimplemented\n");
-}
-
-bool XCoreInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- const std::vector<CalleeSavedInfo> &CSI) const
+ MachineBasicBlock::iterator I,
+ unsigned DestReg, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const
{
- if (CSI.empty()) {
- return true;
- }
+ DebugLoc DL;
+ if (I != MBB.end()) DL = I->getDebugLoc();
MachineFunction *MF = MBB.getParent();
- const MachineFrameInfo *MFI = MF->getFrameInfo();
- MachineModuleInfo *MMI = MFI->getMachineModuleInfo();
- XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>();
-
- bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF);
-
- for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
- it != CSI.end(); ++it) {
- // Add the callee-saved register as live-in. It's killed at the spill.
- MBB.addLiveIn(it->getReg());
-
- storeRegToStackSlot(MBB, MI, it->getReg(), true,
- it->getFrameIdx(), it->getRegClass());
- if (emitFrameMoves) {
- unsigned SaveLabelId = MMI->NextLabelID();
- BuildMI(MBB, MI, get(XCore::DBG_LABEL)).addImm(SaveLabelId);
- XFI->getSpillLabels().push_back(
- std::pair<unsigned, CalleeSavedInfo>(SaveLabelId, *it));
- }
- }
- return true;
-}
-
-bool XCoreInstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- const std::vector<CalleeSavedInfo> &CSI) const
-{
- bool AtStart = MI == MBB.begin();
- MachineBasicBlock::iterator BeforeI = MI;
- if (!AtStart)
- --BeforeI;
- for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
- it != CSI.end(); ++it) {
-
- loadRegFromStackSlot(MBB, MI, it->getReg(),
- it->getFrameIdx(),
- it->getRegClass());
- assert(MI != MBB.begin() &&
- "loadRegFromStackSlot didn't insert any code!");
- // Insert in reverse order. loadRegFromStackSlot can insert multiple
- // instructions.
- if (AtStart)
- MI = MBB.begin();
- else {
- MI = BeforeI;
- ++MI;
- }
- }
- return true;
-}
-
-/// BlockHasNoFallThrough - Analyse if MachineBasicBlock does not
-/// fall-through into its successor block.
-bool XCoreInstrInfo::
-BlockHasNoFallThrough(const MachineBasicBlock &MBB) const
-{
- if (MBB.empty()) return false;
-
- switch (MBB.back().getOpcode()) {
- case XCore::RETSP_u6: // Return.
- case XCore::RETSP_lu6:
- case XCore::BAU_1r: // Indirect branch.
- case XCore::BRFU_u6: // Uncond branch.
- case XCore::BRFU_lu6:
- case XCore::BRBU_u6:
- case XCore::BRBU_lu6:
- return true;
- default: return false;
- }
+ const MachineFrameInfo &MFI = *MF->getFrameInfo();
+ MachineMemOperand *MMO =
+ MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIndex),
+ MachineMemOperand::MOLoad,
+ MFI.getObjectSize(FrameIndex),
+ MFI.getObjectAlignment(FrameIndex));
+ BuildMI(MBB, I, DL, get(XCore::LDWFI), DestReg)
+ .addFrameIndex(FrameIndex)
+ .addImm(0)
+ .addMemOperand(MMO);
}
/// ReverseBranchCondition - Return the inverse opcode of the
/// specified Branch instruction.
bool XCoreInstrInfo::
-ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const
-{
+ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
assert((Cond.size() == 2) &&
"Invalid XCore branch condition!");
Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm()));
return false;
}
+
+static inline bool isImmU6(unsigned val) {
+ return val < (1 << 6);
+}
+
+static inline bool isImmU16(unsigned val) {
+ return val < (1 << 16);
+}
+
+MachineBasicBlock::iterator XCoreInstrInfo::loadImmediate(
+ MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ unsigned Reg, uint64_t Value) const {
+ DebugLoc dl;
+ if (MI != MBB.end()) dl = MI->getDebugLoc();
+ if (isMask_32(Value)) {
+ int N = Log2_32(Value) + 1;
+ return BuildMI(MBB, MI, dl, get(XCore::MKMSK_rus), Reg).addImm(N);
+ }
+ if (isImmU16(Value)) {
+ int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6;
+ return BuildMI(MBB, MI, dl, get(Opcode), Reg).addImm(Value);
+ }
+ MachineConstantPool *ConstantPool = MBB.getParent()->getConstantPool();
+ const Constant *C = ConstantInt::get(
+ Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Value);
+ unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
+ return BuildMI(MBB, MI, dl, get(XCore::LDWCP_lru6), Reg)
+ .addConstantPoolIndex(Idx);
+}