Add support for AssertSext and AssertZext, folding other extensions with
them.  This allows for elminination of redundant extends in the entry
blocks of functions on PowerPC.

Add support for i32 x i32 -> i64 multiplies, by recognizing when the inputs
to ISD::MUL in ExpandOp are actually just extended i32 values and not real
i64 values.  this allows us to codegen

int mulhs(int a, int b) { return ((long long)a * b) >> 32; }
as:
_mulhs:
        mulhw r3, r4, r3
        blr

instead of:
_mulhs:
        mulhwu r2, r4, r3
        srawi r5, r3, 31
        mullw r5, r4, r5
        add r2, r2, r5
        srawi r4, r4, 31
        mullw r3, r4, r3
        add r3, r2, r3
        blr

with a similar improvement on x86.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23147 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index dab757e..c929806 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -631,7 +631,8 @@
         unsigned ExtSrcTyBits = MVT::getSizeInBits(ExtSrcTy);
         MVT::ValueType ExtDstTy = N1.getValueType();
         unsigned ExtDstTyBits = MVT::getSizeInBits(ExtDstTy);
-        
+
+        if (Cond == ISD::SETEQ || Cond == ISD::SETNE) {
         // If the extended part has any inconsistent bits, it cannot ever
         // compare equal.  In other words, they have to be all ones or all
         // zeros.
@@ -644,6 +645,7 @@
         return getSetCC(VT, getZeroExtendInReg(N1.getOperand(0), ExtSrcTy),
                         getConstant(C2 & (~0ULL >> 64-ExtSrcTyBits), ExtDstTy),
                         Cond);
+        }
       }
 
       uint64_t MinVal, MaxVal;
@@ -1192,6 +1194,8 @@
     assert(EVT <= VT && "Not rounding down!");
     break;
   }
+  case ISD::AssertSext:
+  case ISD::AssertZext:
   case ISD::SIGN_EXTEND_INREG: {
     MVT::ValueType EVT = cast<VTSDNode>(N2)->getVT();
     assert(VT == N1.getValueType() && "Not an inreg extend!");
@@ -1394,6 +1398,14 @@
             // we know the result of the AND will be the AND mask itself.
             return N2;
           }
+      } else if (N1.getOpcode() == ISD::AssertZext) {
+        // If we are masking out the part of our input that was already masked
+        // out, just return the input directly.
+        unsigned ExtendBits =
+        MVT::getSizeInBits(cast<VTSDNode>(N1.getOperand(1))->getVT());
+        uint64_t ExtendMask = (1ULL << ExtendBits) - 1;
+        if (ExtendMask == C2)
+          return N1.getOperand(0);
       }
       break;
     case ISD::OR:
@@ -1579,14 +1591,15 @@
     if (EVT == VT) return N1;  // Not actually extending
 
     // If we are sign extending an extension, use the original source.
-    if (N1.getOpcode() == ISD::SIGN_EXTEND_INREG)
+    if (N1.getOpcode() == ISD::SIGN_EXTEND_INREG ||
+        N1.getOpcode() == ISD::AssertSext)
       if (cast<VTSDNode>(N1.getOperand(1))->getVT() <= EVT)
         return N1;
 
     // If we are sign extending a sextload, return just the load.
     if (N1.getOpcode() == ISD::SEXTLOAD)
       if (cast<VTSDNode>(N1.getOperand(3))->getVT() <= EVT)
-        return N1;
+        return N1;    
 
     // If we are extending the result of a setcc, and we already know the
     // contents of the top bits, eliminate the extension.
@@ -1594,7 +1607,7 @@
         TLI.getSetCCResultContents() ==
                         TargetLowering::ZeroOrNegativeOneSetCCResult)
       return N1;
-
+    
     // If we are sign extending the result of an (and X, C) operation, and we
     // know the extended bits are zeros already, don't do the extend.
     if (N1.getOpcode() == ISD::AND)
@@ -2195,6 +2208,8 @@
   case ISD::VALUETYPE:     return "ValueType";
   case ISD::EntryToken:    return "EntryToken";
   case ISD::TokenFactor:   return "TokenFactor";
+  case ISD::AssertSext:    return "AssertSext";
+  case ISD::AssertZext:    return "AssertZext";
   case ISD::Constant:      return "Constant";
   case ISD::TargetConstant: return "TargetConstant";
   case ISD::ConstantFP:    return "ConstantFP";