summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Korobeynikov <asl@math.spbu.ru>2009-11-07 17:15:06 +0000
committerAnton Korobeynikov <asl@math.spbu.ru>2009-11-07 17:15:06 +0000
commit6534f83ae8c39284ae51fbf478ce0c37d0c892a2 (patch)
treebc7f6b5215bd2a3162233cd58983bc1fc482e36f
parent8983da729aa1ca99a11a3b98ae6280dfcdbadb39 (diff)
downloadllvm-6534f83ae8c39284ae51fbf478ce0c37d0c892a2.tar.gz
llvm-6534f83ae8c39284ae51fbf478ce0c37d0c892a2.tar.bz2
llvm-6534f83ae8c39284ae51fbf478ce0c37d0c892a2.tar.xz
Add some dummy support for post-incremented loads
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@86385 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/MSP430/MSP430ISelDAGToDAG.cpp40
-rw-r--r--lib/Target/MSP430/MSP430ISelLowering.cpp48
-rw-r--r--lib/Target/MSP430/MSP430ISelLowering.h6
-rw-r--r--lib/Target/MSP430/MSP430InstrInfo.td7
-rw-r--r--test/CodeGen/MSP430/postinc.ll25
5 files changed, 122 insertions, 4 deletions
diff --git a/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
index 37a6107c25..b45690b57a 100644
--- a/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
+++ b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
@@ -147,6 +147,7 @@ namespace {
DenseMap<SDNode*, SDNode*> RMWStores;
void PreprocessForRMW();
SDNode *Select(SDValue Op);
+ SDNode *SelectIndexedLoad(SDValue Op);
bool SelectAddr(SDValue Op, SDValue Addr, SDValue &Base, SDValue &Disp);
#ifndef NDEBUG
@@ -596,6 +597,40 @@ void MSP430DAGToDAGISel::PreprocessForRMW() {
}
}
+
+SDNode *MSP430DAGToDAGISel::SelectIndexedLoad(SDValue Op) {
+ LoadSDNode *LD = cast<LoadSDNode>(Op);
+ ISD::MemIndexedMode AM = LD->getAddressingMode();
+ if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD)
+ return NULL;
+
+ EVT VT = LD->getMemoryVT();
+
+ unsigned Opcode = 0;
+ switch (VT.getSimpleVT().SimpleTy) {
+ case MVT::i8:
+ // Sanity check
+ if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 1)
+ return NULL;
+
+ Opcode = MSP430::MOV8rm_POST;
+ break;
+ case MVT::i16:
+ // Sanity check
+ if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 2)
+ return NULL;
+
+ Opcode = MSP430::MOV16rm_POST;
+ break;
+ default:
+ return NULL;
+ }
+
+ return CurDAG->getMachineNode(Opcode, Op.getDebugLoc(),
+ VT.getSimpleVT().SimpleTy, MVT::i16, MVT::Other,
+ LD->getBasePtr(), LD->getChain());
+}
+
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void MSP430DAGToDAGISel::InstructionSelect() {
@@ -653,6 +688,11 @@ SDNode *MSP430DAGToDAGISel::Select(SDValue Op) {
return CurDAG->getMachineNode(MSP430::ADD16ri, dl, MVT::i16,
TFI, CurDAG->getTargetConstant(0, MVT::i16));
}
+ case ISD::LOAD:
+ if (SDNode *ResNode = SelectIndexedLoad(Op))
+ return ResNode;
+ // Other cases are autogenerated.
+ break;
}
// Select the default instruction
diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp
index 09be40cf4a..47a977798d 100644
--- a/lib/Target/MSP430/MSP430ISelLowering.cpp
+++ b/lib/Target/MSP430/MSP430ISelLowering.cpp
@@ -62,10 +62,14 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) :
setBooleanContents(ZeroOrOneBooleanContent);
setSchedulingPreference(SchedulingForLatency);
- setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
- setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
- setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
- setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand);
+ // We have post-incremented loads / stores
+ setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal);
+ setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal);
+
+ setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
+ setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
+ setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
+ setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand);
setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand);
// We don't have any truncstores
@@ -670,6 +674,42 @@ SDValue MSP430TargetLowering::LowerSIGN_EXTEND(SDValue Op,
DAG.getValueType(Val.getValueType()));
}
+/// getPostIndexedAddressParts - returns true by value, base pointer and
+/// offset pointer and addressing mode by reference if this node can be
+/// combined with a load / store to form a post-indexed load / store.
+bool MSP430TargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
+ SDValue &Base,
+ SDValue &Offset,
+ ISD::MemIndexedMode &AM,
+ SelectionDAG &DAG) const {
+
+ LoadSDNode *LD = cast<LoadSDNode>(N);
+ if (LD->getExtensionType() != ISD::NON_EXTLOAD)
+ return false;
+
+ EVT VT = LD->getMemoryVT();
+ if (VT != MVT::i8 && VT != MVT::i16)
+ return false;
+
+ if (Op->getOpcode() != ISD::ADD)
+ return false;
+
+ if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Op->getOperand(1))) {
+ uint64_t RHSC = RHS->getZExtValue();
+ if ((VT == MVT::i16 && RHSC != 2) ||
+ (VT == MVT::i8 && RHSC != 1))
+ return false;
+
+ Base = Op->getOperand(0);
+ Offset = DAG.getConstant(RHSC, VT);
+ AM = ISD::POST_INC;
+ return true;
+ }
+
+ return false;
+}
+
+
const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (Opcode) {
default: return NULL;
diff --git a/lib/Target/MSP430/MSP430ISelLowering.h b/lib/Target/MSP430/MSP430ISelLowering.h
index fdbc384f1d..d413ccb385 100644
--- a/lib/Target/MSP430/MSP430ISelLowering.h
+++ b/lib/Target/MSP430/MSP430ISelLowering.h
@@ -136,6 +136,12 @@ namespace llvm {
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG);
+ virtual bool getPostIndexedAddressParts(SDNode *N, SDNode *Op,
+ SDValue &Base,
+ SDValue &Offset,
+ ISD::MemIndexedMode &AM,
+ SelectionDAG &DAG) const;
+
const MSP430Subtarget &Subtarget;
const MSP430TargetMachine &TM;
};
diff --git a/lib/Target/MSP430/MSP430InstrInfo.td b/lib/Target/MSP430/MSP430InstrInfo.td
index 2b50669198..6d7b87c362 100644
--- a/lib/Target/MSP430/MSP430InstrInfo.td
+++ b/lib/Target/MSP430/MSP430InstrInfo.td
@@ -215,6 +215,13 @@ def MOVZX16rm8 : Pseudo<(outs GR16:$dst), (ins memsrc:$src),
"mov.b\t{$src, $dst}",
[(set GR16:$dst, (zextloadi16i8 addr:$src))]>;
+let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$base = $base_wb" in {
+def MOV8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR16:$base),
+ "mov.b\t{@$base+, $dst}", []>;
+def MOV16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$base),
+ "mov.w\t{@$base+, $dst}", []>;
+}
+
// Any instruction that defines a 8-bit result leaves the high half of the
// register. Truncate can be lowered to EXTRACT_SUBREG, and CopyFromReg may
// be copying from a truncate, but any other 8-bit operation will zero-extend
diff --git a/test/CodeGen/MSP430/postinc.ll b/test/CodeGen/MSP430/postinc.ll
new file mode 100644
index 0000000000..424b4f79cd
--- /dev/null
+++ b/test/CodeGen/MSP430/postinc.ll
@@ -0,0 +1,25 @@
+; RUN: llc < %s | FileCheck %s
+target datalayout = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8"
+target triple = "msp430"
+
+define zeroext i16 @add(i16* nocapture %a, i16 zeroext %n) nounwind readonly {
+entry:
+ %cmp8 = icmp eq i16 %n, 0 ; <i1> [#uses=1]
+ br i1 %cmp8, label %for.end, label %for.body
+
+for.body: ; preds = %for.body, %entry
+ %i.010 = phi i16 [ 0, %entry ], [ %inc, %for.body ] ; <i16> [#uses=2]
+ %sum.09 = phi i16 [ 0, %entry ], [ %add, %for.body ] ; <i16> [#uses=1]
+ %arrayidx = getelementptr i16* %a, i16 %i.010 ; <i16*> [#uses=1]
+; CHECK: add:
+; CHECK: mov.w @r15+, r11
+ %tmp4 = load i16* %arrayidx ; <i16> [#uses=1]
+ %add = add i16 %tmp4, %sum.09 ; <i16> [#uses=2]
+ %inc = add i16 %i.010, 1 ; <i16> [#uses=2]
+ %exitcond = icmp eq i16 %inc, %n ; <i1> [#uses=1]
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.body, %entry
+ %sum.0.lcssa = phi i16 [ 0, %entry ], [ %add, %for.body ] ; <i16> [#uses=1]
+ ret i16 %sum.0.lcssa
+}