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
This commit is contained in:
Chris Lattner 2006-03-03 00:00:25 +00:00
parent bad08000f1
commit 03dd465215
6 changed files with 55 additions and 38 deletions

View File

@ -24,12 +24,6 @@ namespace llvm {
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 @@ namespace llvm {
/// 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

View File

@ -148,9 +148,12 @@ namespace llvm {
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 @@ namespace llvm {
// 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 @@ namespace llvm {
// 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 @@ namespace llvm {
// 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));

View File

@ -59,13 +59,16 @@ namespace Intrinsic {
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

View File

@ -545,8 +545,10 @@ void GraphBuilder::visitCallSite(CallSite CS) {
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 @@ void GraphBuilder::visitCallSite(CallSite CS) {
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();

View File

@ -99,15 +99,18 @@ void DefaultIntrinsicLowering::AddPrototypes(Module &M) {
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 @@ void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
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 @@ void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
(*(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 @@ void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
(*(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;

View File

@ -955,9 +955,18 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
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: {