Split memcpy/memset/memmove intrinsics into i32/i64 versions, resolving
PR709, and paving the way for future progress.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26476 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/llvm/Assembly/AutoUpgrade.h b/include/llvm/Assembly/AutoUpgrade.h
index b8f9e22..0bc69a8 100644
--- a/include/llvm/Assembly/AutoUpgrade.h
+++ b/include/llvm/Assembly/AutoUpgrade.h
@@ -24,12 +24,6 @@
   class Value;
   class BasicBlock;
 
-  /// This function determines if the \p Name provides is a name for which the
-  /// auto-upgrade to a non-overloaded name applies.
-  /// @returns True if the function name is upgradeable, false otherwise.
-  /// @brief Determine if a name is an upgradeable intrinsic name.
-  bool IsUpgradeableIntrinsicName(const std::string& Name);
-
   /// This function inspects the Function \p F to see if it is an old overloaded
   /// intrinsic. If it is, the Function's name is changed to add a suffix that
   /// indicates the kind of arguments or result that it accepts. In LLVM release
@@ -56,14 +50,10 @@
   /// non-overloaded names. This function inspects the CallInst \p CI to see 
   /// if it is a call to an old overloaded intrinsic. If it is, a new CallInst 
   /// is created that uses the correct Function and possibly casts the 
-  /// argument and result to an unsigned type.  The caller can use the 
-  /// returned Instruction to replace the existing one. Note that the
-  /// Instruction* returned could be a CallInst or a CastInst depending on
-  /// whether casting was necessary.
+  /// argument and result to an unsigned type.
   /// @param CI The CallInst to potentially auto-upgrade.
-  /// @returns An instrution to replace \p CI with.
   /// @brief Get replacement instruction for overloaded intrinsic function call.
-  Instruction* UpgradeIntrinsicCall(CallInst* CI, Function* newF = 0);
+  void UpgradeIntrinsicCall(CallInst* CI, Function* newF = 0);
 
   /// Upgrade both the function and all the calls made to it, if that function
   /// needs to be upgraded. This is like a combination of the above two
