[TTI] getMemcpyCost
authorSjoerd Meijer <sjoerd.meijer@arm.com>
Wed, 20 Mar 2019 14:15:46 +0000 (14:15 +0000)
committerSjoerd Meijer <sjoerd.meijer@arm.com>
Wed, 20 Mar 2019 14:15:46 +0000 (14:15 +0000)
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

llvm/include/llvm/Analysis/TargetTransformInfo.h
llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
llvm/test/Analysis/CostModel/ARM/memcpy.ll [new file with mode: 0644]

index f185e9bee28d62f038095376e05a64dd178721cc..085fcac1fe03f01a04f1808d1e0e6dc6cf82b657 100644 (file)
@@ -246,6 +246,10 @@ public:
                        ArrayRef<const Value *> 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<const Value *> 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<const Value *> Operands) override {
     return Impl.getUserCost(U, Operands);
   }
index b244a49f940eb39a2674d652290d4cadb436db4d..8e667268f04a1e5ee76cf5644c333e8c4654832b 100644 (file)
@@ -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<Type *> 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<Instruction>(U));
+
     case Intrinsic::annotation:
     case Intrinsic::assume:
     case Intrinsic::sideeffect:
diff --git a/llvm/test/Analysis/CostModel/ARM/memcpy.ll b/llvm/test/Analysis/CostModel/ARM/memcpy.ll
new file mode 100644 (file)
index 0000000..aa0bee6
--- /dev/null
@@ -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