diff options
| author | Nate Begeman <natebegeman@mac.com> | 2006-02-01 07:19:44 +0000 | 
|---|---|---|
| committer | Nate Begeman <natebegeman@mac.com> | 2006-02-01 07:19:44 +0000 | 
| commit | 7e7f439f85689228e94cdb1fba63071ac0c91b74 (patch) | |
| tree | 11db7e4490d5ab2fc3cf643c8e978018b618a7a6 /llvm | |
| parent | 3da1bb520e6e97a70d86770cffd4206849024f44 (diff) | |
| download | bcm5719-llvm-7e7f439f85689228e94cdb1fba63071ac0c91b74.tar.gz bcm5719-llvm-7e7f439f85689228e94cdb1fba63071ac0c91b74.zip  | |
Fix some of the stuff in the PPC README file, and clean up legalization
of the SELECT_CC, BR_CC, and BRTWOWAY_CC nodes.
llvm-svn: 25875
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 52 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 424 | ||||
| -rw-r--r-- | llvm/lib/Target/Alpha/AlphaISelLowering.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/IA64/IA64ISelLowering.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 49 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/README.txt | 42 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 2 | 
7 files changed, 300 insertions, 275 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 101ce81d448..6fd1fe4b789 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1081,6 +1081,16 @@ SDOperand DAGCombiner::visitOR(SDNode *N) {      WorkList.push_back(ORNode.Val);      return DAG.getNode(ISD::ZERO_EXTEND, VT, ORNode);    } +  // fold (or (shl/srl/sra x), (shl/srl/sra y)) -> (shl/srl/sra (or x, y)) +  if (((N0.getOpcode() == ISD::SHL && N1.getOpcode() == ISD::SHL) || +       (N0.getOpcode() == ISD::SRL && N1.getOpcode() == ISD::SRL) || +       (N0.getOpcode() == ISD::SRA && N1.getOpcode() == ISD::SRA)) && +      N0.getOperand(1) == N1.getOperand(1)) { +    SDOperand ORNode = DAG.getNode(ISD::OR, N0.getOperand(0).getValueType(), +                                   N0.getOperand(0), N1.getOperand(0)); +    WorkList.push_back(ORNode.Val); +    return DAG.getNode(N0.getOpcode(), VT, ORNode, N0.getOperand(1)); +  }    // canonicalize shl to left side in a shl/srl pair, to match rotate    if (N0.getOpcode() == ISD::SRL && N1.getOpcode() == ISD::SHL)      std::swap(N0, N1); @@ -1196,6 +1206,16 @@ SDOperand DAGCombiner::visitXOR(SDNode *N) {      WorkList.push_back(XORNode.Val);      return DAG.getNode(ISD::ZERO_EXTEND, VT, XORNode);    } +  // fold (xor (shl/srl/sra x), (shl/srl/sra y)) -> (shl/srl/sra (xor x, y)) +  if (((N0.getOpcode() == ISD::SHL && N1.getOpcode() == ISD::SHL) || +       (N0.getOpcode() == ISD::SRL && N1.getOpcode() == ISD::SRL) || +       (N0.getOpcode() == ISD::SRA && N1.getOpcode() == ISD::SRA)) && +      N0.getOperand(1) == N1.getOperand(1)) { +    SDOperand XORNode = DAG.getNode(ISD::XOR, N0.getOperand(0).getValueType(), +                                    N0.getOperand(0), N1.getOperand(0)); +    WorkList.push_back(XORNode.Val); +    return DAG.getNode(N0.getOpcode(), VT, XORNode, N0.getOperand(1)); +  }    return SDOperand();  } @@ -1396,14 +1416,20 @@ SDOperand DAGCombiner::visitSELECT(SDNode *N) {    // fold X ? Y : X --> X ? Y : 0 --> X & Y    if (MVT::i1 == VT && N0 == N2)      return DAG.getNode(ISD::AND, VT, N0, N1); -      // If we can fold this based on the true/false value, do so.    if (SimplifySelectOps(N, N1, N2))      return SDOperand(); -      // fold selects based on a setcc into other things, such as min/max/abs    if (N0.getOpcode() == ISD::SETCC) -    return SimplifySelect(N0, N1, N2); +    // FIXME: +    // Check against MVT::Other for SELECT_CC, which is a workaround for targets +    // having to say they don't support SELECT_CC on every type the DAG knows +    // about, since there is no way to mark an opcode illegal at all value types +    if (TLI.isOperationLegal(ISD::SELECT_CC, MVT::Other)) +      return DAG.getNode(ISD::SELECT_CC, VT, N0.getOperand(0), N0.getOperand(1), +                         N1, N2, N0.getOperand(2)); +    else +      return SimplifySelect(N0, N1, N2);    return SDOperand();  } @@ -1927,6 +1953,13 @@ SDOperand DAGCombiner::visitBRCOND(SDNode *N) {    // unconditional branch    if (N1C && N1C->getValue() == 1)      return DAG.getNode(ISD::BR, MVT::Other, Chain, N2); +  // fold a brcond with a setcc condition into a BR_CC node if BR_CC is legal +  // on the target. +  if (N1.getOpcode() == ISD::SETCC &&  +      TLI.isOperationLegal(ISD::BR_CC, MVT::Other)) { +    return DAG.getNode(ISD::BR_CC, MVT::Other, Chain, N1.getOperand(2), +                       N1.getOperand(0), N1.getOperand(1), N2); +  }    return SDOperand();  } @@ -1943,6 +1976,19 @@ SDOperand DAGCombiner::visitBRCONDTWOWAY(SDNode *N) {    // unconditional branch to false mbb    if (N1C && N1C->isNullValue())      return DAG.getNode(ISD::BR, MVT::Other, Chain, N3); +  // fold a brcondtwoway with a setcc condition into a BRTWOWAY_CC node if  +  // BRTWOWAY_CC is legal on the target. +  if (N1.getOpcode() == ISD::SETCC &&  +      TLI.isOperationLegal(ISD::BRTWOWAY_CC, MVT::Other)) { +    std::vector<SDOperand> Ops; +    Ops.push_back(Chain); +    Ops.push_back(N1.getOperand(2)); +    Ops.push_back(N1.getOperand(0)); +    Ops.push_back(N1.getOperand(1)); +    Ops.push_back(N2); +    Ops.push_back(N3); +    return DAG.getNode(ISD::BRTWOWAY_CC, MVT::Other, Ops); +  }    return SDOperand();  } diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 02031eccea9..23e544212e7 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -106,6 +106,8 @@ private:    void ExpandOp(SDOperand O, SDOperand &Lo, SDOperand &Hi);    SDOperand PromoteOp(SDOperand O); +  void LegalizeSetCCOperands(SDOperand &LHS, SDOperand &RHS, SDOperand &CC); +        SDOperand ExpandLibCall(const char *Name, SDNode *Node,                            SDOperand &Hi);    SDOperand ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, @@ -717,33 +719,22 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {      break;    case ISD::BR_CC:      Tmp1 = LegalizeOp(Node->getOperand(0));  // Legalize the chain. -    if (!isTypeLegal(Node->getOperand(2).getValueType())) { -      Tmp2 = LegalizeOp(DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), -                                    Node->getOperand(2),  // LHS -                                    Node->getOperand(3),  // RHS -                                    Node->getOperand(1))); -      // If we get a SETCC back from legalizing the SETCC node we just -      // created, then use its LHS, RHS, and CC directly in creating a new -      // node.  Otherwise, select between the true and false value based on -      // comparing the result of the legalized with zero. -      if (Tmp2.getOpcode() == ISD::SETCC) { -        Result = DAG.getNode(ISD::BR_CC, MVT::Other, Tmp1, Tmp2.getOperand(2), -                             Tmp2.getOperand(0), Tmp2.getOperand(1), -                             Node->getOperand(4)); -      } else { -        Result = DAG.getNode(ISD::BR_CC, MVT::Other, Tmp1,  -                             DAG.getCondCode(ISD::SETNE), -                             Tmp2, DAG.getConstant(0, Tmp2.getValueType()),  -                             Node->getOperand(4)); -      } -      break; -    } +    Tmp2 = Node->getOperand(2);              // LHS  +    Tmp3 = Node->getOperand(3);              // RHS +    Tmp4 = Node->getOperand(1);              // CC -    Tmp2 = LegalizeOp(Node->getOperand(2));   // LHS -    Tmp3 = LegalizeOp(Node->getOperand(3));   // RHS - -    Result = DAG.UpdateNodeOperands(Result, Tmp1, Node->getOperand(1), Tmp2, -                                    Tmp3, Node->getOperand(4)); +    LegalizeSetCCOperands(Tmp2, Tmp3, Tmp4); +     +    // If we didn't get both a LHS and RHS back from LegalizeSetCCOperands, +    // the LHS is a legal SETCC itself.  In this case, we need to compare +    // the result against zero to select between true and false values. +    if (Tmp3.Val == 0) { +      Tmp3 = DAG.getConstant(0, Tmp2.getValueType()); +      Tmp4 = DAG.getCondCode(ISD::SETNE); +    } +     +    Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp4, Tmp2, Tmp3,  +                                    Node->getOperand(4));      switch (TLI.getOperationAction(ISD::BR_CC, Tmp3.getValueType())) {      default: assert(0 && "Unexpected action for BR_CC!"); @@ -805,61 +796,44 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {        break;      }      break; -  case ISD::BRTWOWAY_CC: +  case ISD::BRTWOWAY_CC: {      Tmp1 = LegalizeOp(Node->getOperand(0));  // Legalize the chain. -    if (isTypeLegal(Node->getOperand(2).getValueType())) { -      Tmp2 = LegalizeOp(Node->getOperand(2));   // LHS -      Tmp3 = LegalizeOp(Node->getOperand(3));   // RHS -      if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(2) || -          Tmp3 != Node->getOperand(3)) { -        std::vector<SDOperand> Ops; -        Ops.push_back(Tmp1); -        Ops.push_back(Node->getOperand(1)); -        Ops.push_back(Tmp2); -        Ops.push_back(Tmp3); -        Ops.push_back(Node->getOperand(4)); -        Ops.push_back(Node->getOperand(5)); -        Result = DAG.UpdateNodeOperands(Result, Ops); -      } +    Tmp2 = Node->getOperand(2);              // LHS  +    Tmp3 = Node->getOperand(3);              // RHS +    Tmp4 = Node->getOperand(1);              // CC +     +    LegalizeSetCCOperands(Tmp2, Tmp3, Tmp4); +     +    // If we didn't get both a LHS and RHS back from LegalizeSetCCOperands, +    // the LHS is a legal SETCC itself.  In this case, we need to compare +    // the result against zero to select between true and false values. +    if (Tmp3.Val == 0) { +      Tmp3 = DAG.getConstant(0, Tmp2.getValueType()); +      Tmp4 = DAG.getCondCode(ISD::SETNE); +    } +    std::vector<SDOperand> Ops; +    Ops.push_back(Tmp1); +    Ops.push_back(Tmp4); +    Ops.push_back(Tmp2); +    Ops.push_back(Tmp3); +    Ops.push_back(Node->getOperand(4)); +    Ops.push_back(Node->getOperand(5)); +    Result = DAG.UpdateNodeOperands(Result, Ops); + +    // Everything is legal, see if we should expand this op or something. +    switch (TLI.getOperationAction(ISD::BRTWOWAY_CC, MVT::Other)) { +    default: assert(0 && "This action is not supported yet!"); +    case TargetLowering::Legal: break; +    case TargetLowering::Expand:  +      Result = DAG.getNode(ISD::BRCOND, MVT::Other, Tmp1, +                           DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), Tmp2, +                                       Tmp3, Tmp4),  +                           Result.getOperand(4)); +      Result = DAG.getNode(ISD::BR, MVT::Other, Result, Result.getOperand(5));        break; -    } else { -      Tmp2 = LegalizeOp(DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), -                                    Node->getOperand(2),  // LHS -                                    Node->getOperand(3),  // RHS -                                    Node->getOperand(1))); -      // If this target does not support BRTWOWAY_CC, lower it to a BRCOND/BR -      // pair. -      switch (TLI.getOperationAction(ISD::BRTWOWAY_CC, MVT::Other)) { -      default: assert(0 && "This action is not supported yet!"); -      case TargetLowering::Legal: { -        // If we get a SETCC back from legalizing the SETCC node we just -        // created, then use its LHS, RHS, and CC directly in creating a new -        // node.  Otherwise, select between the true and false value based on -        // comparing the result of the legalized with zero. -        std::vector<SDOperand> Ops; -        Ops.push_back(Tmp1); -        if (Tmp2.getOpcode() == ISD::SETCC) { -          Ops.push_back(Tmp2.getOperand(2)); -          Ops.push_back(Tmp2.getOperand(0)); -          Ops.push_back(Tmp2.getOperand(1)); -        } else { -          Ops.push_back(DAG.getCondCode(ISD::SETNE)); -          Ops.push_back(Tmp2); -          Ops.push_back(DAG.getConstant(0, Tmp2.getValueType())); -        } -        Ops.push_back(Node->getOperand(4)); -        Ops.push_back(Node->getOperand(5)); -        Result = DAG.UpdateNodeOperands(Result, Ops); -        break; -      } -      case TargetLowering::Expand:  -        Result = DAG.getNode(ISD::BRCOND, MVT::Other, Tmp1, Tmp2, -                             Node->getOperand(4)); -        Result = DAG.getNode(ISD::BR, MVT::Other, Result, Node->getOperand(5)); -        break; -      }      }      break; +  }    case ISD::LOAD: {      Tmp1 = LegalizeOp(Node->getOperand(0));  // Legalize the chain.      Tmp2 = LegalizeOp(Node->getOperand(1));  // Legalize the pointer. @@ -1315,156 +1289,47 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {      }      }      break; -  case ISD::SELECT_CC: +  case ISD::SELECT_CC: { +    Tmp1 = Node->getOperand(0);               // LHS +    Tmp2 = Node->getOperand(1);               // RHS      Tmp3 = LegalizeOp(Node->getOperand(2));   // True      Tmp4 = LegalizeOp(Node->getOperand(3));   // False +    SDOperand CC = Node->getOperand(4); -    if (isTypeLegal(Node->getOperand(0).getValueType())) { -      Tmp1 = LegalizeOp(Node->getOperand(0));   // LHS -      Tmp2 = LegalizeOp(Node->getOperand(1));   // RHS -       -      Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3, Tmp4,  -                                      Node->getOperand(4)); -       -      // Everything is legal, see if we should expand this op or something. -      switch (TLI.getOperationAction(ISD::SELECT_CC, -                                     Node->getOperand(0).getValueType())) { -      default: assert(0 && "This action is not supported yet!"); -      case TargetLowering::Legal: break; -      case TargetLowering::Custom: -        Tmp1 = TLI.LowerOperation(Result, DAG); -        if (Tmp1.Val) Result = Tmp1; -        break; -      } +    LegalizeSetCCOperands(Tmp1, Tmp2, CC); +     +    // If we didn't get both a LHS and RHS back from LegalizeSetCCOperands, +    // the LHS is a legal SETCC itself.  In this case, we need to compare +    // the result against zero to select between true and false values. +    if (Tmp2.Val == 0) { +      Tmp2 = DAG.getConstant(0, Tmp1.getValueType()); +      CC = DAG.getCondCode(ISD::SETNE); +    } +    Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3, Tmp4, CC); + +    // Everything is legal, see if we should expand this op or something. +    switch (TLI.getOperationAction(ISD::SELECT_CC, Tmp3.getValueType())) { +    default: assert(0 && "This action is not supported yet!"); +    case TargetLowering::Legal: break; +    case TargetLowering::Custom: +      Tmp1 = TLI.LowerOperation(Result, DAG); +      if (Tmp1.Val) Result = Tmp1;        break; -    } else { -      Tmp1 = LegalizeOp(DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), -                                    Node->getOperand(0),  // LHS -                                    Node->getOperand(1),  // RHS -                                    Node->getOperand(4))); -      // If we get a SETCC back from legalizing the SETCC node we just -      // created, then use its LHS, RHS, and CC directly in creating a new -      // node.  Otherwise, select between the true and false value based on -      // comparing the result of the legalized with zero. -      if (Tmp1.getOpcode() == ISD::SETCC) { -        Result = DAG.getNode(ISD::SELECT_CC, Tmp3.getValueType(), -                             Tmp1.getOperand(0), Tmp1.getOperand(1), -                             Tmp3, Tmp4, Tmp1.getOperand(2)); -      } else { -        Result = DAG.getSelectCC(Tmp1, -                                 DAG.getConstant(0, Tmp1.getValueType()),  -                                 Tmp3, Tmp4, ISD::SETNE); -      }      }      break; +  }    case ISD::SETCC: -    switch (getTypeAction(Node->getOperand(0).getValueType())) { -    case Legal: -      Tmp1 = LegalizeOp(Node->getOperand(0));   // LHS -      Tmp2 = LegalizeOp(Node->getOperand(1));   // RHS -      break; -    case Promote: -      Tmp1 = PromoteOp(Node->getOperand(0));   // LHS -      Tmp2 = PromoteOp(Node->getOperand(1));   // RHS - -      // If this is an FP compare, the operands have already been extended. -      if (MVT::isInteger(Node->getOperand(0).getValueType())) { -        MVT::ValueType VT = Node->getOperand(0).getValueType(); -        MVT::ValueType NVT = TLI.getTypeToTransformTo(VT); - -        // Otherwise, we have to insert explicit sign or zero extends.  Note -        // that we could insert sign extends for ALL conditions, but zero extend -        // is cheaper on many machines (an AND instead of two shifts), so prefer -        // it. -        switch (cast<CondCodeSDNode>(Node->getOperand(2))->get()) { -        default: assert(0 && "Unknown integer comparison!"); -        case ISD::SETEQ: -        case ISD::SETNE: -        case ISD::SETUGE: -        case ISD::SETUGT: -        case ISD::SETULE: -        case ISD::SETULT: -          // ALL of these operations will work if we either sign or zero extend -          // the operands (including the unsigned comparisons!).  Zero extend is -          // usually a simpler/cheaper operation, so prefer it. -          Tmp1 = DAG.getZeroExtendInReg(Tmp1, VT); -          Tmp2 = DAG.getZeroExtendInReg(Tmp2, VT); -          break; -        case ISD::SETGE: -        case ISD::SETGT: -        case ISD::SETLT: -        case ISD::SETLE: -          Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp1, -                             DAG.getValueType(VT)); -          Tmp2 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp2, -                             DAG.getValueType(VT)); -          break; -        } -      } +    Tmp1 = Node->getOperand(0); +    Tmp2 = Node->getOperand(1); +    Tmp3 = Node->getOperand(2); +    LegalizeSetCCOperands(Tmp1, Tmp2, Tmp3); +     +    // If we had to Expand the SetCC operands into a SELECT node, then it may  +    // not always be possible to return a true LHS & RHS.  In this case, just  +    // return the value we legalized, returned in the LHS +    if (Tmp2.Val == 0) { +      Result = Tmp1;        break; -    case Expand: -      SDOperand LHSLo, LHSHi, RHSLo, RHSHi; -      ExpandOp(Node->getOperand(0), LHSLo, LHSHi); -      ExpandOp(Node->getOperand(1), RHSLo, RHSHi); -      switch (cast<CondCodeSDNode>(Node->getOperand(2))->get()) { -      case ISD::SETEQ: -      case ISD::SETNE: -        if (RHSLo == RHSHi) -          if (ConstantSDNode *RHSCST = dyn_cast<ConstantSDNode>(RHSLo)) -            if (RHSCST->isAllOnesValue()) { -              // Comparison to -1. -              Tmp1 = DAG.getNode(ISD::AND, LHSLo.getValueType(), LHSLo, LHSHi); -              Tmp2 = RHSLo; -              break; -            } - -        Tmp1 = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSLo, RHSLo); -        Tmp2 = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSHi, RHSHi); -        Tmp1 = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp2); -        Tmp2 = DAG.getConstant(0, Tmp1.getValueType()); -        break; -      default: -        // If this is a comparison of the sign bit, just look at the top part. -        // X > -1,  x < 0 -        if (ConstantSDNode *CST = dyn_cast<ConstantSDNode>(Node->getOperand(1))) -          if ((cast<CondCodeSDNode>(Node->getOperand(2))->get() == ISD::SETLT && -               CST->getValue() == 0) ||              // X < 0 -              (cast<CondCodeSDNode>(Node->getOperand(2))->get() == ISD::SETGT && -               (CST->isAllOnesValue()))) {            // X > -1 -            Tmp1 = LHSHi; -            Tmp2 = RHSHi; -            break; -          } - -        // FIXME: This generated code sucks. -        ISD::CondCode LowCC; -        switch (cast<CondCodeSDNode>(Node->getOperand(2))->get()) { -        default: assert(0 && "Unknown integer setcc!"); -        case ISD::SETLT: -        case ISD::SETULT: LowCC = ISD::SETULT; break; -        case ISD::SETGT: -        case ISD::SETUGT: LowCC = ISD::SETUGT; break; -        case ISD::SETLE: -        case ISD::SETULE: LowCC = ISD::SETULE; break; -        case ISD::SETGE: -        case ISD::SETUGE: LowCC = ISD::SETUGE; break; -        } - -        // Tmp1 = lo(op1) < lo(op2)   // Always unsigned comparison -        // Tmp2 = hi(op1) < hi(op2)   // Signedness depends on operands -        // dest = hi(op1) == hi(op2) ? Tmp1 : Tmp2; - -        // NOTE: on targets without efficient SELECT of bools, we can always use -        // this identity: (B1 ? B2 : B3) --> (B1 & B2)|(!B1&B3) -        Tmp1 = DAG.getSetCC(Node->getValueType(0), LHSLo, RHSLo, LowCC); -        Tmp2 = DAG.getNode(ISD::SETCC, Node->getValueType(0), LHSHi, RHSHi, -                           Node->getOperand(2)); -        Result = DAG.getSetCC(Node->getValueType(0), LHSHi, RHSHi, ISD::SETEQ); -        Result = LegalizeOp(DAG.getNode(ISD::SELECT, Tmp1.getValueType(), -                                        Result, Tmp1, Tmp2)); -        AddLegalizedOperand(SDOperand(Node, 0), Result); -        return Result; -      }      }      switch (TLI.getOperationAction(ISD::SETCC, Tmp1.getValueType())) { @@ -2699,6 +2564,127 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) {    return Result;  } +/// LegalizeSetCCOperands - Attempts to create a legal LHS and RHS for a SETCC +/// with condition CC on the current target.  This usually involves legalizing +/// or promoting the arguments.  In the case where LHS and RHS must be expanded, +/// there may be no choice but to create a new SetCC node to represent the +/// legalized value of setcc lhs, rhs.  In this case, the value is returned in +/// LHS, and the SDOperand returned in RHS has a nil SDNode value. +void SelectionDAGLegalize::LegalizeSetCCOperands(SDOperand &LHS, +                                                 SDOperand &RHS, +                                                 SDOperand &CC) { +  SDOperand Tmp1, Tmp2, Result;     +   +  switch (getTypeAction(LHS.getValueType())) { +  case Legal: +    Tmp1 = LegalizeOp(LHS);   // LHS +    Tmp2 = LegalizeOp(RHS);   // RHS +    break; +  case Promote: +    Tmp1 = PromoteOp(LHS);   // LHS +    Tmp2 = PromoteOp(RHS);   // RHS + +    // If this is an FP compare, the operands have already been extended. +    if (MVT::isInteger(LHS.getValueType())) { +      MVT::ValueType VT = LHS.getValueType(); +      MVT::ValueType NVT = TLI.getTypeToTransformTo(VT); + +      // Otherwise, we have to insert explicit sign or zero extends.  Note +      // that we could insert sign extends for ALL conditions, but zero extend +      // is cheaper on many machines (an AND instead of two shifts), so prefer +      // it. +      switch (cast<CondCodeSDNode>(CC)->get()) { +      default: assert(0 && "Unknown integer comparison!"); +      case ISD::SETEQ: +      case ISD::SETNE: +      case ISD::SETUGE: +      case ISD::SETUGT: +      case ISD::SETULE: +      case ISD::SETULT: +        // ALL of these operations will work if we either sign or zero extend +        // the operands (including the unsigned comparisons!).  Zero extend is +        // usually a simpler/cheaper operation, so prefer it. +        Tmp1 = DAG.getZeroExtendInReg(Tmp1, VT); +        Tmp2 = DAG.getZeroExtendInReg(Tmp2, VT); +        break; +      case ISD::SETGE: +      case ISD::SETGT: +      case ISD::SETLT: +      case ISD::SETLE: +        Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp1, +                           DAG.getValueType(VT)); +        Tmp2 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp2, +                           DAG.getValueType(VT)); +        break; +      } +    } +    break; +  case Expand: +    SDOperand LHSLo, LHSHi, RHSLo, RHSHi; +    ExpandOp(LHS, LHSLo, LHSHi); +    ExpandOp(RHS, RHSLo, RHSHi); +    switch (cast<CondCodeSDNode>(CC)->get()) { +    case ISD::SETEQ: +    case ISD::SETNE: +      if (RHSLo == RHSHi) +        if (ConstantSDNode *RHSCST = dyn_cast<ConstantSDNode>(RHSLo)) +          if (RHSCST->isAllOnesValue()) { +            // Comparison to -1. +            Tmp1 = DAG.getNode(ISD::AND, LHSLo.getValueType(), LHSLo, LHSHi); +            Tmp2 = RHSLo; +            break; +          } + +      Tmp1 = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSLo, RHSLo); +      Tmp2 = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSHi, RHSHi); +      Tmp1 = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp2); +      Tmp2 = DAG.getConstant(0, Tmp1.getValueType()); +      break; +    default: +      // If this is a comparison of the sign bit, just look at the top part. +      // X > -1,  x < 0 +      if (ConstantSDNode *CST = dyn_cast<ConstantSDNode>(RHS)) +        if ((cast<CondCodeSDNode>(CC)->get() == ISD::SETLT &&  +             CST->getValue() == 0) ||             // X < 0 +            (cast<CondCodeSDNode>(CC)->get() == ISD::SETGT && +             CST->isAllOnesValue())) {            // X > -1 +          Tmp1 = LHSHi; +          Tmp2 = RHSHi; +          break; +        } + +      // FIXME: This generated code sucks. +      ISD::CondCode LowCC; +      switch (cast<CondCodeSDNode>(CC)->get()) { +      default: assert(0 && "Unknown integer setcc!"); +      case ISD::SETLT: +      case ISD::SETULT: LowCC = ISD::SETULT; break; +      case ISD::SETGT: +      case ISD::SETUGT: LowCC = ISD::SETUGT; break; +      case ISD::SETLE: +      case ISD::SETULE: LowCC = ISD::SETULE; break; +      case ISD::SETGE: +      case ISD::SETUGE: LowCC = ISD::SETUGE; break; +      } + +      // Tmp1 = lo(op1) < lo(op2)   // Always unsigned comparison +      // Tmp2 = hi(op1) < hi(op2)   // Signedness depends on operands +      // dest = hi(op1) == hi(op2) ? Tmp1 : Tmp2; + +      // NOTE: on targets without efficient SELECT of bools, we can always use +      // this identity: (B1 ? B2 : B3) --> (B1 & B2)|(!B1&B3) +      Tmp1 = DAG.getSetCC(TLI.getSetCCResultTy(), LHSLo, RHSLo, LowCC); +      Tmp2 = DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), LHSHi, RHSHi, CC); +      Result = DAG.getSetCC(TLI.getSetCCResultTy(), LHSHi, RHSHi, ISD::SETEQ); +      Result = LegalizeOp(DAG.getNode(ISD::SELECT, Tmp1.getValueType(), +                                      Result, Tmp1, Tmp2)); +      Tmp1 = Result; +    } +  } +  LHS = Tmp1; +  RHS = Tmp2; +} +  /// ExpandBIT_CONVERT - Expand a BIT_CONVERT node into a store/load combination.  /// The resultant code need not be legal.  Note that SrcOp is the input operand  /// to the BIT_CONVERT, not the BIT_CONVERT node itself. diff --git a/llvm/lib/Target/Alpha/AlphaISelLowering.cpp b/llvm/lib/Target/Alpha/AlphaISelLowering.cpp index 2990146899b..c9cafd478e5 100644 --- a/llvm/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/llvm/lib/Target/Alpha/AlphaISelLowering.cpp @@ -56,6 +56,8 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM)    setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);    setOperationAction(ISD::BRTWOWAY_CC,  MVT::Other, Expand); +  setOperationAction(ISD::BR_CC,        MVT::Other, Expand); +  setOperationAction(ISD::SELECT_CC,    MVT::Other, Expand);    setOperationAction(ISD::EXTLOAD, MVT::i1,  Promote);    setOperationAction(ISD::EXTLOAD, MVT::f32, Expand); diff --git a/llvm/lib/Target/IA64/IA64ISelLowering.cpp b/llvm/lib/Target/IA64/IA64ISelLowering.cpp index 11b95c4e02e..1c835a8c98d 100644 --- a/llvm/lib/Target/IA64/IA64ISelLowering.cpp +++ b/llvm/lib/Target/IA64/IA64ISelLowering.cpp @@ -35,10 +35,14 @@ IA64TargetLowering::IA64TargetLowering(TargetMachine &TM)        // register class for predicate registers        addRegisterClass(MVT::i1, IA64::PRRegisterClass); +      setOperationAction(ISD::BR_CC            , MVT::Other, Expand);        setOperationAction(ISD::BRCONDTWOWAY     , MVT::Other, Expand);        setOperationAction(ISD::BRTWOWAY_CC      , MVT::Other, Expand);        setOperationAction(ISD::FP_ROUND_INREG   , MVT::f32  , Expand); +      // ia64 uses SELECT not SELECT_CC +      setOperationAction(ISD::SELECT_CC        , MVT::Other,  Expand); +              // We need to handle ISD::RET for void functions ourselves,        // so we get a chance to restore ar.pfs before adding a        // br.ret insn diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 28beeafce16..ec35f37e96e 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -13,6 +13,7 @@  #include "PPCISelLowering.h"  #include "PPCTargetMachine.h" +#include "llvm/ADT/VectorExtras.h"  #include "llvm/CodeGen/MachineFrameInfo.h"  #include "llvm/CodeGen/MachineFunction.h"  #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -20,7 +21,7 @@  #include "llvm/CodeGen/SSARegMap.h"  #include "llvm/Constants.h"  #include "llvm/Function.h" -#include "llvm/ADT/VectorExtras.h" +#include "llvm/Support/MathExtras.h"  using namespace llvm;  PPCTargetLowering::PPCTargetLowering(TargetMachine &TM) @@ -85,7 +86,7 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM)    setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);    setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); -  // PowerPC wants to optimize setcc i32, imm a bit. +  // PowerPC wants to optimize integer setcc a bit    setOperationAction(ISD::SETCC, MVT::i32, Custom);    // PowerPC does not have BRCOND* which requires SetCC @@ -452,15 +453,41 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {    }    case ISD::SETCC: {      ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); -    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) -      if (C->getValue() && !C->isAllOnesValue()) -        if (CC == ISD::SETEQ || CC == ISD::SETNE ||  -            CC == ISD::SETLT || CC == ISD::SETGT) { -          MVT::ValueType VT = Op.getValueType(); -          SDOperand SUB = DAG.getNode(ISD::SUB, Op.getOperand(0).getValueType(), -                                      Op.getOperand(0), Op.getOperand(1)); -          return DAG.getSetCC(VT, SUB, DAG.getConstant(0, VT), CC); -        } +     +    // If we're comparing for equality to zero, expose the fact that this is +    // implented as a ctlz/srl pair on ppc, so that the dag combiner can +    // fold the new nodes. +    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) { +      if (C->isNullValue() && CC == ISD::SETEQ) { +        MVT::ValueType VT = Op.getOperand(0).getValueType(); +        SDOperand Zext = Op.getOperand(0); +        if (VT < MVT::i32) { +          VT = MVT::i32; +          Zext = DAG.getNode(ISD::ZERO_EXTEND, VT, Op.getOperand(0)); +        }  +        unsigned Log2b = Log2_32(MVT::getSizeInBits(VT)); +        SDOperand Clz = DAG.getNode(ISD::CTLZ, VT, Zext); +        SDOperand Scc = DAG.getNode(ISD::SRL, VT, Clz, +                                    DAG.getConstant(Log2b, getShiftAmountTy())); +        return DAG.getNode(ISD::TRUNCATE, getSetCCResultTy(), Scc); +      } +      // Leave comparisons against 0 and -1 alone for now, since they're usually  +      // optimized.  FIXME: revisit this when we can custom lower all setcc +      // optimizations. +      if (C->isAllOnesValue() || C->isNullValue()) +        break; +    } +         +    // If we have an integer seteq/setne, turn it into a compare against zero +    // by subtracting the rhs from the lhs, which is faster than setting a +    // condition register, reading it back out, and masking the correct bit. +    MVT::ValueType LHSVT = Op.getOperand(0).getValueType(); +    if (MVT::isInteger(LHSVT) && (CC == ISD::SETEQ || CC == ISD::SETNE)) { +      MVT::ValueType VT = Op.getValueType(); +      SDOperand Sub = DAG.getNode(ISD::SUB, LHSVT, Op.getOperand(0),  +                                  Op.getOperand(1)); +      return DAG.getSetCC(VT, Sub, DAG.getConstant(0, LHSVT), CC); +    }      break;    }    case ISD::VASTART: { diff --git a/llvm/lib/Target/PowerPC/README.txt b/llvm/lib/Target/PowerPC/README.txt index 1b05e7c4f0d..e23c6e77b5b 100644 --- a/llvm/lib/Target/PowerPC/README.txt +++ b/llvm/lib/Target/PowerPC/README.txt @@ -280,32 +280,6 @@ void bar() { struct foo R = { 1.0, 2.0 }; xxx(R); }  ===-------------------------------------------------------------------------=== -For this: - -int h(int i, int j, int k) { - return (i==0||j==0||k == 0); -} - -We currently emit this: - -_h: -        cntlzw r2, r3 -        cntlzw r3, r4 -        cntlzw r4, r5 -        srwi r2, r2, 5 -        srwi r3, r3, 5 -        srwi r4, r4, 5 -        or r2, r3, r2 -        or r3, r2, r4 -        blr - -The ctlz/shift instructions are created by the isel, so the dag combiner doesn't -have a chance to pull the shifts through the or's (eliminating two  -instructions).  SETCC nodes should be custom lowered in this case, not expanded -by the isel. - -===-------------------------------------------------------------------------=== -  Darwin Stub LICM optimization:  Loops like this: @@ -461,19 +435,3 @@ This could be done in the dag combiner, by swapping a BR_CC when a SETCC of the  same operands (but backwards) exists.  In this case, this wouldn't save us   anything though, because the compares still wouldn't be shared. -===-------------------------------------------------------------------------=== - -A simple case we generate suboptimal code on: - -int test(int X) { -  return X == 0 ? 32 : 0; -} - -_test: -        cntlzw r2, r3 -        srwi r2, r2, 5 -        slwi r3, r2, 5 -        blr - -The shifts should be one 'andi'. - diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index d692780179c..0a63cfa1260 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -117,6 +117,8 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)    }    setOperationAction(ISD::BRCONDTWOWAY     , MVT::Other, Expand);    setOperationAction(ISD::BRTWOWAY_CC      , MVT::Other, Expand); +  setOperationAction(ISD::BR_CC            , MVT::Other, Expand); +  setOperationAction(ISD::SELECT_CC        , MVT::Other, Expand);    setOperationAction(ISD::MEMMOVE          , MVT::Other, Expand);    setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16  , Expand);    setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8   , Expand);  | 

