blob: 2ca118b5aaee991fb3c2bc593b04c5df53742fc4 [file] [log] [blame]
commit f1764d5b594ff6edbf8d17d196eb0b7a653ac0fc
Author: Nick Desaulniers <ndesaulniers@google.com>
Date: Tue Jan 24 14:54:50 2023 -0800
[InlineCost] model calls to llvm.objectsize.*
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
diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp
index bce71b26d538..5bcc8a2f384a 100644
--- a/llvm/lib/Analysis/InlineCost.cpp
+++ b/llvm/lib/Analysis/InlineCost.cpp
@@ -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
index 000000000000..bdbbb101268e
--- /dev/null
+++ b/llvm/test/Transforms/Inline/call-intrinsic-objectsize.ll
@@ -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
+}
+