Skip to content

Commit 668c5c6

Browse files
committed
[Attributor][FIX] Use liveness information of the right function
When we use liveness for edges during the `genericValueTraversal` we need to make sure to use the AAIsDead of the correct function. This patch adds the proper logic and some simple caching scheme. We also add an assertion to the `isEdgeDead` call to make sure future misuse is detected earlier. Fixes #53872
1 parent 48a31c8 commit 668c5c6

File tree

6 files changed

+121
-73
lines changed

6 files changed

+121
-73
lines changed

llvm/lib/Transforms/IPO/AttributorAttributes.cpp

+27-16
Original file line numberDiff line numberDiff line change
@@ -265,13 +265,18 @@ static bool genericValueTraversal(
265265
function_ref<Value *(Value *)> StripCB = nullptr,
266266
bool Intraprocedural = false) {
267267

268-
const AAIsDead *LivenessAA = nullptr;
269-
if (IRP.getAnchorScope())
270-
LivenessAA = &A.getAAFor<AAIsDead>(
271-
QueryingAA,
272-
IRPosition::function(*IRP.getAnchorScope(), IRP.getCallBaseContext()),
273-
DepClassTy::NONE);
274-
bool AnyDead = false;
268+
struct LivenessInfo {
269+
const AAIsDead *LivenessAA = nullptr;
270+
bool AnyDead = false;
271+
};
272+
DenseMap<const Function *, LivenessInfo> LivenessAAs;
273+
auto GetLivenessInfo = [&](const Function &F) -> LivenessInfo & {
274+
LivenessInfo &LI = LivenessAAs[&F];
275+
if (!LI.LivenessAA)
276+
LI.LivenessAA = &A.getAAFor<AAIsDead>(QueryingAA, IRPosition::function(F),
277+
DepClassTy::NONE);
278+
return LI;
279+
};
275280

276281
Value *InitialV = &IRP.getAssociatedValue();
277282
using Item = std::pair<Value *, const Instruction *>;
@@ -341,13 +346,12 @@ static bool genericValueTraversal(
341346

342347
// Look through phi nodes, visit all live operands.
343348
if (auto *PHI = dyn_cast<PHINode>(V)) {
344-
assert(LivenessAA &&
345-
"Expected liveness in the presence of instructions!");
349+
LivenessInfo &LI = GetLivenessInfo(*PHI->getFunction());
346350
for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) {
347351
BasicBlock *IncomingBB = PHI->getIncomingBlock(u);
348-
if (LivenessAA->isEdgeDead(IncomingBB, PHI->getParent())) {
349-
AnyDead = true;
350-
UsedAssumedInformation |= !LivenessAA->isAtFixpoint();
352+
if (LI.LivenessAA->isEdgeDead(IncomingBB, PHI->getParent())) {
353+
LI.AnyDead = true;
354+
UsedAssumedInformation |= !LI.LivenessAA->isAtFixpoint();
351355
continue;
352356
}
353357
Worklist.push_back(
@@ -401,8 +405,10 @@ static bool genericValueTraversal(
401405
} while (!Worklist.empty());
402406

403407
// If we actually used liveness information so we have to record a dependence.
404-
if (AnyDead)
405-
A.recordDependence(*LivenessAA, QueryingAA, DepClassTy::OPTIONAL);
408+
for (auto &It : LivenessAAs)
409+
if (It.second.AnyDead)
410+
A.recordDependence(*It.second.LivenessAA, QueryingAA,
411+
DepClassTy::OPTIONAL);
406412

407413
// All values have been visited.
408414
return true;
@@ -1230,11 +1236,13 @@ struct AAPointerInfoImpl
12301236
// Run the user callback on all writes we cannot skip and return if that
12311237
// succeeded for all or not.
12321238
unsigned NumInterferingWrites = InterferingWrites.size();
1233-
for (auto &It : InterferingWrites)
1239+
for (auto &It : InterferingWrites) {
12341240
if (!DT || NumInterferingWrites > MaxInterferingWrites ||
1235-
!CanSkipAccess(*It.first, It.second))
1241+
!CanSkipAccess(*It.first, It.second)) {
12361242
if (!UserCB(*It.first, It.second))
12371243
return false;
1244+
}
1245+
}
12381246
return true;
12391247
}
12401248

@@ -3821,6 +3829,9 @@ struct AAIsDeadFunction : public AAIsDead {
38213829
ChangeStatus updateImpl(Attributor &A) override;
38223830

38233831
bool isEdgeDead(const BasicBlock *From, const BasicBlock *To) const override {
3832+
assert(From->getParent() == getAnchorScope() &&
3833+
To->getParent() == getAnchorScope() &&
3834+
"Used AAIsDead of the wrong function");
38243835
return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
38253836
}
38263837

llvm/test/Transforms/Attributor/IPConstantProp/return-constant.ll

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2-
; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3-
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
2+
; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3+
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
44
; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
55
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
66

llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2-
; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=8 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3-
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=8 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
2+
; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3+
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
44
; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
55
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
66

llvm/test/Transforms/Attributor/align.ll

+61-45
Original file line numberDiff line numberDiff line change
@@ -171,24 +171,30 @@ define internal i8* @f2(i8* readnone %0) local_unnamed_addr #0 {
171171
; IS__CGSCC_OPM: Function Attrs: noinline nounwind uwtable
172172
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f2
173173
; IS__CGSCC_OPM-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
174-
; IS__CGSCC_OPM-NEXT: unreachable
175-
; IS__CGSCC_OPM: 2:
176-
; IS__CGSCC_OPM-NEXT: unreachable
174+
; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
175+
; IS__CGSCC_OPM-NEXT: br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]]
177176
; IS__CGSCC_OPM: 3:
178-
; IS__CGSCC_OPM-NEXT: unreachable
177+
; IS__CGSCC_OPM-NEXT: br label [[TMP6:%.*]]
179178
; IS__CGSCC_OPM: 4:
180-
; IS__CGSCC_OPM-NEXT: unreachable
179+
; IS__CGSCC_OPM-NEXT: [[TMP5:%.*]] = tail call i8* @f3(i8* nonnull @a2)
180+
; IS__CGSCC_OPM-NEXT: br label [[TMP6]]
181+
; IS__CGSCC_OPM: 6:
182+
; IS__CGSCC_OPM-NEXT: [[TMP7:%.*]] = phi i8* [ undef, [[TMP3]] ], [ [[TMP5]], [[TMP4]] ]
183+
; IS__CGSCC_OPM-NEXT: ret i8* [[TMP7]]
181184
;
182-
; IS__CGSCC_NPM: Function Attrs: noinline nounwind uwtable
185+
; IS__CGSCC_NPM: Function Attrs: noinline norecurse nounwind uwtable
183186
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f2
184187
; IS__CGSCC_NPM-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
185-
; IS__CGSCC_NPM-NEXT: unreachable
186-
; IS__CGSCC_NPM: 2:
187-
; IS__CGSCC_NPM-NEXT: unreachable
188+
; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
189+
; IS__CGSCC_NPM-NEXT: br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]]
188190
; IS__CGSCC_NPM: 3:
189-
; IS__CGSCC_NPM-NEXT: unreachable
191+
; IS__CGSCC_NPM-NEXT: br label [[TMP6:%.*]]
190192
; IS__CGSCC_NPM: 4:
191-
; IS__CGSCC_NPM-NEXT: unreachable
193+
; IS__CGSCC_NPM-NEXT: [[TMP5:%.*]] = tail call i8* @f3()
194+
; IS__CGSCC_NPM-NEXT: br label [[TMP6]]
195+
; IS__CGSCC_NPM: 6:
196+
; IS__CGSCC_NPM-NEXT: [[TMP7:%.*]] = phi i8* [ undef, [[TMP3]] ], [ @a1, [[TMP4]] ]
197+
; IS__CGSCC_NPM-NEXT: ret i8* [[TMP7]]
192198
;
193199
%2 = icmp eq i8* %0, null
194200
br i1 %2, label %5, label %3
@@ -211,21 +217,23 @@ define internal i8* @f2(i8* readnone %0) local_unnamed_addr #0 {
211217
define internal i8* @f3(i8* readnone %0) local_unnamed_addr #0 {
212218
; IS__CGSCC_OPM: Function Attrs: noinline nounwind uwtable
213219
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f3
214-
; IS__CGSCC_OPM-SAME: (i8* nonnull readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2]] {
215-
; IS__CGSCC_OPM-NEXT: br label [[TMP3:%.*]]
216-
; IS__CGSCC_OPM: 2:
217-
; IS__CGSCC_OPM-NEXT: unreachable
220+
; IS__CGSCC_OPM-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2]] {
221+
; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
222+
; IS__CGSCC_OPM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP4:%.*]]
218223
; IS__CGSCC_OPM: 3:
219-
; IS__CGSCC_OPM-NEXT: ret i8* @a1
224+
; IS__CGSCC_OPM-NEXT: br label [[TMP4]]
225+
; IS__CGSCC_OPM: 4:
226+
; IS__CGSCC_OPM-NEXT: [[TMP5:%.*]] = phi i8* [ @a2, [[TMP3]] ], [ @a1, [[TMP1:%.*]] ]
227+
; IS__CGSCC_OPM-NEXT: ret i8* [[TMP5]]
220228
;
221-
; IS__CGSCC_NPM: Function Attrs: noinline nounwind uwtable
229+
; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable
222230
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f3
223-
; IS__CGSCC_NPM-SAME: (i8* nonnull readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] {
224-
; IS__CGSCC_NPM-NEXT: br label [[TMP3:%.*]]
225-
; IS__CGSCC_NPM: 2:
231+
; IS__CGSCC_NPM-SAME: () local_unnamed_addr #[[ATTR0]] {
232+
; IS__CGSCC_NPM-NEXT: br label [[TMP2:%.*]]
233+
; IS__CGSCC_NPM: 1:
226234
; IS__CGSCC_NPM-NEXT: unreachable
227-
; IS__CGSCC_NPM: 3:
228-
; IS__CGSCC_NPM-NEXT: ret i8* @a1
235+
; IS__CGSCC_NPM: 2:
236+
; IS__CGSCC_NPM-NEXT: ret i8* undef
229237
;
230238
%2 = icmp eq i8* %0, null
231239
br i1 %2, label %3, label %5
@@ -292,24 +300,30 @@ define internal i8* @f2b(i8* readnone %0) local_unnamed_addr #0 {
292300
; IS__CGSCC_OPM: Function Attrs: noinline nounwind uwtable
293301
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f2b
294302
; IS__CGSCC_OPM-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2]] {
295-
; IS__CGSCC_OPM-NEXT: unreachable
296-
; IS__CGSCC_OPM: 2:
297-
; IS__CGSCC_OPM-NEXT: unreachable
303+
; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
304+
; IS__CGSCC_OPM-NEXT: br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]]
298305
; IS__CGSCC_OPM: 3:
299-
; IS__CGSCC_OPM-NEXT: unreachable
306+
; IS__CGSCC_OPM-NEXT: br label [[TMP6:%.*]]
300307
; IS__CGSCC_OPM: 4:
301-
; IS__CGSCC_OPM-NEXT: unreachable
308+
; IS__CGSCC_OPM-NEXT: [[TMP5:%.*]] = tail call i8* @f3b(i8* nonnull @a2)
309+
; IS__CGSCC_OPM-NEXT: br label [[TMP6]]
310+
; IS__CGSCC_OPM: 6:
311+
; IS__CGSCC_OPM-NEXT: [[TMP7:%.*]] = phi i8* [ undef, [[TMP3]] ], [ [[TMP5]], [[TMP4]] ]
312+
; IS__CGSCC_OPM-NEXT: ret i8* [[TMP7]]
302313
;
303-
; IS__CGSCC_NPM: Function Attrs: noinline nounwind uwtable
314+
; IS__CGSCC_NPM: Function Attrs: noinline norecurse nounwind uwtable
304315
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f2b
305316
; IS__CGSCC_NPM-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] {
306-
; IS__CGSCC_NPM-NEXT: unreachable
307-
; IS__CGSCC_NPM: 2:
308-
; IS__CGSCC_NPM-NEXT: unreachable
317+
; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
318+
; IS__CGSCC_NPM-NEXT: br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]]
309319
; IS__CGSCC_NPM: 3:
310-
; IS__CGSCC_NPM-NEXT: unreachable
320+
; IS__CGSCC_NPM-NEXT: br label [[TMP6:%.*]]
311321
; IS__CGSCC_NPM: 4:
312-
; IS__CGSCC_NPM-NEXT: unreachable
322+
; IS__CGSCC_NPM-NEXT: [[TMP5:%.*]] = tail call i8* @f3b()
323+
; IS__CGSCC_NPM-NEXT: br label [[TMP6]]
324+
; IS__CGSCC_NPM: 6:
325+
; IS__CGSCC_NPM-NEXT: [[TMP7:%.*]] = phi i8* [ undef, [[TMP3]] ], [ @a1, [[TMP4]] ]
326+
; IS__CGSCC_NPM-NEXT: ret i8* [[TMP7]]
313327
;
314328
%2 = icmp eq i8* %0, null
315329
br i1 %2, label %5, label %3
@@ -333,21 +347,23 @@ define internal i8* @f3b(i8* readnone %0) local_unnamed_addr #0 {
333347
;
334348
; IS__CGSCC_OPM: Function Attrs: noinline nounwind uwtable
335349
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f3b
336-
; IS__CGSCC_OPM-SAME: (i8* nonnull readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2]] {
337-
; IS__CGSCC_OPM-NEXT: br label [[TMP3:%.*]]
338-
; IS__CGSCC_OPM: 2:
339-
; IS__CGSCC_OPM-NEXT: unreachable
350+
; IS__CGSCC_OPM-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2]] {
351+
; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
352+
; IS__CGSCC_OPM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP4:%.*]]
340353
; IS__CGSCC_OPM: 3:
341-
; IS__CGSCC_OPM-NEXT: ret i8* @a1
354+
; IS__CGSCC_OPM-NEXT: br label [[TMP4]]
355+
; IS__CGSCC_OPM: 4:
356+
; IS__CGSCC_OPM-NEXT: [[TMP5:%.*]] = phi i8* [ @a2, [[TMP3]] ], [ @a1, [[TMP1:%.*]] ]
357+
; IS__CGSCC_OPM-NEXT: ret i8* [[TMP5]]
342358
;
343-
; IS__CGSCC_NPM: Function Attrs: noinline nounwind uwtable
359+
; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable
344360
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f3b
345-
; IS__CGSCC_NPM-SAME: (i8* nonnull readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] {
346-
; IS__CGSCC_NPM-NEXT: br label [[TMP3:%.*]]
347-
; IS__CGSCC_NPM: 2:
361+
; IS__CGSCC_NPM-SAME: () local_unnamed_addr #[[ATTR0]] {
362+
; IS__CGSCC_NPM-NEXT: br label [[TMP2:%.*]]
363+
; IS__CGSCC_NPM: 1:
348364
; IS__CGSCC_NPM-NEXT: unreachable
349-
; IS__CGSCC_NPM: 3:
350-
; IS__CGSCC_NPM-NEXT: ret i8* @a1
365+
; IS__CGSCC_NPM: 2:
366+
; IS__CGSCC_NPM-NEXT: ret i8* undef
351367
;
352368
%2 = icmp eq i8* %0, null
353369
br i1 %2, label %3, label %5
@@ -1131,7 +1147,7 @@ attributes #2 = { null_pointer_is_valid }
11311147
; IS__CGSCC_OPM: attributes #[[ATTR12]] = { readonly willreturn }
11321148
;.
11331149
; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone willreturn uwtable }
1134-
; IS__CGSCC_NPM: attributes #[[ATTR1]] = { noinline nounwind uwtable }
1150+
; IS__CGSCC_NPM: attributes #[[ATTR1]] = { noinline norecurse nounwind uwtable }
11351151
; IS__CGSCC_NPM: attributes #[[ATTR2]] = { nounwind }
11361152
; IS__CGSCC_NPM: attributes #[[ATTR3]] = { nofree nosync nounwind }
11371153
; IS__CGSCC_NPM: attributes #[[ATTR4]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn }

0 commit comments

Comments
 (0)