}
struct AANonNullImpl : AANonNull {
- AANonNullImpl(const IRPosition &IRP) : AANonNull(IRP) {}
+ AANonNullImpl(const IRPosition &IRP)
+ : AANonNull(IRP),
+ NullIsDefined(NullPointerIsDefined(
+ getAnchorScope(),
+ getAssociatedValue().getType()->getPointerAddressSpace())) {}
/// See AbstractAttribute::initialize(...).
void initialize(Attributor &A) override {
- if (hasAttr({Attribute::NonNull, Attribute::Dereferenceable}))
+ if (!NullIsDefined &&
+ hasAttr({Attribute::NonNull, Attribute::Dereferenceable}))
indicateOptimisticFixpoint();
else
AANonNull::initialize(A);
const std::string getAsStr() const override {
return getAssumed() ? "nonnull" : "may-null";
}
+
+ /// Flag to determine if the underlying value can be null and still allow
+ /// valid accesses.
+ const bool NullIsDefined;
};
/// NonNull attribute for a floating value.
if (isKnownNonNull())
return Change;
+ if (!NullIsDefined) {
+ const auto &DerefAA = A.getAAFor<AADereferenceable>(*this, getIRPosition());
+ if (DerefAA.getAssumedDereferenceableBytes())
+ return Change;
+ }
+
const DataLayout &DL = A.getDataLayout();
auto VisitValueCB = [&](Value &V, AAAlign::StateType &T,
const auto &AA = A.getAAFor<AANonNull>(*this, IRPosition::value(V));
if (!Stripped && this == &AA) {
if (!isKnownNonZero(&V, DL, 0, /* TODO: AC */ nullptr,
- /* TODO: CtxI */ nullptr,
+ /* CtxI */ getCtxI(),
/* TODO: DT */ nullptr))
T.indicatePessimisticFixpoint();
} else {
ret i32 addrspace(3)* %q
}
+; FNATTR: define i32 addrspace(3)* @as(i32 addrspace(3)* readnone returned dereferenceable(4) %p)
+; FIXME: We should propagate dereferenceable here but *not* nonnull
+; ATTRIBUTOR: define dereferenceable_or_null(4) i32 addrspace(3)* @as(i32 addrspace(3)* readnone returned dereferenceable(4) dereferenceable_or_null(4) %p)
+define i32 addrspace(3)* @as(i32 addrspace(3)* dereferenceable(4) %p) {
+ ret i32 addrspace(3)* %p
+}
+
; BOTH: define internal nonnull i32* @g2()
define internal i32* @g2() {
ret i32* inttoptr (i64 4 to i32*)
-; RUN: opt -functionattrs -enable-nonnull-arg-prop -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=6 -S < %s | FileCheck %s
+; RUN: opt -functionattrs -enable-nonnull-arg-prop -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=7 -S < %s | FileCheck %s
;
; This is an evolved example to stress test SCC parameter attribute propagation.
; The SCC in this test is made up of the following six function, three of which