diff --git a/include/llvm/IntrinsicInst.h b/include/llvm/IntrinsicInst.h
index 517cc3d..775726d 100644
--- a/include/llvm/IntrinsicInst.h
+++ b/include/llvm/IntrinsicInst.h
@@ -148,9 +148,12 @@
     static inline bool classof(const MemIntrinsic *) { return true; }
     static inline bool classof(const IntrinsicInst *I) {
       switch (I->getIntrinsicID()) {
-      case Intrinsic::memcpy:
-      case Intrinsic::memmove:
-      case Intrinsic::memset:
+      case Intrinsic::memcpy_i32:
+      case Intrinsic::memcpy_i64:
+      case Intrinsic::memmove_i32:
+      case Intrinsic::memmove_i64:
+      case Intrinsic::memset_i32:
+      case Intrinsic::memset_i64:
         return true;
       default: return false;
       }
@@ -183,7 +186,8 @@
     // Methods for support type inquiry through isa, cast, and dyn_cast:
     static inline bool classof(const MemCpyInst *) { return true; }
     static inline bool classof(const IntrinsicInst *I) {
-      return I->getIntrinsicID() == Intrinsic::memcpy;
+      return I->getIntrinsicID() == Intrinsic::memcpy_i32 ||
+             I->getIntrinsicID() == Intrinsic::memcpy_i64;
     }
     static inline bool classof(const Value *V) {
       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
@@ -211,14 +215,15 @@
     // Methods for support type inquiry through isa, cast, and dyn_cast:
     static inline bool classof(const MemMoveInst *) { return true; }
     static inline bool classof(const IntrinsicInst *I) {
-      return I->getIntrinsicID() == Intrinsic::memmove;
+      return I->getIntrinsicID() == Intrinsic::memmove_i32 ||
+             I->getIntrinsicID() == Intrinsic::memmove_i64;
     }
     static inline bool classof(const Value *V) {
       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
     }
   };
 
-  /// MemSetInst - This class wraps the llvm.memcpy intrinsic.
+  /// MemSetInst - This class wraps the llvm.memset intrinsic.
   ///
   struct MemSetInst : public MemIntrinsic {
     /// get* - Return the arguments to the instruction.
@@ -234,7 +239,8 @@
     // Methods for support type inquiry through isa, cast, and dyn_cast:
     static inline bool classof(const MemSetInst *) { return true; }
     static inline bool classof(const IntrinsicInst *I) {
-      return I->getIntrinsicID() == Intrinsic::memset;
+      return I->getIntrinsicID() == Intrinsic::memset_i32 ||
+             I->getIntrinsicID() == Intrinsic::memset_i64;
     }
     static inline bool classof(const Value *V) {
       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
diff --git a/include/llvm/Intrinsics.h b/include/llvm/Intrinsics.h
index 37589c5..62c58f0 100644
--- a/include/llvm/Intrinsics.h
+++ b/include/llvm/Intrinsics.h
@@ -59,13 +59,16 @@
     dbg_declare,      // Declare a local object
 
     // Standard C library intrinsics.
-    memcpy,         // Copy non-overlapping memory blocks
-    memmove,        // Copy potentially overlapping memory blocks
-    memset,         // Fill memory with a byte value
-    isunordered_f32,// Return true if either float argument is a NaN
-    isunordered_f64,// Return true if either double argument is a NaN
-    sqrt_f32,       // Square root of float
-    sqrt_f64,       // Square root of double
+    memcpy_i32,      // Copy non-overlapping memory blocks.  i32 size.
+    memcpy_i64,      // Copy non-overlapping memory blocks.  i64 size.
+    memmove_i32,     // Copy potentially overlapping memory blocks.  i32 size.
+    memmove_i64,     // Copy potentially overlapping memory blocks.  i64 size.
+    memset_i32,      // Fill memory with a byte value.  i32 size.
+    memset_i64,      // Fill memory with a byte value.  i64 size.
+    isunordered_f32, // Return true if either float argument is a NaN
+    isunordered_f64, // Return true if either double argument is a NaN
+    sqrt_f32,        // Square root of float
+    sqrt_f64,        // Square root of double
 
     // Bit manipulation instrinsics.
     bswap_i16,      // Byteswap 16 bits
diff --git a/lib/Analysis/DataStructure/Local.cpp b/lib/Analysis/DataStructure/Local.cpp
index 2b0ac90..10c9bb2 100644
--- a/lib/Analysis/DataStructure/Local.cpp
+++ b/lib/Analysis/DataStructure/Local.cpp
@@ -545,8 +545,10 @@
         return;
       case Intrinsic::vaend:
         return;  // noop
-      case Intrinsic::memmove:
-      case Intrinsic::memcpy: {
+      case Intrinsic::memmove_i32:
+      case Intrinsic::memcpy_i32: 
+      case Intrinsic::memmove_i64:
+      case Intrinsic::memcpy_i64: {
         // Merge the first & second arguments, and mark the memory read and
         // modified.
         DSNodeHandle RetNH = getValueDest(**CS.arg_begin());
@@ -555,7 +557,8 @@
           N->setModifiedMarker()->setReadMarker();
         return;
       }
-      case Intrinsic::memset:
+      case Intrinsic::memset_i32:
+      case Intrinsic::memset_i64:
         // Mark the memory modified.
         if (DSNode *N = getValueDest(**CS.arg_begin()).getNode())
           N->setModifiedMarker();
diff --git a/lib/CodeGen/IntrinsicLowering.cpp b/lib/CodeGen/IntrinsicLowering.cpp
index c47a107..a02d464 100644
--- a/lib/CodeGen/IntrinsicLowering.cpp
+++ b/lib/CodeGen/IntrinsicLowering.cpp
@@ -99,15 +99,18 @@
         EnsureFunctionExists(M, "abort", I->arg_end(), I->arg_end(),
                              Type::VoidTy);
         break;
-      case Intrinsic::memcpy:
+      case Intrinsic::memcpy_i32:
+      case Intrinsic::memcpy_i64:
         EnsureFunctionExists(M, "memcpy", I->arg_begin(), --I->arg_end(),
                              I->arg_begin()->getType());
         break;
-      case Intrinsic::memmove:
+      case Intrinsic::memmove_i32:
+      case Intrinsic::memmove_i64:
         EnsureFunctionExists(M, "memmove", I->arg_begin(), --I->arg_end(),
                              I->arg_begin()->getType());
         break;
-      case Intrinsic::memset:
+      case Intrinsic::memset_i32:
+      case Intrinsic::memset_i64:
         M.getOrInsertFunction("memset", PointerType::get(Type::SByteTy),
                               PointerType::get(Type::SByteTy),
                               Type::IntTy, (--(--I->arg_end()))->getType(),
@@ -405,7 +408,8 @@
       CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
     break;    // Simply strip out debugging intrinsics
 
-  case Intrinsic::memcpy: {
+  case Intrinsic::memcpy_i32:
+  case Intrinsic::memcpy_i64: {
     // The memcpy intrinsic take an extra alignment argument that the memcpy
     // libc function does not.
     static Function *MemcpyFCache = 0;
@@ -413,7 +417,8 @@
                     (*(CI->op_begin()+1))->getType(), MemcpyFCache);
     break;
   }
-  case Intrinsic::memmove: {
+  case Intrinsic::memmove_i32: 
+  case Intrinsic::memmove_i64: {
     // The memmove intrinsic take an extra alignment argument that the memmove
     // libc function does not.
     static Function *MemmoveFCache = 0;
@@ -421,7 +426,8 @@
                     (*(CI->op_begin()+1))->getType(), MemmoveFCache);
     break;
   }
-  case Intrinsic::memset: {
+  case Intrinsic::memset_i32:
+  case Intrinsic::memset_i64: {
     // The memset intrinsic take an extra alignment argument that the memset
     // libc function does not.
     static Function *MemsetFCache = 0;
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index cb69a2a..10ee2d5 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -955,9 +955,18 @@
   case Intrinsic::longjmp:
     return "_longjmp"+!TLI.usesUnderscoreSetJmpLongJmp();
     break;
-  case Intrinsic::memcpy:  visitMemIntrinsic(I, ISD::MEMCPY); return 0;
-  case Intrinsic::memset:  visitMemIntrinsic(I, ISD::MEMSET); return 0;
-  case Intrinsic::memmove: visitMemIntrinsic(I, ISD::MEMMOVE); return 0;
+  case Intrinsic::memcpy_i32:
+  case Intrinsic::memcpy_i64:
+    visitMemIntrinsic(I, ISD::MEMCPY);
+    return 0;
+  case Intrinsic::memset_i32:
+  case Intrinsic::memset_i64:
+    visitMemIntrinsic(I, ISD::MEMSET);
+    return 0;
+  case Intrinsic::memmove_i32:
+  case Intrinsic::memmove_i64:
+    visitMemIntrinsic(I, ISD::MEMMOVE);
+    return 0;
     
   case Intrinsic::readport:
   case Intrinsic::readio: {