Skip to content

Commit 92ef545

Browse files
committed
[IPSCCP] Remove noundef when zapping return values
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
1 parent a790d77 commit 92ef545

File tree

2 files changed

+16
-9
lines changed

2 files changed

+16
-9
lines changed

llvm/lib/Transforms/IPO/SCCP.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,14 @@ static bool runIPSCCP(
338338

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

355360
for (Use &Arg : CB->args())
356361
CB->removeParamAttr(CB->getArgOperandNo(&Arg), Attribute::Returned);
362+
CB->removeRetAttrs(UBImplyingAttributes);
357363
}
358364
}
359365

llvm/test/Transforms/SCCP/ipsccp-noundef.ll

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,48 @@
22
@g = external global i8
33

44
define internal noundef i32 @ret_noundef() {
5-
; CHECK-LABEL: define internal noundef i32 @ret_noundef() {
5+
; CHECK-LABEL: define internal i32 @ret_noundef() {
66
; CHECK-NEXT: ret i32 undef
77
;
88
ret i32 0
99
}
1010

1111
define internal dereferenceable(1) ptr @ret_dereferenceable() {
12-
; CHECK-LABEL: define internal dereferenceable(1) ptr @ret_dereferenceable() {
12+
; CHECK-LABEL: define internal ptr @ret_dereferenceable() {
1313
; CHECK-NEXT: ret ptr undef
1414
;
1515
ret ptr @g
1616
}
1717

1818
define internal dereferenceable_or_null(1) ptr @ret_dereferenceable_or_null() {
19-
; CHECK-LABEL: define internal dereferenceable_or_null(1) ptr @ret_dereferenceable_or_null() {
19+
; CHECK-LABEL: define internal ptr @ret_dereferenceable_or_null() {
2020
; CHECK-NEXT: ret ptr undef
2121
;
2222
ret ptr @g
2323
}
2424

25+
; Non-null is fine, because it does not cause immediate UB.
2526
define internal nonnull ptr @ret_nonnull() {
2627
; CHECK-LABEL: define internal nonnull ptr @ret_nonnull() {
2728
; CHECK-NEXT: ret ptr undef
2829
;
2930
ret ptr @g
3031
}
3132

32-
define internal nonnull noundef ptr @ret_nonnull_noundef() {
33-
; CHECK-LABEL: define internal noundef nonnull ptr @ret_nonnull_noundef() {
33+
define internal nonnull ptr @ret_nonnull_noundef() {
34+
; CHECK-LABEL: define internal nonnull ptr @ret_nonnull_noundef() {
3435
; CHECK-NEXT: ret ptr undef
3536
;
3637
ret ptr @g
3738
}
3839

3940
define void @test() {
4041
; CHECK-LABEL: define void @test() {
41-
; CHECK-NEXT: [[TMP1:%.*]] = call noundef i32 @ret_noundef()
42-
; CHECK-NEXT: [[TMP2:%.*]] = call dereferenceable(1) ptr @ret_dereferenceable()
43-
; CHECK-NEXT: [[TMP3:%.*]] = call dereferenceable_or_null(1) ptr @ret_dereferenceable_or_null()
42+
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @ret_noundef()
43+
; CHECK-NEXT: [[TMP2:%.*]] = call ptr @ret_dereferenceable()
44+
; CHECK-NEXT: [[TMP3:%.*]] = call ptr @ret_dereferenceable_or_null()
4445
; CHECK-NEXT: [[TMP4:%.*]] = call nonnull ptr @ret_nonnull()
45-
; CHECK-NEXT: [[TMP5:%.*]] = call noundef nonnull ptr @ret_nonnull_noundef()
46+
; CHECK-NEXT: [[TMP5:%.*]] = call nonnull ptr @ret_nonnull_noundef()
4647
; CHECK-NEXT: ret void
4748
;
4849
call noundef i32 @ret_noundef()

0 commit comments

Comments
 (0)