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
This commit is contained in:
Anton Korobeynikov 2009-11-07 17:15:06 +00:00
parent 8983da729a
commit 6534f83ae8
5 changed files with 122 additions and 4 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;
};

View File

@ -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

View File

@ -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
}