diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index d575ee617f3..bdc49513eba 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -883,6 +883,16 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { } Result = LegalizeOp(Result); // Relegalize new nodes. break; + case TargetLowering::Custom: { + SDOperand Tmp = + TLI.LowerOperation(DAG.getNode(ISD::BRCOND, Node->getValueType(0), + Tmp1, Tmp2, Node->getOperand(2)), DAG); + if (Tmp.Val) { + Result = LegalizeOp(Tmp); + break; + } + // FALLTHROUGH if the target thinks it is legal. + } case TargetLowering::Legal: // Basic block destination (Op#2) is always legal. if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(1)) diff --git a/lib/Target/TargetSelectionDAG.td b/lib/Target/TargetSelectionDAG.td index 5e7554d9dd5..5ee107bfdb5 100644 --- a/lib/Target/TargetSelectionDAG.td +++ b/lib/Target/TargetSelectionDAG.td @@ -131,10 +131,6 @@ def SDTBr : SDTypeProfile<0, 1, [ // br SDTCisVT<0, OtherVT> ]>; -def SDTBrCond : SDTypeProfile<0, 2, [ // brcond - SDTCisInt<0>, SDTCisVT<1, OtherVT> -]>; - def SDTRet : SDTypeProfile<0, 0, []>; // ret def SDTWritePort : SDTypeProfile<0, 2, [ // writeport @@ -256,7 +252,6 @@ def select : SDNode<"ISD::SELECT" , SDTSelect>; def selectcc : SDNode<"ISD::SELECT_CC" , SDTSelectCC>; def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>; -def brcond : SDNode<"ISD::BRCOND" , SDTBrCond, [SDNPHasChain]>; def ret : SDNode<"ISD::RET" , SDTRet, [SDNPHasChain]>; def writeport : SDNode<"ISD::WRITEPORT" , SDTWritePort, [SDNPHasChain]>; diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index dac14daf49a..776ff6c8a91 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -31,7 +31,6 @@ static cl::opt<bool> EnableFastCC("enable-x86-fastcc", cl::Hidden, X86TargetLowering::X86TargetLowering(TargetMachine &TM) : TargetLowering(TM) { - // Set up the TargetLowering object. // X86 is weird, it always uses i8 for shift amounts and setcc results. @@ -81,6 +80,9 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) setOperationAction(ISD::FP_TO_SINT , MVT::i8 , Promote); setOperationAction(ISD::FP_TO_SINT , MVT::i16 , Promote); + if (X86DAGIsel) { + setOperationAction(ISD::BRCOND , MVT::Other, Custom); + } setOperationAction(ISD::BRCONDTWOWAY , MVT::Other, Expand); setOperationAction(ISD::BRTWOWAY_CC , MVT::Other, Expand); setOperationAction(ISD::MEMMOVE , MVT::Other, Expand); @@ -949,5 +951,22 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { return DAG.getNode(X86ISD::CMOV, Op.getValueType(), Op.getOperand(1), Op.getOperand(2), CC, Cond); } + case ISD::BRCOND: { + SDOperand Chain = Op.getOperand(0); + SDOperand Cond = Op.getOperand(1); + SDOperand Dest = Op.getOperand(2); + SDOperand CC; + // TODO: handle Cond == OR / AND / XOR + if (Cond.getOpcode() == ISD::SETCC) { + CC = Cond.getOperand(2); + Cond = DAG.getNode(X86ISD::CMP, MVT::Flag, + Cond.getOperand(0), Cond.getOperand(1)); + } else { + CC = DAG.getCondCode(ISD::SETNE); + Cond = DAG.getNode(X86ISD::TEST, MVT::Flag, Cond, Cond); + } + return DAG.getNode(X86ISD::BRCOND, Op.getValueType(), + Op.getOperand(0), Op.getOperand(2), CC, Cond); + } } } diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 26cc7d5ec6a..918b23420db 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -72,6 +72,9 @@ namespace llvm { /// X86 conditional moves. CMOV, + + /// X86 conditional branches. + BRCOND, }; } diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index f5b109a9725..07ff869b203 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -24,10 +24,15 @@ def SDTX86Cmov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT>, SDTCisVT<4, FlagVT>]>; -def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest, []>; -def X86test : SDNode<"X86ISD::TEST", SDTX86CmpTest, []>; +def SDTX86BrCond : SDTypeProfile<0, 3, + [SDTCisVT<0, OtherVT>, + SDTCisVT<1, OtherVT>, SDTCisVT<2, FlagVT>]>; -def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov, []>; +def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest, []>; +def X86test : SDNode<"X86ISD::TEST", SDTX86CmpTest, []>; + +def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov, []>; +def X86Brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, [SDNPHasChain]>; //===----------------------------------------------------------------------===// // X86 Operand Definitions. @@ -268,21 +273,33 @@ let isBranch = 1, isTerminator = 1 in let isBarrier = 1 in def JMP : IBr<0xE9, (ops brtarget:$dst), "jmp $dst", [(br bb:$dst)]>; + +def JE : IBr<0x84, (ops brtarget:$dst), "je $dst", + [(X86Brcond bb:$dst, SETEQ, STATUS)]>, Imp<[STATUS],[]>, TB; +def JNE : IBr<0x85, (ops brtarget:$dst), "jne $dst", + [(X86Brcond bb:$dst, SETNE, STATUS)]>, Imp<[STATUS],[]>, TB; +def JL : IBr<0x8C, (ops brtarget:$dst), "jl $dst", + [(X86Brcond bb:$dst, SETLT, STATUS)]>, Imp<[STATUS],[]>, TB; +def JLE : IBr<0x8E, (ops brtarget:$dst), "jle $dst", + [(X86Brcond bb:$dst, SETLE, STATUS)]>, Imp<[STATUS],[]>, TB; +def JG : IBr<0x8F, (ops brtarget:$dst), "jg $dst", + [(X86Brcond bb:$dst, SETGT, STATUS)]>, Imp<[STATUS],[]>, TB; +def JGE : IBr<0x8D, (ops brtarget:$dst), "jge $dst", + [(X86Brcond bb:$dst, SETGE, STATUS)]>, Imp<[STATUS],[]>, TB; + def JB : IBr<0x82, (ops brtarget:$dst), "jb $dst", - []>, TB; -def JAE : IBr<0x83, (ops brtarget:$dst), "jae $dst", []>, TB; -def JE : IBr<0x84, (ops brtarget:$dst), "je $dst", []>, TB; -def JNE : IBr<0x85, (ops brtarget:$dst), "jne $dst", []>, TB; -def JBE : IBr<0x86, (ops brtarget:$dst), "jbe $dst", []>, TB; -def JA : IBr<0x87, (ops brtarget:$dst), "ja $dst", []>, TB; + [(X86Brcond bb:$dst, SETULT, STATUS)]>, Imp<[STATUS],[]>, TB; +def JBE : IBr<0x86, (ops brtarget:$dst), "jbe $dst", + [(X86Brcond bb:$dst, SETULE, STATUS)]>, Imp<[STATUS],[]>, TB; +def JA : IBr<0x87, (ops brtarget:$dst), "ja $dst", + [(X86Brcond bb:$dst, SETUGT, STATUS)]>, Imp<[STATUS],[]>, TB; +def JAE : IBr<0x83, (ops brtarget:$dst), "jae $dst", + [(X86Brcond bb:$dst, SETUGE, STATUS)]>, Imp<[STATUS],[]>, TB; + def JS : IBr<0x88, (ops brtarget:$dst), "js $dst", []>, TB; def JNS : IBr<0x89, (ops brtarget:$dst), "jns $dst", []>, TB; def JP : IBr<0x8A, (ops brtarget:$dst), "jp $dst", []>, TB; def JNP : IBr<0x8B, (ops brtarget:$dst), "jnp $dst", []>, TB; -def JL : IBr<0x8C, (ops brtarget:$dst), "jl $dst", []>, TB; -def JGE : IBr<0x8D, (ops brtarget:$dst), "jge $dst", []>, TB; -def JLE : IBr<0x8E, (ops brtarget:$dst), "jle $dst", []>, TB; -def JG : IBr<0x8F, (ops brtarget:$dst), "jg $dst", []>, TB; //===----------------------------------------------------------------------===// // Call Instructions...