Skip to content

Commit 36f0838

Browse files
committed
[FunctionAttrs] Consider non-willreturn functions during capture inference
Matching the CaptureTracking change in abd97d9, only directly infer captures(none) for readonly+nocapture+willreturn+void. Part of #129090.
1 parent 76910f9 commit 36f0838

File tree

3 files changed

+55
-20
lines changed

3 files changed

+55
-20
lines changed

llvm/lib/Transforms/IPO/FunctionAttrs.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1249,7 +1249,7 @@ static void addArgumentAttrs(const SCCNodeSet &SCCNodes,
12491249

12501250
// Functions that are readonly (or readnone) and nounwind and don't return
12511251
// a value can't capture arguments. Don't analyze them.
1252-
if (F->onlyReadsMemory() && F->doesNotThrow() &&
1252+
if (F->onlyReadsMemory() && F->doesNotThrow() && F->willReturn() &&
12531253
F->getReturnType()->isVoidTy()) {
12541254
for (Argument &A : F->args()) {
12551255
if (A.getType()->isPointerTy() && !A.hasNoCaptureAttr()) {

llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
; code path which isn't ever executed.
1111

1212
; CHECK: define void @test0_yes(ptr captures(none) %p) #0 {
13-
define void @test0_yes(ptr %p) nounwind {
13+
define void @test0_yes(ptr %p) nounwind willreturn {
1414
store i32 0, ptr %p, !tbaa !1
1515
ret void
1616
}
1717

1818
; CHECK: define void @test0_no(ptr writeonly captures(none) initializes((0, 4)) %p) #1 {
19-
define void @test0_no(ptr %p) nounwind {
19+
define void @test0_no(ptr %p) nounwind willreturn {
2020
store i32 0, ptr %p, !tbaa !2
2121
ret void
2222
}
@@ -25,13 +25,13 @@ define void @test0_no(ptr %p) nounwind {
2525
; TBAA says only accesses constant memory.
2626

2727
; CHECK: define void @test1_yes(ptr captures(none) %p) #2 {
28-
define void @test1_yes(ptr %p) nounwind {
28+
define void @test1_yes(ptr %p) nounwind willreturn {
2929
call void @callee(ptr %p), !tbaa !1
3030
ret void
3131
}
3232

3333
; CHECK: define void @test1_no(ptr %p) #3 {
34-
define void @test1_no(ptr %p) nounwind {
34+
define void @test1_no(ptr %p) nounwind willreturn {
3535
call void @callee(ptr %p), !tbaa !2
3636
ret void
3737
}
@@ -44,40 +44,41 @@ define void @test1_no(ptr %p) nounwind {
4444
; isn't necessarily invalid.
4545

4646
; CHECK: define void @test2_yes(ptr captures(none) %p, ptr captures(none) %q, i64 %n) #0 {
47-
define void @test2_yes(ptr %p, ptr %q, i64 %n) nounwind {
47+
define void @test2_yes(ptr %p, ptr %q, i64 %n) nounwind willreturn {
4848
call void @llvm.memcpy.p0.p0.i64(ptr %p, ptr %q, i64 %n, i1 false), !tbaa !1
4949
ret void
5050
}
5151

5252
; CHECK: define void @test2_no(ptr writeonly captures(none) %p, ptr readonly captures(none) %q, i64 %n) #4 {
53-
define void @test2_no(ptr %p, ptr %q, i64 %n) nounwind {
53+
define void @test2_no(ptr %p, ptr %q, i64 %n) nounwind willreturn {
5454
call void @llvm.memcpy.p0.p0.i64(ptr %p, ptr %q, i64 %n, i1 false), !tbaa !2
5555
ret void
5656
}
5757

5858
; Similar to the others, va_arg only accesses memory through its operand.
5959

6060
; CHECK: define i32 @test3_yes(ptr captures(none) %p) #0 {
61-
define i32 @test3_yes(ptr %p) nounwind {
61+
define i32 @test3_yes(ptr %p) nounwind willreturn {
6262
%t = va_arg ptr %p, i32, !tbaa !1
6363
ret i32 %t
6464
}
6565

6666
; CHECK: define i32 @test3_no(ptr captures(none) %p) #4 {
67-
define i32 @test3_no(ptr %p) nounwind {
67+
define i32 @test3_no(ptr %p) nounwind willreturn {
6868
%t = va_arg ptr %p, i32, !tbaa !2
6969
ret i32 %t
7070
}
7171

72-
declare void @callee(ptr %p) nounwind
73-
declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1) nounwind
72+
declare void @callee(ptr %p) nounwind willreturn
73+
declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1) nounwind willreturn
7474

7575
; CHECK: attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
7676
; CHECK: attributes #1 = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
77-
; CHECK: attributes #2 = { nofree nosync nounwind memory(none) }
78-
; CHECK: attributes #3 = { nounwind }
77+
; CHECK: attributes #2 = { mustprogress nofree nosync nounwind willreturn memory(none) }
78+
; CHECK: attributes #3 = { mustprogress nounwind willreturn }
7979
; CHECK: attributes #4 = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) }
80-
; CHECK: attributes #5 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
80+
; CHECK: attributes #5 = { nounwind willreturn }
81+
; CHECK: attributes #6 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
8182

8283
; Root note.
8384
!0 = !{ }

llvm/test/Transforms/FunctionAttrs/nocapture.ll

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -361,15 +361,15 @@ define void @nc3(ptr %p) {
361361
}
362362

363363
declare void @external_not_willreturn(ptr) readonly nounwind
364-
define void @readononly_nounwind_not_willreturn(ptr %p) {
364+
define void @readonly_nounwind_not_willreturn(ptr %p) {
365365
; FNATTRS: Function Attrs: nofree nounwind memory(read)
366-
; FNATTRS-LABEL: define void @readononly_nounwind_not_willreturn
366+
; FNATTRS-LABEL: define void @readonly_nounwind_not_willreturn
367367
; FNATTRS-SAME: (ptr readonly [[P:%.*]]) #[[ATTR9:[0-9]+]] {
368368
; FNATTRS-NEXT: call void @external_not_willreturn(ptr [[P]])
369369
; FNATTRS-NEXT: ret void
370370
;
371371
; ATTRIBUTOR: Function Attrs: nosync nounwind memory(read)
372-
; ATTRIBUTOR-LABEL: define void @readononly_nounwind_not_willreturn
372+
; ATTRIBUTOR-LABEL: define void @readonly_nounwind_not_willreturn
373373
; ATTRIBUTOR-SAME: (ptr readonly captures(none) [[P:%.*]]) #[[ATTR7:[0-9]+]] {
374374
; ATTRIBUTOR-NEXT: call void @external_not_willreturn(ptr readonly captures(none) [[P]]) #[[ATTR4]]
375375
; ATTRIBUTOR-NEXT: ret void
@@ -379,15 +379,15 @@ define void @readononly_nounwind_not_willreturn(ptr %p) {
379379
}
380380

381381
declare void @external_willreturn(ptr) readonly nounwind willreturn
382-
define void @readononly_nounwind_willreturn(ptr %p) {
382+
define void @readonly_nounwind_willreturn(ptr %p) {
383383
; FNATTRS: Function Attrs: mustprogress nofree nounwind willreturn memory(read)
384-
; FNATTRS-LABEL: define void @readononly_nounwind_willreturn
384+
; FNATTRS-LABEL: define void @readonly_nounwind_willreturn
385385
; FNATTRS-SAME: (ptr readonly captures(none) [[P:%.*]]) #[[ATTR11:[0-9]+]] {
386386
; FNATTRS-NEXT: call void @external_willreturn(ptr [[P]])
387387
; FNATTRS-NEXT: ret void
388388
;
389389
; ATTRIBUTOR: Function Attrs: mustprogress nosync nounwind willreturn memory(read)
390-
; ATTRIBUTOR-LABEL: define void @readononly_nounwind_willreturn
390+
; ATTRIBUTOR-LABEL: define void @readonly_nounwind_willreturn
391391
; ATTRIBUTOR-SAME: (ptr readonly captures(none) [[P:%.*]]) #[[ATTR9:[0-9]+]] {
392392
; ATTRIBUTOR-NEXT: call void @external_willreturn(ptr readonly captures(none) [[P]]) #[[ATTR21:[0-9]+]]
393393
; ATTRIBUTOR-NEXT: ret void
@@ -432,6 +432,40 @@ define void @callsite_readonly_nounwind_willreturn(ptr %f, ptr %p) {
432432
ret void
433433
}
434434

435+
define void @self_readonly_nounwind_not_willreturn(ptr %p) readonly nounwind {
436+
; FNATTRS: Function Attrs: nofree nounwind memory(read)
437+
; FNATTRS-LABEL: define void @self_readonly_nounwind_not_willreturn
438+
; FNATTRS-SAME: (ptr [[P:%.*]]) #[[ATTR9]] {
439+
; FNATTRS-NEXT: call void @capture(ptr [[P]])
440+
; FNATTRS-NEXT: ret void
441+
;
442+
; ATTRIBUTOR: Function Attrs: nosync nounwind memory(read)
443+
; ATTRIBUTOR-LABEL: define void @self_readonly_nounwind_not_willreturn
444+
; ATTRIBUTOR-SAME: (ptr captures(none) [[P:%.*]]) #[[ATTR7]] {
445+
; ATTRIBUTOR-NEXT: call void @capture(ptr [[P]])
446+
; ATTRIBUTOR-NEXT: ret void
447+
;
448+
call void @capture(ptr %p)
449+
ret void
450+
}
451+
452+
define void @self_readonly_nounwind_willreturn(ptr %p) readonly nounwind willreturn {
453+
; FNATTRS: Function Attrs: mustprogress nofree nounwind willreturn memory(read)
454+
; FNATTRS-LABEL: define void @self_readonly_nounwind_willreturn
455+
; FNATTRS-SAME: (ptr captures(none) [[P:%.*]]) #[[ATTR11]] {
456+
; FNATTRS-NEXT: call void @capture(ptr [[P]])
457+
; FNATTRS-NEXT: ret void
458+
;
459+
; ATTRIBUTOR: Function Attrs: mustprogress nosync nounwind willreturn memory(read)
460+
; ATTRIBUTOR-LABEL: define void @self_readonly_nounwind_willreturn
461+
; ATTRIBUTOR-SAME: (ptr captures(none) [[P:%.*]]) #[[ATTR9]] {
462+
; ATTRIBUTOR-NEXT: call void @capture(ptr [[P]])
463+
; ATTRIBUTOR-NEXT: ret void
464+
;
465+
call void @capture(ptr %p)
466+
ret void
467+
}
468+
435469
; It would be acceptable to add readnone to %y1_1 and %y1_2.
436470
define void @test1_1(ptr %x1_1, ptr %y1_1, i1 %c) {
437471
; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, inaccessiblemem: none)

0 commit comments

Comments
 (0)