diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp --- a/llvm/lib/Analysis/InlineCost.cpp +++ b/llvm/lib/Analysis/InlineCost.cpp @@ -23,6 +23,7 @@ #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/MemoryBuiltins.h" #include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" @@ -388,6 +389,7 @@ template bool simplifyInstruction(Instruction &I, Callable Evaluate); bool simplifyIntrinsicCallIsConstant(CallBase &CB); + bool simplifyIntrinsicCallObjectSize(CallBase &CB); ConstantInt *stripAndComputeInBoundsConstantOffsets(Value *&V); /// Return true if the given argument to the function being considered for @@ -1553,6 +1555,16 @@ return true; } +bool CallAnalyzer::simplifyIntrinsicCallObjectSize(CallBase &CB) { + Value *V = lowerObjectSizeCall(&cast(CB), DL, nullptr, + /*MustSucceed=*/true); + if (auto *CV = dyn_cast_or_null(V)) { + SimplifiedValues[&CB] = CV; + return true; + } + return false; +} + bool CallAnalyzer::visitBitCast(BitCastInst &I) { // Propagate constants through bitcasts. if (simplifyInstruction(I, [&](SmallVectorImpl &COps) { @@ -2178,6 +2190,8 @@ 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 --- /dev/null +++ b/llvm/test/Transforms/Inline/call-intrinsic-objectsize.ll @@ -0,0 +1,56 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes=inline -S %s -debug-only=inline-cost -inline-threshold=20 \ +; RUN: 2>&1 | FileCheck %s + +%struct.nodemask_t = type { [16 x i64] } +@numa_nodes_parsed = external dso_local global %struct.nodemask_t, section ".init.data", align 8 + +@foo = private unnamed_addr constant { i16, i16, [13 x i8] } { i16 -1, i16 0, [13 x i8] c"'nodemask_t'\00" } +@.src = private unnamed_addr constant [26 x i8] c"arch/x86/mm/amdtopology.c\00", align 1 +@bar = private unnamed_addr global { { [26 x i8]*, i32, i32 }, { i16, i16, [13 x i8] }*, i8, i8 } { { [26 x i8]*, i32, i32 } { [26 x i8]* @.src, i32 110, i32 7 }, { i16, i16, [13 x i8] }* @foo, i8 1, i8 3 } + +declare dso_local void @__ubsan_handle_type_mismatch_v1(i8*, i64) +declare i64 @llvm.objectsize.i64.p0i8(i8*, 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.p0i8(i8* bitcast (%struct.nodemask_t* @numa_nodes_parsed to i8*), 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 @__ubsan_handle_type_mismatch_v1(i8* bitcast ({ { [26 x i8]*, i32, i32 }, { i16, i16, [13 x i8] }*, i8, i8 }* @bar to i8*), i64 ptrtoint (%struct.nodemask_t* @numa_nodes_parsed to i64)) +; 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() { +; CHECK-LABEL: @callee( +; CHECK-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.objectsize.i64.p0i8(i8* bitcast (%struct.nodemask_t* @numa_nodes_parsed to i8*), i1 false, i1 false, i1 false) +; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i64 [[TMP1]], 128 +; CHECK-NEXT: br i1 [[TMP2]], label [[CONT95:%.*]], label [[HANDLER_TYPE_MISMATCH94:%.*]] +; CHECK: handler.type_mismatch94: +; CHECK-NEXT: call void @__ubsan_handle_type_mismatch_v1(i8* bitcast ({ { [26 x i8]*, i32, i32 }, { i16, i16, [13 x i8] }*, i8, i8 }* @bar to i8*), i64 ptrtoint (%struct.nodemask_t* @numa_nodes_parsed to i64)) +; CHECK-NEXT: br label [[CONT95]] +; CHECK: cont95: +; CHECK-NEXT: ret i64 [[TMP1]] +; + %1 = tail call i64 @llvm.objectsize.i64.p0i8(i8* bitcast (%struct.nodemask_t* @numa_nodes_parsed to i8*), 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 @__ubsan_handle_type_mismatch_v1(i8* bitcast ({ { [26 x i8]*, i32, i32 }, { i16, i16, [13 x i8] }*, i8, i8 }* @bar to i8*), i64 ptrtoint (%struct.nodemask_t* @numa_nodes_parsed to i64)) + br label %cont95 + +cont95: + ret i64 %1 +} +