[InlineCost] model calls to llvm.objectsize.*
authorNick Desaulniers <ndesaulniers@google.com>
Tue, 24 Jan 2023 22:54:50 +0000 (14:54 -0800)
committerNick Desaulniers <ndesaulniers@google.com>
Tue, 24 Jan 2023 23:09:57 +0000 (15:09 -0800)
Very similar to https://reviews.llvm.org/D111272. We very often can
evaluate calls to llvm.objectsize.* regardless of inlining. Don't count
calls to llvm.objectsize.* against the InlineCost when we can evaluate
the call to a constant.

Link: https://github.com/ClangBuiltLinux/linux/issues/1302
Reviewed By: manojgupta

Differential Revision: https://reviews.llvm.org/D111456

llvm/lib/Analysis/InlineCost.cpp
llvm/test/Transforms/Inline/call-intrinsic-objectsize.ll [new file with mode: 0644]

index bce71b2..5bcc8a2 100644 (file)
@@ -22,6 +22,7 @@
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/Analysis/InstructionSimplify.h"
 #include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/MemoryBuiltins.h"
 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
 #include "llvm/Analysis/ProfileSummaryInfo.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
@@ -419,6 +420,7 @@ protected:
   bool simplifyCallSite(Function *F, CallBase &Call);
   bool simplifyInstruction(Instruction &I);
   bool simplifyIntrinsicCallIsConstant(CallBase &CB);
+  bool simplifyIntrinsicCallObjectSize(CallBase &CB);
   ConstantInt *stripAndComputeInBoundsConstantOffsets(Value *&V);
 
   /// Return true if the given argument to the function being considered for
@@ -1602,6 +1604,20 @@ bool CallAnalyzer::simplifyIntrinsicCallIsConstant(CallBase &CB) {
   return true;
 }
 
+bool CallAnalyzer::simplifyIntrinsicCallObjectSize(CallBase &CB) {
+  // As per the langref, "The fourth argument to llvm.objectsize determines if
+  // the value should be evaluated at runtime."
+  if(cast<ConstantInt>(CB.getArgOperand(3))->isOne())
+    return false;
+
+  Value *V = lowerObjectSizeCall(&cast<IntrinsicInst>(CB), DL, nullptr,
+                                 /*MustSucceed=*/true);
+  Constant *C = dyn_cast_or_null<Constant>(V);
+  if (C)
+    SimplifiedValues[&CB] = C;
+  return C;
+}
+
 bool CallAnalyzer::visitBitCast(BitCastInst &I) {
   // Propagate constants through bitcasts.
   if (simplifyInstruction(I))
@@ -2214,6 +2230,8 @@ bool CallAnalyzer::visitCallBase(CallBase &Call) {
       return true;
     case Intrinsic::is_constant:
       return simplifyIntrinsicCallIsConstant(Call);
+    case Intrinsic::objectsize:
+      return simplifyIntrinsicCallObjectSize(Call);
     }
   }
 
diff --git a/llvm/test/Transforms/Inline/call-intrinsic-objectsize.ll b/llvm/test/Transforms/Inline/call-intrinsic-objectsize.ll
new file mode 100644 (file)
index 0000000..bdbbb10
--- /dev/null
@@ -0,0 +1,50 @@
+; RUN: opt -passes=inline -S %s -inline-threshold=20 2>&1 | FileCheck %s
+
+%struct.nodemask_t = type { [16 x i64] }
+@numa_nodes_parsed = external constant %struct.nodemask_t, align 8
+
+declare void @foo()
+declare i64 @llvm.objectsize.i64.p0(ptr, i1 immarg, i1 immarg, i1 immarg)
+
+; Test that we inline @callee into @caller.
+define i64 @caller() {
+; CHECK-LABEL: @caller(
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call i64 @llvm.objectsize.i64.p0(ptr @numa_nodes_parsed, i1 false, i1 false, i1 false)
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp uge i64 [[TMP1]], 128
+; CHECK-NEXT:    br i1 [[TMP2]], label %[[CALLEE_EXIT:.*]], label %[[HANDLER_TYPE_MISMATCH94_I:.*]]
+; CHECK:       [[HANDLER_TYPE_MISMATCH94_I]]:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label %[[CALLEE_EXIT]]
+; CHECK:       [[CALLEE_EXIT]]:
+; CHECK-NEXT:    ret i64 [[TMP1]]
+;
+  %1 = tail call i64 @callee()
+  ret i64 %1
+}
+
+; Testing the InlineCost of the call to @llvm.objectsize.i64.p0i8.
+; Do not change the linkage of @callee; that will give it a severe discount in
+; cost (LastCallToStaticBonus).
+define i64 @callee() {
+  %1 = tail call i64 @llvm.objectsize.i64.p0(ptr @numa_nodes_parsed, i1 false, i1 false, i1 false)
+  %2 = icmp uge i64 %1, 128
+  br i1 %2, label %cont95, label %handler.type_mismatch94
+
+handler.type_mismatch94:
+  call void @foo()
+  call void @foo()
+  call void @foo()
+  call void @foo()
+  call void @foo()
+  call void @foo()
+  br label %cont95
+
+cont95:
+  ret i64 %1
+}
+