From: Andrew Lenharth Date: Tue, 8 Feb 2005 00:40:03 +0000 (+0000) Subject: BranchCC, nifty X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=445171aaf66294398abe7064a76bbc9f056e5366;p=oota-llvm.git BranchCC, nifty git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@20067 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Alpha/AlphaISelPattern.cpp b/lib/Target/Alpha/AlphaISelPattern.cpp index ccc10d3fdea..d4d2812f396 100644 --- a/lib/Target/Alpha/AlphaISelPattern.cpp +++ b/lib/Target/Alpha/AlphaISelPattern.cpp @@ -288,6 +288,9 @@ namespace { static const unsigned notIn = (unsigned)(-1); std::map ExprMap; + //CCInvMap sometimes (SetNE) we have the inverse CC code for free + std::map CCInvMap; + public: ISel(TargetMachine &TM) : SelectionDAGISel(AlphaLowering), AlphaLowering(TM) { } @@ -300,6 +303,7 @@ namespace { // Clear state used for selection. ExprMap.clear(); + CCInvMap.clear(); } unsigned SelectExpr(SDOperand N); @@ -307,6 +311,7 @@ namespace { void Select(SDOperand N); void SelectAddr(SDOperand N, unsigned& Reg, long& offset); + void SelectBranchCC(SDOperand N); }; } @@ -354,6 +359,115 @@ void ISel::SelectAddr(SDOperand N, unsigned& Reg, long& offset) return; } +void ISel::SelectBranchCC(SDOperand N) +{ + assert(N.getOpcode() == ISD::BRCOND && "Not a BranchCC???"); + MachineBasicBlock *Dest = cast(N.getOperand(2))->getBasicBlock(); + unsigned Opc; + + Select(N.getOperand(0)); //chain + SDOperand CC = N.getOperand(1); + + if (CC.getOpcode() == ISD::SETCC) + { + SetCCSDNode* SetCC = dyn_cast(CC.Val); + if (MVT::isInteger(SetCC->getOperand(0).getValueType())) { + //Dropping the CC is only useful if we are comparing to 0 + bool isZero0 = false; + bool isZero1 = false; + bool isNE = false; + + if(SetCC->getOperand(0).getOpcode() == ISD::Constant && + cast(SetCC->getOperand(0))->getValue() == 0) + isZero0 = true; + if(SetCC->getOperand(1).getOpcode() == ISD::Constant && + cast(SetCC->getOperand(1))->getValue() == 0) + isZero1 = true; + if(SetCC->getCondition() == ISD::SETNE) + isNE = true; + + if (isZero0) + { + switch (SetCC->getCondition()) { + default: CC.Val->dump(); assert(0 && "Unknown integer comparison!"); + case ISD::SETEQ: Opc = Alpha::BEQ; break; + case ISD::SETLT: Opc = Alpha::BGT; break; + case ISD::SETLE: Opc = Alpha::BGE; break; + case ISD::SETGT: Opc = Alpha::BLT; break; + case ISD::SETGE: Opc = Alpha::BLE; break; + case ISD::SETULT: Opc = Alpha::BNE; break; + case ISD::SETUGT: assert(0 && "0 > (unsigned) x is never true"); break; + case ISD::SETULE: assert(0 && "0 <= (unsigned) x is always true"); break; + case ISD::SETUGE: Opc = Alpha::BEQ; break; //Technically you could have this CC + case ISD::SETNE: Opc = Alpha::BNE; break; + } + unsigned Tmp1 = SelectExpr(SetCC->getOperand(1)); + BuildMI(BB, Opc, 2).addReg(Tmp1).addMBB(Dest); + return; + } + else if (isZero1) + { + switch (SetCC->getCondition()) { + default: CC.Val->dump(); assert(0 && "Unknown integer comparison!"); + case ISD::SETEQ: Opc = Alpha::BEQ; break; + case ISD::SETLT: Opc = Alpha::BLT; break; + case ISD::SETLE: Opc = Alpha::BLE; break; + case ISD::SETGT: Opc = Alpha::BGT; break; + case ISD::SETGE: Opc = Alpha::BGE; break; + case ISD::SETULT: assert(0 && "x (unsigned) < 0 is never true"); break; + case ISD::SETUGT: Opc = Alpha::BNE; break; + case ISD::SETULE: Opc = Alpha::BEQ; break; //Technically you could have this CC + case ISD::SETUGE: assert(0 && "x (unsgined >= 0 is always true"); break; + case ISD::SETNE: Opc = Alpha::BNE; break; + } + unsigned Tmp1 = SelectExpr(SetCC->getOperand(0)); + BuildMI(BB, Opc, 2).addReg(Tmp1).addMBB(Dest); + return; + } + else + { + unsigned Tmp1 = SelectExpr(CC); + if (isNE) + BuildMI(BB, Alpha::BEQ, 2).addReg(CCInvMap[CC]).addMBB(Dest); + else + BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest); + return; + } + } else { //FP + //Any comparison between 2 values should be codegened as an folded branch, as moving + //CC to the integer register is very expensive + //for a cmp b: c = a - b; + //a = b: c = 0 + //a < b: c < 0 + //a > b: c > 0 + unsigned Tmp1 = SelectExpr(SetCC->getOperand(0)); + unsigned Tmp2 = SelectExpr(SetCC->getOperand(1)); + unsigned Tmp3 = MakeReg(MVT::f64); + BuildMI(BB, Alpha::SUBT, 2, Tmp3).addReg(Tmp1).addReg(Tmp2); + + switch (SetCC->getCondition()) { + default: CC.Val->dump(); assert(0 && "Unknown FP comparison!"); + case ISD::SETEQ: Opc = Alpha::FBEQ; break; + case ISD::SETLT: Opc = Alpha::FBLT; break; + case ISD::SETLE: Opc = Alpha::FBLE; break; + case ISD::SETGT: Opc = Alpha::FBGT; break; + case ISD::SETGE: Opc = Alpha::FBGE; break; + case ISD::SETNE: Opc = Alpha::FBNE; break; + } + BuildMI(BB, Opc, 2).addReg(Tmp3).addMBB(Dest); + return; + } + abort(); //Should never be reached + } + else + { //Giveup and do the stupid thing + unsigned Tmp1 = SelectExpr(CC); + BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest); + return; + } + abort(); //Should never be reached +} + unsigned ISel::SelectExprFP(SDOperand N, unsigned Result) { unsigned Tmp1, Tmp2, Tmp3; @@ -886,6 +1000,8 @@ unsigned ISel::SelectExpr(SDOperand N) { Tmp2 = SelectExpr(N.getOperand(1)); Tmp3 = MakeReg(MVT::i64); BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2); + //Remeber we have the Inv for this CC + CCInvMap[N] = Tmp3; //and invert BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Alpha::R31).addReg(Tmp3); return Result; @@ -1180,13 +1296,7 @@ void ISel::Select(SDOperand N) { assert(0 && "Node not handled yet!"); case ISD::BRCOND: { - MachineBasicBlock *Dest = - cast(N.getOperand(2))->getBasicBlock(); - - Select(N.getOperand(0)); //chain - - Tmp1 = SelectExpr(N.getOperand(1)); - BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest); + SelectBranchCC(N); return; }