Refactor a bunch of includes so that TargetMachine.h doesn't have to include
[oota-llvm.git] / lib / CodeGen / SelectionDAG / DAGCombiner.cpp
index ac70150f8e0c94b35e3f7e9b13dd7ebec100e482..0aaee2f04320ae1115cfd74ef64c3f54f80ccfa8 100644 (file)
@@ -76,7 +76,7 @@ namespace {
     SDOperand CombineTo(SDNode *N, const std::vector<SDOperand> &To) {
       ++NodesCombined;
       DEBUG(std::cerr << "\nReplacing "; N->dump();
-            std::cerr << "\nWith: "; To[0].Val->dump();
+            std::cerr << "\nWith: "; To[0].Val->dump(&DAG);
             std::cerr << " and " << To.size()-1 << " other values\n");
       std::vector<SDNode*> NowDead;
       DAG.ReplaceAllUsesWith(N, To, &NowDead);
@@ -128,7 +128,7 @@ namespace {
       // Replace the old value with the new one.
       ++NodesCombined;
       DEBUG(std::cerr << "\nReplacing "; TLO.Old.Val->dump();
-            std::cerr << "\nWith: "; TLO.New.Val->dump());
+            std::cerr << "\nWith: "; TLO.New.Val->dump(&DAG));
 
       std::vector<SDNode*> NowDead;
       DAG.ReplaceAllUsesOfValueWith(TLO.Old, TLO.New, NowDead);
@@ -188,6 +188,7 @@ namespace {
     SDOperand visitSETCC(SDNode *N);
     SDOperand visitSIGN_EXTEND(SDNode *N);
     SDOperand visitZERO_EXTEND(SDNode *N);
+    SDOperand visitANY_EXTEND(SDNode *N);
     SDOperand visitSIGN_EXTEND_INREG(SDNode *N);
     SDOperand visitTRUNCATE(SDNode *N);
     SDOperand visitBIT_CONVERT(SDNode *N);
@@ -222,6 +223,7 @@ namespace {
     SDOperand ReassociateOps(unsigned Opc, SDOperand LHS, SDOperand RHS);
     
     bool SimplifySelectOps(SDNode *SELECT, SDOperand LHS, SDOperand RHS);
+    SDOperand SimplifyBinOpWithSameOpcodeHands(SDNode *N);
     SDOperand SimplifySelect(SDOperand N0, SDOperand N1, SDOperand N2);
     SDOperand SimplifySelectCC(SDOperand N0, SDOperand N1, SDOperand N2, 
                                SDOperand N3, ISD::CondCode CC);
@@ -575,7 +577,7 @@ void DAGCombiner::Run(bool RunningAfterLegalize) {
       // mechanics for us, we have no work to do in this case.
       if (RV.Val != N) {
         DEBUG(std::cerr << "\nReplacing "; N->dump();
-              std::cerr << "\nWith: "; RV.Val->dump();
+              std::cerr << "\nWith: "; RV.Val->dump(&DAG);
               std::cerr << '\n');
         std::vector<SDNode*> NowDead;
         DAG.ReplaceAllUsesWith(N, std::vector<SDOperand>(1, RV), &NowDead);
@@ -627,6 +629,7 @@ SDOperand DAGCombiner::visit(SDNode *N) {
   case ISD::SETCC:              return visitSETCC(N);
   case ISD::SIGN_EXTEND:        return visitSIGN_EXTEND(N);
   case ISD::ZERO_EXTEND:        return visitZERO_EXTEND(N);
+  case ISD::ANY_EXTEND:         return visitANY_EXTEND(N);
   case ISD::SIGN_EXTEND_INREG:  return visitSIGN_EXTEND_INREG(N);
   case ISD::TRUNCATE:           return visitTRUNCATE(N);
   case ISD::BIT_CONVERT:        return visitBIT_CONVERT(N);
@@ -677,7 +680,8 @@ SDOperand DAGCombiner::visitTokenFactor(SDNode *N) {
   // If the token factor has two operands and one is the entry token, replace
   // the token factor with the other operand.
   if (N->getNumOperands() == 2) {
-    if (N->getOperand(0).getOpcode() == ISD::EntryToken)
+    if (N->getOperand(0).getOpcode() == ISD::EntryToken ||
+        N->getOperand(0) == N->getOperand(1))
       return N->getOperand(1);
     if (N->getOperand(1).getOpcode() == ISD::EntryToken)
       return N->getOperand(0);
@@ -691,8 +695,11 @@ SDOperand DAGCombiner::visitTokenFactor(SDNode *N) {
       Changed = true;
       for (unsigned j = 0, e = Op.getNumOperands(); j != e; ++j)
         Ops.push_back(Op.getOperand(j));
-    } else {
+    } else if (i == 0 || N->getOperand(i) != N->getOperand(i-1)) {
       Ops.push_back(Op);
+    } else {
+      // Deleted an operand that was the same as the last one.
+      Changed = true;
     }
   }
   if (Changed)
@@ -1035,6 +1042,45 @@ SDOperand DAGCombiner::visitMULHU(SDNode *N) {
   return SDOperand();
 }
 
+/// SimplifyBinOpWithSameOpcodeHands - If this is a binary operator with
+/// two operands of the same opcode, try to simplify it.
+SDOperand DAGCombiner::SimplifyBinOpWithSameOpcodeHands(SDNode *N) {
+  SDOperand N0 = N->getOperand(0), N1 = N->getOperand(1);
+  MVT::ValueType VT = N0.getValueType();
+  assert(N0.getOpcode() == N1.getOpcode() && "Bad input!");
+  
+  // For each of OP in AND/OR/XOR:
+  // fold (OP (zext x), (zext y)) -> (zext (OP x, y))
+  // fold (OP (sext x), (sext y)) -> (sext (OP x, y))
+  // fold (OP (aext x), (aext y)) -> (aext (OP x, y))
+  // fold (OP (trunc x), (trunc y)) -> (trunc (OP x, y))
+  if ((N0.getOpcode() == ISD::ZERO_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND||
+       N0.getOpcode() == ISD::SIGN_EXTEND || N0.getOpcode() == ISD::TRUNCATE) &&
+      N0.getOperand(0).getValueType() == N1.getOperand(0).getValueType()) {
+    SDOperand ORNode = DAG.getNode(N->getOpcode(), 
+                                   N0.getOperand(0).getValueType(),
+                                   N0.getOperand(0), N1.getOperand(0));
+    AddToWorkList(ORNode.Val);
+    return DAG.getNode(N0.getOpcode(), VT, ORNode);
+  }
+  
+  // For each of OP in SHL/SRL/SRA/AND...
+  //   fold (and (OP x, z), (OP y, z)) -> (OP (and x, y), z)
+  //   fold (or  (OP x, z), (OP y, z)) -> (OP (or  x, y), z)
+  //   fold (xor (OP x, z), (OP y, z)) -> (OP (xor x, y), z)
+  if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL ||
+       N0.getOpcode() == ISD::SRA || N0.getOpcode() == ISD::AND) &&
+      N0.getOperand(1) == N1.getOperand(1)) {
+    SDOperand ORNode = DAG.getNode(N->getOpcode(),
+                                   N0.getOperand(0).getValueType(),
+                                   N0.getOperand(0), N1.getOperand(0));
+    AddToWorkList(ORNode.Val);
+    return DAG.getNode(N0.getOpcode(), VT, ORNode, N0.getOperand(1));
+  }
+  
+  return SDOperand();
+}
+
 SDOperand DAGCombiner::visitAND(SDNode *N) {
   SDOperand N0 = N->getOperand(0);
   SDOperand N1 = N->getOperand(1);
@@ -1121,25 +1167,13 @@ SDOperand DAGCombiner::visitAND(SDNode *N) {
         return DAG.getSetCC(N0.getValueType(), LL, LR, Result);
     }
   }
-  // fold (and (zext x), (zext y)) -> (zext (and x, y))
-  if (N0.getOpcode() == ISD::ZERO_EXTEND && 
-      N1.getOpcode() == ISD::ZERO_EXTEND &&
-      N0.getOperand(0).getValueType() == N1.getOperand(0).getValueType()) {
-    SDOperand ANDNode = DAG.getNode(ISD::AND, N0.getOperand(0).getValueType(),
-                                    N0.getOperand(0), N1.getOperand(0));
-    AddToWorkList(ANDNode.Val);
-    return DAG.getNode(ISD::ZERO_EXTEND, VT, ANDNode);
-  }
-  // fold (and (shl/srl/sra x), (shl/srl/sra y)) -> (shl/srl/sra (and 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 ANDNode = DAG.getNode(ISD::AND, N0.getOperand(0).getValueType(),
-                                    N0.getOperand(0), N1.getOperand(0));
-    AddToWorkList(ANDNode.Val);
-    return DAG.getNode(N0.getOpcode(), VT, ANDNode, N0.getOperand(1));
+
+  // Simplify: and (op x...), (op y...)  -> (op (and x, y))
+  if (N0.getOpcode() == N1.getOpcode()) {
+    SDOperand Tmp = SimplifyBinOpWithSameOpcodeHands(N);
+    if (Tmp.Val) return Tmp;
   }
+  
   // fold (and (sign_extend_inreg x, i16 to i32), 1) -> (and x, 1)
   // fold (and (sra)) -> (and (srl)) when possible.
   if (!MVT::isVector(VT) &&
@@ -1292,25 +1326,13 @@ SDOperand DAGCombiner::visitOR(SDNode *N) {
         return DAG.getSetCC(N0.getValueType(), LL, LR, Result);
     }
   }
-  // fold (or (zext x), (zext y)) -> (zext (or x, y))
-  if (N0.getOpcode() == ISD::ZERO_EXTEND && 
-      N1.getOpcode() == ISD::ZERO_EXTEND &&
-      N0.getOperand(0).getValueType() == N1.getOperand(0).getValueType()) {
-    SDOperand ORNode = DAG.getNode(ISD::OR, N0.getOperand(0).getValueType(),
-                                   N0.getOperand(0), N1.getOperand(0));
-    AddToWorkList(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));
-    AddToWorkList(ORNode.Val);
-    return DAG.getNode(N0.getOpcode(), VT, ORNode, N0.getOperand(1));
+  
+  // Simplify: or (op x...), (op y...)  -> (op (or x, y))
+  if (N0.getOpcode() == N1.getOpcode()) {
+    SDOperand Tmp = SimplifyBinOpWithSameOpcodeHands(N);
+    if (Tmp.Val) return Tmp;
   }
+
   // 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);
@@ -1429,26 +1451,13 @@ SDOperand DAGCombiner::visitXOR(SDNode *N) {
       return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops);
     }
   }
-  // fold (xor (zext x), (zext y)) -> (zext (xor x, y))
-  if (N0.getOpcode() == ISD::ZERO_EXTEND && 
-      N1.getOpcode() == ISD::ZERO_EXTEND &&
-      N0.getOperand(0).getValueType() == N1.getOperand(0).getValueType()) {
-    SDOperand XORNode = DAG.getNode(ISD::XOR, N0.getOperand(0).getValueType(),
-                                   N0.getOperand(0), N1.getOperand(0));
-    AddToWorkList(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));
-    AddToWorkList(XORNode.Val);
-    return DAG.getNode(N0.getOpcode(), VT, XORNode, N0.getOperand(1));
+  
+  // Simplify: xor (op x...), (op y...)  -> (op (xor x, y))
+  if (N0.getOpcode() == N1.getOpcode()) {
+    SDOperand Tmp = SimplifyBinOpWithSameOpcodeHands(N);
+    if (Tmp.Val) return Tmp;
   }
-
+  
   // Simplify the expression using non-local knowledge.
   if (!MVT::isVector(VT) &&
       SimplifyDemandedBits(SDOperand(N, 0)))
@@ -1570,6 +1579,11 @@ SDOperand DAGCombiner::visitSRA(SDNode *N) {
     }
   }
   
+  // Simplify, based on bits shifted out of the LHS. 
+  if (N1C && SimplifyDemandedBits(SDOperand(N, 0)))
+    return SDOperand(N, 0);
+  
+  
   // If the sign bit is known to be zero, switch this to a SRL.
   if (TLI.MaskedValueIsZero(N0, MVT::getIntVTSignBit(VT)))
     return DAG.getNode(ISD::SRL, VT, N0, N1);
@@ -1610,6 +1624,18 @@ SDOperand DAGCombiner::visitSRL(SDNode *N) {
                        DAG.getConstant(c1 + c2, N1.getValueType()));
   }
   
+  // fold (srl (anyextend x), c) -> (anyextend (srl x, c))
+  if (N1C && N0.getOpcode() == ISD::ANY_EXTEND) {
+    // Shifting in all undef bits?
+    MVT::ValueType SmallVT = N0.getOperand(0).getValueType();
+    if (N1C->getValue() >= MVT::getSizeInBits(SmallVT))
+      return DAG.getNode(ISD::UNDEF, VT);
+
+    SDOperand SmallShift = DAG.getNode(ISD::SRL, SmallVT, N0.getOperand(0), N1);
+    AddToWorkList(SmallShift.Val);
+    return DAG.getNode(ISD::ANY_EXTEND, VT, SmallShift);
+  }
+  
   // fold (srl (ctlz x), "5") -> x  iff x has one bit set (the low bit).
   if (N1C && N0.getOpcode() == ISD::CTLZ && 
       N1C->getValue() == Log2_32(MVT::getSizeInBits(VT))) {
@@ -1647,33 +1673,30 @@ SDOperand DAGCombiner::visitSRL(SDNode *N) {
 
 SDOperand DAGCombiner::visitCTLZ(SDNode *N) {
   SDOperand N0 = N->getOperand(0);
-  ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
   MVT::ValueType VT = N->getValueType(0);
 
   // fold (ctlz c1) -> c2
-  if (N0C)
+  if (isa<ConstantSDNode>(N0))
     return DAG.getNode(ISD::CTLZ, VT, N0);
   return SDOperand();
 }
 
 SDOperand DAGCombiner::visitCTTZ(SDNode *N) {
   SDOperand N0 = N->getOperand(0);
-  ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
   MVT::ValueType VT = N->getValueType(0);
   
   // fold (cttz c1) -> c2
-  if (N0C)
+  if (isa<ConstantSDNode>(N0))
     return DAG.getNode(ISD::CTTZ, VT, N0);
   return SDOperand();
 }
 
 SDOperand DAGCombiner::visitCTPOP(SDNode *N) {
   SDOperand N0 = N->getOperand(0);
-  ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
   MVT::ValueType VT = N->getValueType(0);
   
   // fold (ctpop c1) -> c2
-  if (N0C)
+  if (isa<ConstantSDNode>(N0))
     return DAG.getNode(ISD::CTPOP, VT, N0);
   return SDOperand();
 }
@@ -1773,21 +1796,24 @@ SDOperand DAGCombiner::visitSETCC(SDNode *N) {
 
 SDOperand DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
   SDOperand N0 = N->getOperand(0);
-  ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
   MVT::ValueType VT = N->getValueType(0);
 
   // fold (sext c1) -> c1
-  if (N0C)
+  if (ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0))
     return DAG.getNode(ISD::SIGN_EXTEND, VT, N0);
+  
   // fold (sext (sext x)) -> (sext x)
-  if (N0.getOpcode() == ISD::SIGN_EXTEND)
+  // fold (sext (aext x)) -> (sext x)
+  if (N0.getOpcode() == ISD::SIGN_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND)
     return DAG.getNode(ISD::SIGN_EXTEND, VT, N0.getOperand(0));
+  
   // fold (sext (truncate x)) -> (sextinreg x) iff x size == sext size.
   if (N0.getOpcode() == ISD::TRUNCATE && N0.getOperand(0).getValueType() == VT&&
       (!AfterLegalize || 
        TLI.isOperationLegal(ISD::SIGN_EXTEND_INREG, N0.getValueType())))
     return DAG.getNode(ISD::SIGN_EXTEND_INREG, VT, N0.getOperand(0),
                        DAG.getValueType(N0.getValueType()));
+  
   // fold (sext (load x)) -> (sext (truncate (sextload x)))
   if (N0.getOpcode() == ISD::LOAD && N0.hasOneUse() &&
       (!AfterLegalize||TLI.isOperationLegal(ISD::SEXTLOAD, N0.getValueType()))){
@@ -1804,9 +1830,9 @@ SDOperand DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
   // fold (sext ( extload x)) -> (sext (truncate (sextload x)))
   if ((N0.getOpcode() == ISD::SEXTLOAD || N0.getOpcode() == ISD::EXTLOAD) &&
       N0.hasOneUse()) {
-    SDOperand ExtLoad = DAG.getNode(ISD::SEXTLOAD, VT, N0.getOperand(0),
-                                    N0.getOperand(1), N0.getOperand(2),
-                                    N0.getOperand(3));
+    MVT::ValueType EVT = cast<VTSDNode>(N0.getOperand(3))->getVT();
+    SDOperand ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, VT, N0.getOperand(0),
+                                       N0.getOperand(1), N0.getOperand(2), EVT);
     CombineTo(N, ExtLoad);
     CombineTo(N0.Val, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
               ExtLoad.getValue(1));
@@ -1818,14 +1844,14 @@ SDOperand DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
 
 SDOperand DAGCombiner::visitZERO_EXTEND(SDNode *N) {
   SDOperand N0 = N->getOperand(0);
-  ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
   MVT::ValueType VT = N->getValueType(0);
 
   // fold (zext c1) -> c1
-  if (N0C)
+  if (ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0))
     return DAG.getNode(ISD::ZERO_EXTEND, VT, N0);
   // fold (zext (zext x)) -> (zext x)
-  if (N0.getOpcode() == ISD::ZERO_EXTEND)
+  // fold (zext (aext x)) -> (zext x)
+  if (N0.getOpcode() == ISD::ZERO_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND)
     return DAG.getNode(ISD::ZERO_EXTEND, VT, N0.getOperand(0));
   // fold (zext (truncate x)) -> (zextinreg x) iff x size == zext size.
   if (N0.getOpcode() == ISD::TRUNCATE && N0.getOperand(0).getValueType() == VT&&
@@ -1847,9 +1873,56 @@ SDOperand DAGCombiner::visitZERO_EXTEND(SDNode *N) {
   // fold (zext ( extload x)) -> (zext (truncate (zextload x)))
   if ((N0.getOpcode() == ISD::ZEXTLOAD || N0.getOpcode() == ISD::EXTLOAD) &&
       N0.hasOneUse()) {
-    SDOperand ExtLoad = DAG.getNode(ISD::ZEXTLOAD, VT, N0.getOperand(0),
-                                    N0.getOperand(1), N0.getOperand(2),
-                                    N0.getOperand(3));
+    MVT::ValueType EVT = cast<VTSDNode>(N0.getOperand(3))->getVT();
+    SDOperand ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, VT, N0.getOperand(0),
+                                       N0.getOperand(1), N0.getOperand(2), EVT);
+    CombineTo(N, ExtLoad);
+    CombineTo(N0.Val, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
+              ExtLoad.getValue(1));
+    return SDOperand(N, 0);   // Return N so it doesn't get rechecked!
+  }
+  return SDOperand();
+}
+
+SDOperand DAGCombiner::visitANY_EXTEND(SDNode *N) {
+  SDOperand N0 = N->getOperand(0);
+  MVT::ValueType VT = N->getValueType(0);
+  
+  // fold (aext c1) -> c1
+  if (isa<ConstantSDNode>(N0))
+    return DAG.getNode(ISD::ANY_EXTEND, VT, N0);
+  // fold (aext (aext x)) -> (aext x)
+  // fold (aext (zext x)) -> (zext x)
+  // fold (aext (sext x)) -> (sext x)
+  if (N0.getOpcode() == ISD::ANY_EXTEND  ||
+      N0.getOpcode() == ISD::ZERO_EXTEND ||
+      N0.getOpcode() == ISD::SIGN_EXTEND)
+    return DAG.getNode(N0.getOpcode(), VT, N0.getOperand(0));
+  
+  // fold (aext (truncate x)) -> x iff x size == zext size.
+  if (N0.getOpcode() == ISD::TRUNCATE && N0.getOperand(0).getValueType() == VT)
+    return N0.getOperand(0);
+  // fold (aext (load x)) -> (aext (truncate (extload x)))
+  if (N0.getOpcode() == ISD::LOAD && N0.hasOneUse() &&
+      (!AfterLegalize||TLI.isOperationLegal(ISD::EXTLOAD, N0.getValueType()))) {
+    SDOperand ExtLoad = DAG.getExtLoad(ISD::EXTLOAD, VT, N0.getOperand(0),
+                                       N0.getOperand(1), N0.getOperand(2),
+                                       N0.getValueType());
+    CombineTo(N, ExtLoad);
+    CombineTo(N0.Val, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
+              ExtLoad.getValue(1));
+    return SDOperand(N, 0);   // Return N so it doesn't get rechecked!
+  }
+  
+  // fold (aext (zextload x)) -> (aext (truncate (zextload x)))
+  // fold (aext (sextload x)) -> (aext (truncate (sextload x)))
+  // fold (aext ( extload x)) -> (aext (truncate (extload  x)))
+  if ((N0.getOpcode() == ISD::ZEXTLOAD || N0.getOpcode() == ISD::EXTLOAD ||
+       N0.getOpcode() == ISD::SEXTLOAD) &&
+      N0.hasOneUse()) {
+    MVT::ValueType EVT = cast<VTSDNode>(N0.getOperand(3))->getVT();
+    SDOperand ExtLoad = DAG.getExtLoad(N0.getOpcode(), VT, N0.getOperand(0),
+                                       N0.getOperand(1), N0.getOperand(2), EVT);
     CombineTo(N, ExtLoad);
     CombineTo(N0.Val, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
               ExtLoad.getValue(1));
@@ -1858,47 +1931,46 @@ SDOperand DAGCombiner::visitZERO_EXTEND(SDNode *N) {
   return SDOperand();
 }
 
+
 SDOperand DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) {
   SDOperand N0 = N->getOperand(0);
   SDOperand N1 = N->getOperand(1);
-  ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
   MVT::ValueType VT = N->getValueType(0);
   MVT::ValueType EVT = cast<VTSDNode>(N1)->getVT();
   unsigned EVTBits = MVT::getSizeInBits(EVT);
   
   // fold (sext_in_reg c1) -> c1
-  if (N0C) {
-    SDOperand Truncate = DAG.getConstant(N0C->getValue(), EVT);
-    return DAG.getNode(ISD::SIGN_EXTEND, VT, Truncate);
-  }
-  // fold (sext_in_reg (sext_in_reg x, VT2), VT1) -> (sext_in_reg x, minVT) pt1
-  if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG && 
-      cast<VTSDNode>(N0.getOperand(1))->getVT() <= EVT) {
+  if (isa<ConstantSDNode>(N0) || N0.getOpcode() == ISD::UNDEF)
+    return DAG.getNode(ISD::SIGN_EXTEND_INREG, VT, N0, N1);
+  
+  // If the input is already sign extended, just drop the extension.
+  if (TLI.ComputeNumSignBits(N0) >= MVT::getSizeInBits(VT)-EVTBits+1)
     return N0;
-  }
+  
   // fold (sext_in_reg (sext_in_reg x, VT2), VT1) -> (sext_in_reg x, minVT) pt2
   if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG &&
       EVT < cast<VTSDNode>(N0.getOperand(1))->getVT()) {
     return DAG.getNode(ISD::SIGN_EXTEND_INREG, VT, N0.getOperand(0), N1);
   }
-  // fold (sext_in_reg (assert_sext x)) -> (assert_sext x)
-  if (N0.getOpcode() == ISD::AssertSext && 
-      cast<VTSDNode>(N0.getOperand(1))->getVT() <= EVT) {
-    return N0;
-  }
-  // fold (sext_in_reg (sextload x)) -> (sextload x)
-  if (N0.getOpcode() == ISD::SEXTLOAD && 
-      cast<VTSDNode>(N0.getOperand(3))->getVT() <= EVT) {
-    return N0;
-  }
-  // fold (sext_in_reg (setcc x)) -> setcc x iff (setcc x) == 0 or -1
-  if (N0.getOpcode() == ISD::SETCC &&
-      TLI.getSetCCResultContents() == 
-        TargetLowering::ZeroOrNegativeOneSetCCResult)
-    return N0;
+
   // fold (sext_in_reg x) -> (zext_in_reg x) if the sign bit is zero
   if (TLI.MaskedValueIsZero(N0, 1ULL << (EVTBits-1)))
     return DAG.getZeroExtendInReg(N0, EVT);
+  
+  // fold (sext_in_reg (srl X, 24), i8) -> sra X, 24
+  // fold (sext_in_reg (srl X, 23), i8) -> sra X, 23 iff possible.
+  // We already fold "(sext_in_reg (srl X, 25), i8) -> srl X, 25" above.
+  if (N0.getOpcode() == ISD::SRL) {
+    if (ConstantSDNode *ShAmt = dyn_cast<ConstantSDNode>(N0.getOperand(1)))
+      if (ShAmt->getValue()+EVTBits <= MVT::getSizeInBits(VT)) {
+        // We can turn this into an SRA iff the input to the SRL is already sign
+        // extended enough.
+        unsigned InSignBits = TLI.ComputeNumSignBits(N0.getOperand(0));
+        if (MVT::getSizeInBits(VT)-(ShAmt->getValue()+EVTBits) < InSignBits)
+          return DAG.getNode(ISD::SRA, VT, N0.getOperand(0), N0.getOperand(1));
+      }
+  }
+  
   // fold (sext_inreg (extload x)) -> (sextload x)
   if (N0.getOpcode() == ISD::EXTLOAD && 
       EVT == cast<VTSDNode>(N0.getOperand(3))->getVT() &&
@@ -1926,20 +1998,20 @@ SDOperand DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) {
 
 SDOperand DAGCombiner::visitTRUNCATE(SDNode *N) {
   SDOperand N0 = N->getOperand(0);
-  ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
   MVT::ValueType VT = N->getValueType(0);
 
   // noop truncate
   if (N0.getValueType() == N->getValueType(0))
     return N0;
   // fold (truncate c1) -> c1
-  if (N0C)
+  if (isa<ConstantSDNode>(N0))
     return DAG.getNode(ISD::TRUNCATE, VT, N0);
   // fold (truncate (truncate x)) -> (truncate x)
   if (N0.getOpcode() == ISD::TRUNCATE)
     return DAG.getNode(ISD::TRUNCATE, VT, N0.getOperand(0));
   // fold (truncate (ext x)) -> (ext x) or (truncate x) or x
-  if (N0.getOpcode() == ISD::ZERO_EXTEND || N0.getOpcode() == ISD::SIGN_EXTEND){
+  if (N0.getOpcode() == ISD::ZERO_EXTEND || N0.getOpcode() == ISD::SIGN_EXTEND||
+      N0.getOpcode() == ISD::ANY_EXTEND) {
     if (N0.getValueType() < VT)
       // if the source is smaller than the dest, we still need an extend
       return DAG.getNode(N0.getOpcode(), VT, N0.getOperand(0));
@@ -2359,6 +2431,20 @@ SDOperand DAGCombiner::visitFP_EXTEND(SDNode *N) {
   // fold (fp_extend c1fp) -> c1fp
   if (N0CFP)
     return DAG.getNode(ISD::FP_EXTEND, VT, N0);
+  
+  // fold (fpext (load x)) -> (fpext (fpround (extload x)))
+  if (N0.getOpcode() == ISD::LOAD && N0.hasOneUse() &&
+      (!AfterLegalize||TLI.isOperationLegal(ISD::EXTLOAD, N0.getValueType()))) {
+    SDOperand ExtLoad = DAG.getExtLoad(ISD::EXTLOAD, VT, N0.getOperand(0),
+                                       N0.getOperand(1), N0.getOperand(2),
+                                       N0.getValueType());
+    CombineTo(N, ExtLoad);
+    CombineTo(N0.Val, DAG.getNode(ISD::FP_ROUND, N0.getValueType(), ExtLoad),
+              ExtLoad.getValue(1));
+    return SDOperand(N, 0);   // Return N so it doesn't get rechecked!
+  }
+  
+  
   return SDOperand();
 }