Skip to content

Commit

Permalink
[ValueTracking] Don't assume readonly function will return
Browse files Browse the repository at this point in the history
This is similar to D94106, but for the
isGuaranteedToTransferExecutionToSuccessor() helper. We should not
assume that readonly functions will return, as this is only true for
mustprogress functions (in which case we already infer willreturn).
As with the DCE change, for now continue assuming that readonly
intrinsics will return, as not all target intrinsics have been
annotated yet.

Differential Revision: https://reviews.llvm.org/D95288
  • Loading branch information
nikic committed Jan 24, 2021
1 parent c50457f commit 5d12b97
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 85 deletions.
21 changes: 4 additions & 17 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5040,23 +5040,10 @@ bool llvm::isGuaranteedToTransferExecutionToSuccessor(const Instruction *I) {
if (CB->hasFnAttr(Attribute::WillReturn))
return true;

// Non-throwing call sites can loop infinitely, call exit/pthread_exit
// etc. and thus not return. However, LLVM already assumes that
//
// - Thread exiting actions are modeled as writes to memory invisible to
// the program.
//
// - Loops that don't have side effects (side effects are volatile/atomic
// stores and IO) always terminate (see http://llvm.org/PR965).
// Furthermore IO itself is also modeled as writes to memory invisible to
// the program.
//
// We rely on those assumptions here, and use the memory effects of the call
// target as a proxy for checking that it always returns.

// FIXME: This isn't aggressive enough; a call which only writes to a global
// is guaranteed to return.
return CB->onlyReadsMemory() || CB->onlyAccessesArgMemory();
// FIXME: Temporarily assume that all side-effect free intrinsics will
// return. Remove this workaround once all intrinsics are appropriately
// annotated.
return isa<IntrinsicInst>(CB) && CB->onlyReadsMemory();
}

