[llvm] b3fec10 - [Attributor] Improve NonNull deduction
Johannes Doerfert via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 25 20:31:35 PDT 2023
Author: Johannes Doerfert
Date: 2023-07-25T20:31:21-07:00
New Revision: b3fec1067a15a5b619e3ebb3467babdb5b2f5799
URL: https://github.com/llvm/llvm-project/commit/b3fec1067a15a5b619e3ebb3467babdb5b2f5799
DIFF: https://github.com/llvm/llvm-project/commit/b3fec1067a15a5b619e3ebb3467babdb5b2f5799.diff
LOG: [Attributor] Improve NonNull deduction
We can improve our deduction if we stop at PHI and select instructions
and also iterate the returned values explicitly. The latter helps with
isImpliedByIR deductions.
Added:
Modified:
llvm/include/llvm/Transforms/IPO/Attributor.h
llvm/lib/Transforms/IPO/Attributor.cpp
llvm/lib/Transforms/IPO/AttributorAttributes.cpp
llvm/test/Transforms/Attributor/depgraph.ll
llvm/test/Transforms/Attributor/nonnull.ll
llvm/test/Transforms/Attributor/value-simplify.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h
index 8a5a0955d1326d..2ea223482c6015 100644
--- a/llvm/include/llvm/Transforms/IPO/Attributor.h
+++ b/llvm/include/llvm/Transforms/IPO/Attributor.h
@@ -2289,7 +2289,7 @@ struct Attributor {
/// present in \p Opcode and return true if \p Pred holds on all of them.
bool checkForAllInstructions(function_ref<bool(Instruction &)> Pred,
const Function *Fn,
- const AbstractAttribute &QueryingAA,
+ const AbstractAttribute *QueryingAA,
const ArrayRef<unsigned> &Opcodes,
bool &UsedAssumedInformation,
bool CheckBBLivenessOnly = false,
diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp
index 4cb2ad68e0b3ce..73198127f445c6 100644
--- a/llvm/lib/Transforms/IPO/Attributor.cpp
+++ b/llvm/lib/Transforms/IPO/Attributor.cpp
@@ -723,7 +723,7 @@ isPotentiallyReachable(Attributor &A, const Instruction &FromI,
// Check if we can reach returns.
bool UsedAssumedInformation = false;
- if (A.checkForAllInstructions(ReturnInstCB, FromFn, QueryingAA,
+ if (A.checkForAllInstructions(ReturnInstCB, FromFn, &QueryingAA,
{Instruction::Ret}, UsedAssumedInformation)) {
LLVM_DEBUG(dbgs() << "[AA] No return is reachable, done\n");
continue;
@@ -1967,7 +1967,7 @@ static bool checkForAllInstructionsImpl(
bool Attributor::checkForAllInstructions(function_ref<bool(Instruction &)> Pred,
const Function *Fn,
- const AbstractAttribute &QueryingAA,
+ const AbstractAttribute *QueryingAA,
const ArrayRef<unsigned> &Opcodes,
bool &UsedAssumedInformation,
bool CheckBBLivenessOnly,
@@ -1978,12 +1978,12 @@ bool Attributor::checkForAllInstructions(function_ref<bool(Instruction &)> Pred,
const IRPosition &QueryIRP = IRPosition::function(*Fn);
const auto *LivenessAA =
- CheckPotentiallyDead
+ CheckPotentiallyDead && QueryingAA
? nullptr
- : (getAAFor<AAIsDead>(QueryingAA, QueryIRP, DepClassTy::NONE));
+ : (getAAFor<AAIsDead>(*QueryingAA, QueryIRP, DepClassTy::NONE));
auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn);
- if (!checkForAllInstructionsImpl(this, OpcodeInstMap, Pred, &QueryingAA,
+ if (!checkForAllInstructionsImpl(this, OpcodeInstMap, Pred, QueryingAA,
LivenessAA, Opcodes, UsedAssumedInformation,
CheckBBLivenessOnly, CheckPotentiallyDead))
return false;
@@ -1999,7 +1999,7 @@ bool Attributor::checkForAllInstructions(function_ref<bool(Instruction &)> Pred,
bool CheckPotentiallyDead) {
const IRPosition &IRP = QueryingAA.getIRPosition();
const Function *AssociatedFunction = IRP.getAssociatedFunction();
- return checkForAllInstructions(Pred, AssociatedFunction, QueryingAA, Opcodes,
+ return checkForAllInstructions(Pred, AssociatedFunction, &QueryingAA, Opcodes,
UsedAssumedInformation, CheckBBLivenessOnly,
CheckPotentiallyDead);
}
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 60dca479fa06a8..68e258bb61de8e 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -2457,9 +2457,6 @@ bool AANonNull::isImpliedByIR(Attributor &A, const IRPosition &IRP,
if (A.hasAttr(IRP, AttrKinds, IgnoreSubsumingPositions, Attribute::NonNull))
return true;
- if (IRP.getPositionKind() == IRP_RETURNED)
- return false;
-
DominatorTree *DT = nullptr;
AssumptionCache *AC = nullptr;
InformationCache &InfoCache = A.getInfoCache();
@@ -2470,9 +2467,27 @@ bool AANonNull::isImpliedByIR(Attributor &A, const IRPosition &IRP,
}
}
- if (!isKnownNonZero(&IRP.getAssociatedValue(), A.getDataLayout(), 0, AC,
- IRP.getCtxI(), DT))
+ SmallVector<AA::ValueAndContext> Worklist;
+ if (IRP.getPositionKind() != IRP_RETURNED) {
+ Worklist.push_back({IRP.getAssociatedValue(), IRP.getCtxI()});
+ } else {
+ bool UsedAssumedInformation = false;
+ if (!A.checkForAllInstructions(
+ [&](Instruction &I) {
+ Worklist.push_back({*cast<ReturnInst>(I).getReturnValue(), &I});
+ return true;
+ },
+ IRP.getAssociatedFunction(), nullptr, {Instruction::Ret},
+ UsedAssumedInformation))
+ return false;
+ }
+
+ if (llvm::any_of(Worklist, [&](AA::ValueAndContext VAC) {
+ return !isKnownNonZero(VAC.getValue(), A.getDataLayout(), 0, AC,
+ VAC.getCtxI(), DT);
+ }))
return false;
+
A.manifestAttrs(IRP, {Attribute::get(IRP.getAnchorValue().getContext(),
Attribute::NonNull)});
return true;
@@ -2617,6 +2632,23 @@ struct AANonNullFloating : public AANonNullImpl {
Values.size() != 1 || Values.front().getValue() != AssociatedValue;
if (!Stripped) {
+ bool IsKnown;
+ if (auto *PHI = dyn_cast<PHINode>(AssociatedValue))
+ if (llvm::all_of(PHI->incoming_values(), [&](Value *Op) {
+ return AA::hasAssumedIRAttr<Attribute::NonNull>(
+ A, this, IRPosition::value(*Op), DepClassTy::OPTIONAL,
+ IsKnown);
+ }))
+ return ChangeStatus::UNCHANGED;
+ if (auto *Select = dyn_cast<SelectInst>(AssociatedValue))
+ if (AA::hasAssumedIRAttr<Attribute::NonNull>(
+ A, this, IRPosition::value(*Select->getFalseValue()),
+ DepClassTy::OPTIONAL, IsKnown) &&
+ AA::hasAssumedIRAttr<Attribute::NonNull>(
+ A, this, IRPosition::value(*Select->getTrueValue()),
+ DepClassTy::OPTIONAL, IsKnown))
+ return ChangeStatus::UNCHANGED;
+
// If we haven't stripped anything we might still be able to use a
//
diff erent AA, but only if the IRP changes. Effectively when we
// interpret this not as a call site value but as a floating/argument
@@ -2641,10 +2673,11 @@ struct AANonNullFloating : public AANonNullImpl {
/// NonNull attribute for function return value.
struct AANonNullReturned final
: AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
- false, AANonNull::IRAttributeKind> {
+ false, AANonNull::IRAttributeKind, false> {
AANonNullReturned(const IRPosition &IRP, Attributor &A)
: AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
- false, Attribute::NonNull>(IRP, A) {}
+ false, Attribute::NonNull, false>(IRP, A) {
+ }
/// See AbstractAttribute::getAsStr().
const std::string getAsStr(Attributor *A) const override {
diff --git a/llvm/test/Transforms/Attributor/depgraph.ll b/llvm/test/Transforms/Attributor/depgraph.ll
index 9f01c766b6628a..22186edefaf27d 100644
--- a/llvm/test/Transforms/Attributor/depgraph.ll
+++ b/llvm/test/Transforms/Attributor/depgraph.ll
@@ -112,7 +112,7 @@ define ptr @checkAndAdvance(ptr align 16 %0) {
; GRAPH-NEXT: updates [AAPotentialValues] for CtxI ' %6 = call ptr @checkAndAdvance(ptr %5)' at position {cs_ret: [@-1]} with state set-state(< { %5 = getelementptr inbounds i32, ptr %0, i64 4[3], %5 = getelementptr inbounds i32, ptr %0, i64 4[3], } >)
; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, ptr %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned
; GRAPH-NEXT: updates [AAAlign] for CtxI ' %2 = load i32, ptr %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance at -1]} with state align<1-16>
-; GRAPH-NEXT: updates [AANonNull] for CtxI ' %2 = load i32, ptr %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance at -1]} with state nonnull
+; GRAPH-NEXT: updates [AANonNull] for CtxI ' %.0 = phi ptr [ %6, %4 ], [ %0, %7 ]' at position {flt:.0 [.0 at -1]} with state nonnull
; GRAPH-EMPTY:
; GRAPH-NEXT: [AAPotentialValues] for CtxI ' %5 = getelementptr inbounds i32, ptr %0, i64 4' at position {flt: [@-1]} with state set-state(< { %5 = getelementptr inbounds i32, ptr %0, i64 4[3], } >)
; GRAPH-EMPTY:
@@ -207,6 +207,9 @@ define ptr @checkAndAdvance(ptr align 16 %0) {
; GRAPH-EMPTY:
; GRAPH-NEXT: [AANonNull] for CtxI ' %2 = load i32, ptr %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance at -1]} with state nonnull
; GRAPH-EMPTY:
+; GRAPH-NEXT: [AANonNull] for CtxI ' %.0 = phi ptr [ %6, %4 ], [ %0, %7 ]' at position {flt:.0 [.0 at -1]} with state nonnull
+; GRAPH-NEXT: updates [AANonNull] for CtxI ' %2 = load i32, ptr %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance at -1]} with state nonnull
+; GRAPH-EMPTY:
; GRAPH-NEXT: [AANonNull] for CtxI ' %2 = load i32, ptr %0, align 4' at position {arg: [@0]} with state nonnull
; GRAPH-EMPTY:
; GRAPH-NEXT: [AANoAlias] for CtxI ' %2 = load i32, ptr %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance at -1]} with state may-alias
diff --git a/llvm/test/Transforms/Attributor/nonnull.ll b/llvm/test/Transforms/Attributor/nonnull.ll
index 1e964c6ce3f254..b646af63c49c96 100644
--- a/llvm/test/Transforms/Attributor/nonnull.ll
+++ b/llvm/test/Transforms/Attributor/nonnull.ll
@@ -1522,7 +1522,6 @@ define void @nonnull_caller(ptr %p) {
call void @nonnull_callee(ptr %p)
ret void
}
-
declare void @nonnull_callee(ptr nonnull %p)
define ptr @phi(ptr %p) {
@@ -1555,15 +1554,15 @@ define void @phi_caller(ptr %p) {
; TUNIT: Function Attrs: nounwind
; TUNIT-LABEL: define {{[^@]+}}@phi_caller
; TUNIT-SAME: (ptr nofree [[P:%.*]]) #[[ATTR5]] {
-; TUNIT-NEXT: [[C:%.*]] = call ptr @phi(ptr noalias nofree readnone [[P]]) #[[ATTR19:[0-9]+]]
-; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree readnone [[C]]) #[[ATTR5]]
+; TUNIT-NEXT: [[C:%.*]] = call nonnull ptr @phi(ptr noalias nofree readnone [[P]]) #[[ATTR19:[0-9]+]]
+; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree nonnull readnone [[C]]) #[[ATTR5]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: nounwind
; CGSCC-LABEL: define {{[^@]+}}@phi_caller
; CGSCC-SAME: (ptr nofree [[P:%.*]]) #[[ATTR4]] {
-; CGSCC-NEXT: [[C:%.*]] = call ptr @phi(ptr noalias nofree readnone [[P]]) #[[ATTR15]]
-; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree readnone [[C]]) #[[ATTR4]]
+; CGSCC-NEXT: [[C:%.*]] = call nonnull ptr @phi(ptr noalias nofree readnone [[P]]) #[[ATTR15]]
+; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree nonnull readnone [[C]]) #[[ATTR4]]
; CGSCC-NEXT: ret void
;
%c = call ptr @phi(ptr %p)
@@ -1595,15 +1594,15 @@ define void @multi_ret_caller(ptr %p) {
; TUNIT: Function Attrs: nounwind
; TUNIT-LABEL: define {{[^@]+}}@multi_ret_caller
; TUNIT-SAME: (ptr nofree [[P:%.*]]) #[[ATTR5]] {
-; TUNIT-NEXT: [[C:%.*]] = call ptr @multi_ret(ptr noalias nofree readnone [[P]]) #[[ATTR19]]
-; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree readnone [[C]]) #[[ATTR5]]
+; TUNIT-NEXT: [[C:%.*]] = call nonnull ptr @multi_ret(ptr noalias nofree readnone [[P]]) #[[ATTR19]]
+; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree nonnull readnone [[C]]) #[[ATTR5]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: nounwind
; CGSCC-LABEL: define {{[^@]+}}@multi_ret_caller
; CGSCC-SAME: (ptr nofree [[P:%.*]]) #[[ATTR4]] {
-; CGSCC-NEXT: [[C:%.*]] = call ptr @multi_ret(ptr noalias nofree readnone [[P]]) #[[ATTR15]]
-; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree readnone [[C]]) #[[ATTR4]]
+; CGSCC-NEXT: [[C:%.*]] = call nonnull ptr @multi_ret(ptr noalias nofree readnone [[P]]) #[[ATTR15]]
+; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree nonnull readnone [[C]]) #[[ATTR4]]
; CGSCC-NEXT: ret void
;
%c = call ptr @multi_ret(ptr %p)
diff --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll
index 31fc0746db2ce1..56d6f4c33ecb45 100644
--- a/llvm/test/Transforms/Attributor/value-simplify.ll
+++ b/llvm/test/Transforms/Attributor/value-simplify.ll
@@ -502,7 +502,7 @@ define ptr @complicated_args_preallocated() {
; CGSCC-SAME: () #[[ATTR4:[0-9]+]] {
; CGSCC-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR13]]
; CGSCC-NEXT: [[CALL:%.*]] = call ptr @test_preallocated(ptr nofree noundef writeonly preallocated(i32) align 4294967296 null) #[[ATTR14:[0-9]+]] [ "preallocated"(token [[C]]) ]
-; CGSCC-NEXT: ret ptr null
+; CGSCC-NEXT: unreachable
;
%c = call token @llvm.call.preallocated.setup(i32 1)
%call = call ptr @test_preallocated(ptr preallocated(i32) null) ["preallocated"(token %c)]
More information about the llvm-commits
mailing list