summaryrefslogtreecommitdiff
path: root/lib/Target/MSP430
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-10-23 14:19:52 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-10-23 14:19:52 +0000
commit4a142eb28942073eb27a112b5ca1cca3f01beb9c (patch)
tree22cc59e4b240d84c3a5a60531119c4eca914a256 /lib/Target/MSP430
parent5cd822fa9bbb9622241e3bf4d7674ed49ccde5b9 (diff)
Diffstat (limited to 'lib/Target/MSP430')
-rw-r--r--lib/Target/MSP430/AsmPrinter/CMakeLists.txt2
-rw-r--r--lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp63
-rw-r--r--lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp116
-rw-r--r--lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.h46
-rw-r--r--lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp147
-rw-r--r--lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.h49
-rw-r--r--lib/Target/MSP430/MSP430.h14
-rw-r--r--lib/Target/MSP430/MSP430ISelDAGToDAG.cpp292
-rw-r--r--lib/Target/MSP430/MSP430ISelLowering.cpp27
-rw-r--r--lib/Target/MSP430/MSP430InstrInfo.cpp165
-rw-r--r--lib/Target/MSP430/MSP430InstrInfo.h30
-rw-r--r--lib/Target/MSP430/MSP430InstrInfo.td4
-rw-r--r--lib/Target/MSP430/MSP430TargetMachine.cpp2
13 files changed, 853 insertions, 104 deletions
diff --git a/lib/Target/MSP430/AsmPrinter/CMakeLists.txt b/lib/Target/MSP430/AsmPrinter/CMakeLists.txt
index 6e6688746463..f1eb8851b656 100644
--- a/lib/Target/MSP430/AsmPrinter/CMakeLists.txt
+++ b/lib/Target/MSP430/AsmPrinter/CMakeLists.txt
@@ -1,6 +1,8 @@
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. )
add_llvm_library(LLVMMSP430AsmPrinter
+ MSP430InstPrinter.cpp
MSP430AsmPrinter.cpp
+ MSP430MCInstLower.cpp
)
add_dependencies(LLVMMSP430AsmPrinter MSP430CodeGenTable_gen)
diff --git a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp
index 852019febf5e..ace358e86d77 100644
--- a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp
+++ b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp
@@ -15,7 +15,9 @@
#define DEBUG_TYPE "asm-printer"
#include "MSP430.h"
#include "MSP430InstrInfo.h"
+#include "MSP430InstPrinter.h"
#include "MSP430MCAsmInfo.h"
+#include "MSP430MCInstLower.h"
#include "MSP430TargetMachine.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
@@ -26,12 +28,14 @@
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Mangler.h"
@@ -41,6 +45,10 @@ using namespace llvm;
STATISTIC(EmittedInsts, "Number of machine instrs printed");
+static cl::opt<bool>
+EnableMCInst("enable-msp430-mcinst-printer", cl::Hidden,
+ cl::desc("enable experimental mcinst gunk in the msp430 backend"));
+
namespace {
class VISIBILITY_HIDDEN MSP430AsmPrinter : public AsmPrinter {
public:
@@ -52,8 +60,14 @@ namespace {
return "MSP430 Assembly Printer";
}
+ void printMCInst(const MCInst *MI) {
+ MSP430InstPrinter(O, *MAI).printInstruction(MI);
+ }
void printOperand(const MachineInstr *MI, int OpNum,
const char* Modifier = 0);
+ void printPCRelImmOperand(const MachineInstr *MI, int OpNum) {
+ printOperand(MI, OpNum);
+ }
void printSrcMemOperand(const MachineInstr *MI, int OpNum,
const char* Modifier = 0);
void printCCOperand(const MachineInstr *MI, int OpNum);
@@ -67,6 +81,7 @@ namespace {
bool PrintAsmMemoryOperand(const MachineInstr *MI,
unsigned OpNo, unsigned AsmVariant,
const char *ExtraCode);
+ void printInstructionThroughMCStreamer(const MachineInstr *MI);
void emitFunctionHeader(const MachineFunction &MF);
bool runOnMachineFunction(MachineFunction &F);
@@ -148,7 +163,11 @@ void MSP430AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
processDebugLoc(MI, true);
// Call the autogenerated instruction printer routines.
- printInstruction(MI);
+ if (EnableMCInst) {
+ printInstructionThroughMCStreamer(MI);
+ } else {
+ printInstruction(MI);
+ }
if (VerboseAsm && !MI->getDebugLoc().isUnknown())
EmitComments(*MI);
@@ -231,22 +250,22 @@ void MSP430AsmPrinter::printCCOperand(const MachineInstr *MI, int OpNum) {
default:
llvm_unreachable("Unsupported CC code");
break;
- case MSP430::COND_E:
+ case MSP430CC::COND_E:
O << "eq";
break;
- case MSP430::COND_NE:
+ case MSP430CC::COND_NE:
O << "ne";
break;
- case MSP430::COND_HS:
+ case MSP430CC::COND_HS:
O << "hs";
break;
- case MSP430::COND_LO:
+ case MSP430CC::COND_LO:
O << "lo";
break;
- case MSP430::COND_GE:
+ case MSP430CC::COND_GE:
O << "ge";
break;
- case MSP430::COND_L:
+ case MSP430CC::COND_L:
O << 'l';
break;
}
@@ -275,6 +294,36 @@ bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
return false;
}
+//===----------------------------------------------------------------------===//
+void MSP430AsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI)
+{
+
+ MSP430MCInstLower MCInstLowering(OutContext, *Mang, *this);
+
+ switch (MI->getOpcode()) {
+ case TargetInstrInfo::DBG_LABEL:
+ case TargetInstrInfo::EH_LABEL:
+ case TargetInstrInfo::GC_LABEL:
+ printLabel(MI);
+ return;
+ case TargetInstrInfo::KILL:
+ return;
+ case TargetInstrInfo::INLINEASM:
+ O << '\t';
+ printInlineAsm(MI);
+ return;
+ case TargetInstrInfo::IMPLICIT_DEF:
+ printImplicitDef(MI);
+ return;
+ default: break;
+ }
+
+ MCInst TmpInst;
+ MCInstLowering.Lower(MI, TmpInst);
+
+ printMCInst(&TmpInst);
+}
+
// Force static initialization.
extern "C" void LLVMInitializeMSP430AsmPrinter() {
RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target);
diff --git a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp
new file mode 100644
index 000000000000..a3ecc674dc40
--- /dev/null
+++ b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp
@@ -0,0 +1,116 @@
+//===-- MSP430InstPrinter.cpp - Convert MSP430 MCInst to assembly syntax --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class prints an MSP430 MCInst to a .s file.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "asm-printer"
+#include "MSP430.h"
+#include "MSP430InstrInfo.h"
+#include "MSP430InstPrinter.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+using namespace llvm;
+
+
+// Include the auto-generated portion of the assembly writer.
+#define MachineInstr MCInst
+#define MSP430AsmPrinter MSP430InstPrinter // FIXME: REMOVE.
+#define NO_ASM_WRITER_BOILERPLATE
+#include "MSP430GenAsmWriter.inc"
+#undef MachineInstr
+#undef MSP430AsmPrinter
+
+void MSP430InstPrinter::printInst(const MCInst *MI) {
+ printInstruction(MI);
+}
+
+void MSP430InstPrinter::printPCRelImmOperand(const MCInst *MI, unsigned OpNo) {
+ const MCOperand &Op = MI->getOperand(OpNo);
+ if (Op.isImm())
+ O << Op.getImm();
+ else {
+ assert(Op.isExpr() && "unknown pcrel immediate operand");
+ Op.getExpr()->print(O, &MAI);
+ }
+}
+
+void MSP430InstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
+ const char *Modifier) {
+ assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
+ const MCOperand &Op = MI->getOperand(OpNo);
+ if (Op.isReg()) {
+ O << getRegisterName(Op.getReg());
+ } else if (Op.isImm()) {
+ O << '#' << Op.getImm();
+ } else {
+ assert(Op.isExpr() && "unknown operand kind in printOperand");
+ O << '#';
+ Op.getExpr()->print(O, &MAI);
+ }
+}
+
+void MSP430InstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo,
+ const char *Modifier) {
+ const MCOperand &Base = MI->getOperand(OpNo);
+ const MCOperand &Disp = MI->getOperand(OpNo+1);
+
+ // FIXME: move global to displacement field!
+ if (Base.isExpr()) {
+ O << '&';
+ Base.getExpr()->print(O, &MAI);
+ } else if (Disp.isImm() && !Base.isReg())
+ printOperand(MI, OpNo);
+ else if (Base.isReg()) {
+ if (Disp.getImm()) {
+ O << Disp.getImm() << '(';
+ printOperand(MI, OpNo);
+ O << ')';
+ } else {
+ O << '@';
+ printOperand(MI, OpNo);
+ }
+ } else {
+ Base.dump();
+ Disp.dump();
+ llvm_unreachable("Unsupported memory operand");
+ }
+}
+
+void MSP430InstPrinter::printCCOperand(const MCInst *MI, unsigned OpNo) {
+ unsigned CC = MI->getOperand(OpNo).getImm();
+
+ switch (CC) {
+ default:
+ llvm_unreachable("Unsupported CC code");
+ break;
+ case MSP430CC::COND_E:
+ O << "eq";
+ break;
+ case MSP430CC::COND_NE:
+ O << "ne";
+ break;
+ case MSP430CC::COND_HS:
+ O << "hs";
+ break;
+ case MSP430CC::COND_LO:
+ O << "lo";
+ break;
+ case MSP430CC::COND_GE:
+ O << "ge";
+ break;
+ case MSP430CC::COND_L:
+ O << 'l';
+ break;
+ }
+}
diff --git a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.h b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.h
new file mode 100644
index 000000000000..2fac800fcd79
--- /dev/null
+++ b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.h
@@ -0,0 +1,46 @@
+//===-- MSP430InstPrinter.h - Convert MSP430 MCInst to assembly syntax ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class prints a MSP430 MCInst to a .s file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MSP430INSTPRINTER_H
+#define MSP430INSTPRINTER_H
+
+#include "llvm/MC/MCInstPrinter.h"
+
+namespace llvm
+{
+
+ class MCOperand;
+
+ class MSP430InstPrinter : public MCInstPrinter {
+ public:
+ MSP430InstPrinter(raw_ostream &O, const MCAsmInfo &MAI) :
+ MCInstPrinter(O, MAI){
+ }
+
+ virtual void printInst(const MCInst *MI);
+
+ // Autogenerated by tblgen.
+ void printInstruction(const MCInst *MI);
+ static const char *getRegisterName(unsigned RegNo);
+
+ void printOperand(const MCInst *MI, unsigned OpNo,
+ const char *Modifier = 0);
+ void printPCRelImmOperand(const MCInst *MI, unsigned OpNo);
+ void printSrcMemOperand(const MCInst *MI, unsigned OpNo,
+ const char *Modifier = 0);
+ void printCCOperand(const MCInst *MI, unsigned OpNo);
+
+ };
+}
+
+#endif
diff --git a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp
new file mode 100644
index 000000000000..f505b239b631
--- /dev/null
+++ b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp
@@ -0,0 +1,147 @@
+//===-- MSP430MCInstLower.cpp - Convert MSP430 MachineInstr to an MCInst---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains code to lower MSP430 MachineInstrs to their corresponding
+// MCInst records.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MSP430MCInstLower.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Mangler.h"
+#include "llvm/ADT/SmallString.h"
+using namespace llvm;
+
+MCSymbol *MSP430MCInstLower::
+GetGlobalAddressSymbol(const MachineOperand &MO) const {
+ const GlobalValue *GV = MO.getGlobal();
+
+ SmallString<128> Name;
+ Mang.getNameWithPrefix(Name, GV, false);
+
+ switch (MO.getTargetFlags()) {
+ default: llvm_unreachable(0 && "Unknown target flag on GV operand");
+ case 0: break;
+ }
+
+ return Ctx.GetOrCreateSymbol(Name.str());
+}
+
+MCSymbol *MSP430MCInstLower::
+GetExternalSymbolSymbol(const MachineOperand &MO) const {
+ SmallString<128> Name;
+ Name += Printer.MAI->getGlobalPrefix();
+ Name += MO.getSymbolName();
+
+ switch (MO.getTargetFlags()) {
+ default: assert(0 && "Unknown target flag on GV operand");
+ case 0: break;
+ }
+
+ return Ctx.GetOrCreateSymbol(Name.str());
+}
+
+MCSymbol *MSP430MCInstLower::
+GetJumpTableSymbol(const MachineOperand &MO) const {
+ SmallString<256> Name;
+ raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "JTI"
+ << Printer.getFunctionNumber() << '_'
+ << MO.getIndex();
+
+ switch (MO.getTargetFlags()) {
+ default: llvm_unreachable("Unknown target flag on GV operand");
+ case 0: break;
+ }
+
+ // Create a symbol for the name.
+ return Ctx.GetOrCreateSymbol(Name.str());
+}
+
+MCSymbol *MSP430MCInstLower::
+GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
+ SmallString<256> Name;
+ raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "CPI"
+ << Printer.getFunctionNumber() << '_'
+ << MO.getIndex();
+
+ switch (MO.getTargetFlags()) {
+ default: llvm_unreachable("Unknown target flag on GV operand");
+ case 0: break;
+ }
+
+ // Create a symbol for the name.
+ return Ctx.GetOrCreateSymbol(Name.str());
+}
+
+MCOperand MSP430MCInstLower::
+LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const {
+ // FIXME: We would like an efficient form for this, so we don't have to do a
+ // lot of extra uniquing.
+ const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx);
+
+ switch (MO.getTargetFlags()) {
+ default: llvm_unreachable("Unknown target flag on GV operand");
+ case 0: break;
+ }
+
+ if (!MO.isJTI() && MO.getOffset())
+ Expr = MCBinaryExpr::CreateAdd(Expr,
+ MCConstantExpr::Create(MO.getOffset(), Ctx),
+ Ctx);
+ return MCOperand::CreateExpr(Expr);
+}
+
+void MSP430MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
+ OutMI.setOpcode(MI->getOpcode());
+
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ const MachineOperand &MO = MI->getOperand(i);
+
+ MCOperand MCOp;
+ switch (MO.getType()) {
+ default:
+ MI->dump();
+ assert(0 && "unknown operand type");
+ case MachineOperand::MO_Register:
+ // Ignore all implicit register operands.
+ if (MO.isImplicit()) continue;
+ MCOp = MCOperand::CreateReg(MO.getReg());
+ break;
+ case MachineOperand::MO_Immediate:
+ MCOp = MCOperand::CreateImm(MO.getImm());
+ break;
+ case MachineOperand::MO_MachineBasicBlock:
+ MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
+ Printer.GetMBBSymbol(MO.getMBB()->getNumber()), Ctx));
+ break;
+ case MachineOperand::MO_GlobalAddress:
+ MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
+ break;
+ case MachineOperand::MO_ExternalSymbol:
+ MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
+ break;
+ case MachineOperand::MO_JumpTableIndex:
+ MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO));
+ break;
+ case MachineOperand::MO_ConstantPoolIndex:
+ MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO));
+ break;
+ }
+
+ OutMI.addOperand(MCOp);
+ }
+}
diff --git a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.h b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.h
new file mode 100644
index 000000000000..a2b99ae83c01
--- /dev/null
+++ b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.h
@@ -0,0 +1,49 @@
+//===-- MSP430MCInstLower.h - Lower MachineInstr to MCInst ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MSP430_MCINSTLOWER_H
+#define MSP430_MCINSTLOWER_H
+
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+ class AsmPrinter;
+ class MCAsmInfo;
+ class MCContext;
+ class MCInst;
+ class MCOperand;
+ class MCSymbol;
+ class MachineInstr;
+ class MachineModuleInfoMachO;
+ class MachineOperand;
+ class Mangler;
+
+ /// MSP430MCInstLower - This class is used to lower an MachineInstr
+ /// into an MCInst.
+class VISIBILITY_HIDDEN MSP430MCInstLower {
+ MCContext &Ctx;
+ Mangler &Mang;
+
+ AsmPrinter &Printer;
+public:
+ MSP430MCInstLower(MCContext &ctx, Mangler &mang, AsmPrinter &printer)
+ : Ctx(ctx), Mang(mang), Printer(printer) {}
+ void Lower(const MachineInstr *MI, MCInst &OutMI) const;
+
+ MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const;
+
+ MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const;
+ MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const;
+ MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const;
+ MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const;
+};
+
+}
+
+#endif
diff --git a/lib/Target/MSP430/MSP430.h b/lib/Target/MSP430/MSP430.h
index d9f5f8629541..1ff178d99d90 100644
--- a/lib/Target/MSP430/MSP430.h
+++ b/lib/Target/MSP430/MSP430.h
@@ -17,6 +17,20 @@
#include "llvm/Target/TargetMachine.h"
+namespace MSP430CC {
+ // MSP430 specific condition code.
+ enum CondCodes {
+ COND_E = 0, // aka COND_Z
+ COND_NE = 1, // aka COND_NZ
+ COND_HS = 2, // aka COND_C
+ COND_LO = 3, // aka COND_NC
+ COND_GE = 4,
+ COND_L = 5,
+
+ COND_INVALID = -1
+ };
+}
+
namespace llvm {
class MSP430TargetMachine;
class FunctionPass;
diff --git a/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
index 4195a88f8de0..b7d928249c02 100644
--- a/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
+++ b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
@@ -26,6 +26,7 @@
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetLowering.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@@ -34,6 +35,14 @@
using namespace llvm;
+#ifndef NDEBUG
+static cl::opt<bool>
+ViewRMWDAGs("view-msp430-rmw-dags", cl::Hidden,
+ cl::desc("Pop up a window to show isel dags after RMW preprocess"));
+#else
+static const bool ViewRMWDAGs = false;
+#endif
+
STATISTIC(NumLoadMoved, "Number of loads moved below TokenFactor");
/// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine
@@ -56,6 +65,9 @@ namespace {
return "MSP430 DAG->DAG Pattern Instruction Selection";
}
+ bool IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
+ SDNode *Root) const;
+
virtual bool
SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
std::vector<SDValue> &OutOps);
@@ -64,6 +76,7 @@ namespace {
#include "MSP430GenDAGISel.inc"
private:
+ DenseMap<SDNode*, SDNode*> RMWStores;
void PreprocessForRMW();
SDNode *Select(SDValue Op);
bool SelectAddr(SDValue Op, SDValue Addr, SDValue &Base, SDValue &Disp);
@@ -130,7 +143,6 @@ bool MSP430DAGToDAGISel::SelectAddr(SDValue Op, SDValue Addr,
return true;
}
-
bool MSP430DAGToDAGISel::
SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
std::vector<SDValue> &OutOps) {
@@ -148,31 +160,54 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
return false;
}
+bool MSP430DAGToDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
+ SDNode *Root) const {
+ if (OptLevel == CodeGenOpt::None) return false;
+
+ /// RMW preprocessing creates the following code:
+ /// [Load1]
+ /// ^ ^
+ /// / |
+ /// / |
+ /// [Load2] |
+ /// ^ ^ |
+ /// | | |
+ /// | \-|
+ /// | |
+ /// | [Op]
+ /// | ^
+ /// | |
+ /// \ /
+ /// \ /
+ /// [Store]
+ ///
+ /// The path Store => Load2 => Load1 is via chain. Note that in general it is
+ /// not allowed to fold Load1 into Op (and Store) since it will creates a
+ /// cycle. However, this is perfectly legal for the loads moved below the
+ /// TokenFactor by PreprocessForRMW. Query the map Store => Load1 (created
+ /// during preprocessing) to determine whether it's legal to introduce such
+ /// "cycle" for a moment.
+ DenseMap<SDNode*, SDNode*>::iterator I = RMWStores.find(Root);
+ if (I != RMWStores.end() && I->second == N)
+ return true;
+
+ // Proceed to 'generic' cycle finder code
+ return SelectionDAGISel::IsLegalAndProfitableToFold(N, U, Root);
+}
+
+
/// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand
/// and move load below the TokenFactor. Replace store's chain operand with
/// load's chain result.
-/// Shamelessly stolen from X86.
static void MoveBelowTokenFactor(SelectionDAG *CurDAG, SDValue Load,
SDValue Store, SDValue TF) {
SmallVector<SDValue, 4> Ops;
- bool isRMW = false;
- SDValue TF0, TF1, NewTF;
for (unsigned i = 0, e = TF.getNode()->getNumOperands(); i != e; ++i)
- if (Load.getNode() == TF.getOperand(i).getNode()) {
- TF0 = Load.getOperand(0);
- Ops.push_back(TF0);
- } else {
- TF1 = TF.getOperand(i);
- Ops.push_back(TF1);
- if (LoadSDNode* LD = dyn_cast<LoadSDNode>(TF1))
- isRMW = !LD->isVolatile();
- }
-
- if (isRMW && TF1.getOperand(0).getNode() == TF0.getNode())
- NewTF = TF0;
- else
- NewTF = CurDAG->UpdateNodeOperands(TF, &Ops[0], Ops.size());
-
+ if (Load.getNode() == TF.getOperand(i).getNode())
+ Ops.push_back(Load.getOperand(0));
+ else
+ Ops.push_back(TF.getOperand(i));
+ SDValue NewTF = CurDAG->UpdateNodeOperands(TF, &Ops[0], Ops.size());
SDValue NewLoad = CurDAG->UpdateNodeOperands(Load, NewTF,
Load.getOperand(1),
Load.getOperand(2));
@@ -180,12 +215,43 @@ static void MoveBelowTokenFactor(SelectionDAG *CurDAG, SDValue Load,
Store.getOperand(2), Store.getOperand(3));
}
-/// isRMWLoad - Return true if N is a load that's part of RMW sub-DAG. The chain
-/// produced by the load must only be used by the store's chain operand,
-/// otherwise this may produce a cycle in the DAG.
-/// Shamelessly stolen from X86. FIXME: Should we make this function common?
-static bool isRMWLoad(SDValue N, SDValue Chain, SDValue Address,
- SDValue &Load) {
+/// MoveBelowTokenFactor2 - Replace TokenFactor operand with load's chain operand
+/// and move load below the TokenFactor. Replace store's chain operand with
+/// load's chain result. This a version which sinks two loads below token factor.
+/// Look into PreprocessForRMW comments for explanation of transform.
+static void MoveBelowTokenFactor2(SelectionDAG *CurDAG,
+ SDValue Load1, SDValue Load2,
+ SDValue Store, SDValue TF) {
+ SmallVector<SDValue, 4> Ops;
+ for (unsigned i = 0, e = TF.getNode()->getNumOperands(); i != e; ++i) {
+ SDNode* N = TF.getOperand(i).getNode();
+ if (Load2.getNode() == N)
+ Ops.push_back(Load2.getOperand(0));
+ else if (Load1.getNode() != N)
+ Ops.push_back(TF.getOperand(i));
+ }
+
+ SDValue NewTF = SDValue(CurDAG->MorphNodeTo(TF.getNode(),
+ TF.getOpcode(),
+ TF.getNode()->getVTList(),
+ &Ops[0], Ops.size()), TF.getResNo());
+ SDValue NewLoad2 = CurDAG->UpdateNodeOperands(Load2, NewTF,
+ Load2.getOperand(1),
+ Load2.getOperand(2));
+
+ SDValue NewLoad1 = CurDAG->UpdateNodeOperands(Load1, NewLoad2.getValue(1),
+ Load1.getOperand(1),
+ Load1.getOperand(2));
+
+ CurDAG->UpdateNodeOperands(Store,
+ NewLoad1.getValue(1),
+ Store.getOperand(1),
+ Store.getOperand(2), Store.getOperand(3));
+}
+
+/// isAllowedToSink - return true if N a load which can be moved below token
+/// factor. Basically, the load should be non-volatile and has single use.
+static bool isLoadAllowedToSink(SDValue N, SDValue Chain) {
if (N.getOpcode() == ISD::BIT_CONVERT)
N = N.getOperand(0);
@@ -199,10 +265,19 @@ static bool isRMWLoad(SDValue N, SDValue Chain, SDValue Address,
if (ExtType != ISD::NON_EXTLOAD && ExtType != ISD::EXTLOAD)
return false;
- if (N.hasOneUse() &&
- LD->hasNUsesOfValue(1, 1) &&
- N.getOperand(1) == Address &&
- LD->isOperandOf(Chain.getNode())) {
+ return (N.hasOneUse() &&
+ LD->hasNUsesOfValue(1, 1) &&
+ LD->isOperandOf(Chain.getNode()));
+}
+
+
+/// isRMWLoad - Return true if N is a load that's part of RMW sub-DAG.
+/// The chain produced by the load must only be used by the store's chain
+/// operand, otherwise this may produce a cycle in the DAG.
+static bool isRMWLoad(SDValue N, SDValue Chain, SDValue Address,
+ SDValue &Load) {
+ if (isLoadAllowedToSink(N, Chain) &&
+ N.getOperand(1) == Address) {
Load = N;
return true;
}
@@ -210,57 +285,140 @@ static bool isRMWLoad(SDValue N, SDValue Chain, SDValue Address,
}
/// PreprocessForRMW - Preprocess the DAG to make instruction selection better.
-/// Shamelessly stolen from X86.
+/// This is only run if not in -O0 mode.
+/// This allows the instruction selector to pick more read-modify-write
+/// instructions. This is a common case:
+///
+/// [Load chain]
+/// ^
+/// |
+/// [Load]
+/// ^ ^
+/// | |
+/// / \-
+/// / |
+/// [TokenFactor] [Op]
+/// ^ ^
+/// | |
+/// \ /
+/// \ /
+/// [Store]
+///
+/// The fact the store's chain operand != load's chain will prevent the
+/// (store (op (load))) instruction from being selected. We can transform it to:
+///
+/// [Load chain]
+/// ^
+/// |
+/// [TokenFactor]
+/// ^
+/// |
+/// [Load]
+/// ^ ^
+/// | |
+/// | \-
+/// | |
+/// | [Op]
+/// | ^
+/// | |
+/// \ /
+/// \ /
+/// [Store]
+///
+/// We also recognize the case where second operand of Op is load as well and
+/// move it below token factor as well creating DAG as follows:
+///
+/// [Load chain]
+/// ^
+/// |
+/// [TokenFactor]
+/// ^
+/// |
+/// [Load1]
+/// ^ ^
+/// / |
+/// / |
+/// [Load2] |
+/// ^ ^ |
+/// | | |
+/// | \-|
+/// | |
+/// | [Op]
+/// | ^
+/// | |
+/// \ /
+/// \ /
+/// [Store]
+///
+/// This allows selection of mem-mem instructions. Yay!
+
void MSP430DAGToDAGISel::PreprocessForRMW() {
for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
E = CurDAG->allnodes_end(); I != E; ++I) {
if (!ISD::isNON_TRUNCStore(I))
continue;
-
SDValue Chain = I->getOperand(0);
+
if (Chain.getNode()->getOpcode() != ISD::TokenFactor)
continue;
- SDValue N1 = I->getOperand(1); // Value to store
- SDValue N2 = I->getOperand(2); // Address of store
-
- if (!N1.hasOneUse())
+ SDValue N1 = I->getOperand(1);
+ SDValue N2 = I->getOperand(2);
+ if ((N1.getValueType().isFloatingPoint() &&
+ !N1.getValueType().isVector()) ||
+ !N1.hasOneUse())
continue;
- bool RModW = false;
- SDValue Load;
+ unsigned RModW = 0;
+ SDValue Load1, Load2;
unsigned Opcode = N1.getNode()->getOpcode();
switch (Opcode) {
- case ISD::ADD:
- case ISD::AND:
- case ISD::OR:
- case ISD::XOR:
- case ISD::ADDC:
- case ISD::ADDE: {
- SDValue N10 = N1.getOperand(0);
- SDValue N11 = N1.getOperand(1);
- RModW = isRMWLoad(N10, Chain, N2, Load);
-
- if (!RModW && isRMWLoad(N11, Chain, N2, Load)) {
- // Swap the operands, making the RMW load the first operand seems
- // to help selection and prevent token chain loops.
- N1 = CurDAG->UpdateNodeOperands(N1, N11, N10);
- RModW = true;
- }
- break;
+ case ISD::ADD:
+ case ISD::AND:
+ case ISD::OR:
+ case ISD::XOR:
+ case ISD::ADDC:
+ case ISD::ADDE: {
+ SDValue N10 = N1.getOperand(0);
+ SDValue N11 = N1.getOperand(1);
+ if (isRMWLoad(N10, Chain, N2, Load1)) {
+ if (isLoadAllowedToSink(N11, Chain)) {
+ Load2 = N11;
+ RModW = 2;
+ } else
+ RModW = 1;
+ } else if (isRMWLoad(N11, Chain, N2, Load1)) {
+ if (isLoadAllowedToSink(N10, Chain)) {
+ Load2 = N10;
+ RModW = 2;
+ } else
+ RModW = 1;
}
- case ISD::SUB:
- case ISD::SUBC:
- case ISD::SUBE: {
- SDValue N10 = N1.getOperand(0);
- RModW = isRMWLoad(N10, Chain, N2, Load);
- break;
+ break;
+ }
+ case ISD::SUB:
+ case ISD::SUBC:
+ case ISD::SUBE: {
+ SDValue N10 = N1.getOperand(0);
+ SDValue N11 = N1.getOperand(1);
+ if (isRMWLoad(N10, Chain, N2, Load1)) {
+ if (isLoadAllowedToSink(N11, Chain)) {
+ Load2 = N11;
+ RModW = 2;
+ } else
+ RModW = 1;
}
+ break;
+ }
}
- if (RModW) {
- MoveBelowTokenFactor(CurDAG, Load, SDValue(I, 0), Chain);
- ++NumLoadMoved;
+ NumLoadMoved += RModW;
+ if (RModW == 1)
+ MoveBelowTokenFactor(CurDAG, Load1, SDValue(I, 0), Chain);
+ else if (RModW == 2) {
+ MoveBelowTokenFactor2(CurDAG, Load1, Load2, SDValue(I, 0), Chain);
+ SDNode* Store = I;
+ RMWStores[Store] = Load2.getNode();
}
}
}
@@ -268,8 +426,15 @@ void MSP430DAGToDAGISel::PreprocessForRMW() {
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void MSP430DAGToDAGISel::InstructionSelect() {
+ std::string BlockName;
+ if (ViewRMWDAGs)
+ BlockName = MF->getFunction()->getNameStr() + ":" +
+ BB->getBasicBlock()->getNameStr();
+
PreprocessForRMW();
+ if (ViewRMWDAGs) CurDAG->viewGraph("RMW preprocessed:" + BlockName);
+
DEBUG(errs() << "Selection DAG after RMW preprocessing:\n");
DEBUG(CurDAG->dump());
@@ -282,6 +447,7 @@ void MSP430DAGToDAGISel::InstructionSelect() {
DEBUG(errs() << "===== Instruction selection ends:\n");
CurDAG->RemoveDeadNodes();
+ RMWStores.clear();
}
SDNode *MSP430DAGToDAGISel::Select(SDValue Op) {
diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp
index b56f069b54de..34e6d2c948bd 100644
--- a/lib/Target/MSP430/MSP430ISelLowering.cpp
+++ b/lib/Target/MSP430/MSP430ISelLowering.cpp
@@ -567,44 +567,45 @@ SDValue MSP430TargetLowering::LowerExternalSymbol(SDValue Op,
return DAG.getNode(MSP430ISD::Wrapper, dl, getPointerTy(), Result);;
}
-static SDValue EmitCMP(SDValue &LHS, SDValue &RHS, unsigned &TargetCC,
+static SDValue EmitCMP(SDValue &LHS, SDValue &RHS, SDValue &TargetCC,
ISD::CondCode CC,
DebugLoc dl, SelectionDAG &DAG) {
// FIXME: Handle bittests someday
assert(!LHS.getValueType().isFloatingPoint() && "We don't handle FP yet");
// FIXME: Handle jump negative someday
- TargetCC = MSP430::COND_INVALID;
+ MSP430CC::CondCodes TCC = MSP430CC::COND_INVALID;
switch (CC) {
default: llvm_unreachable("Invalid integer condition!");
case ISD::SETEQ:
- TargetCC = MSP430::COND_E; // aka COND_Z
+ TCC = MSP430CC::COND_E; // aka COND_Z
break;
case ISD::SETNE:
- TargetCC = MSP430::COND_NE; // aka COND_NZ
+ TCC = MSP430CC::COND_NE; // aka COND_NZ
break;
case ISD::SETULE:
std::swap(LHS, RHS); // FALLTHROUGH
case ISD::SETUGE:
- TargetCC = MSP430::COND_HS; // aka COND_C
+ TCC = MSP430CC::COND_HS; // aka COND_C
break;
case ISD::SETUGT:
std::swap(LHS, RHS); // FALLTHROUGH
case ISD::SETULT:
- TargetCC = MSP430::COND_LO; // aka COND_NC
+ TCC = MSP430CC::COND_LO; // aka COND_NC
break;
case ISD::SETLE:
std::swap(LHS, RHS); // FALLTHROUGH
case ISD::SETGE:
- TargetCC = MSP430::COND_GE;
+ TCC = MSP430CC::COND_GE;
break;
case ISD::SETGT:
std::swap(LHS, RHS); // FALLTHROUGH
case ISD::SETLT:
- TargetCC = MSP430::COND_L;
+ TCC = MSP430CC::COND_L;
break;
}
+ TargetCC = DAG.getConstant(TCC, MVT::i8);
return DAG.getNode(MSP430ISD::CMP, dl, MVT::Flag, LHS, RHS);
}
@@ -617,13 +618,11 @@ SDValue MSP430TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) {
SDValue Dest = Op.getOperand(4);
DebugLoc dl = Op.getDebugLoc();
- unsigned TargetCC = MSP430::COND_INVALID;
+ SDValue TargetCC;
SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG);
return DAG.getNode(MSP430ISD::BR_CC, dl, Op.getValueType(),
- Chain,
- Dest, DAG.getConstant(TargetCC, MVT::i8),
- Flag);
+ Chain, Dest, TargetCC, Flag);
}
SDValue MSP430TargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
@@ -634,14 +633,14 @@ SDValue MSP430TargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
DebugLoc dl = Op.getDebugLoc();
- unsigned TargetCC = MSP430::COND_INVALID;
+ SDValue TargetCC;
SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG);
SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Flag);
SmallVector<SDValue, 4> Ops;
Ops.push_back(TrueV);
Ops.push_back(FalseV);
- Ops.push_back(DAG.getConstant(TargetCC, MVT::i8));
+ Ops.push_back(TargetCC);
Ops.push_back(Flag);
return DAG.getNode(MSP430ISD::SELECT_CC, dl, VTs, &Ops[0], Ops.size());
diff --git a/lib/Target/MSP430/MSP430InstrInfo.cpp b/lib/Target/MSP430/MSP430InstrInfo.cpp
index 37fbb6d9999b..a6d9638cf598 100644
--- a/lib/Target/MSP430/MSP430InstrInfo.cpp
+++ b/lib/Target/MSP430/MSP430InstrInfo.cpp
@@ -151,6 +151,163 @@ MSP430InstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
return true;
}
+unsigned MSP430InstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
+ MachineBasicBlock::iterator I = MBB.end();
+ unsigned Count = 0;
+
+ while (I != MBB.begin()) {
+ --I;
+ if (I->getOpcode() != MSP430::JMP &&
+ I->getOpcode() != MSP430::JCC)
+ break;
+ // Remove the branch.
+ I->eraseFromParent();
+ I = MBB.end();
+ ++Count;
+ }
+
+ return Count;
+}
+
+bool MSP430InstrInfo::
+ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
+ assert(Cond.size() == 1 && "Invalid Xbranch condition!");
+
+ MSP430CC::CondCodes CC = static_cast<MSP430CC::CondCodes>(Cond[0].getImm());
+
+ switch (CC) {
+ default:
+ assert(0 && "Invalid branch condition!");
+ break;
+ case MSP430CC::COND_E:
+ CC = MSP430CC::COND_NE;
+ break;
+ case MSP430CC::COND_NE:
+ CC = MSP430CC::COND_E;
+ break;
+ case MSP430CC::COND_L:
+ CC = MSP430CC::COND_GE;
+ break;
+ case MSP430CC::COND_GE:
+ CC = MSP430CC::COND_L;
+ break;
+ case MSP430CC::COND_HS:
+ CC = MSP430CC::COND_LO;
+ break;
+ case MSP430CC::COND_LO:
+ CC = MSP430CC::COND_HS;
+ break;
+ }
+
+ Cond[0].setImm(CC);
+ return false;
+}
+
+bool MSP430InstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB)const{
+ if (MBB.empty()) return false;
+
+ switch (MBB.back().getOpcode()) {
+ case MSP430::RET: // Return.
+ case MSP430::JMP: // Uncond branch.
+ return true;
+ default: return false;
+ }
+}
+
+bool MSP430InstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const {
+ const TargetInstrDesc &TID = MI->getDesc();
+ if (!TID.isTerminator()) return false;
+
+ // Conditional branch is a special case.
+ if (TID.isBranch() && !TID.isBarrier())
+ return true;
+ if (!TID.isPredicable())
+ return true;
+ return !isPredicated(MI);
+}
+
+bool MSP430InstrInfo::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();
+ while (I != MBB.begin()) {
+ --I;
+ // 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.
+ if (I->getOpcode() == MSP430::JMP) {
+ if (!AllowModify) {
+ TBB = I->getOperand(0).getMBB();
+ continue;
+ }
+
+ // If the block has any instructions after a JMP, delete them.
+ while (next(I) != MBB.end())
+ 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();
+ continue;
+ }
+
+ // TBB is used to indicate the unconditinal destination.
+ TBB = I->getOperand(0).getMBB();
+ continue;
+ }
+
+ // Handle conditional branches.
+ assert(I->getOpcode() == MSP430::JCC && "Invalid conditional branch");
+ MSP430CC::CondCodes BranchCode =
+ static_cast<MSP430CC::CondCodes>(I->getOperand(1).getImm());
+ if (BranchCode == MSP430CC::COND_INVALID)
+ return true; // Can't handle weird stuff.
+
+ // Working from the bottom, handle the first conditional branch.
+ if (Cond.empty()) {
+ 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;
+
+ MSP430CC::CondCodes OldBranchCode = (MSP430CC::CondCodes)Cond[0].getImm();
+ // If the conditions are the same, we can leave them alone.
+ if (OldBranchCode == BranchCode)
+ continue;
+
+ return true;
+ }
+
+ return false;
+}
+
unsigned
MSP430InstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
MachineBasicBlock *FBB,
@@ -172,7 +329,13 @@ MSP430InstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
// Conditional branch.
unsigned Count = 0;
- llvm_unreachable("Implement conditional branches!");
+ BuildMI(&MBB, dl, get(MSP430::JCC)).addMBB(TBB).addImm(Cond[0].getImm());
+ ++Count;
+ if (FBB) {
+ // Two-way Conditional branch. Insert the second branch.
+ BuildMI(&MBB, dl, get(MSP430::JMP)).addMBB(FBB);
+ ++Count;
+ }
return Count;
}
diff --git a/lib/Target/MSP430/MSP430InstrInfo.h b/lib/Target/MSP430/MSP430InstrInfo.h
index e07aacad9dc2..35e35db01c49 100644
--- a/lib/Target/MSP430/MSP430InstrInfo.h
+++ b/lib/Target/MSP430/MSP430InstrInfo.h
@@ -21,20 +21,6 @@ namespace llvm {
class MSP430TargetMachine;
-namespace MSP430 {
- // MSP430 specific condition code.
- enum CondCode {
- COND_E = 0, // aka COND_Z
- COND_NE = 1, // aka COND_NZ
- COND_HS = 2, // aka COND_C
- COND_LO = 3, // aka COND_NC
- COND_GE = 4,
- COND_L = 5,
-
- COND_INVALID
- };
-}
-
class MSP430InstrInfo : public TargetInstrInfoImpl {
const MSP430RegisterInfo RI;
MSP430TargetMachine &TM;
@@ -73,9 +59,19 @@ public:
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI) const;
- virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
- MachineBasicBlock *FBB,
- const SmallVectorImpl<MachineOperand> &Cond) const;
+ // Branch folding goodness
+ bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const;
+ bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
+ bool isUnpredicatedTerminator(const MachineInstr *MI) const;
+ bool AnalyzeBranch(MachineBasicBlock &MBB,
+ MachineBasicBlock *&TBB, MachineBasicBlock *&FBB,
+ SmallVectorImpl<MachineOperand> &Cond,
+ bool AllowModify) const;
+
+ unsigned RemoveBranch(MachineBasicBlock &MBB) const;
+ unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+ MachineBasicBlock *FBB,
+ const SmallVectorImpl<MachineOperand> &Cond) const;
};
diff --git a/lib/Target/MSP430/MSP430InstrInfo.td b/lib/Target/MSP430/MSP430InstrInfo.td
index f7e0d2bad638..e202175561cb 100644
--- a/lib/Target/MSP430/MSP430InstrInfo.td
+++ b/lib/Target/MSP430/MSP430InstrInfo.td
@@ -71,7 +71,9 @@ def memdst : Operand<i16> {
}
// Branch targets have OtherVT type.
-def brtarget : Operand<OtherVT>;
+def brtarget : Operand<OtherVT> {
+ let PrintMethod = "printPCRelImmOperand";
+}
// Operand for printing out a condition code.
def cc : Operand<i8> {
diff --git a/lib/Target/MSP430/MSP430TargetMachine.cpp b/lib/Target/MSP430/MSP430TargetMachine.cpp
index 5e21f8ea29ef..da54507ab66c 100644
--- a/lib/Target/MSP430/MSP430TargetMachine.cpp
+++ b/lib/Target/MSP430/MSP430TargetMachine.cpp
@@ -32,7 +32,7 @@ MSP430TargetMachine::MSP430TargetMachine(const Target &T,
LLVMTargetMachine(T, TT),
Subtarget(TT, FS),
// FIXME: Check TargetData string.
- DataLayout("e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8"),
+ DataLayout("e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32"),
InstrInfo(*this), TLInfo(*this),
FrameInfo(TargetFrameInfo::StackGrowsDown, 2, -2) { }