diff options
-rw-r--r-- | llvm/include/llvm/Transforms/IPO/Attributor.h | 6 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/Attributor.cpp | 25 | ||||
-rw-r--r-- | llvm/test/Transforms/FunctionAttrs/nocapture.ll | 18 | ||||
-rw-r--r-- | llvm/test/Transforms/FunctionAttrs/nonnull.ll | 4 | ||||
-rw-r--r-- | llvm/test/Transforms/FunctionAttrs/readattrs.ll | 2 |
5 files changed, 36 insertions, 19 deletions
diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h index 2b7a4a04b08..3dbe0fcd76e 100644 --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -1128,6 +1128,12 @@ struct IntegerState : public AbstractState { return *this; } + /// Remove the bits in \p BitsEncoding from the "known bits". + IntegerState &removeKnownBits(base_t BitsEncoding) { + Known = (Known & ~BitsEncoding); + return *this; + } + /// Keep only "assumed bits" also set in \p BitsEncoding but all known ones. IntegerState &intersectAssumedBits(base_t BitsEncoding) { // Make sure we never loose any "known bits". diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index dadf3722a6f..d7c49a248de 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -3838,17 +3838,23 @@ struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating { void initialize(Attributor &A) override { AAMemoryBehaviorFloating::initialize(A); - // TODO: From readattrs.ll: "inalloca parameters are always - // considered written" - if (hasAttr({Attribute::InAlloca})) - removeAssumedBits(NO_WRITES); - // Initialize the use vector with all direct uses of the associated value. Argument *Arg = getAssociatedArgument(); if (!Arg || !Arg->getParent()->hasExactDefinition()) indicatePessimisticFixpoint(); } + ChangeStatus manifest(Attributor &A) override { + // TODO: From readattrs.ll: "inalloca parameters are always + // considered written" + if (hasAttr({Attribute::InAlloca})) { + removeKnownBits(NO_WRITES); + removeAssumedBits(NO_WRITES); + } + return AAMemoryBehaviorFloating::manifest(A); + } + + /// See AbstractAttribute::trackStatistics() void trackStatistics() const override { if (isAssumedReadNone()) @@ -4017,10 +4023,13 @@ ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &A) { // Make sure the value is not captured (except through "return"), if // it is, any information derived would be irrelevant anyway as we cannot - // check the potential aliases introduced by the capture. + // check the potential aliases introduced by the capture. However, no need + // to fall back to anythign less optimistic than the function state. const auto &ArgNoCaptureAA = A.getAAFor<AANoCapture>(*this, IRP); - if (!ArgNoCaptureAA.isAssumedNoCaptureMaybeReturned()) - return indicatePessimisticFixpoint(); + if (!ArgNoCaptureAA.isAssumedNoCaptureMaybeReturned()) { + S.intersectAssumedBits(FnMemAA.getAssumed()); + return ChangeStatus::CHANGED; + } // The current assumed state used to determine a change. auto AssumedState = S.getAssumed(); diff --git a/llvm/test/Transforms/FunctionAttrs/nocapture.ll b/llvm/test/Transforms/FunctionAttrs/nocapture.ll index 6f2699a3bdb..e0580849983 100644 --- a/llvm/test/Transforms/FunctionAttrs/nocapture.ll +++ b/llvm/test/Transforms/FunctionAttrs/nocapture.ll @@ -11,14 +11,16 @@ define i32* @c1(i32* %q) { ret i32* %q } -; EITHER: define void @c2(i32* %q) +; FNATTR: define void @c2(i32* %q) +; ATTRIBUTOR: define void @c2(i32* writeonly %q) ; It would also be acceptable to mark %q as readnone. Update @c3 too. define void @c2(i32* %q) { store i32* %q, i32** @g ret void } -; EITHER: define void @c3(i32* %q) +; FNATTR: define void @c3(i32* %q) +; ATTRIBUTOR: define void @c3(i32* writeonly %q) define void @c3(i32* %q) { call void @c2(i32* %q) ret void @@ -39,7 +41,8 @@ l1: @lookup_table = global [2 x i1] [ i1 0, i1 1 ] -; EITHER: define i1 @c5(i32* %q, i32 %bitno) +; FNATTR: define i1 @c5(i32* %q, i32 %bitno) +; ATTRIBUTOR: define i1 @c5(i32* readonly %q, i32 %bitno) define i1 @c5(i32* %q, i32 %bitno) { %tmp = ptrtoint i32* %q to i32 %tmp2 = lshr i32 %tmp, %bitno @@ -52,8 +55,7 @@ define i1 @c5(i32* %q, i32 %bitno) { declare void @throw_if_bit_set(i8*, i8) readonly -; FNATTR: define i1 @c6(i8* readonly %q, i8 %bit) -; ATTRIBUTOR: define i1 @c6(i8* %q, i8 %bit) +; EITHER: define i1 @c6(i8* readonly %q, i8 %bit) define i1 @c6(i8* %q, i8 %bit) personality i32 (...)* @__gxx_personality_v0 { invoke void @throw_if_bit_set(i8* %q, i8 %bit) to label %ret0 unwind label %ret1 @@ -75,8 +77,7 @@ define i1* @lookup_bit(i32* %q, i32 %bitno) readnone nounwind { ret i1* %lookup } -; FNATTR: define i1 @c7(i32* readonly %q, i32 %bitno) -; ATTRIBUTOR: define i1 @c7(i32* %q, i32 %bitno) +; EITHER: define i1 @c7(i32* readonly %q, i32 %bitno) define i1 @c7(i32* %q, i32 %bitno) { %ptr = call i1* @lookup_bit(i32* %q, i32 %bitno) %val = load i1, i1* %ptr @@ -271,7 +272,8 @@ entry: } @g3 = global i8* null -; EITHER: define void @captureStrip(i8* %p) +; FNATTR: define void @captureStrip(i8* %p) +; ATTRIBUTOR: define void @captureStrip(i8* writeonly %p) define void @captureStrip(i8* %p) { %b = call i8* @llvm.strip.invariant.group.p0i8(i8* %p) store i8* %b, i8** @g3 diff --git a/llvm/test/Transforms/FunctionAttrs/nonnull.ll b/llvm/test/Transforms/FunctionAttrs/nonnull.ll index f893e1db889..21e5ae1f7ec 100644 --- a/llvm/test/Transforms/FunctionAttrs/nonnull.ll +++ b/llvm/test/Transforms/FunctionAttrs/nonnull.ll @@ -198,7 +198,7 @@ bb4: ; preds = %bb1 bb6: ; preds = %bb1 ; FIXME: missing nonnull. It should be @f2(i32* nonnull %arg) -; ATTRIBUTOR: %tmp7 = tail call nonnull i32* @f2(i32* %arg) +; ATTRIBUTOR: %tmp7 = tail call nonnull i32* @f2(i32* readonly %arg) %tmp7 = tail call i32* @f2(i32* %arg) ret i32* %tmp7 @@ -209,7 +209,7 @@ bb9: ; preds = %bb4, %bb define internal i32* @f2(i32* %arg) { ; FIXME: missing nonnull. It should be nonnull @f2(i32* nonnull %arg) -; ATTRIBUTOR: define internal nonnull i32* @f2(i32* %arg) +; ATTRIBUTOR: define internal nonnull i32* @f2(i32* readonly %arg) bb: ; FIXME: missing nonnull. It should be @f1(i32* nonnull readonly %arg) diff --git a/llvm/test/Transforms/FunctionAttrs/readattrs.ll b/llvm/test/Transforms/FunctionAttrs/readattrs.ll index 76075684bff..cccdeaad765 100644 --- a/llvm/test/Transforms/FunctionAttrs/readattrs.ll +++ b/llvm/test/Transforms/FunctionAttrs/readattrs.ll @@ -39,7 +39,7 @@ define void @test4_2(i8* %p) { } ; FNATTR: define void @test5(i8** nocapture %p, i8* %q) -; ATTRIBUTOR: define void @test5(i8** nocapture nonnull writeonly dereferenceable(8) %p, i8* %q) +; ATTRIBUTOR: define void @test5(i8** nocapture nonnull writeonly dereferenceable(8) %p, i8* writeonly %q) ; Missed optz'n: we could make %q readnone, but don't break test6! define void @test5(i8** %p, i8* %q) { store i8* %q, i8** %p |