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  | 

