From 06ac0820a6cefa6896000054d8e4906326c0cce6 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Sat, 7 Nov 2009 17:15:25 +0000 Subject: [PATCH] First try of the post-inc operands handling... Not fully worked, though :( git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@86386 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/MSP430/MSP430ISelDAGToDAG.cpp | 87 +++++++++++++++++++++--- lib/Target/MSP430/MSP430ISelLowering.cpp | 2 +- lib/Target/MSP430/MSP430InstrInfo.td | 9 +++ 3 files changed, 87 insertions(+), 11 deletions(-) diff --git a/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp index b45690b57a2..ac01bf81c34 100644 --- a/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp +++ b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp @@ -43,6 +43,9 @@ ViewRMWDAGs("view-msp430-rmw-dags", cl::Hidden, static const bool ViewRMWDAGs = false; #endif +static cl::opt +EnablePostIncOps("enable-msp430-post-inc-ops", cl::Hidden); + STATISTIC(NumLoadMoved, "Number of loads moved below TokenFactor"); @@ -148,6 +151,9 @@ namespace { void PreprocessForRMW(); SDNode *Select(SDValue Op); SDNode *SelectIndexedLoad(SDValue Op); + SDNode *SelectIndexedBinOp(SDValue Op, SDValue N1, SDValue N2, + unsigned Opc8, unsigned Opc16); + bool SelectAddr(SDValue Op, SDValue Addr, SDValue &Base, SDValue &Disp); #ifndef NDEBUG @@ -598,39 +604,85 @@ void MSP430DAGToDAGISel::PreprocessForRMW() { } -SDNode *MSP430DAGToDAGISel::SelectIndexedLoad(SDValue Op) { - LoadSDNode *LD = cast(Op); +static bool isValidIndexedLoad(const LoadSDNode *LD) { ISD::MemIndexedMode AM = LD->getAddressingMode(); if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD) - return NULL; + return false; EVT VT = LD->getMemoryVT(); - unsigned Opcode = 0; switch (VT.getSimpleVT().SimpleTy) { case MVT::i8: // Sanity check if (cast(LD->getOffset())->getZExtValue() != 1) - return NULL; + return false; - Opcode = MSP430::MOV8rm_POST; break; case MVT::i16: // Sanity check if (cast(LD->getOffset())->getZExtValue() != 2) - return NULL; + return false; + break; + default: + return false; + } + + return true; +} + +SDNode *MSP430DAGToDAGISel::SelectIndexedLoad(SDValue Op) { + LoadSDNode *LD = cast(Op); + if (!isValidIndexedLoad(LD)) + return NULL; + + MVT VT = LD->getMemoryVT().getSimpleVT(); + + unsigned Opcode = 0; + switch (VT.SimpleTy) { + case MVT::i8: + Opcode = MSP430::MOV8rm_POST; + break; + case MVT::i16: 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()); + return CurDAG->getMachineNode(Opcode, Op.getDebugLoc(), + VT, MVT::i16, MVT::Other, + LD->getBasePtr(), LD->getChain()); } +SDNode *MSP430DAGToDAGISel::SelectIndexedBinOp(SDValue Op, + SDValue N1, SDValue N2, + unsigned Opc8, unsigned Opc16) { + if (N1.getOpcode() == ISD::LOAD && + N1.hasOneUse() && + IsLegalAndProfitableToFold(N1.getNode(), Op.getNode(), Op.getNode())) { + LoadSDNode *LD = cast(N1); + if (!isValidIndexedLoad(LD)) + return NULL; + + MVT VT = LD->getMemoryVT().getSimpleVT(); + unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8); + MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1); + MemRefs0[0] = cast(N1)->getMemOperand(); + SDValue Ops0[] = { N2, LD->getBasePtr(), LD->getChain() }; + SDNode *ResNode = + CurDAG->SelectNodeTo(Op.getNode(), Opc, + VT, MVT::i16, MVT::Other, + Ops0, 3); + cast(ResNode)->setMemRefs(MemRefs0, MemRefs0 + 1); + ReplaceUses(SDValue(N1.getNode(), 2), SDValue(ResNode, 3)); + return ResNode; + } + + return NULL; +} + + /// InstructionSelect - This callback is invoked by /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. void MSP430DAGToDAGISel::InstructionSelect() { @@ -693,6 +745,21 @@ SDNode *MSP430DAGToDAGISel::Select(SDValue Op) { return ResNode; // Other cases are autogenerated. break; + case ISD::ADD: + if (EnablePostIncOps) { + if (SDNode *ResNode = + SelectIndexedBinOp(Op, + Op.getOperand(0), Op.getOperand(1), + MSP430::ADD8rm_POST, MSP430::ADD16rm_POST)) + return ResNode; + else if (SDNode *ResNode = + SelectIndexedBinOp(Op, Op.getOperand(1), Op.getOperand(0), + MSP430::ADD8rm_POST, MSP430::ADD16rm_POST)) + 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 47a977798da..326ea9af57b 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -62,7 +62,7 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) : setBooleanContents(ZeroOrOneBooleanContent); setSchedulingPreference(SchedulingForLatency); - // We have post-incremented loads / stores + // We have post-incremented loads / stores. setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal); setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal); diff --git a/lib/Target/MSP430/MSP430InstrInfo.td b/lib/Target/MSP430/MSP430InstrInfo.td index 6d7b87c362a..33e468df565 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.td +++ b/lib/Target/MSP430/MSP430InstrInfo.td @@ -287,6 +287,15 @@ def ADD16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), [(set GR16:$dst, (add GR16:$src1, (load addr:$src2))), (implicit SRW)]>; +let mayLoad = 1, hasExtraDefRegAllocReq = 1, +Constraints = "$base = $base_wb, $src1 = $dst" in { +def ADD8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base), + "add.b\t{@$base+, $dst}", []>; +def ADD16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base), + "add.w\t{@$base+, $dst}", []>; +} + + def ADD8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), "add.b\t{$src2, $dst}", [(set GR8:$dst, (add GR8:$src1, imm:$src2)),