From 291223409c6139b5d56efc769088e23ecee44faf Mon Sep 17 00:00:00 2001 From: Denis Antrushin Date: Wed, 3 May 2023 00:16:42 +0700 Subject: [PATCH] [InlineCost] Consider branches with !make.implicit metadata as free. !make.implicit metadata attached to branch means it will very likely be eliminated (together with associated cmp instruction). Reviewed By: apilipenko Differential Revision: https://reviews.llvm.org/D149747 --- llvm/lib/Analysis/InlineCost.cpp | 26 +++++++++++++++++----- llvm/test/Transforms/Inline/implicit-null-check.ll | 24 ++++++++++++++++++++ 2 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 llvm/test/Transforms/Inline/implicit-null-check.ll diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp index 09d4b81..02871aa 100644 --- a/llvm/lib/Analysis/InlineCost.cpp +++ b/llvm/lib/Analysis/InlineCost.cpp @@ -1976,14 +1976,27 @@ bool CallAnalyzer::visitCmpInst(CmpInst &I) { } } + auto isImplicitNullCheckCmp = [](const CmpInst &I) { + for (auto *User : I.users()) + if (auto *Instr = dyn_cast(User)) + if (!Instr->getMetadata(LLVMContext::MD_make_implicit)) + return false; + return true; + }; + // If the comparison is an equality comparison with null, we can simplify it // if we know the value (argument) can't be null - if (I.isEquality() && isa(I.getOperand(1)) && - isKnownNonNullInCallee(I.getOperand(0))) { - bool IsNotEqual = I.getPredicate() == CmpInst::ICMP_NE; - SimplifiedValues[&I] = IsNotEqual ? ConstantInt::getTrue(I.getType()) - : ConstantInt::getFalse(I.getType()); - return true; + if (I.isEquality() && isa(I.getOperand(1))) { + if (isKnownNonNullInCallee(I.getOperand(0))) { + bool IsNotEqual = I.getPredicate() == CmpInst::ICMP_NE; + SimplifiedValues[&I] = IsNotEqual ? ConstantInt::getTrue(I.getType()) + : ConstantInt::getFalse(I.getType()); + return true; + } + // Implicit null checks act as unconditional branches and their comparisons + // should be treated as simplified and free of cost. + if (isImplicitNullCheckCmp(I)) + return true; } return handleSROA(I.getOperand(0), isa(I.getOperand(1))); } @@ -2265,6 +2278,7 @@ bool CallAnalyzer::visitBranchInst(BranchInst &BI) { // inliner more regular and predictable. Interestingly, conditional branches // which will fold away are also free. return BI.isUnconditional() || isa(BI.getCondition()) || + BI.getMetadata(LLVMContext::MD_make_implicit) || isa_and_nonnull( SimplifiedValues.lookup(BI.getCondition())); } diff --git a/llvm/test/Transforms/Inline/implicit-null-check.ll b/llvm/test/Transforms/Inline/implicit-null-check.ll new file mode 100644 index 0000000..06e6ae6 --- /dev/null +++ b/llvm/test/Transforms/Inline/implicit-null-check.ll @@ -0,0 +1,24 @@ +; RUN: opt -passes=inline -inline-threshold=10 -S < %s | FileCheck %s + +declare void @foo() + +; CHECK-LABEL: @caller +; CHECK-NOT: %res = call i64 @callee(ptr %p) +define i64 @caller(ptr %p) { + %res = call i64 @callee(ptr %p) + ret i64 %res +} + +define i64 @callee(ptr %p) { + %null_check = icmp eq ptr %p, null + br i1 %null_check, label %is_null, label %non_null, !make.implicit !0 + +is_null: + call void @foo() + ret i64 0 + +non_null: + ret i64 1 +} + +!0 = !{} -- 2.7.4