| 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 |
| +} |
| + |