// Other instructions return normally.
Expand Down
40 changes: 19 additions & 21 deletions llvm/test/Transforms/Attributor/nocapture-1.ll
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ define void @c3(i32* %q) {
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly
; IS__CGSCC____-LABEL: define {{[^@]+}}@c3
; IS__CGSCC____-SAME: (i32* nofree writeonly [[Q:%.*]]) [[ATTR1]] {
; IS__CGSCC____-NEXT: call void @c2(i32* nofree writeonly [[Q]]) [[ATTR16:#.*]]
; IS__CGSCC____-NEXT: call void @c2(i32* nofree writeonly [[Q]]) [[ATTR17:#.*]]
; IS__CGSCC____-NEXT: ret void
;
call void @c2(i32* %q)
Expand Down Expand Up @@ -215,14 +215,14 @@ define i1 @c7(i32* %q, i32 %bitno) {
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@c7
; IS__TUNIT____-SAME: (i32* nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) [[ATTR2]] {
; IS__TUNIT____-NEXT: [[PTR:%.*]] = call i1* @lookup_bit(i32* noalias nofree readnone [[Q]], i32 [[BITNO]]) [[ATTR14:#.*]]
; IS__TUNIT____-NEXT: [[PTR:%.*]] = call i1* @lookup_bit(i32* noalias nofree readnone [[Q]], i32 [[BITNO]]) [[ATTR15:#.*]]
; IS__TUNIT____-NEXT: [[VAL:%.*]] = load i1, i1* [[PTR]], align 1
; IS__TUNIT____-NEXT: ret i1 [[VAL]]
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@c7
; IS__CGSCC____-SAME: (i32* nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) [[ATTR2]] {
; IS__CGSCC____-NEXT: [[PTR:%.*]] = call i1* @lookup_bit(i32* noalias nofree readnone [[Q]], i32 [[BITNO]]) [[ATTR17:#.*]]
; IS__CGSCC____-NEXT: [[PTR:%.*]] = call i1* @lookup_bit(i32* noalias nofree readnone [[Q]], i32 [[BITNO]]) [[ATTR18:#.*]]
; IS__CGSCC____-NEXT: [[VAL:%.*]] = load i1, i1* [[PTR]], align 1
; IS__CGSCC____-NEXT: ret i1 [[VAL]]
;
Expand Down Expand Up @@ -330,7 +330,7 @@ define void @nc2(i32* %p, i32* %q) {
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@nc2
; IS__CGSCC____-SAME: (i32* nocapture nofree [[P:%.*]], i32* nofree [[Q:%.*]]) [[ATTR5]] {
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @nc1(i32* nofree [[Q]], i32* nocapture nofree [[P]], i1 noundef false) [[ATTR18:#.*]]
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @nc1(i32* nofree [[Q]], i32* nocapture nofree [[P]], i1 noundef false) [[ATTR14:#.*]]
; IS__CGSCC____-NEXT: ret void
;
%1 = call i32 @nc1(i32* %q, i32* %p, i1 0) ; <i32> [#uses=0]
Expand All @@ -355,13 +355,13 @@ define void @nc4(i8* %p) {
; IS__TUNIT____: Function Attrs: argmemonly nounwind
; IS__TUNIT____-LABEL: define {{[^@]+}}@nc4
; IS__TUNIT____-SAME: (i8* [[P:%.*]]) [[ATTR6:#.*]] {
; IS__TUNIT____-NEXT: call void @external(i8* readonly [[P]]) [[ATTR11:#.*]]
; IS__TUNIT____-NEXT: call void @external(i8* readonly [[P]]) [[ATTR16:#.*]]
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____: Function Attrs: argmemonly nounwind
; IS__CGSCC____-LABEL: define {{[^@]+}}@nc4
; IS__CGSCC____-SAME: (i8* [[P:%.*]]) [[ATTR6:#.*]] {
; IS__CGSCC____-NEXT: call void @external(i8* readonly [[P]]) [[ATTR13:#.*]]
; IS__CGSCC____-NEXT: call void @external(i8* readonly [[P]]) [[ATTR19:#.*]]
; IS__CGSCC____-NEXT: ret void
;
call void @external(i8* %p)
Expand Down Expand Up @@ -609,15 +609,15 @@ define void @nocaptureLaunder(i8* %p) {
; IS__TUNIT____-LABEL: define {{[^@]+}}@nocaptureLaunder
; IS__TUNIT____-SAME: (i8* nocapture nofree [[P:%.*]]) [[ATTR5]] {
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) [[ATTR15:#.*]]
; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) [[ATTR17:#.*]]
; IS__TUNIT____-NEXT: store i8 42, i8* [[B]], align 1
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@nocaptureLaunder
; IS__CGSCC____-SAME: (i8* nocapture nofree [[P:%.*]]) [[ATTR10:#.*]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) [[ATTR17]]
; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) [[ATTR18]]
; IS__CGSCC____-NEXT: store i8 42, i8* [[B]], align 1
; IS__CGSCC____-NEXT: ret void
;
Expand All @@ -632,14 +632,14 @@ define void @captureLaunder(i8* %p) {
; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@captureLaunder
; IS__TUNIT____-SAME: (i8* nofree [[P:%.*]]) [[ATTR5]] {
; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) [[ATTR15]]
; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) [[ATTR17]]
; IS__TUNIT____-NEXT: store i8* [[B]], i8** @g2, align 8
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@captureLaunder
; IS__CGSCC____-SAME: (i8* nofree [[P:%.*]]) [[ATTR10]] {
; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) [[ATTR17]]
; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) [[ATTR18]]
; IS__CGSCC____-NEXT: store i8* [[B]], i8** @g2, align 8
; IS__CGSCC____-NEXT: ret void
;
Expand All @@ -653,15 +653,15 @@ define void @nocaptureStrip(i8* %p) {
; IS__TUNIT____-LABEL: define {{[^@]+}}@nocaptureStrip
; IS__TUNIT____-SAME: (i8* nocapture nofree writeonly [[P:%.*]]) [[ATTR1]] {
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) [[ATTR15]]
; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) [[ATTR17]]
; IS__TUNIT____-NEXT: store i8 42, i8* [[B]], align 1
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn writeonly
; IS__CGSCC____-LABEL: define {{[^@]+}}@nocaptureStrip
; IS__CGSCC____-SAME: (i8* nocapture nofree writeonly [[P:%.*]]) [[ATTR11:#.*]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) [[ATTR17]]
; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) [[ATTR18]]
; IS__CGSCC____-NEXT: store i8 42, i8* [[B]], align 1
; IS__CGSCC____-NEXT: ret void
;
Expand All @@ -676,14 +676,14 @@ define void @captureStrip(i8* %p) {
; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly
; IS__TUNIT____-LABEL: define {{[^@]+}}@captureStrip
; IS__TUNIT____-SAME: (i8* nofree writeonly [[P:%.*]]) [[ATTR1]] {
; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) [[ATTR15]]
; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) [[ATTR17]]
; IS__TUNIT____-NEXT: store i8* [[B]], i8** @g3, align 8
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn writeonly
; IS__CGSCC____-LABEL: define {{[^@]+}}@captureStrip
; IS__CGSCC____-SAME: (i8* nofree writeonly [[P:%.*]]) [[ATTR11]] {
; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) [[ATTR17]]
; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) [[ATTR18]]
; IS__CGSCC____-NEXT: store i8* [[B]], i8** @g3, align 8
; IS__CGSCC____-NEXT: ret void
;
Expand Down Expand Up @@ -840,17 +840,15 @@ entry:
ret i8* %p
}

declare i8* @maybe_returned_ptr(i8* readonly %ptr) readonly nounwind
declare i8 @maybe_returned_val(i8* %ptr) readonly nounwind
declare void @val_use(i8 %ptr) readonly nounwind
declare i8* @maybe_returned_ptr(i8* readonly %ptr) readonly nounwind willreturn
declare i8 @maybe_returned_val(i8* %ptr) readonly nounwind willreturn
declare void @val_use(i8 %ptr) readonly nounwind willreturn

; FIXME: Both pointers should be nocapture
define void @ptr_uses(i8* %ptr, i8* %wptr) {
; CHECK: Function Attrs: nounwind
; CHECK: Function Attrs: nounwind willreturn
; CHECK-LABEL: define {{[^@]+}}@ptr_uses
; CHECK-SAME: (i8* [[PTR:%.*]], i8* nocapture nonnull writeonly dereferenceable(1) [[WPTR:%.*]]) [[ATTR13:#.*]] {
; CHECK-NEXT: [[CALL_PTR:%.*]] = call i8* @maybe_returned_ptr(i8* readonly [[PTR]]) [[ATTR4]]
; CHECK-NEXT: [[CALL_VAL:%.*]] = call i8 @maybe_returned_val(i8* readonly [[CALL_PTR]]) [[ATTR4]]
; CHECK-SAME: (i8* [[PTR:%.*]], i8* nocapture nonnull writeonly dereferenceable(1) [[WPTR:%.*]]) [[ATTR14:#.*]] {
; CHECK-NEXT: store i8 0, i8* [[WPTR]], align 1
; CHECK-NEXT: ret void
;
Expand Down
38 changes: 13 additions & 25 deletions llvm/test/Transforms/Attributor/nonnull.ll
Original file line number Diff line number Diff line change
Expand Up @@ -146,34 +146,22 @@ define i8* @test3(i1 %c) {
; nonnull if neither can ever return null. (In this case, they
; just never return period.)
define i8* @test4_helper() {
; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone
; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test4_helper
; NOT_CGSCC_NPM-SAME: () [[ATTR2:#.*]] {
; NOT_CGSCC_NPM-NEXT: [[RET:%.*]] = call i8* @test4()
; NOT_CGSCC_NPM-NEXT: unreachable
;
; IS__CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test4_helper
; IS__CGSCC_NPM-SAME: () [[ATTR2:#.*]] {
; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = call i8* @test4()
; IS__CGSCC_NPM-NEXT: unreachable
; CHECK: Function Attrs: nofree noreturn nosync nounwind readnone
; CHECK-LABEL: define {{[^@]+}}@test4_helper
; CHECK-SAME: () [[ATTR2:#.*]] {
; CHECK-NEXT: [[RET:%.*]] = call i8* @test4() [[ATTR2]]
; CHECK-NEXT: unreachable
;
%ret = call i8* @test4()
ret i8* %ret
}

define i8* @test4() {
; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone
; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test4
; NOT_CGSCC_NPM-SAME: () [[ATTR2]] {
; NOT_CGSCC_NPM-NEXT: [[RET:%.*]] = call i8* @test4_helper()
; NOT_CGSCC_NPM-NEXT: unreachable
;
; IS__CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test4
; IS__CGSCC_NPM-SAME: () [[ATTR2]] {
; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = call i8* @test4_helper()
; IS__CGSCC_NPM-NEXT: unreachable
; CHECK: Function Attrs: nofree noreturn nosync nounwind readnone
; CHECK-LABEL: define {{[^@]+}}@test4
; CHECK-SAME: () [[ATTR2]] {
; CHECK-NEXT: [[RET:%.*]] = call i8* @test4_helper() [[ATTR2]]
; CHECK-NEXT: unreachable
;
%ret = call i8* @test4_helper()
ret i8* %ret
Expand Down Expand Up @@ -802,7 +790,7 @@ declare void @use1nonnull(i8* nonnull %x);
declare void @use2nonnull(i8* nonnull %x, i8* nonnull %y);
declare void @use3nonnull(i8* nonnull %x, i8* nonnull %y, i8* nonnull %z);

declare i8 @use1safecall(i8* %x) readonly nounwind ; readonly+nounwind guarantees that execution continues to successor
declare i8 @use1safecall(i8* %x) readonly nounwind willreturn ; nounwind+willreturn guarantees that execution continues to successor

; Can't extend non-null to parent for any argument because the 2nd call is not guaranteed to execute.

Expand Down Expand Up @@ -1524,7 +1512,7 @@ define i8* @mybasename(i8* nofree readonly %str) {
; NOT_CGSCC_OPM: Function Attrs: nofree nounwind readonly willreturn
; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@mybasename
; NOT_CGSCC_OPM-SAME: (i8* nofree readonly [[STR:%.*]]) [[ATTR11:#.*]] {
; NOT_CGSCC_OPM-NEXT: [[CALL:%.*]] = call i8* @strrchr(i8* nofree readonly [[STR]], i32 noundef 47) [[ATTR15:#.*]]
; NOT_CGSCC_OPM-NEXT: [[CALL:%.*]] = call i8* @strrchr(i8* nofree readonly [[STR]], i32 noundef 47) [[ATTR14]]
; NOT_CGSCC_OPM-NEXT: [[TOBOOL:%.*]] = icmp ne i8* [[CALL]], null
; NOT_CGSCC_OPM-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[CALL]], i64 1
; NOT_CGSCC_OPM-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i8* [[ADD_PTR]], i8* [[STR]]
Expand All @@ -1533,7 +1521,7 @@ define i8* @mybasename(i8* nofree readonly %str) {
; IS__CGSCC_OPM: Function Attrs: nofree nounwind readonly willreturn
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@mybasename
; IS__CGSCC_OPM-SAME: (i8* nofree readonly [[STR:%.*]]) [[ATTR12:#.*]] {
; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i8* @strrchr(i8* nofree readonly [[STR]], i32 noundef 47) [[ATTR16:#.*]]
; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i8* @strrchr(i8* nofree readonly [[STR]], i32 noundef 47) [[ATTR15]]
; IS__CGSCC_OPM-NEXT: [[TOBOOL:%.*]] = icmp ne i8* [[CALL]], null
; IS__CGSCC_OPM-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[CALL]], i64 1
; IS__CGSCC_OPM-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i8* [[ADD_PTR]], i8* [[STR]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ define i32* @external_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) {
;
; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind
; IS__CGSCC____-LABEL: define {{[^@]+}}@external_ret2_nrw
; IS__CGSCC____-SAME: (i32* nofree [[N0:%.*]], i32* nofree nonnull align 4 dereferenceable(4) [[R0:%.*]], i32* nofree returned [[W0:%.*]]) [[ATTR0:#.*]] {
; IS__CGSCC____-SAME: (i32* nofree [[N0:%.*]], i32* nofree [[R0:%.*]], i32* nofree returned [[W0:%.*]]) [[ATTR0:#.*]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @internal_ret0_nw(i32* nofree [[N0]], i32* nofree [[W0]]) [[ATTR2:#.*]]
; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32* @internal_ret1_rrw(i32* nofree nonnull align 4 dereferenceable(4) [[R0]], i32* nofree nonnull align 4 dereferenceable(4) [[R0]], i32* nofree [[W0]]) [[ATTR2]]
Expand Down Expand Up @@ -179,7 +179,7 @@ define internal i32* @internal_ret1_rrw(i32* %r0, i32* %r1, i32* %w0) {
; IS__CGSCC____: if.then:
; IS__CGSCC____-NEXT: br label [[RETURN:%.*]]
; IS__CGSCC____: if.end:
; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @internal_ret1_rw(i32* nofree nonnull align 4 dereferenceable(4) [[R0]], i32* nofree nonnull align 4 dereferenceable(4) [[W0]]) [[ATTR2]]
; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @internal_ret1_rw(i32* nofree nonnull align 4 dereferenceable(4) [[R0]], i32* nofree [[W0]]) [[ATTR2]]
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i32, i32* [[R0]], align 4
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = load i32, i32* [[R1]], align 4
; IS__CGSCC____-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP1]], [[TMP2]]
Expand Down Expand Up @@ -306,7 +306,7 @@ define internal i32* @internal_ret1_rw(i32* %r0, i32* %w0) {
; IS__CGSCC____: if.then:
; IS__CGSCC____-NEXT: br label [[RETURN:%.*]]
; IS__CGSCC____: if.end:
; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @internal_ret1_rrw(i32* nofree nonnull align 4 dereferenceable(4) [[R0]], i32* nofree nonnull align 4 dereferenceable(4) [[R0]], i32* nofree nonnull align 4 dereferenceable(4) [[W0]]) [[ATTR2]]
; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @internal_ret1_rrw(i32* nofree nonnull align 4 dereferenceable(4) [[R0]], i32* nofree nonnull align 4 dereferenceable(4) [[R0]], i32* nofree [[W0]]) [[ATTR2]]
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i32, i32* [[R0]], align 4
; IS__CGSCC____-NEXT: store i32 [[TMP1]], i32* [[W0]], align 4
; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32* @internal_ret0_nw(i32* nofree nonnull align 4 dereferenceable(4) [[R0]], i32* nofree nonnull align 4 dereferenceable(4) [[W0]]) [[ATTR2]]
Expand Down Expand Up @@ -352,10 +352,10 @@ define i32* @external_source_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) {
;
; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind
; IS__CGSCC____-LABEL: define {{[^@]+}}@external_source_ret2_nrw
; IS__CGSCC____-SAME: (i32* nofree [[N0:%.*]], i32* nofree align 4 [[R0:%.*]], i32* nofree returned [[W0:%.*]]) [[ATTR0]] {
; IS__CGSCC____-SAME: (i32* nofree [[N0:%.*]], i32* nofree [[R0:%.*]], i32* nofree returned [[W0:%.*]]) [[ATTR0]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @external_sink_ret2_nrw(i32* nofree [[N0]], i32* nocapture nofree readonly align 4 [[R0]], i32* nofree writeonly "no-capture-maybe-returned" [[W0]]) [[ATTR4:#.*]]
; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32* @external_ret2_nrw(i32* nofree [[N0]], i32* nofree align 4 [[R0]], i32* nofree [[W0]]) [[ATTR3]]
; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @external_sink_ret2_nrw(i32* nofree [[N0]], i32* nocapture nofree readonly [[R0]], i32* nofree writeonly "no-capture-maybe-returned" [[W0]]) [[ATTR4:#.*]]
; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32* @external_ret2_nrw(i32* nofree [[N0]], i32* nofree [[R0]], i32* nofree [[W0]]) [[ATTR3]]
; IS__CGSCC____-NEXT: ret i32* [[CALL1]]
;
entry:
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Transforms/FunctionAttrs/nonnull.ll
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ declare void @use1nonnull_without_noundef(i8* nonnull %x);
declare void @use2nonnull(i8* nonnull noundef %x, i8* nonnull noundef %y);
declare void @use3nonnull(i8* nonnull noundef %x, i8* nonnull noundef %y, i8* nonnull noundef %z);

declare i8 @use1safecall(i8* %x) readonly nounwind ; readonly+nounwind guarantees that execution continues to successor
declare i8 @use1safecall(i8* %x) nounwind willreturn ; nounwind+willreturn guarantees that execution continues to successor

; Without noundef, nonnull cannot be propagated to the parent

Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/GVNHoist/hoist-convergent.ll
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,5 @@ if.end:
declare float @convergent_func(float, float) #0
declare float @func(float, float) #1

attributes #0 = { nounwind readnone convergent }
attributes #1 = { nounwind readnone }
attributes #0 = { nounwind readnone convergent willreturn }
attributes #1 = { nounwind readnone willreturn }
2 changes: 1 addition & 1 deletion llvm/test/Transforms/GVNHoist/hoist-pr31891.ll
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ declare void @useit1(float)
declare void @useit2(float)

attributes #0 = { noinline nounwind readnone uwtable }
attributes #1 = { nounwind readnone }
attributes #1 = { nounwind readnone willreturn }
attributes #2 = { noinline nounwind uwtable }

!llvm.dbg.cu = !{!0}
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/Inline/ret_attr_update.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
; RUN: opt < %s -inline-threshold=0 -always-inline -S | FileCheck %s
; RUN: opt < %s -passes=always-inline -S | FileCheck %s

declare i8* @foo(i8*) argmemonly nounwind
declare i8* @foo(i8*) nounwind willreturn

define i8* @callee(i8 *%p) alwaysinline {
; CHECK-LABEL: @callee(
Expand Down Expand Up @@ -120,7 +120,7 @@ define i8* @test4(i8* %ptr, i64 %x) {
ret i8* %p
}

declare i8* @baz(i8*) nounwind readonly
declare i8* @baz(i8*) nounwind willreturn
define internal i8* @callee5(i8* %p) alwaysinline {
%r = call i8* @foo(i8* %p)
%v = call i8* @baz(i8* %p)
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Transforms/JumpThreading/assume.ll
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ error:
ret void
}

declare void @dummy(i1) nounwind argmemonly
declare void @dummy(i1) nounwind willreturn
define void @can_fold_some_use_before_assume(i32* %array) {

; CHECK-LABEL:@can_fold_some_use_before_assume
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Transforms/JumpThreading/guards.ll
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ BB2:
ret void
}

declare void @dummy(i1) nounwind argmemonly
declare void @dummy(i1) nounwind willreturn
; same as dont_fold_guard1 but there's a use immediately after guard and before
; branch. We can fold that use.
define void @dont_fold_guard2(i8* %addr, i32 %i, i32 %length) {
Expand Down
Loading

0 comments on commit 5d12b97

Please sign in to comment.