From ed1a51af376b9027db60ff060e0a2572493df07b Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Sun, 3 May 2009 13:12:06 +0000 Subject: [PATCH] Add first draft for conditions, conditional branches, etc git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@70743 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/MSP430/MSP430ISelLowering.cpp | 83 ++++++++++++++++++++++ lib/Target/MSP430/MSP430ISelLowering.h | 19 +++++- lib/Target/MSP430/MSP430InstrInfo.h | 15 ++++ lib/Target/MSP430/MSP430InstrInfo.td | 87 +++++++++++++++++++++++- 4 files changed, 202 insertions(+), 2 deletions(-) diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp index 11b1fb442e9..2354c8370ce 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -70,6 +70,10 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) : setOperationAction(ISD::SRA, MVT::i16, Custom); setOperationAction(ISD::RET, MVT::Other, Custom); setOperationAction(ISD::GlobalAddress, MVT::i16, Custom); + setOperationAction(ISD::BR_CC, MVT::Other, Expand); + setOperationAction(ISD::BRCOND, MVT::Other, Custom); + setOperationAction(ISD::SETCC, MVT::i8 , Custom); + setOperationAction(ISD::SETCC, MVT::i16 , Custom); } SDValue MSP430TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { @@ -79,6 +83,8 @@ SDValue MSP430TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { case ISD::RET: return LowerRET(Op, DAG); case ISD::CALL: return LowerCALL(Op, DAG); case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); + case ISD::SETCC: return LowerSETCC(Op, DAG); + case ISD::BRCOND: return LowerBRCOND(Op, DAG); default: assert(0 && "unimplemented operand"); return SDValue(); @@ -437,6 +443,80 @@ SDValue MSP430TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) getPointerTy(), Result); } +MVT MSP430TargetLowering::getSetCCResultType(MVT VT) const { + return MVT::i8; +} + +SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { + assert(Op.getValueType() == MVT::i8 && "SetCC type must be 8-bit integer"); + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + DebugLoc dl = Op.getDebugLoc(); + ISD::CondCode CC = cast(Op.getOperand(2))->get(); + + // FIXME: Handle bittests someday + assert(!LHS.getValueType().isFloatingPoint() && "We don't handle FP yet"); + + // FIXME: Handle jump negative someday + unsigned TargetCC = 0; + switch (CC) { + default: assert(0 && "Invalid integer condition!"); + case ISD::SETEQ: + TargetCC = MSP430::COND_E; // aka COND_Z + break; + case ISD::SETNE: + TargetCC = MSP430::COND_NE; // aka COND_NZ + break; + case ISD::SETULE: + std::swap(LHS, RHS); // FALLTHROUGH + case ISD::SETUGE: + TargetCC = MSP430::COND_HS; // aka COND_C + break; + case ISD::SETUGT: + std::swap(LHS, RHS); // FALLTHROUGH + case ISD::SETULT: + TargetCC = MSP430::COND_LO; // aka COND_NC + break; + case ISD::SETLE: + std::swap(LHS, RHS); // FALLTHROUGH + case ISD::SETGE: + TargetCC = MSP430::COND_GE; + break; + case ISD::SETGT: + std::swap(LHS, RHS); // FALLTHROUGH + case ISD::SETLT: + TargetCC = MSP430::COND_L; + break; + } + + SDValue Cond = DAG.getNode(MSP430ISD::CMP, dl, MVT::i16, LHS, RHS); + return DAG.getNode(MSP430ISD::SETCC, dl, MVT::i8, + DAG.getConstant(TargetCC, MVT::i8), Cond); +} + +SDValue MSP430TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) { + SDValue Chain = Op.getOperand(0); + SDValue Cond = Op.getOperand(1); + SDValue Dest = Op.getOperand(2); + DebugLoc dl = Op.getDebugLoc(); + SDValue CC; + + // Lower condition if not lowered yet + if (Cond.getOpcode() == ISD::SETCC) + Cond = LowerSETCC(Cond, DAG); + + // If condition flag is set by a MSP430ISD::CMP, then use it as the condition + // setting operand in place of the MSP430ISD::SETCC. + if (Cond.getOpcode() == MSP430ISD::SETCC) { + CC = Cond.getOperand(0); + Cond = Cond.getOperand(1); + } else + assert(0 && "Unimplemented condition!"); + + return DAG.getNode(MSP430ISD::BRCOND, dl, Op.getValueType(), + Chain, Dest, CC, Cond); +} + const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const { switch (Opcode) { default: return NULL; @@ -444,5 +524,8 @@ const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const { case MSP430ISD::RRA: return "MSP430ISD::RRA"; case MSP430ISD::CALL: return "MSP430ISD::CALL"; case MSP430ISD::Wrapper: return "MSP430ISD::Wrapper"; + case MSP430ISD::BRCOND: return "MSP430ISD::BRCOND"; + case MSP430ISD::CMP: return "MSP430ISD::CMP"; + case MSP430ISD::SETCC: return "MSP430ISD::SETCC"; } } diff --git a/lib/Target/MSP430/MSP430ISelLowering.h b/lib/Target/MSP430/MSP430ISelLowering.h index a1f03ac9633..c0ababd8b8a 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.h +++ b/lib/Target/MSP430/MSP430ISelLowering.h @@ -36,7 +36,20 @@ namespace llvm { /// Wrapper - A wrapper node for TargetConstantPool, TargetExternalSymbol, /// and TargetGlobalAddress. - Wrapper + Wrapper, + + /// CMP - Compare instruction. + CMP, + + /// SetCC. Operand 0 is condition code, and operand 1 is the flag + /// operand produced by a CMP instruction. + SETCC, + + /// MSP430 conditional branches. Operand 0 is the chain operand, operand 1 + /// is the block to branch if condition is true, operand 2 is the + /// condition code, and operand 3 is the flag operand produced by a CMP + /// instruction. + BRCOND }; } @@ -54,12 +67,16 @@ namespace llvm { /// DAG node. virtual const char *getTargetNodeName(unsigned Opcode) const; + virtual MVT getSetCCResultType(MVT VT) const; + SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG); SDValue LowerCALL(SDValue Op, SelectionDAG &DAG); SDValue LowerRET(SDValue Op, SelectionDAG &DAG); SDValue LowerCCCArguments(SDValue Op, SelectionDAG &DAG); SDValue LowerShifts(SDValue Op, SelectionDAG &DAG); SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG); + SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG); + SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG); SDValue LowerCCCCallTo(SDValue Op, SelectionDAG &DAG, unsigned CC); diff --git a/lib/Target/MSP430/MSP430InstrInfo.h b/lib/Target/MSP430/MSP430InstrInfo.h index 02287d5c206..0803e2d77cd 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.h +++ b/lib/Target/MSP430/MSP430InstrInfo.h @@ -21,6 +21,21 @@ namespace llvm { class MSP430TargetMachine; +namespace MSP430 { + // MSP430 specific condition code. These correspond to MSP430_*_COND in + // MSP430InstrInfo.td. They must be kept in synch. + 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; diff --git a/lib/Target/MSP430/MSP430InstrInfo.td b/lib/Target/MSP430/MSP430InstrInfo.td index 8ab41ad46cd..83a236e8532 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.td +++ b/lib/Target/MSP430/MSP430InstrInfo.td @@ -26,6 +26,11 @@ def SDT_MSP430Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; def SDT_MSP430CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i16>]>; def SDT_MSP430CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i16>, SDTCisVT<1, i16>]>; def SDT_MSP430Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; +def SDT_MSP430SetCC : SDTypeProfile<1, 2, [SDTCisVT<0, i8>, + SDTCisVT<1, i8>, SDTCisVT<2, i16>]>; +def SDT_MSP430Cmp : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>; +def SDT_MSP430BrCond : SDTypeProfile<0, 3, [SDTCisVT<0, OtherVT>, + SDTCisVT<1, i8>, SDTCisVT<2, i16>]>; //===----------------------------------------------------------------------===// // MSP430 Specific Node Definitions. @@ -43,7 +48,10 @@ def MSP430callseq_start : def MSP430callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MSP430CallSeqEnd, [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; -def MSP430Wrapper : SDNode<"MSP430ISD::Wrapper", SDT_MSP430Wrapper>; +def MSP430Wrapper : SDNode<"MSP430ISD::Wrapper", SDT_MSP430Wrapper>; +def MSP430setcc : SDNode<"MSP430ISD::SETCC", SDT_MSP430SetCC>; +def MSP430cmp : SDNode<"MSP430ISD::CMP", SDT_MSP430Cmp>; +def MSP430brcond : SDNode<"MSP430ISD::BRCOND", SDT_MSP430BrCond, [SDNPHasChain]>; //===----------------------------------------------------------------------===// // MSP430 Operand Definitions. @@ -60,6 +68,9 @@ def memdst : Operand { let MIOperandInfo = (ops GR16, i16imm); } +// Branch targets have OtherVT type. +def brtarget : Operand; + //===----------------------------------------------------------------------===// // MSP430 Complex Pattern Definitions. //===----------------------------------------------------------------------===// @@ -71,6 +82,15 @@ def addr : ComplexPattern; def zextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (zextloadi8 node:$ptr))>; def extloadi16i8 : PatFrag<(ops node:$ptr), (i16 ( extloadi8 node:$ptr))>; +// MSP430 specific condition code. These correspond to CondCode in +// MSP430InstrInfo.h. They must be kept in synch. +def MSP430_COND_E : PatLeaf<(i8 0)>; // aka COND_Z +def MSP430_COND_NE : PatLeaf<(i8 1)>; // aka COND_NZ +def MSP430_COND_HS : PatLeaf<(i8 2)>; // aka COND_C +def MSP430_COND_LO : PatLeaf<(i8 3)>; // aka COND_NC +def MSP430_COND_GE : PatLeaf<(i8 4)>; +def MSP430_COND_L : PatLeaf<(i8 5)>; + //===----------------------------------------------------------------------===// // Instruction list.. @@ -92,11 +112,31 @@ def ADJCALLSTACKUP : Pseudo<(outs), (ins i16imm:$amt1, i16imm:$amt2), let neverHasSideEffects = 1 in def NOP : Pseudo<(outs), (ins), "nop", []>; +//===----------------------------------------------------------------------===// +// Control Flow Instructions... +// + // FIXME: Provide proper encoding! let isReturn = 1, isTerminator = 1 in { def RET : Pseudo<(outs), (ins), "ret", [(MSP430retflag)]>; } +// Conditional branches +let isBranch = 1, isTerminator = 1, Uses = [SRW] in { +def JE : Pseudo<(outs), (ins brtarget:$dst), "je\t$dst", + [(MSP430brcond bb:$dst, MSP430_COND_E, SRW)]>; +def JNE : Pseudo<(outs), (ins brtarget:$dst), "jne\t$dst", + [(MSP430brcond bb:$dst, MSP430_COND_NE, SRW)]>; +def JHS : Pseudo<(outs), (ins brtarget:$dst), "jhs\t$dst", + [(MSP430brcond bb:$dst, MSP430_COND_HS, SRW)]>; +def JLO : Pseudo<(outs), (ins brtarget:$dst), "jlo\t$dst", + [(MSP430brcond bb:$dst, MSP430_COND_LO, SRW)]>; +def JGE : Pseudo<(outs), (ins brtarget:$dst), "jge\t$dst", + [(MSP430brcond bb:$dst, MSP430_COND_GE, SRW)]>; +def JL : Pseudo<(outs), (ins brtarget:$dst), "jl\t$dst", + [(MSP430brcond bb:$dst, MSP430_COND_L, SRW)]>; +} // Uses = [SRW] + //===----------------------------------------------------------------------===// // Call Instructions... // @@ -613,6 +653,51 @@ def OR16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), } // isTwoAddress = 1 +// Integer comparisons +let Defs = [SRW] in { +def CMP8rr : Pseudo<(outs), (ins GR8:$src1, GR8:$src2), + "cmp.b\t{$src2, $src1|$src1, $src2}", + [(MSP430cmp GR8:$src1, GR8:$src2), (implicit SRW)]>; +def CMP16rr : Pseudo<(outs), (ins GR16:$src1, GR16:$src2), + "cmp.w\t{$src2, $src1|$src1, $src2}", + [(MSP430cmp GR16:$src1, GR16:$src2), (implicit SRW)]>; + +def CMP8ri : Pseudo<(outs), (ins GR8:$src1, i8imm:$src2), + "cmp.b\t{$src2, $src1|$src1, $src2}", + [(MSP430cmp GR8:$src1, imm:$src2), (implicit SRW)]>; +def CMP16ri : Pseudo<(outs), (ins GR16:$src1, i16imm:$src2), + "cmp.w\t{$src2, $src1|$src1, $src2}", + [(MSP430cmp GR16:$src1, imm:$src2), (implicit SRW)]>; + +def CMP8rm : Pseudo<(outs), (ins GR8:$src1, memsrc:$src2), + "cmp.b\t{$src2, $src1|$src1, $src2}", + [(MSP430cmp GR8:$src1, (load addr:$src2)), (implicit SRW)]>; +def CMP16rm : Pseudo<(outs), (ins GR16:$src1, memsrc:$src2), + "cmp.w\t{$src2, $src1|$src1, $src2}", + [(MSP430cmp GR16:$src1, (load addr:$src2)), (implicit SRW)]>; + +def CMP8mr : Pseudo<(outs), (ins memsrc:$src1, GR8:$src2), + "cmp.b\t{$src2, $src1|$src1, $src2}", + [(MSP430cmp (load addr:$src1), GR8:$src2), (implicit SRW)]>; +def CMP16mr : Pseudo<(outs), (ins memsrc:$src1, GR16:$src2), + "cmp.w\t{$src2, $src1|$src1, $src2}", + [(MSP430cmp (load addr:$src1), GR16:$src2), (implicit SRW)]>; + +def CMP8mi : Pseudo<(outs), (ins memsrc:$src1, i8imm:$src2), + "cmp.b\t{$src2, $src1|$src1, $src2}", + [(MSP430cmp (load addr:$src1), (i8 imm:$src2)), (implicit SRW)]>; +def CMP16mi : Pseudo<(outs), (ins memsrc:$src1, i16imm:$src2), + "cmp.w\t{$src2, $src1|$src1, $src2}", + [(MSP430cmp (load addr:$src1), (i16 imm:$src2)), (implicit SRW)]>; + +def CMP8mm : Pseudo<(outs), (ins memsrc:$src1, memsrc:$src2), + "cmp.b\t{$src2, $src1|$src1, $src2}", + [(MSP430cmp (load addr:$src1), (i8 (load addr:$src2))), (implicit SRW)]>; +def CMP16mm : Pseudo<(outs), (ins memsrc:$src1, memsrc:$src2), + "cmp.w\t{$src2, $src1|$src1, $src2}", + [(MSP430cmp (load addr:$src1), (i16 (load addr:$src2))), (implicit SRW)]>; +} // Defs = [SRW] + //===----------------------------------------------------------------------===// // Non-Instruction Patterns -- 2.34.1