From 612776ec7fbf1b642e82d24707a034834d314fa0 Mon Sep 17 00:00:00 2001 From: Sjoerd Meijer Date: Wed, 20 Mar 2019 14:15:46 +0000 Subject: [PATCH] [TTI] getMemcpyCost This adds new function getMemcpyCost to TTI so that the cost of a memcpy can be modeled and queried. The default implementation returns Expensive, but targets can override this function to model the cost more accurately. Differential Revision: https://reviews.llvm.org/D59252 llvm-svn: 356555 --- include/llvm/Analysis/TargetTransformInfo.h | 8 ++++++++ include/llvm/Analysis/TargetTransformInfoImpl.h | 9 ++++++++- test/Analysis/CostModel/ARM/memcpy.ll | 13 +++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 test/Analysis/CostModel/ARM/memcpy.ll diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index f185e9bee28..085fcac1fe0 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -246,6 +246,10 @@ public: ArrayRef Arguments, const User *U = nullptr) const; + /// \Return the expected cost of a memcpy, which could e.g. depend on the + /// source/destination type and alignment and the number of bytes copied. + int getMemcpyCost(const Instruction *I) const; + /// \return The estimated number of case clusters when lowering \p 'SI'. /// \p JTSize Set a jump table size only when \p SI is suitable for a jump /// table. @@ -1053,6 +1057,7 @@ public: virtual int getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, ArrayRef Arguments, const User *U) = 0; + virtual int getMemcpyCost(const Instruction *I) = 0; virtual unsigned getEstimatedNumberOfCaseClusters(const SwitchInst &SI, unsigned &JTSize) = 0; virtual int @@ -1267,6 +1272,9 @@ public: const User *U = nullptr) override { return Impl.getIntrinsicCost(IID, RetTy, Arguments, U); } + int getMemcpyCost(const Instruction *I) { + return Impl.getMemcpyCost(I); + } int getUserCost(const User *U, ArrayRef Operands) override { return Impl.getUserCost(U, Operands); } diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h index b244a49f940..8e667268f04 100644 --- a/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -140,15 +140,22 @@ public: unsigned getInliningThresholdMultiplier() { return 1; } + unsigned getMemcpyCost(const Instruction *I) { + return TTI::TCC_Expensive; + } + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, ArrayRef ParamTys, const User *U) { switch (IID) { default: // Intrinsics rarely (if ever) have normal argument setup constraints. // Model them as having a basic instruction cost. - // FIXME: This is wrong for libc intrinsics. return TTI::TCC_Basic; + // TODO: other libc intrinsics. + case Intrinsic::memcpy: + return getMemcpyCost(dyn_cast(U)); + case Intrinsic::annotation: case Intrinsic::assume: case Intrinsic::sideeffect: diff --git a/test/Analysis/CostModel/ARM/memcpy.ll b/test/Analysis/CostModel/ARM/memcpy.ll new file mode 100644 index 00000000000..aa0bee633ff --- /dev/null +++ b/test/Analysis/CostModel/ARM/memcpy.ll @@ -0,0 +1,13 @@ +; RUN: opt < %s -cost-model -analyze -cost-kind=code-size | FileCheck %s + +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" +target triple = "thumbv7m-arm-unknown-eabi" + +define void @memcpy(i8* %d, i8* %s, i32 %N) { +entry: +; CHECK: cost of 4 for instruction: call void @llvm.memcpy.p0i8.p0i8.i32 + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %d, i8* align 1 %s, i32 36, i1 false) + ret void +} + +declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i1) #1