Skip to content

Commit

Permalink
[IPSCCP] Remove noundef when zapping return values
Browse files Browse the repository at this point in the history
When replacing return values with undef, we should also drop the
noundef attribute (and other UB implying attributes).

Differential Revision: https://reviews.llvm.org/D144461
  • Loading branch information
nikic authored and CarlosAlbertoEnciso committed Feb 22, 2023
1 parent a2a00d0 commit d54ec86
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 9 deletions.
6 changes: 6 additions & 0 deletions llvm/lib/Transforms/IPO/SCCP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,9 +338,14 @@ static bool runIPSCCP(

// Remove the returned attribute for zapped functions and the
// corresponding call sites.
// Also remove any attributes that convert an undef return value into
// immediate undefined behavior
AttributeMask UBImplyingAttributes =
AttributeFuncs::getUBImplyingAttributes();
for (Function *F : FuncZappedReturn) {
for (Argument &A : F->args())
F->removeParamAttr(A.getArgNo(), Attribute::Returned);
F->removeRetAttrs(UBImplyingAttributes);
for (Use &U : F->uses()) {
CallBase *CB = dyn_cast<CallBase>(U.getUser());
if (!CB) {
Expand All @@ -354,6 +359,7 @@ static bool runIPSCCP(

for (Use &Arg : CB->args())
CB->removeParamAttr(CB->getArgOperandNo(&Arg), Attribute::Returned);
CB->removeRetAttrs(UBImplyingAttributes);
}
}

Expand Down
19 changes: 10 additions & 9 deletions llvm/test/Transforms/SCCP/ipsccp-noundef.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,48 @@
@g = external global i8

define internal noundef i32 @ret_noundef() {
; CHECK-LABEL: define internal noundef i32 @ret_noundef() {
; CHECK-LABEL: define internal i32 @ret_noundef() {
; CHECK-NEXT: ret i32 undef
;
ret i32 0
}

define internal dereferenceable(1) ptr @ret_dereferenceable() {
; CHECK-LABEL: define internal dereferenceable(1) ptr @ret_dereferenceable() {
; CHECK-LABEL: define internal ptr @ret_dereferenceable() {
; CHECK-NEXT: ret ptr undef
;
ret ptr @g
}

define internal dereferenceable_or_null(1) ptr @ret_dereferenceable_or_null() {
; CHECK-LABEL: define internal dereferenceable_or_null(1) ptr @ret_dereferenceable_or_null() {
; CHECK-LABEL: define internal ptr @ret_dereferenceable_or_null() {
; CHECK-NEXT: ret ptr undef
;
ret ptr @g
}

; Non-null is fine, because it does not cause immediate UB.
define internal nonnull ptr @ret_nonnull() {
; CHECK-LABEL: define internal nonnull ptr @ret_nonnull() {
; CHECK-NEXT: ret ptr undef
;
ret ptr @g
}

define internal nonnull noundef ptr @ret_nonnull_noundef() {
; CHECK-LABEL: define internal noundef nonnull ptr @ret_nonnull_noundef() {
define internal nonnull ptr @ret_nonnull_noundef() {
; CHECK-LABEL: define internal nonnull ptr @ret_nonnull_noundef() {
; CHECK-NEXT: ret ptr undef
;
ret ptr @g
}

define void @test() {
; CHECK-LABEL: define void @test() {
; CHECK-NEXT: [[TMP1:%.*]] = call noundef i32 @ret_noundef()
; CHECK-NEXT: [[TMP2:%.*]] = call dereferenceable(1) ptr @ret_dereferenceable()
; CHECK-NEXT: [[TMP3:%.*]] = call dereferenceable_or_null(1) ptr @ret_dereferenceable_or_null()
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @ret_noundef()
; CHECK-NEXT: [[TMP2:%.*]] = call ptr @ret_dereferenceable()
; CHECK-NEXT: [[TMP3:%.*]] = call ptr @ret_dereferenceable_or_null()
; CHECK-NEXT: [[TMP4:%.*]] = call nonnull ptr @ret_nonnull()
; CHECK-NEXT: [[TMP5:%.*]] = call noundef nonnull ptr @ret_nonnull_noundef()
; CHECK-NEXT: [[TMP5:%.*]] = call nonnull ptr @ret_nonnull_noundef()
; CHECK-NEXT: ret void
;
call noundef i32 @ret_noundef()
Expand Down

0 comments on commit d54ec86

Please sign in to comment.