llvm.org GIT mirror llvm / a217383
[BasicAA] Fix handling of invariant group launders Summary: A recent patch ([[ https://reviews.llvm.org/rL331587 | rL331587 ]]) to Capture Tracking taught it that the `launder_invariant_group` intrinsic captures its argument only by returning it. Unfortunately, BasicAA still considered every call instruction as a possible escape source and hence concluded that the result of a `launder_invariant_group` call cannot alias any local non-escaping value. This led to [[ https://bugs.llvm.org/show_bug.cgi?id=37458 | bug 37458 ]]. This patch updates the relevant check for escape sources in BasicAA. Reviewers: Prazek, kuhar, rsmith, hfinkel, sanjoy, xbolva00 Reviewed By: hfinkel, xbolva00 Subscribers: JDevlieghere, hiraditya, llvm-commits Differential Revision: https://reviews.llvm.org/D46900 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@332466 91177308-0d34-0410-b5e6-96231b3b80d8 Krzysztof Pszeniczny 2 years ago
3 changed file(s) with 62 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
131131 /// Returns true if the pointer is one which would have been considered an
132132 /// escape by isNonEscapingLocalObject.
133133 static bool isEscapeSource(const Value *V) {
134 if (isa(V) || isa(V) || isa(V))
134 if (auto CS = ImmutableCallSite(V)) {
135 // launder_invariant_group captures its argument only by returning it,
136 // so it might not be considered an escape by isNonEscapingLocalObject.
137 // Note that adding similar special cases for intrinsics in CaptureTracking
138 // requires handling them here too.
139 if (CS.getIntrinsicID() == Intrinsic::launder_invariant_group)
140 return false;
141
142 return true;
143 }
144
145 if (isa(V))
135146 return true;
136147
137148 // The load case works because isNonEscapingLocalObject considers all
248248
249249 // launder.invariant.group only captures pointer by returning it,
250250 // so the pointer wasn't captured if returned pointer is not captured.
251 // Note that adding similar special cases for intrinsics requires handling
252 // them in 'isEscapeSource' in BasicAA.
251253 if (CS.getIntrinsicID() == Intrinsic::launder_invariant_group) {
252254 AddUses(I);
253255 break;
0 ; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
1 ; RUN: opt < %s -basicaa -gvn -S | FileCheck -check-prefix=CHECK-GVN %s
2
3 ; The input *.ll had been adapted from bug 37458:
4 ;
5 ; struct A { virtual void f(); int n; };
6 ;
7 ; int h() {
8 ; A a;
9 ; a.n = 42;
10 ; return __builtin_launder(&a)->n;
11 ; }
12
13 %struct.A = type <{ i8*, i8 }>
14
15 ; CHECK: testLaunderInvariantGroupIsNotEscapeSource
16 ; CHECK-GVN: testLaunderInvariantGroupIsNotEscapeSource
17 define i8 @testLaunderInvariantGroupIsNotEscapeSource() {
18 ; CHECK-DAG: MustAlias: %struct.A* %a, i8* %a.bitcast
19 ; CHECK-DAG: PartialAlias: %struct.A* %a, i8* %n
20 ; CHECK-DAG: NoAlias: i8* %a.bitcast, i8* %n
21 ; CHECK-DAG: MustAlias: %struct.A* %a, i8* %a.laundered
22 ; CHECK-DAG: MustAlias: i8* %a.bitcast, i8* %a.laundered
23 ; CHECK-DAG: NoAlias: i8* %a.laundered, i8* %n
24 ; CHECK-DAG: PartialAlias: %struct.A* %a, i8* %n.laundered
25 ; CHECK-DAG: NoAlias: i8* %a.bitcast, i8* %n.laundered
26 ; CHECK-DAG: MustAlias: i8* %n, i8* %n.laundered
27 ; CHECK-DAG: NoAlias: i8* %a.laundered, i8* %n.laundered
28 ; CHECK-DAG: NoModRef: Ptr: %struct.A* %a <-> %a.laundered = call i8* @llvm.launder.invariant.group.p0i8(i8* nonnull %a.bitcast)
29 ; CHECK-DAG: NoModRef: Ptr: i8* %a.bitcast <-> %a.laundered = call i8* @llvm.launder.invariant.group.p0i8(i8* nonnull %a.bitcast)
30 ; CHECK-DAG: NoModRef: Ptr: i8* %n <-> %a.laundered = call i8* @llvm.launder.invariant.group.p0i8(i8* nonnull %a.bitcast)
31 ; CHECK-DAG: NoModRef: Ptr: i8* %a.laundered <-> %a.laundered = call i8* @llvm.launder.invariant.group.p0i8(i8* nonnull %a.bitcast)
32 ; CHECK-DAG: NoModRef: Ptr: i8* %n.laundered <-> %a.laundered = call i8* @llvm.launder.invariant.group.p0i8(i8* nonnull %a.bitcast)
33
34 entry:
35 %a = alloca %struct.A, align 8
36 %a.bitcast = bitcast %struct.A* %a to i8*
37 %n = getelementptr inbounds %struct.A, %struct.A* %a, i64 0, i32 1
38 store i8 42, i8* %n
39 %a.laundered = call i8* @llvm.launder.invariant.group.p0i8(i8* nonnull %a.bitcast)
40 %n.laundered = getelementptr inbounds i8, i8* %a.laundered, i64 8
41 %v = load i8, i8* %n.laundered
42 ; make sure that the load from %n.laundered to %v aliases the store of 42 to %n
43 ; CHECK-GVN: ret i8 42
44 ret i8 %v
45 }
46
47 declare i8* @llvm.launder.invariant.group.p0i8(i8*)