Fix for PR3040:
[oota-llvm.git] / lib / CodeGen / SelectionDAG / DAGCombiner.cpp
index 0622c552d5a218fc726bf6f1dd9943dadb583fee..eb6481c996a77a2aa7ad8a3234f6a3fa2b9f6a3f 100644 (file)
@@ -892,16 +892,18 @@ SDValue combineShlAddConstant(SDValue N0, SDValue N1, SelectionDAG &DAG) {
 
 static
 SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp,
-                            SelectionDAG &DAG) {
+                            SelectionDAG &DAG, const TargetLowering &TLI,
+                            bool AfterLegalize) {
   MVT VT = N->getValueType(0);
   unsigned Opc = N->getOpcode();
   bool isSlctCC = Slct.getOpcode() == ISD::SELECT_CC;
   SDValue LHS = isSlctCC ? Slct.getOperand(2) : Slct.getOperand(1);
   SDValue RHS = isSlctCC ? Slct.getOperand(3) : Slct.getOperand(2);
   ISD::CondCode CC = ISD::SETCC_INVALID;
-  if (isSlctCC)
+
+  if (isSlctCC) {
     CC = cast<CondCodeSDNode>(Slct.getOperand(4))->get();
-  else {
+  else {
     SDValue CCOp = Slct.getOperand(0);
     if (CCOp.getOpcode() == ISD::SETCC)
       CC = cast<CondCodeSDNode>(CCOp.getOperand(2))->get();
@@ -911,17 +913,23 @@ SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp,
   bool InvCC = false;
   assert ((Opc == ISD::ADD || (Opc == ISD::SUB && Slct == N->getOperand(1))) &&
           "Bad input!");
+
   if (LHS.getOpcode() == ISD::Constant &&
-      cast<ConstantSDNode>(LHS)->isNullValue())
+      cast<ConstantSDNode>(LHS)->isNullValue()) {
     DoXform = true;
-  else if (CC != ISD::SETCC_INVALID &&
-           RHS.getOpcode() == ISD::Constant &&
-           cast<ConstantSDNode>(RHS)->isNullValue()) {
+  else if (CC != ISD::SETCC_INVALID &&
+             RHS.getOpcode() == ISD::Constant &&
+             cast<ConstantSDNode>(RHS)->isNullValue()) {
     std::swap(LHS, RHS);
     SDValue Op0 = Slct.getOperand(0);
-    bool isInt = (isSlctCC ? Op0.getValueType() :
-                  Op0.getOperand(0).getValueType()).isInteger();
+    MVT OpVT = isSlctCC ? Op0.getValueType() :
+                          Op0.getOperand(0).getValueType();
+    bool isInt = OpVT.isInteger();
     CC = ISD::getSetCCInverse(CC, isInt);
+
+    if (AfterLegalize && !TLI.isCondCodeLegal(CC, OpVT))
+      return SDValue();         // Inverse operator isn't legal.
+
     DoXform = true;
     InvCC = true;
   }
@@ -1029,11 +1037,11 @@ SDValue DAGCombiner::visitADD(SDNode *N) {
 
   // fold (add (select cc, 0, c), x) -> (select cc, x, (add, x, c))
   if (N0.getOpcode() == ISD::SELECT && N0.getNode()->hasOneUse()) {
-    SDValue Result = combineSelectAndUse(N, N0, N1, DAG);
+    SDValue Result = combineSelectAndUse(N, N0, N1, DAG, TLI, AfterLegalize);
     if (Result.getNode()) return Result;
   }
   if (N1.getOpcode() == ISD::SELECT && N1.getNode()->hasOneUse()) {
-    SDValue Result = combineSelectAndUse(N, N1, N0, DAG);
+    SDValue Result = combineSelectAndUse(N, N1, N0, DAG, TLI, AfterLegalize);
     if (Result.getNode()) return Result;
   }
 
@@ -1131,7 +1139,7 @@ SDValue DAGCombiner::visitSUB(SDNode *N) {
     return N0.getOperand(0);
   // fold (sub x, (select cc, 0, c)) -> (select cc, x, (sub, x, c))
   if (N1.getOpcode() == ISD::SELECT && N1.getNode()->hasOneUse()) {
-    SDValue Result = combineSelectAndUse(N, N1, N0, DAG);
+    SDValue Result = combineSelectAndUse(N, N1, N0, DAG, TLI, AfterLegalize);
     if (Result.getNode()) return Result;
   }
   // If either operand of a sub is undef, the result is undef
@@ -1720,7 +1728,8 @@ SDValue DAGCombiner::visitAND(SDNode *N) {
     if (LL == RL && LR == RR) {
       bool isInteger = LL.getValueType().isInteger();
       ISD::CondCode Result = ISD::getSetCCAndOperation(Op0, Op1, isInteger);
-      if (Result != ISD::SETCC_INVALID)
+      if (Result != ISD::SETCC_INVALID &&
+          (!AfterLegalize || TLI.isCondCodeLegal(Result, LL.getValueType())))
         return DAG.getSetCC(N0.getValueType(), LL, LR, Result);
     }
   }
@@ -1904,7 +1913,8 @@ SDValue DAGCombiner::visitOR(SDNode *N) {
     if (LL == RL && LR == RR) {
       bool isInteger = LL.getValueType().isInteger();
       ISD::CondCode Result = ISD::getSetCCOrOperation(Op0, Op1, isInteger);
-      if (Result != ISD::SETCC_INVALID)
+      if (Result != ISD::SETCC_INVALID &&
+          (!AfterLegalize || TLI.isCondCodeLegal(Result, LL.getValueType())))
         return DAG.getSetCC(N0.getValueType(), LL, LR, Result);
     }
   }
@@ -2154,18 +2164,27 @@ SDValue DAGCombiner::visitXOR(SDNode *N) {
   SDValue RXOR = ReassociateOps(ISD::XOR, N0, N1);
   if (RXOR.getNode() != 0)
     return RXOR;
+
   // fold !(x cc y) -> (x !cc y)
   if (N1C && N1C->getAPIntValue() == 1 && isSetCCEquivalent(N0, LHS, RHS, CC)) {
     bool isInt = LHS.getValueType().isInteger();
     ISD::CondCode NotCC = ISD::getSetCCInverse(cast<CondCodeSDNode>(CC)->get(),
                                                isInt);
-    if (N0.getOpcode() == ISD::SETCC)
-      return DAG.getSetCC(VT, LHS, RHS, NotCC);
-    if (N0.getOpcode() == ISD::SELECT_CC)
-      return DAG.getSelectCC(LHS, RHS, N0.getOperand(2),N0.getOperand(3),NotCC);
-    assert(0 && "Unhandled SetCC Equivalent!");
-    abort();
+
+    if (!AfterLegalize || TLI.isCondCodeLegal(NotCC, LHS.getValueType())) {
+      switch (N0.getOpcode()) {
+      default:
+        assert(0 && "Unhandled SetCC Equivalent!");
+        abort();
+      case ISD::SETCC:
+        return DAG.getSetCC(VT, LHS, RHS, NotCC);
+      case ISD::SELECT_CC:
+        return DAG.getSelectCC(LHS, RHS, N0.getOperand(2),
+                               N0.getOperand(3), NotCC);
+      }
+    }
   }
+
   // fold (not (zext (setcc x, y))) -> (zext (not (setcc x, y)))
   if (N1C && N1C->getAPIntValue() == 1 && N0.getOpcode() == ISD::ZERO_EXTEND &&
       N0.getNode()->hasOneUse() &&
@@ -4995,6 +5014,12 @@ SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) {
   SDValue ShufMask = N->getOperand(2);
   unsigned NumElts = ShufMask.getNumOperands();
 
+  SDValue N0 = N->getOperand(0);
+  SDValue N1 = N->getOperand(1);
+
+  assert(N0.getValueType().getVectorNumElements() == NumElts &&
+        "Vector shuffle must be normalized in DAG");
+
   // If the shuffle mask is an identity operation on the LHS, return the LHS.
   bool isIdentity = true;
   for (unsigned i = 0; i != NumElts; ++i) {
@@ -5041,8 +5066,6 @@ SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) {
       }
     }
 
-  SDValue N0 = N->getOperand(0);
-  SDValue N1 = N->getOperand(1);
   // Normalize unary shuffle so the RHS is undef.
   if (isUnary && VecNum == 1)
     std::swap(N0, N1);
@@ -5153,6 +5176,7 @@ SDValue DAGCombiner::XformToShuffleWithZero(SDNode *N) {
       // Return the new VECTOR_SHUFFLE node.
       MVT EVT = RHS.getValueType().getVectorElementType();
       MVT VT = MVT::getVectorVT(EVT, NumElts);
+      MVT MaskVT = MVT::getVectorVT(TLI.getPointerTy(), NumElts);
       std::vector<SDValue> Ops;
       LHS = DAG.getNode(ISD::BIT_CONVERT, VT, LHS);
       Ops.push_back(LHS);
@@ -5160,7 +5184,7 @@ SDValue DAGCombiner::XformToShuffleWithZero(SDNode *N) {
       std::vector<SDValue> ZeroOps(NumElts, DAG.getConstant(0, EVT));
       Ops.push_back(DAG.getNode(ISD::BUILD_VECTOR, VT,
                                 &ZeroOps[0], ZeroOps.size()));
-      Ops.push_back(DAG.getNode(ISD::BUILD_VECTOR, VT,
+      Ops.push_back(DAG.getNode(ISD::BUILD_VECTOR, MaskVT,
                                 &IdxOps[0], IdxOps.size()));
       SDValue Result = DAG.getNode(ISD::VECTOR_SHUFFLE, VT,
                                      &Ops[0], Ops.size());