From d5089a9794b46918128c2fec1b5ec1d20f7572fa Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Wed, 27 Apr 2011 01:45:07 +0000 Subject: [PATCH] Refactor out code to fast-isel a memcpy operation with a small constant length. (I'm planning to use this to implement byval.) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@130274 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86FastISel.cpp | 72 +++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index 257b4741cee..2a5c6282d73 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -132,6 +132,9 @@ private: } bool isTypeLegal(const Type *Ty, MVT &VT, bool AllowI1 = false); + + bool TryEmitSmallMemcpy(X86AddressMode DestAM, + X86AddressMode SrcAM, uint64_t Len); }; } // end anonymous namespace. @@ -1323,6 +1326,40 @@ bool X86FastISel::X86SelectExtractValue(const Instruction *I) { return false; } +bool X86FastISel::TryEmitSmallMemcpy(X86AddressMode DestAM, + X86AddressMode SrcAM, uint64_t Len) { + // Make sure we don't bloat code by inlining very large memcpy's. + bool i64Legal = TLI.isTypeLegal(MVT::i64); + if (Len > (i64Legal ? 32 : 16)) return false; + + // We don't care about alignment here since we just emit integer accesses. + while (Len) { + MVT VT; + if (Len >= 8 && i64Legal) + VT = MVT::i64; + else if (Len >= 4) + VT = MVT::i32; + else if (Len >= 2) + VT = MVT::i16; + else { + assert(Len == 1); + VT = MVT::i8; + } + + unsigned Reg; + bool RV = X86FastEmitLoad(VT, SrcAM, Reg); + RV &= X86FastEmitStore(VT, Reg, DestAM); + assert(RV && "Failed to emit load or store??"); + + unsigned Size = VT.getSizeInBits()/8; + Len -= Size; + DestAM.Disp += Size; + SrcAM.Disp += Size; + } + + return true; +} + bool X86FastISel::X86VisitIntrinsicCall(const IntrinsicInst &I) { // FIXME: Handle more intrinsics. switch (I.getIntrinsicID()) { @@ -1332,45 +1369,16 @@ bool X86FastISel::X86VisitIntrinsicCall(const IntrinsicInst &I) { // Don't handle volatile or variable length memcpys. if (MCI.isVolatile() || !isa(MCI.getLength())) return false; - - // Don't inline super long memcpys. We could lower these to a memcpy call, - // but we might as well bail out. + uint64_t Len = cast(MCI.getLength())->getZExtValue(); - bool i64Legal = TLI.isTypeLegal(MVT::i64); - if (Len > (i64Legal ? 32 : 16)) return false; // Get the address of the dest and source addresses. X86AddressMode DestAM, SrcAM; if (!X86SelectAddress(MCI.getRawDest(), DestAM) || !X86SelectAddress(MCI.getRawSource(), SrcAM)) return false; - - // We don't care about alignment here since we just emit integer accesses. - while (Len) { - MVT VT; - if (Len >= 8 && i64Legal) - VT = MVT::i64; - else if (Len >= 4) - VT = MVT::i32; - else if (Len >= 2) - VT = MVT::i16; - else { - assert(Len == 1); - VT = MVT::i8; - } - - unsigned Reg; - bool RV = X86FastEmitLoad(VT, SrcAM, Reg); - RV &= X86FastEmitStore(VT, Reg, DestAM); - assert(RV && "Failed to emit load or store??"); - - unsigned Size = VT.getSizeInBits()/8; - Len -= Size; - DestAM.Disp += Size; - SrcAM.Disp += Size; - } - - return true; + + return TryEmitSmallMemcpy(DestAM, SrcAM, Len); } case Intrinsic::stackprotector: { -- 2.34.1