llvm.org GIT mirror llvm / d552441
[Attributor][MemBehavior] Fallback to the function state for arguments Even if an argument is captured, we cannot have an effect the function does not have. This is fine except for the special case of `inalloca` as it does not behave by the rules. TODO: Maybe the special rule for `inalloca` is wrong after all. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@374736 91177308-0d34-0410-b5e6-96231b3b80d8 Johannes Doerfert 1 year, 1 month ago
5 changed file(s) with 36 addition(s) and 19 deletion(s). Raw diff Collapse all Expand all
11271127 return *this;
11281128 }
11291129
1130 /// Remove the bits in \p BitsEncoding from the "known bits".
1131 IntegerState &removeKnownBits(base_t BitsEncoding) {
1132 Known = (Known & ~BitsEncoding);
1133 return *this;
1134 }
1135
11301136 /// Keep only "assumed bits" also set in \p BitsEncoding but all known ones.
11311137 IntegerState &intersectAssumedBits(base_t BitsEncoding) {
11321138 // Make sure we never loose any "known bits".
38373837 void initialize(Attributor &A) override {
38383838 AAMemoryBehaviorFloating::initialize(A);
38393839
3840 // TODO: From readattrs.ll: "inalloca parameters are always
3841 // considered written"
3842 if (hasAttr({Attribute::InAlloca}))
3843 removeAssumedBits(NO_WRITES);
3844
38453840 // Initialize the use vector with all direct uses of the associated value.
38463841 Argument *Arg = getAssociatedArgument();
38473842 if (!Arg || !Arg->getParent()->hasExactDefinition())
38483843 indicatePessimisticFixpoint();
38493844 }
3845
3846 ChangeStatus manifest(Attributor &A) override {
3847 // TODO: From readattrs.ll: "inalloca parameters are always
3848 // considered written"
3849 if (hasAttr({Attribute::InAlloca})) {
3850 removeKnownBits(NO_WRITES);
3851 removeAssumedBits(NO_WRITES);
3852 }
3853 return AAMemoryBehaviorFloating::manifest(A);
3854 }
3855
38503856
38513857 /// See AbstractAttribute::trackStatistics()
38523858 void trackStatistics() const override {
40164022
40174023 // Make sure the value is not captured (except through "return"), if
40184024 // it is, any information derived would be irrelevant anyway as we cannot
4019 // check the potential aliases introduced by the capture.
4025 // check the potential aliases introduced by the capture. However, no need
4026 // to fall back to anythign less optimistic than the function state.
40204027 const auto &ArgNoCaptureAA = A.getAAFor(*this, IRP);
4021 if (!ArgNoCaptureAA.isAssumedNoCaptureMaybeReturned())
4022 return indicatePessimisticFixpoint();
4028 if (!ArgNoCaptureAA.isAssumedNoCaptureMaybeReturned()) {
4029 S.intersectAssumedBits(FnMemAA.getAssumed());
4030 return ChangeStatus::CHANGED;
4031 }
40234032
40244033 // The current assumed state used to determine a change.
40254034 auto AssumedState = S.getAssumed();
1010 ret i32* %q
1111 }
1212
13 ; EITHER: define void @c2(i32* %q)
13 ; FNATTR: define void @c2(i32* %q)
14 ; ATTRIBUTOR: define void @c2(i32* writeonly %q)
1415 ; It would also be acceptable to mark %q as readnone. Update @c3 too.
1516 define void @c2(i32* %q) {
1617 store i32* %q, i32** @g
1718 ret void
1819 }
1920
20 ; EITHER: define void @c3(i32* %q)
21 ; FNATTR: define void @c3(i32* %q)
22 ; ATTRIBUTOR: define void @c3(i32* writeonly %q)
2123 define void @c3(i32* %q) {
2224 call void @c2(i32* %q)
2325 ret void
3840
3941 @lookup_table = global [2 x i1] [ i1 0, i1 1 ]
4042
41 ; EITHER: define i1 @c5(i32* %q, i32 %bitno)
43 ; FNATTR: define i1 @c5(i32* %q, i32 %bitno)
44 ; ATTRIBUTOR: define i1 @c5(i32* readonly %q, i32 %bitno)
4245 define i1 @c5(i32* %q, i32 %bitno) {
4346 %tmp = ptrtoint i32* %q to i32
4447 %tmp2 = lshr i32 %tmp, %bitno
5154
5255 declare void @throw_if_bit_set(i8*, i8) readonly
5356
54 ; FNATTR: define i1 @c6(i8* readonly %q, i8 %bit)
55 ; ATTRIBUTOR: define i1 @c6(i8* %q, i8 %bit)
57 ; EITHER: define i1 @c6(i8* readonly %q, i8 %bit)
5658 define i1 @c6(i8* %q, i8 %bit) personality i32 (...)* @__gxx_personality_v0 {
5759 invoke void @throw_if_bit_set(i8* %q, i8 %bit)
5860 to label %ret0 unwind label %ret1
7476 ret i1* %lookup
7577 }
7678
77 ; FNATTR: define i1 @c7(i32* readonly %q, i32 %bitno)
78 ; ATTRIBUTOR: define i1 @c7(i32* %q, i32 %bitno)
79 ; EITHER: define i1 @c7(i32* readonly %q, i32 %bitno)
7980 define i1 @c7(i32* %q, i32 %bitno) {
8081 %ptr = call i1* @lookup_bit(i32* %q, i32 %bitno)
8182 %val = load i1, i1* %ptr
270271 }
271272
272273 @g3 = global i8* null
273 ; EITHER: define void @captureStrip(i8* %p)
274 ; FNATTR: define void @captureStrip(i8* %p)
275 ; ATTRIBUTOR: define void @captureStrip(i8* writeonly %p)
274276 define void @captureStrip(i8* %p) {
275277 %b = call i8* @llvm.strip.invariant.group.p0i8(i8* %p)
276278 store i8* %b, i8** @g3
197197
198198 bb6: ; preds = %bb1
199199 ; FIXME: missing nonnull. It should be @f2(i32* nonnull %arg)
200 ; ATTRIBUTOR: %tmp7 = tail call nonnull i32* @f2(i32* %arg)
200 ; ATTRIBUTOR: %tmp7 = tail call nonnull i32* @f2(i32* readonly %arg)
201201 %tmp7 = tail call i32* @f2(i32* %arg)
202202 ret i32* %tmp7
203203
208208
209209 define internal i32* @f2(i32* %arg) {
210210 ; FIXME: missing nonnull. It should be nonnull @f2(i32* nonnull %arg)
211 ; ATTRIBUTOR: define internal nonnull i32* @f2(i32* %arg)
211 ; ATTRIBUTOR: define internal nonnull i32* @f2(i32* readonly %arg)
212212 bb:
213213
214214 ; FIXME: missing nonnull. It should be @f1(i32* nonnull readonly %arg)
3838 }
3939
4040 ; FNATTR: define void @test5(i8** nocapture %p, i8* %q)
41 ; ATTRIBUTOR: define void @test5(i8** nocapture nonnull writeonly dereferenceable(8) %p, i8* %q)
41 ; ATTRIBUTOR: define void @test5(i8** nocapture nonnull writeonly dereferenceable(8) %p, i8* writeonly %q)
4242 ; Missed optz'n: we could make %q readnone, but don't break test6!
4343 define void @test5(i8** %p, i8* %q) {
4444 store i8* %q, i8** %p