From 4d55aca87aeac108980005912d8ea8733d6226e1 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 18 Dec 2005 01:20:35 +0000 Subject: [PATCH] Add initial conditional branch support. This doesn't actually work yet due to a bug in the scheduler. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24807 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Sparc/SparcISelDAGToDAG.cpp | 83 +++++++++++++-- lib/Target/Sparc/SparcInstrFormats.td | 4 +- lib/Target/Sparc/SparcInstrInfo.td | 111 ++++++++++++++------- lib/Target/Sparc/SparcRegisterInfo.td | 8 ++ lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp | 83 +++++++++++++-- lib/Target/SparcV8/SparcV8InstrFormats.td | 4 +- lib/Target/SparcV8/SparcV8InstrInfo.td | 111 ++++++++++++++------- lib/Target/SparcV8/SparcV8RegisterInfo.td | 8 ++ 8 files changed, 320 insertions(+), 92 deletions(-) diff --git a/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/lib/Target/Sparc/SparcISelDAGToDAG.cpp index 770ea8ddc4e..d93f407a757 100644 --- a/lib/Target/Sparc/SparcISelDAGToDAG.cpp +++ b/lib/Target/Sparc/SparcISelDAGToDAG.cpp @@ -27,11 +27,21 @@ using namespace llvm; // TargetLowering Implementation //===----------------------------------------------------------------------===// +namespace V8ISD { + enum { + FIRST_NUMBER = ISD::BUILTIN_OP_END+V8::INSTRUCTION_LIST_END, + CMPICC, // Compare two GPR operands, set icc. + CMPFCC, // Compare two FP operands, set fcc. + BRICC, // Branch to dest on icc condition + BRFCC, // Branch to dest on fcc condition + }; +} + namespace { class SparcV8TargetLowering : public TargetLowering { public: SparcV8TargetLowering(TargetMachine &TM); - + virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); virtual std::vector LowerArguments(Function &F, SelectionDAG &DAG); virtual std::pair @@ -70,6 +80,22 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM) setOperationAction(ISD::UREM, MVT::i32, Expand); setOperationAction(ISD::SREM, MVT::i32, Expand); + // Sparc has no select or setcc: expand to SELECT_CC. + setOperationAction(ISD::SELECT, MVT::i32, Expand); + setOperationAction(ISD::SELECT, MVT::f32, Expand); + setOperationAction(ISD::SELECT, MVT::f64, Expand); + setOperationAction(ISD::SETCC, MVT::i32, Expand); + setOperationAction(ISD::SETCC, MVT::f32, Expand); + setOperationAction(ISD::SETCC, MVT::f64, Expand); + + // Sparc doesn't have BRCOND either, it has BR_CC. + setOperationAction(ISD::BRCOND, MVT::Other, Expand); + setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand); + setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand); + setOperationAction(ISD::BR_CC, MVT::i32, Custom); + setOperationAction(ISD::BR_CC, MVT::f32, Custom); + setOperationAction(ISD::BR_CC, MVT::f64, Custom); + computeRegisterProperties(); } @@ -171,26 +197,52 @@ SDOperand SparcV8TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op, } } -SDOperand SparcV8TargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP, - Value *VAListV, SelectionDAG &DAG) { +SDOperand SparcV8TargetLowering:: +LowerVAStart(SDOperand Chain, SDOperand VAListP, Value *VAListV, + SelectionDAG &DAG) { + assert(0 && "Unimp"); abort(); } -std::pair -SparcV8TargetLowering::LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV, - const Type *ArgTy, SelectionDAG &DAG) { +std::pair SparcV8TargetLowering:: +LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV, + const Type *ArgTy, SelectionDAG &DAG) { assert(0 && "Unimp"); abort(); } -std::pair -SparcV8TargetLowering::LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, - SelectionDAG &DAG) { +std::pair SparcV8TargetLowering:: +LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, + SelectionDAG &DAG) { assert(0 && "Unimp"); abort(); } +SDOperand SparcV8TargetLowering:: +LowerOperation(SDOperand Op, SelectionDAG &DAG) { + switch (Op.getOpcode()) { + default: assert(0 && "Should not custom lower this!"); + case ISD::BR_CC: { + SDOperand Chain = Op.getOperand(0); + SDOperand CC = Op.getOperand(1); + SDOperand LHS = Op.getOperand(2); + SDOperand RHS = Op.getOperand(3); + SDOperand Dest = Op.getOperand(4); + + // Get the condition flag. + if (LHS.getValueType() == MVT::i32) { + SDOperand Cond = DAG.getNode(V8ISD::CMPICC, MVT::Flag, LHS, RHS); + return DAG.getNode(V8ISD::BRICC, MVT::Other, Chain, Dest, CC, Cond); + } else { + SDOperand Cond = DAG.getNode(V8ISD::CMPFCC, MVT::Flag, LHS, RHS); + return DAG.getNode(V8ISD::BRFCC, MVT::Other, Chain, Dest, CC, Cond); + } + } + } +} + + //===----------------------------------------------------------------------===// // Instruction Selector Implementation //===----------------------------------------------------------------------===// @@ -273,8 +325,8 @@ bool SparcV8DAGToDAGISel::SelectADDRri(SDOperand Addr, SDOperand &Base, SDOperand SparcV8DAGToDAGISel::Select(SDOperand Op) { SDNode *N = Op.Val; - if (N->getOpcode() >= ISD::BUILTIN_OP_END/* && - N->getOpcode() < V8ISD::FIRST_NUMBER*/) + if (N->getOpcode() >= ISD::BUILTIN_OP_END && + N->getOpcode() < V8ISD::FIRST_NUMBER) return Op; // Already selected. // If this has already been converted, use it. std::map::iterator CGMI = CodeGenMap.find(Op); @@ -282,6 +334,15 @@ SDOperand SparcV8DAGToDAGISel::Select(SDOperand Op) { switch (N->getOpcode()) { default: break; + case ISD::BasicBlock: return CodeGenMap[Op] = Op; + case V8ISD::CMPICC: { + // FIXME: Handle compare with immediate. + SDOperand LHS = Select(N->getOperand(0)); + SDOperand RHS = Select(N->getOperand(1)); + SDOperand Result = CurDAG->getTargetNode(V8::SUBCCrr, MVT::i32, MVT::Flag, + LHS, RHS); + return CodeGenMap[Op] = Result.getValue(1); + } case ISD::ADD_PARTS: { SDOperand LHSL = Select(N->getOperand(0)); SDOperand LHSH = Select(N->getOperand(1)); diff --git a/lib/Target/Sparc/SparcInstrFormats.td b/lib/Target/Sparc/SparcInstrFormats.td index fcaa3ae1574..1e731213724 100644 --- a/lib/Target/Sparc/SparcInstrFormats.td +++ b/lib/Target/Sparc/SparcInstrFormats.td @@ -33,12 +33,14 @@ class F2_1 op2Val, dag ops, string asmstr, list pattern> : F2 { let Inst{29-25} = rd; } -class F2_2 condVal, bits<3> op2Val, dag ops, string asmstr> : F2 { +class F2_2 condVal, bits<3> op2Val, dag ops, string asmstr, + list pattern> : F2 { bits<4> cond; bit annul = 0; // currently unused dag OperandList = ops; let AsmString = asmstr; + let Pattern = pattern; let cond = condVal; let op2 = op2Val; diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index 0971695edc4..d64b56ed070 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -68,6 +68,19 @@ def MEMri : Operand { let MIOperandInfo = (ops IntRegs, i32imm); } +def SDTV8cmpicc : +SDTypeProfile<1, 2, [SDTCisVT<0, FlagVT>, SDTCisInt<1>, SDTCisSameAs<1, 2>]>; +def SDTV8cmpfcc : +SDTypeProfile<1, 2, [SDTCisVT<0, FlagVT>, SDTCisFP<1>, SDTCisSameAs<1, 2>]>; +def SDTV8brcc : +SDTypeProfile<0, 3, [SDTCisInt<0>, SDTCisVT<1, OtherVT>, SDTCisVT<2, FlagVT>]>; + +def V8cmpicc : SDNode<"V8ISD::CMPICC", SDTV8cmpicc>; +def V8cmpfcc : SDNode<"V8ISD::CMPFCC", SDTV8cmpfcc>; +def V8bricc : SDNode<"V8ISD::BRICC", SDTV8brcc, [SDNPHasChain]>; +def V8brfcc : SDNode<"V8ISD::BRFCC", SDTV8brcc, [SDNPHasChain]>; + + //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// @@ -389,53 +402,81 @@ def RESTOREri : F3_2<2, 0b111101, // Section B.21 - Branch on Integer Condition Codes Instructions, p. 119 // conditional branch class: -class BranchV8 cc, dag ops, string asmstr> - : F2_2 { +class BranchV8 cc, dag ops, string asmstr, list pattern> + : F2_2 { let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; } let isBarrier = 1 in - def BA : BranchV8<0b1000, (ops IntRegs:$dst), "ba $dst">; -def BN : BranchV8<0b0000, (ops IntRegs:$dst), "bn $dst">; -def BNE : BranchV8<0b1001, (ops IntRegs:$dst), "bne $dst">; -def BE : BranchV8<0b0001, (ops IntRegs:$dst), "be $dst">; -def BG : BranchV8<0b1010, (ops IntRegs:$dst), "bg $dst">; -def BLE : BranchV8<0b0010, (ops IntRegs:$dst), "ble $dst">; -def BGE : BranchV8<0b1011, (ops IntRegs:$dst), "bge $dst">; -def BL : BranchV8<0b0011, (ops IntRegs:$dst), "bl $dst">; -def BGU : BranchV8<0b1100, (ops IntRegs:$dst), "bgu $dst">; -def BLEU : BranchV8<0b0100, (ops IntRegs:$dst), "bleu $dst">; -def BCC : BranchV8<0b1101, (ops IntRegs:$dst), "bcc $dst">; -def BCS : BranchV8<0b0101, (ops IntRegs:$dst), "bcs $dst">; + def BA : BranchV8<0b1000, (ops IntRegs:$dst), + "ba $dst", []>; +def BN : BranchV8<0b0000, (ops IntRegs:$dst), + "bn $dst", []>; +def BNE : BranchV8<0b1001, (ops IntRegs:$dst), + "bne $dst", + [(V8bricc IntRegs:$dst, SETNE, ICC)]>; +def BE : BranchV8<0b0001, (ops IntRegs:$dst), + "be $dst", + [(V8bricc IntRegs:$dst, SETEQ, ICC)]>; +def BG : BranchV8<0b1010, (ops IntRegs:$dst), + "bg $dst", []>; +def BLE : BranchV8<0b0010, (ops IntRegs:$dst), + "ble $dst", []>; +def BGE : BranchV8<0b1011, (ops IntRegs:$dst), + "bge $dst", []>; +def BL : BranchV8<0b0011, (ops IntRegs:$dst), + "bl $dst", []>; +def BGU : BranchV8<0b1100, (ops IntRegs:$dst), + "bgu $dst", []>; +def BLEU : BranchV8<0b0100, (ops IntRegs:$dst), + "bleu $dst", []>; +def BCC : BranchV8<0b1101, (ops IntRegs:$dst), + "bcc $dst", []>; +def BCS : BranchV8<0b0101, (ops IntRegs:$dst), + "bcs $dst", []>; // Section B.22 - Branch on Floating-point Condition Codes Instructions, p. 121 // floating-point conditional branch class: -class FPBranchV8 cc, dag ops, string asmstr> - : F2_2 { +class FPBranchV8 cc, dag ops, string asmstr, list pattern> + : F2_2 { let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; } -def FBA : FPBranchV8<0b1000, (ops IntRegs:$dst), "fba $dst">; -def FBN : FPBranchV8<0b0000, (ops IntRegs:$dst), "fbn $dst">; -def FBU : FPBranchV8<0b0111, (ops IntRegs:$dst), "fbu $dst">; -def FBG : FPBranchV8<0b0110, (ops IntRegs:$dst), "fbg $dst">; -def FBUG : FPBranchV8<0b0101, (ops IntRegs:$dst), "fbug $dst">; -def FBL : FPBranchV8<0b0100, (ops IntRegs:$dst), "fbl $dst">; -def FBUL : FPBranchV8<0b0011, (ops IntRegs:$dst), "fbul $dst">; -def FBLG : FPBranchV8<0b0010, (ops IntRegs:$dst), "fblg $dst">; -def FBNE : FPBranchV8<0b0001, (ops IntRegs:$dst), "fbne $dst">; -def FBE : FPBranchV8<0b1001, (ops IntRegs:$dst), "fbe $dst">; -def FBUE : FPBranchV8<0b1010, (ops IntRegs:$dst), "fbue $dst">; -def FBGE : FPBranchV8<0b1011, (ops IntRegs:$dst), "fbge $dst">; -def FBUGE: FPBranchV8<0b1100, (ops IntRegs:$dst), "fbuge $dst">; -def FBLE : FPBranchV8<0b1101, (ops IntRegs:$dst), "fble $dst">; -def FBULE: FPBranchV8<0b1110, (ops IntRegs:$dst), "fbule $dst">; -def FBO : FPBranchV8<0b1111, (ops IntRegs:$dst), "fbo $dst">; +def FBN : FPBranchV8<0b0000, (ops IntRegs:$dst), + "fbn $dst", []>; +def FBU : FPBranchV8<0b0111, (ops IntRegs:$dst), + "fbu $dst", []>; +def FBG : FPBranchV8<0b0110, (ops IntRegs:$dst), + "fbg $dst", []>; +def FBUG : FPBranchV8<0b0101, (ops IntRegs:$dst), + "fbug $dst", []>; +def FBL : FPBranchV8<0b0100, (ops IntRegs:$dst), + "fbl $dst", []>; +def FBUL : FPBranchV8<0b0011, (ops IntRegs:$dst), + "fbul $dst", []>; +def FBLG : FPBranchV8<0b0010, (ops IntRegs:$dst), + "fblg $dst", []>; +def FBNE : FPBranchV8<0b0001, (ops IntRegs:$dst), + "fbne $dst", []>; +def FBE : FPBranchV8<0b1001, (ops IntRegs:$dst), + "fbe $dst", []>; +def FBUE : FPBranchV8<0b1010, (ops IntRegs:$dst), + "fbue $dst", []>; +def FBGE : FPBranchV8<0b1011, (ops IntRegs:$dst), + "fbge $dst", []>; +def FBUGE: FPBranchV8<0b1100, (ops IntRegs:$dst), + "fbuge $dst", []>; +def FBLE : FPBranchV8<0b1101, (ops IntRegs:$dst), + "fble $dst", []>; +def FBULE: FPBranchV8<0b1110, (ops IntRegs:$dst), + "fbule $dst", []>; +def FBO : FPBranchV8<0b1111, (ops IntRegs:$dst), + "fbo $dst", []>; @@ -576,10 +617,12 @@ def FDIVD : F3_3<2, 0b110100, 0b001001110, // is modelled with a forced noop after the instruction. def FCMPS : F3_3<2, 0b110101, 0b001010001, (ops FPRegs:$src1, FPRegs:$src2), - "fcmps $src1, $src2\n\tnop", []>; + "fcmps $src1, $src2\n\tnop", + [(set FCC, (V8cmpfcc FPRegs:$src1, FPRegs:$src2))]>; def FCMPD : F3_3<2, 0b110101, 0b001010010, (ops DFPRegs:$src1, DFPRegs:$src2), - "fcmpd $src1, $src2\n\tnop", []>; + "fcmpd $src1, $src2\n\tnop", + [(set FCC, (V8cmpfcc DFPRegs:$src1, DFPRegs:$src2))]>; //===----------------------------------------------------------------------===// // Non-Instruction Patterns diff --git a/lib/Target/Sparc/SparcRegisterInfo.td b/lib/Target/Sparc/SparcRegisterInfo.td index 52ddf59721a..c6fcc58fc09 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.td +++ b/lib/Target/Sparc/SparcRegisterInfo.td @@ -71,6 +71,14 @@ def D10 : Rd<20, "F20", [F20, F21]>; def D11 : Rd<22, "F22", [F22, F23]>; def D12 : Rd<24, "F24", [F24, F25]>; def D13 : Rd<26, "F26", [F26, F27]>; def D14 : Rd<28, "F28", [F28, F29]>; def D15 : Rd<30, "F30", [F30, F31]>; +/// Integer and FP Condition codes. +let Namespace = "V8" in { + def ICC : Register<"ICC">; + def FCC : Register<"FCC">; +} +def FLAGS_REGS : RegisterClass<"V8", [FlagVT], 32, [ICC, FCC]> { + let Size = 32; +} // Register classes. // diff --git a/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp b/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp index 770ea8ddc4e..d93f407a757 100644 --- a/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp +++ b/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp @@ -27,11 +27,21 @@ using namespace llvm; // TargetLowering Implementation //===----------------------------------------------------------------------===// +namespace V8ISD { + enum { + FIRST_NUMBER = ISD::BUILTIN_OP_END+V8::INSTRUCTION_LIST_END, + CMPICC, // Compare two GPR operands, set icc. + CMPFCC, // Compare two FP operands, set fcc. + BRICC, // Branch to dest on icc condition + BRFCC, // Branch to dest on fcc condition + }; +} + namespace { class SparcV8TargetLowering : public TargetLowering { public: SparcV8TargetLowering(TargetMachine &TM); - + virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); virtual std::vector LowerArguments(Function &F, SelectionDAG &DAG); virtual std::pair @@ -70,6 +80,22 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM) setOperationAction(ISD::UREM, MVT::i32, Expand); setOperationAction(ISD::SREM, MVT::i32, Expand); + // Sparc has no select or setcc: expand to SELECT_CC. + setOperationAction(ISD::SELECT, MVT::i32, Expand); + setOperationAction(ISD::SELECT, MVT::f32, Expand); + setOperationAction(ISD::SELECT, MVT::f64, Expand); + setOperationAction(ISD::SETCC, MVT::i32, Expand); + setOperationAction(ISD::SETCC, MVT::f32, Expand); + setOperationAction(ISD::SETCC, MVT::f64, Expand); + + // Sparc doesn't have BRCOND either, it has BR_CC. + setOperationAction(ISD::BRCOND, MVT::Other, Expand); + setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand); + setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand); + setOperationAction(ISD::BR_CC, MVT::i32, Custom); + setOperationAction(ISD::BR_CC, MVT::f32, Custom); + setOperationAction(ISD::BR_CC, MVT::f64, Custom); + computeRegisterProperties(); } @@ -171,26 +197,52 @@ SDOperand SparcV8TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op, } } -SDOperand SparcV8TargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP, - Value *VAListV, SelectionDAG &DAG) { +SDOperand SparcV8TargetLowering:: +LowerVAStart(SDOperand Chain, SDOperand VAListP, Value *VAListV, + SelectionDAG &DAG) { + assert(0 && "Unimp"); abort(); } -std::pair -SparcV8TargetLowering::LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV, - const Type *ArgTy, SelectionDAG &DAG) { +std::pair SparcV8TargetLowering:: +LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV, + const Type *ArgTy, SelectionDAG &DAG) { assert(0 && "Unimp"); abort(); } -std::pair -SparcV8TargetLowering::LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, - SelectionDAG &DAG) { +std::pair SparcV8TargetLowering:: +LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, + SelectionDAG &DAG) { assert(0 && "Unimp"); abort(); } +SDOperand SparcV8TargetLowering:: +LowerOperation(SDOperand Op, SelectionDAG &DAG) { + switch (Op.getOpcode()) { + default: assert(0 && "Should not custom lower this!"); + case ISD::BR_CC: { + SDOperand Chain = Op.getOperand(0); + SDOperand CC = Op.getOperand(1); + SDOperand LHS = Op.getOperand(2); + SDOperand RHS = Op.getOperand(3); + SDOperand Dest = Op.getOperand(4); + + // Get the condition flag. + if (LHS.getValueType() == MVT::i32) { + SDOperand Cond = DAG.getNode(V8ISD::CMPICC, MVT::Flag, LHS, RHS); + return DAG.getNode(V8ISD::BRICC, MVT::Other, Chain, Dest, CC, Cond); + } else { + SDOperand Cond = DAG.getNode(V8ISD::CMPFCC, MVT::Flag, LHS, RHS); + return DAG.getNode(V8ISD::BRFCC, MVT::Other, Chain, Dest, CC, Cond); + } + } + } +} + + //===----------------------------------------------------------------------===// // Instruction Selector Implementation //===----------------------------------------------------------------------===// @@ -273,8 +325,8 @@ bool SparcV8DAGToDAGISel::SelectADDRri(SDOperand Addr, SDOperand &Base, SDOperand SparcV8DAGToDAGISel::Select(SDOperand Op) { SDNode *N = Op.Val; - if (N->getOpcode() >= ISD::BUILTIN_OP_END/* && - N->getOpcode() < V8ISD::FIRST_NUMBER*/) + if (N->getOpcode() >= ISD::BUILTIN_OP_END && + N->getOpcode() < V8ISD::FIRST_NUMBER) return Op; // Already selected. // If this has already been converted, use it. std::map::iterator CGMI = CodeGenMap.find(Op); @@ -282,6 +334,15 @@ SDOperand SparcV8DAGToDAGISel::Select(SDOperand Op) { switch (N->getOpcode()) { default: break; + case ISD::BasicBlock: return CodeGenMap[Op] = Op; + case V8ISD::CMPICC: { + // FIXME: Handle compare with immediate. + SDOperand LHS = Select(N->getOperand(0)); + SDOperand RHS = Select(N->getOperand(1)); + SDOperand Result = CurDAG->getTargetNode(V8::SUBCCrr, MVT::i32, MVT::Flag, + LHS, RHS); + return CodeGenMap[Op] = Result.getValue(1); + } case ISD::ADD_PARTS: { SDOperand LHSL = Select(N->getOperand(0)); SDOperand LHSH = Select(N->getOperand(1)); diff --git a/lib/Target/SparcV8/SparcV8InstrFormats.td b/lib/Target/SparcV8/SparcV8InstrFormats.td index fcaa3ae1574..1e731213724 100644 --- a/lib/Target/SparcV8/SparcV8InstrFormats.td +++ b/lib/Target/SparcV8/SparcV8InstrFormats.td @@ -33,12 +33,14 @@ class F2_1 op2Val, dag ops, string asmstr, list pattern> : F2 { let Inst{29-25} = rd; } -class F2_2 condVal, bits<3> op2Val, dag ops, string asmstr> : F2 { +class F2_2 condVal, bits<3> op2Val, dag ops, string asmstr, + list pattern> : F2 { bits<4> cond; bit annul = 0; // currently unused dag OperandList = ops; let AsmString = asmstr; + let Pattern = pattern; let cond = condVal; let op2 = op2Val; diff --git a/lib/Target/SparcV8/SparcV8InstrInfo.td b/lib/Target/SparcV8/SparcV8InstrInfo.td index 0971695edc4..d64b56ed070 100644 --- a/lib/Target/SparcV8/SparcV8InstrInfo.td +++ b/lib/Target/SparcV8/SparcV8InstrInfo.td @@ -68,6 +68,19 @@ def MEMri : Operand { let MIOperandInfo = (ops IntRegs, i32imm); } +def SDTV8cmpicc : +SDTypeProfile<1, 2, [SDTCisVT<0, FlagVT>, SDTCisInt<1>, SDTCisSameAs<1, 2>]>; +def SDTV8cmpfcc : +SDTypeProfile<1, 2, [SDTCisVT<0, FlagVT>, SDTCisFP<1>, SDTCisSameAs<1, 2>]>; +def SDTV8brcc : +SDTypeProfile<0, 3, [SDTCisInt<0>, SDTCisVT<1, OtherVT>, SDTCisVT<2, FlagVT>]>; + +def V8cmpicc : SDNode<"V8ISD::CMPICC", SDTV8cmpicc>; +def V8cmpfcc : SDNode<"V8ISD::CMPFCC", SDTV8cmpfcc>; +def V8bricc : SDNode<"V8ISD::BRICC", SDTV8brcc, [SDNPHasChain]>; +def V8brfcc : SDNode<"V8ISD::BRFCC", SDTV8brcc, [SDNPHasChain]>; + + //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// @@ -389,53 +402,81 @@ def RESTOREri : F3_2<2, 0b111101, // Section B.21 - Branch on Integer Condition Codes Instructions, p. 119 // conditional branch class: -class BranchV8 cc, dag ops, string asmstr> - : F2_2 { +class BranchV8 cc, dag ops, string asmstr, list pattern> + : F2_2 { let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; } let isBarrier = 1 in - def BA : BranchV8<0b1000, (ops IntRegs:$dst), "ba $dst">; -def BN : BranchV8<0b0000, (ops IntRegs:$dst), "bn $dst">; -def BNE : BranchV8<0b1001, (ops IntRegs:$dst), "bne $dst">; -def BE : BranchV8<0b0001, (ops IntRegs:$dst), "be $dst">; -def BG : BranchV8<0b1010, (ops IntRegs:$dst), "bg $dst">; -def BLE : BranchV8<0b0010, (ops IntRegs:$dst), "ble $dst">; -def BGE : BranchV8<0b1011, (ops IntRegs:$dst), "bge $dst">; -def BL : BranchV8<0b0011, (ops IntRegs:$dst), "bl $dst">; -def BGU : BranchV8<0b1100, (ops IntRegs:$dst), "bgu $dst">; -def BLEU : BranchV8<0b0100, (ops IntRegs:$dst), "bleu $dst">; -def BCC : BranchV8<0b1101, (ops IntRegs:$dst), "bcc $dst">; -def BCS : BranchV8<0b0101, (ops IntRegs:$dst), "bcs $dst">; + def BA : BranchV8<0b1000, (ops IntRegs:$dst), + "ba $dst", []>; +def BN : BranchV8<0b0000, (ops IntRegs:$dst), + "bn $dst", []>; +def BNE : BranchV8<0b1001, (ops IntRegs:$dst), + "bne $dst", + [(V8bricc IntRegs:$dst, SETNE, ICC)]>; +def BE : BranchV8<0b0001, (ops IntRegs:$dst), + "be $dst", + [(V8bricc IntRegs:$dst, SETEQ, ICC)]>; +def BG : BranchV8<0b1010, (ops IntRegs:$dst), + "bg $dst", []>; +def BLE : BranchV8<0b0010, (ops IntRegs:$dst), + "ble $dst", []>; +def BGE : BranchV8<0b1011, (ops IntRegs:$dst), + "bge $dst", []>; +def BL : BranchV8<0b0011, (ops IntRegs:$dst), + "bl $dst", []>; +def BGU : BranchV8<0b1100, (ops IntRegs:$dst), + "bgu $dst", []>; +def BLEU : BranchV8<0b0100, (ops IntRegs:$dst), + "bleu $dst", []>; +def BCC : BranchV8<0b1101, (ops IntRegs:$dst), + "bcc $dst", []>; +def BCS : BranchV8<0b0101, (ops IntRegs:$dst), + "bcs $dst", []>; // Section B.22 - Branch on Floating-point Condition Codes Instructions, p. 121 // floating-point conditional branch class: -class FPBranchV8 cc, dag ops, string asmstr> - : F2_2 { +class FPBranchV8 cc, dag ops, string asmstr, list pattern> + : F2_2 { let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; } -def FBA : FPBranchV8<0b1000, (ops IntRegs:$dst), "fba $dst">; -def FBN : FPBranchV8<0b0000, (ops IntRegs:$dst), "fbn $dst">; -def FBU : FPBranchV8<0b0111, (ops IntRegs:$dst), "fbu $dst">; -def FBG : FPBranchV8<0b0110, (ops IntRegs:$dst), "fbg $dst">; -def FBUG : FPBranchV8<0b0101, (ops IntRegs:$dst), "fbug $dst">; -def FBL : FPBranchV8<0b0100, (ops IntRegs:$dst), "fbl $dst">; -def FBUL : FPBranchV8<0b0011, (ops IntRegs:$dst), "fbul $dst">; -def FBLG : FPBranchV8<0b0010, (ops IntRegs:$dst), "fblg $dst">; -def FBNE : FPBranchV8<0b0001, (ops IntRegs:$dst), "fbne $dst">; -def FBE : FPBranchV8<0b1001, (ops IntRegs:$dst), "fbe $dst">; -def FBUE : FPBranchV8<0b1010, (ops IntRegs:$dst), "fbue $dst">; -def FBGE : FPBranchV8<0b1011, (ops IntRegs:$dst), "fbge $dst">; -def FBUGE: FPBranchV8<0b1100, (ops IntRegs:$dst), "fbuge $dst">; -def FBLE : FPBranchV8<0b1101, (ops IntRegs:$dst), "fble $dst">; -def FBULE: FPBranchV8<0b1110, (ops IntRegs:$dst), "fbule $dst">; -def FBO : FPBranchV8<0b1111, (ops IntRegs:$dst), "fbo $dst">; +def FBN : FPBranchV8<0b0000, (ops IntRegs:$dst), + "fbn $dst", []>; +def FBU : FPBranchV8<0b0111, (ops IntRegs:$dst), + "fbu $dst", []>; +def FBG : FPBranchV8<0b0110, (ops IntRegs:$dst), + "fbg $dst", []>; +def FBUG : FPBranchV8<0b0101, (ops IntRegs:$dst), + "fbug $dst", []>; +def FBL : FPBranchV8<0b0100, (ops IntRegs:$dst), + "fbl $dst", []>; +def FBUL : FPBranchV8<0b0011, (ops IntRegs:$dst), + "fbul $dst", []>; +def FBLG : FPBranchV8<0b0010, (ops IntRegs:$dst), + "fblg $dst", []>; +def FBNE : FPBranchV8<0b0001, (ops IntRegs:$dst), + "fbne $dst", []>; +def FBE : FPBranchV8<0b1001, (ops IntRegs:$dst), + "fbe $dst", []>; +def FBUE : FPBranchV8<0b1010, (ops IntRegs:$dst), + "fbue $dst", []>; +def FBGE : FPBranchV8<0b1011, (ops IntRegs:$dst), + "fbge $dst", []>; +def FBUGE: FPBranchV8<0b1100, (ops IntRegs:$dst), + "fbuge $dst", []>; +def FBLE : FPBranchV8<0b1101, (ops IntRegs:$dst), + "fble $dst", []>; +def FBULE: FPBranchV8<0b1110, (ops IntRegs:$dst), + "fbule $dst", []>; +def FBO : FPBranchV8<0b1111, (ops IntRegs:$dst), + "fbo $dst", []>; @@ -576,10 +617,12 @@ def FDIVD : F3_3<2, 0b110100, 0b001001110, // is modelled with a forced noop after the instruction. def FCMPS : F3_3<2, 0b110101, 0b001010001, (ops FPRegs:$src1, FPRegs:$src2), - "fcmps $src1, $src2\n\tnop", []>; + "fcmps $src1, $src2\n\tnop", + [(set FCC, (V8cmpfcc FPRegs:$src1, FPRegs:$src2))]>; def FCMPD : F3_3<2, 0b110101, 0b001010010, (ops DFPRegs:$src1, DFPRegs:$src2), - "fcmpd $src1, $src2\n\tnop", []>; + "fcmpd $src1, $src2\n\tnop", + [(set FCC, (V8cmpfcc DFPRegs:$src1, DFPRegs:$src2))]>; //===----------------------------------------------------------------------===// // Non-Instruction Patterns diff --git a/lib/Target/SparcV8/SparcV8RegisterInfo.td b/lib/Target/SparcV8/SparcV8RegisterInfo.td index 52ddf59721a..c6fcc58fc09 100644 --- a/lib/Target/SparcV8/SparcV8RegisterInfo.td +++ b/lib/Target/SparcV8/SparcV8RegisterInfo.td @@ -71,6 +71,14 @@ def D10 : Rd<20, "F20", [F20, F21]>; def D11 : Rd<22, "F22", [F22, F23]>; def D12 : Rd<24, "F24", [F24, F25]>; def D13 : Rd<26, "F26", [F26, F27]>; def D14 : Rd<28, "F28", [F28, F29]>; def D15 : Rd<30, "F30", [F30, F31]>; +/// Integer and FP Condition codes. +let Namespace = "V8" in { + def ICC : Register<"ICC">; + def FCC : Register<"FCC">; +} +def FLAGS_REGS : RegisterClass<"V8", [FlagVT], 32, [ICC, FCC]> { + let Size = 32; +} // Register classes. //