[llvm] [clang] [lld] [FuncAttrs] Deduce `noundef` attributes for return values (PR #76553)
Yingwei Zheng via cfe-commits
cfe-commits at lists.llvm.org
Sun Dec 31 03:09:01 PST 2023
https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/76553
>From 30dcc33c4ea3ab50397a7adbe85fe977d4a400bd Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Fri, 29 Dec 2023 14:27:22 +0800
Subject: [PATCH 1/2] [FuncAttrs] Add pre-commit tests. NFC.
---
llvm/test/Transforms/FunctionAttrs/noundef.ll | 145 ++++++++++++++++++
1 file changed, 145 insertions(+)
create mode 100644 llvm/test/Transforms/FunctionAttrs/noundef.ll
diff --git a/llvm/test/Transforms/FunctionAttrs/noundef.ll b/llvm/test/Transforms/FunctionAttrs/noundef.ll
new file mode 100644
index 00000000000000..9eca495e111e8f
--- /dev/null
+++ b/llvm/test/Transforms/FunctionAttrs/noundef.ll
@@ -0,0 +1,145 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt < %s -passes='function-attrs' -S | FileCheck %s
+
+define i32 @test_ret_constant() {
+; CHECK-LABEL: define i32 @test_ret_constant(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: ret i32 0
+;
+ ret i32 0
+}
+
+define i32 @test_ret_poison() {
+; CHECK-LABEL: define i32 @test_ret_poison(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: ret i32 poison
+;
+ ret i32 poison
+}
+
+define i32 @test_ret_undef() {
+; CHECK-LABEL: define i32 @test_ret_undef(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: ret i32 undef
+;
+ ret i32 undef
+}
+
+define i32 @test_ret_param(i32 %x) {
+; CHECK-LABEL: define i32 @test_ret_param(
+; CHECK-SAME: i32 returned [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: ret i32 [[X]]
+;
+ ret i32 %x
+}
+
+define i32 @test_ret_noundef_param(i32 noundef %x) {
+; CHECK-LABEL: define i32 @test_ret_noundef_param(
+; CHECK-SAME: i32 noundef returned [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: ret i32 [[X]]
+;
+ ret i32 %x
+}
+
+define i32 @test_ret_noundef_expr(i32 noundef %x) {
+; CHECK-LABEL: define i32 @test_ret_noundef_expr(
+; CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[Y:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT: ret i32 [[Y]]
+;
+ %y = add i32 %x, 1
+ ret i32 %y
+}
+
+define i32 @test_ret_create_poison_expr(i32 noundef %x) {
+; CHECK-LABEL: define i32 @test_ret_create_poison_expr(
+; CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[Y:%.*]] = add nsw i32 [[X]], 1
+; CHECK-NEXT: ret i32 [[Y]]
+;
+ %y = add nsw i32 %x, 1
+ ret i32 %y
+}
+
+define i32 @test_ret_freezed(i32 noundef %x) {
+; CHECK-LABEL: define i32 @test_ret_freezed(
+; CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[Y:%.*]] = add nsw i32 [[X]], 1
+; CHECK-NEXT: [[Z:%.*]] = freeze i32 [[Y]]
+; CHECK-NEXT: ret i32 [[Z]]
+;
+ %y = add nsw i32 %x, 1
+ %z = freeze i32 %y
+ ret i32 %z
+}
+
+define i32 @test_ret_control_flow(i32 noundef %x) {
+; CHECK-LABEL: define i32 @test_ret_control_flow(
+; CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[X]], 0
+; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: ret i32 2
+; CHECK: if.else:
+; CHECK-NEXT: [[RET:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT: ret i32 [[RET]]
+;
+ %cond = icmp eq i32 %x, 0
+ br i1 %cond, label %if.then, label %if.else
+if.then:
+ ret i32 2
+if.else:
+ %ret = add i32 %x, 1
+ ret i32 %ret
+}
+
+define i32 @test_ret_control_flow_may_poison(i32 noundef %x) {
+; CHECK-LABEL: define i32 @test_ret_control_flow_may_poison(
+; CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[X]], 0
+; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: ret i32 2
+; CHECK: if.else:
+; CHECK-NEXT: [[RET:%.*]] = add nsw i32 [[X]], 1
+; CHECK-NEXT: ret i32 [[RET]]
+;
+ %cond = icmp eq i32 %x, 0
+ br i1 %cond, label %if.then, label %if.else
+if.then:
+ ret i32 2
+if.else:
+ %ret = add nsw i32 %x, 1
+ ret i32 %ret
+}
+
+; TODO: use context-sensitive analysis
+define i32 @test_ret_control_flow_never_poison(i32 noundef %x) {
+; CHECK-LABEL: define i32 @test_ret_control_flow_never_poison(
+; CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[X]], 2147483647
+; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: ret i32 2
+; CHECK: if.else:
+; CHECK-NEXT: [[RET:%.*]] = add nsw i32 [[X]], 1
+; CHECK-NEXT: ret i32 [[RET]]
+;
+ %cond = icmp eq i32 %x, 2147483647
+ br i1 %cond, label %if.then, label %if.else
+if.then:
+ ret i32 2
+if.else:
+ %ret = add nsw i32 %x, 1
+ ret i32 %ret
+}
+
+define i32 @test_noundef_prop() {
+; CHECK-LABEL: define i32 @test_noundef_prop(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: [[RET:%.*]] = call i32 @test_ret_constant()
+; CHECK-NEXT: ret i32 [[RET]]
+;
+ %ret = call i32 @test_ret_constant()
+ ret i32 %ret
+}
>From fe11127cd7e9ed4669243502eda5991504b9809a Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Fri, 29 Dec 2023 14:28:26 +0800
Subject: [PATCH 2/2] [FuncAttrs] Deduce noundef attrs for return values
---
clang/test/CodeGen/X86/ms-x86-intrinsics.c | 4 +-
clang/test/CodeGen/arm-bf16-params-returns.c | 8 ++--
.../CodeGen/arm-vector_type-params-returns.c | 24 ++++++------
clang/test/CodeGen/ifunc.c | 8 ++--
clang/test/CodeGen/isfpclass.c | 28 +++++++-------
clang/test/CodeGen/ms-mixed-ptr-sizes.c | 8 ++--
.../link-builtin-bitcode-denormal-fp-mode.cu | 16 ++++----
clang/test/CodeGenOpenCL/as_type.cl | 12 +++---
lld/test/COFF/savetemps.ll | 2 +-
.../lto/devirt_validate_vtable_typeinfos.ll | 2 +-
...irt_validate_vtable_typeinfos_mixed_lto.ll | 2 +-
...evirt_validate_vtable_typeinfos_no_rtti.ll | 2 +-
.../lto/devirt_vcall_vis_export_dynamic.ll | 2 +-
lld/test/ELF/lto/devirt_vcall_vis_public.ll | 2 +-
llvm/lib/Transforms/IPO/FunctionAttrs.cpp | 35 ++++++++++++++++++
llvm/test/DebugInfo/X86/array2.ll | 2 +-
llvm/test/ThinLTO/X86/devirt.ll | 2 +-
llvm/test/ThinLTO/X86/devirt2.ll | 2 +-
llvm/test/ThinLTO/X86/devirt_check.ll | 2 +-
llvm/test/ThinLTO/X86/devirt_promote.ll | 2 +-
.../test/ThinLTO/X86/devirt_promote_legacy.ll | 2 +-
.../ThinLTO/X86/devirt_pure_virtual_base.ll | 2 +-
llvm/test/ThinLTO/X86/devirt_single_hybrid.ll | 4 +-
.../ThinLTO/X86/devirt_vcall_vis_hidden.ll | 2 +-
.../ThinLTO/X86/devirt_vcall_vis_public.ll | 4 +-
llvm/test/ThinLTO/X86/funcimport.ll | 2 +-
.../ThinLTO/X86/globals-import-const-fold.ll | 2 +-
llvm/test/ThinLTO/X86/import-constant.ll | 2 +-
.../ThinLTO/X86/index-const-prop-alias.ll | 2 +-
llvm/test/ThinLTO/X86/index-const-prop.ll | 2 +-
.../Transforms/FunctionAttrs/nocapture.ll | 10 ++---
llvm/test/Transforms/FunctionAttrs/nonnull.ll | 37 ++++++++++++-------
llvm/test/Transforms/FunctionAttrs/noundef.ll | 12 +++---
.../out-of-bounds-iterator-bug.ll | 4 +-
llvm/test/Transforms/Inline/devirtualize-3.ll | 2 +-
llvm/test/Transforms/Inline/devirtualize-5.ll | 2 +-
.../Inline/launder.invariant.group.ll | 4 +-
.../constraint-elimination-placement.ll | 22 +++++------
.../PhaseOrdering/X86/merge-functions.ll | 2 +-
.../PhaseOrdering/bitcast-store-branch.ll | 2 +-
.../dce-after-argument-promotion-loads.ll | 2 +-
.../early-arg-attrs-inference.ll | 2 +-
.../PhaseOrdering/gep-null-compare-in-loop.ll | 4 +-
.../test/Transforms/SampleProfile/ctxsplit.ll | 12 +++---
44 files changed, 175 insertions(+), 131 deletions(-)
diff --git a/clang/test/CodeGen/X86/ms-x86-intrinsics.c b/clang/test/CodeGen/X86/ms-x86-intrinsics.c
index b4b8f5dc0b8c55..a1c90d71c8ebf5 100644
--- a/clang/test/CodeGen/X86/ms-x86-intrinsics.c
+++ b/clang/test/CodeGen/X86/ms-x86-intrinsics.c
@@ -145,7 +145,7 @@ unsigned __int64 test__shiftleft128(unsigned __int64 l, unsigned __int64 h,
unsigned char d) {
return __shiftleft128(l, h, d);
}
-// CHECK-X64-LABEL: define dso_local i64 @test__shiftleft128(i64 noundef %l, i64 noundef %h, i8 noundef %d)
+// CHECK-X64-LABEL: define dso_local noundef i64 @test__shiftleft128(i64 noundef %l, i64 noundef %h, i8 noundef %d)
// CHECK-X64: = zext i8 %{{.*}} to i64
// CHECK-X64: = tail call i64 @llvm.fshl.i64(i64 %h, i64 %l, i64 %{{.*}})
// CHECK-X64: ret i64 %
@@ -154,7 +154,7 @@ unsigned __int64 test__shiftright128(unsigned __int64 l, unsigned __int64 h,
unsigned char d) {
return __shiftright128(l, h, d);
}
-// CHECK-X64-LABEL: define dso_local i64 @test__shiftright128(i64 noundef %l, i64 noundef %h, i8 noundef %d)
+// CHECK-X64-LABEL: define dso_local noundef i64 @test__shiftright128(i64 noundef %l, i64 noundef %h, i8 noundef %d)
// CHECK-X64: = zext i8 %{{.*}} to i64
// CHECK-X64: = tail call i64 @llvm.fshr.i64(i64 %h, i64 %l, i64 %{{.*}})
// CHECK-X64: ret i64 %
diff --git a/clang/test/CodeGen/arm-bf16-params-returns.c b/clang/test/CodeGen/arm-bf16-params-returns.c
index 2d33e3f45eacf7..21be0bb151697a 100644
--- a/clang/test/CodeGen/arm-bf16-params-returns.c
+++ b/clang/test/CodeGen/arm-bf16-params-returns.c
@@ -11,7 +11,7 @@
__bf16 test_ret_bf16(__bf16 v) {
return v;
}
-// CHECK32-HARD: define{{.*}} arm_aapcs_vfpcc bfloat @test_ret_bf16(bfloat noundef returned %v) {{.*}} {
+// CHECK32-HARD: define{{.*}} arm_aapcs_vfpcc noundef bfloat @test_ret_bf16(bfloat noundef returned %v) {{.*}} {
// CHECK32-HARD: ret bfloat %v
// CHECK32-SOFTFP: define{{.*}} bfloat @test_ret_bf16(bfloat noundef returned %v) {{.*}} {
// CHECK32-SOFTFP: ret bfloat %v
@@ -23,11 +23,11 @@ __bf16 test_ret_bf16(__bf16 v) {
bfloat16x4_t test_ret_bf16x4_t(bfloat16x4_t v) {
return v;
}
-// CHECK32-HARD: define{{.*}} arm_aapcs_vfpcc <4 x bfloat> @test_ret_bf16x4_t(<4 x bfloat> noundef returned %v) {{.*}} {
+// CHECK32-HARD: define{{.*}} arm_aapcs_vfpcc noundef <4 x bfloat> @test_ret_bf16x4_t(<4 x bfloat> noundef returned %v) {{.*}} {
// CHECK32-HARD: ret <4 x bfloat> %v
-// CHECK32-SOFTFP: define{{.*}} <2 x i32> @test_ret_bf16x4_t(<2 x i32> [[V0:.*]]) {{.*}} {
+// CHECK32-SOFTFP: define{{.*}} noundef <2 x i32> @test_ret_bf16x4_t(<2 x i32> [[V0:.*]]) {{.*}} {
// CHECK32-SOFTFP: ret <2 x i32> %v
-// CHECK64NEON: define{{.*}} <4 x bfloat> @test_ret_bf16x4_t(<4 x bfloat> noundef returned %v) {{.*}} {
+// CHECK64NEON: define{{.*}} noundef <4 x bfloat> @test_ret_bf16x4_t(<4 x bfloat> noundef returned %v) {{.*}} {
// CHECK64NEON: ret <4 x bfloat> %v
#endif
\ No newline at end of file
diff --git a/clang/test/CodeGen/arm-vector_type-params-returns.c b/clang/test/CodeGen/arm-vector_type-params-returns.c
index 14c3512ab81a9f..a55aba9ce06651 100644
--- a/clang/test/CodeGen/arm-vector_type-params-returns.c
+++ b/clang/test/CodeGen/arm-vector_type-params-returns.c
@@ -27,7 +27,7 @@
#endif
// function return types
-// CHECK-LABEL: define dso_local <8 x half> @test_ret_v8f16(
+// CHECK-LABEL: define dso_local noundef <8 x half> @test_ret_v8f16(
// CHECK-SAME: <8 x half> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <8 x half> [[V]]
@@ -36,7 +36,7 @@ float16x8_t test_ret_v8f16(float16x8_t v) {
return v;
}
-// CHECK-LABEL: define dso_local <4 x float> @test_ret_v4f32(
+// CHECK-LABEL: define dso_local noundef <4 x float> @test_ret_v4f32(
// CHECK-SAME: <4 x float> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <4 x float> [[V]]
@@ -45,7 +45,7 @@ float32x4_t test_ret_v4f32(float32x4_t v) {
return v;
}
-// CHECK-LABEL: define dso_local <2 x double> @test_ret_v2f64(
+// CHECK-LABEL: define dso_local noundef <2 x double> @test_ret_v2f64(
// CHECK-SAME: <2 x double> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <2 x double> [[V]]
@@ -54,7 +54,7 @@ float64x2_t test_ret_v2f64(float64x2_t v) {
return v;
}
-// CHECK-LABEL: define dso_local <8 x bfloat> @test_ret_v8bf16(
+// CHECK-LABEL: define dso_local noundef <8 x bfloat> @test_ret_v8bf16(
// CHECK-SAME: <8 x bfloat> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <8 x bfloat> [[V]]
@@ -63,7 +63,7 @@ bfloat16x8_t test_ret_v8bf16(bfloat16x8_t v) {
return v;
}
-// CHECK-LABEL: define dso_local <16 x i8> @test_ret_v16s8(
+// CHECK-LABEL: define dso_local noundef <16 x i8> @test_ret_v16s8(
// CHECK-SAME: <16 x i8> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <16 x i8> [[V]]
@@ -72,7 +72,7 @@ int8x16_t test_ret_v16s8(int8x16_t v) {
return v;
}
-// CHECK-LABEL: define dso_local <8 x i16> @test_ret_v8s16(
+// CHECK-LABEL: define dso_local noundef <8 x i16> @test_ret_v8s16(
// CHECK-SAME: <8 x i16> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <8 x i16> [[V]]
@@ -81,7 +81,7 @@ int16x8_t test_ret_v8s16(int16x8_t v) {
return v;
}
-// CHECK-LABEL: define dso_local <4 x i32> @test_ret_v32s4(
+// CHECK-LABEL: define dso_local noundef <4 x i32> @test_ret_v32s4(
// CHECK-SAME: <4 x i32> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <4 x i32> [[V]]
@@ -90,7 +90,7 @@ int32x4_t test_ret_v32s4(int32x4_t v) {
return v;
}
-// CHECK-LABEL: define dso_local <2 x i64> @test_ret_v64s2(
+// CHECK-LABEL: define dso_local noundef <2 x i64> @test_ret_v64s2(
// CHECK-SAME: <2 x i64> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <2 x i64> [[V]]
@@ -99,7 +99,7 @@ int64x2_t test_ret_v64s2(int64x2_t v) {
return v;
}
-// CHECK-LABEL: define dso_local <16 x i8> @test_ret_v16u8(
+// CHECK-LABEL: define dso_local noundef <16 x i8> @test_ret_v16u8(
// CHECK-SAME: <16 x i8> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <16 x i8> [[V]]
@@ -108,7 +108,7 @@ uint8x16_t test_ret_v16u8(uint8x16_t v) {
return v;
}
-// CHECK-LABEL: define dso_local <8 x i16> @test_ret_v8u16(
+// CHECK-LABEL: define dso_local noundef <8 x i16> @test_ret_v8u16(
// CHECK-SAME: <8 x i16> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <8 x i16> [[V]]
@@ -117,7 +117,7 @@ uint16x8_t test_ret_v8u16(uint16x8_t v) {
return v;
}
-// CHECK-LABEL: define dso_local <4 x i32> @test_ret_v32u4(
+// CHECK-LABEL: define dso_local noundef <4 x i32> @test_ret_v32u4(
// CHECK-SAME: <4 x i32> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <4 x i32> [[V]]
@@ -126,7 +126,7 @@ uint32x4_t test_ret_v32u4(uint32x4_t v) {
return v;
}
-// CHECK-LABEL: define dso_local <2 x i64> @test_ret_v64u2(
+// CHECK-LABEL: define dso_local noundef <2 x i64> @test_ret_v64u2(
// CHECK-SAME: <2 x i64> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <2 x i64> [[V]]
diff --git a/clang/test/CodeGen/ifunc.c b/clang/test/CodeGen/ifunc.c
index a29b500e80bd50..3aa29f7dff74de 100644
--- a/clang/test/CodeGen/ifunc.c
+++ b/clang/test/CodeGen/ifunc.c
@@ -51,11 +51,11 @@ void* goo_ifunc(void) {
// CHECK: call i32 @foo(i32
// CHECK: call void @goo()
-// SAN: define internal nonnull ptr @foo_ifunc() #[[#FOO_IFUNC:]] {
-// MACSAN: define internal nonnull ptr @foo_ifunc() #[[#FOO_IFUNC:]] {
+// SAN: define internal nonnull {{(noundef )?}}ptr @foo_ifunc() #[[#FOO_IFUNC:]] {
+// MACSAN: define internal nonnull {{(noundef )?}}ptr @foo_ifunc() #[[#FOO_IFUNC:]] {
-// SAN: define dso_local noalias ptr @goo_ifunc() #[[#GOO_IFUNC:]] {
-// MACSAN: define noalias ptr @goo_ifunc() #[[#GOO_IFUNC:]] {
+// SAN: define dso_local noalias {{(noundef )?}}ptr @goo_ifunc() #[[#GOO_IFUNC:]] {
+// MACSAN: define noalias {{(noundef )?}}ptr @goo_ifunc() #[[#GOO_IFUNC:]] {
// SAN-DAG: attributes #[[#FOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}
// MACSAN-DAG: attributes #[[#FOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}
diff --git a/clang/test/CodeGen/isfpclass.c b/clang/test/CodeGen/isfpclass.c
index 34873c08e04f87..88d7a21b9733d8 100644
--- a/clang/test/CodeGen/isfpclass.c
+++ b/clang/test/CodeGen/isfpclass.c
@@ -1,7 +1,7 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2
// RUN: %clang_cc1 -triple aarch64-linux-gnu -S -O1 -emit-llvm %s -o - | FileCheck %s
-// CHECK-LABEL: define dso_local i1 @check_isfpclass_finite
+// CHECK-LABEL: define dso_local noundef i1 @check_isfpclass_finite
// CHECK-SAME: (float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = tail call float @llvm.fabs.f32(float [[X]])
@@ -12,7 +12,7 @@ _Bool check_isfpclass_finite(float x) {
return __builtin_isfpclass(x, 504 /*Finite*/);
}
-// CHECK-LABEL: define dso_local i1 @check_isfpclass_finite_strict
+// CHECK-LABEL: define dso_local noundef i1 @check_isfpclass_finite_strict
// CHECK-SAME: (float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.is.fpclass.f32(float [[X]], i32 504) #[[ATTR6:[0-9]+]]
@@ -23,7 +23,7 @@ _Bool check_isfpclass_finite_strict(float x) {
return __builtin_isfpclass(x, 504 /*Finite*/);
}
-// CHECK-LABEL: define dso_local i1 @check_isfpclass_nan_f32
+// CHECK-LABEL: define dso_local noundef i1 @check_isfpclass_nan_f32
// CHECK-SAME: (float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = fcmp uno float [[X]], 0.000000e+00
@@ -33,7 +33,7 @@ _Bool check_isfpclass_nan_f32(float x) {
return __builtin_isfpclass(x, 3 /*NaN*/);
}
-// CHECK-LABEL: define dso_local i1 @check_isfpclass_nan_f32_strict
+// CHECK-LABEL: define dso_local noundef i1 @check_isfpclass_nan_f32_strict
// CHECK-SAME: (float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.is.fpclass.f32(float [[X]], i32 3) #[[ATTR6]]
@@ -44,7 +44,7 @@ _Bool check_isfpclass_nan_f32_strict(float x) {
return __builtin_isfpclass(x, 3 /*NaN*/);
}
-// CHECK-LABEL: define dso_local i1 @check_isfpclass_snan_f64
+// CHECK-LABEL: define dso_local noundef i1 @check_isfpclass_snan_f64
// CHECK-SAME: (double noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.is.fpclass.f64(double [[X]], i32 1)
@@ -54,7 +54,7 @@ _Bool check_isfpclass_snan_f64(double x) {
return __builtin_isfpclass(x, 1 /*SNaN*/);
}
-// CHECK-LABEL: define dso_local i1 @check_isfpclass_snan_f64_strict
+// CHECK-LABEL: define dso_local noundef i1 @check_isfpclass_snan_f64_strict
// CHECK-SAME: (double noundef [[X:%.*]]) local_unnamed_addr #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.is.fpclass.f64(double [[X]], i32 1) #[[ATTR6]]
@@ -65,7 +65,7 @@ _Bool check_isfpclass_snan_f64_strict(double x) {
return __builtin_isfpclass(x, 1 /*NaN*/);
}
-// CHECK-LABEL: define dso_local i1 @check_isfpclass_zero_f16
+// CHECK-LABEL: define dso_local noundef i1 @check_isfpclass_zero_f16
// CHECK-SAME: (half noundef [[X:%.*]]) local_unnamed_addr #[[ATTR3]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = fcmp oeq half [[X]], 0xH0000
@@ -75,7 +75,7 @@ _Bool check_isfpclass_zero_f16(_Float16 x) {
return __builtin_isfpclass(x, 96 /*Zero*/);
}
-// CHECK-LABEL: define dso_local i1 @check_isfpclass_zero_f16_strict
+// CHECK-LABEL: define dso_local noundef i1 @check_isfpclass_zero_f16_strict
// CHECK-SAME: (half noundef [[X:%.*]]) local_unnamed_addr #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.is.fpclass.f16(half [[X]], i32 96) #[[ATTR6]]
@@ -86,7 +86,7 @@ _Bool check_isfpclass_zero_f16_strict(_Float16 x) {
return __builtin_isfpclass(x, 96 /*Zero*/);
}
-// CHECK-LABEL: define dso_local i1 @check_isnan
+// CHECK-LABEL: define dso_local noundef i1 @check_isnan
// CHECK-SAME: (float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.is.fpclass.f32(float [[X]], i32 3) #[[ATTR6]]
@@ -97,7 +97,7 @@ _Bool check_isnan(float x) {
return __builtin_isnan(x);
}
-// CHECK-LABEL: define dso_local i1 @check_isinf
+// CHECK-LABEL: define dso_local noundef i1 @check_isinf
// CHECK-SAME: (float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.is.fpclass.f32(float [[X]], i32 516) #[[ATTR6]]
@@ -108,7 +108,7 @@ _Bool check_isinf(float x) {
return __builtin_isinf(x);
}
-// CHECK-LABEL: define dso_local i1 @check_isfinite
+// CHECK-LABEL: define dso_local noundef i1 @check_isfinite
// CHECK-SAME: (float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.is.fpclass.f32(float [[X]], i32 504) #[[ATTR6]]
@@ -119,7 +119,7 @@ _Bool check_isfinite(float x) {
return __builtin_isfinite(x);
}
-// CHECK-LABEL: define dso_local i1 @check_isnormal
+// CHECK-LABEL: define dso_local noundef i1 @check_isnormal
// CHECK-SAME: (float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.is.fpclass.f32(float [[X]], i32 264) #[[ATTR6]]
@@ -136,7 +136,7 @@ typedef double __attribute__((ext_vector_type(4))) double4;
typedef int __attribute__((ext_vector_type(4))) int4;
typedef long __attribute__((ext_vector_type(4))) long4;
-// CHECK-LABEL: define dso_local <4 x i32> @check_isfpclass_nan_v4f32
+// CHECK-LABEL: define dso_local noundef <4 x i32> @check_isfpclass_nan_v4f32
// CHECK-SAME: (<4 x float> noundef [[X:%.*]]) local_unnamed_addr #[[ATTR3]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = fcmp uno <4 x float> [[X]], zeroinitializer
@@ -147,7 +147,7 @@ int4 check_isfpclass_nan_v4f32(float4 x) {
return __builtin_isfpclass(x, 3 /*NaN*/);
}
-// CHECK-LABEL: define dso_local <4 x i32> @check_isfpclass_nan_strict_v4f32
+// CHECK-LABEL: define dso_local noundef <4 x i32> @check_isfpclass_nan_strict_v4f32
// CHECK-SAME: (<4 x float> noundef [[X:%.*]]) local_unnamed_addr #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = tail call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> [[X]], i32 3) #[[ATTR6]]
diff --git a/clang/test/CodeGen/ms-mixed-ptr-sizes.c b/clang/test/CodeGen/ms-mixed-ptr-sizes.c
index a853c6083cb8ba..89d05fd30b72c2 100644
--- a/clang/test/CodeGen/ms-mixed-ptr-sizes.c
+++ b/clang/test/CodeGen/ms-mixed-ptr-sizes.c
@@ -49,7 +49,7 @@ void test_other(struct Foo *f, __attribute__((address_space(10))) int *i) {
}
int test_compare1(int *__ptr32 __uptr i, int *__ptr64 j) {
- // ALL-LABEL: define dso_local i32 @test_compare1
+ // ALL-LABEL: define dso_local noundef i32 @test_compare1
// X64: %{{.+}} = addrspacecast ptr %j to ptr addrspace(271)
// X64: %cmp = icmp eq ptr addrspace(271) %{{.+}}, %i
// X86: %{{.+}} = addrspacecast ptr addrspace(272) %j to ptr addrspace(271)
@@ -58,7 +58,7 @@ int test_compare1(int *__ptr32 __uptr i, int *__ptr64 j) {
}
int test_compare2(int *__ptr32 __sptr i, int *__ptr64 j) {
- // ALL-LABEL: define dso_local i32 @test_compare2
+ // ALL-LABEL: define dso_local noundef i32 @test_compare2
// X64: %{{.+}} = addrspacecast ptr %j to ptr addrspace(270)
// X64: %cmp = icmp eq ptr addrspace(270) %{{.+}}, %i
// X86: %{{.+}} = addrspacecast ptr addrspace(272) %j to ptr
@@ -67,7 +67,7 @@ int test_compare2(int *__ptr32 __sptr i, int *__ptr64 j) {
}
int test_compare3(int *__ptr32 __uptr i, int *__ptr64 j) {
- // ALL-LABEL: define dso_local i32 @test_compare3
+ // ALL-LABEL: define dso_local noundef i32 @test_compare3
// X64: %{{.+}} = addrspacecast ptr addrspace(271) %i to ptr
// X64: %cmp = icmp eq ptr %{{.+}}, %j
// X86: %{{.+}} = addrspacecast ptr addrspace(271) %i to ptr addrspace(272)
@@ -76,7 +76,7 @@ int test_compare3(int *__ptr32 __uptr i, int *__ptr64 j) {
}
int test_compare4(int *__ptr32 __sptr i, int *__ptr64 j) {
- // ALL-LABEL: define dso_local i32 @test_compare4
+ // ALL-LABEL: define dso_local noundef i32 @test_compare4
// X64: %{{.+}} = addrspacecast ptr addrspace(270) %i to ptr
// X64: %cmp = icmp eq ptr %{{.+}}, %j
// X86: %{{.+}} = addrspacecast ptr %i to ptr addrspace(272)
diff --git a/clang/test/CodeGenCUDA/link-builtin-bitcode-denormal-fp-mode.cu b/clang/test/CodeGenCUDA/link-builtin-bitcode-denormal-fp-mode.cu
index f12eacfb53fab3..ef02668c3697bf 100644
--- a/clang/test/CodeGenCUDA/link-builtin-bitcode-denormal-fp-mode.cu
+++ b/clang/test/CodeGenCUDA/link-builtin-bitcode-denormal-fp-mode.cu
@@ -111,16 +111,16 @@ __global__ void kernel_f64(double* out, double* a, double* b, double* c) {
}
}
-// INTERNALIZE: define internal half @do_f16_stuff({{.*}}) #[[$FUNCATTR:[0-9]+]]
-// INTERNALIZE: define internal float @do_f32_stuff({{.*}}) #[[$FUNCATTR]]
-// INTERNALIZE: define internal double @do_f64_stuff({{.*}}) #[[$FUNCATTR]]
-// INTERNALIZE: define internal float @weak_do_f32_stuff({{.*}}) #[[$WEAK_FUNCATTR:[0-9]+]]
+// INTERNALIZE: define internal {{(noundef )?}}half @do_f16_stuff({{.*}}) #[[$FUNCATTR:[0-9]+]]
+// INTERNALIZE: define internal {{(noundef )?}}float @do_f32_stuff({{.*}}) #[[$FUNCATTR]]
+// INTERNALIZE: define internal {{(noundef )?}}double @do_f64_stuff({{.*}}) #[[$FUNCATTR]]
+// INTERNALIZE: define internal {{(noundef )?}}float @weak_do_f32_stuff({{.*}}) #[[$WEAK_FUNCATTR:[0-9]+]]
-// NOINTERNALIZE: define dso_local half @do_f16_stuff({{.*}}) #[[$FUNCATTR:[0-9]+]]
-// NOINTERNALIZE: define dso_local float @do_f32_stuff({{.*}}) #[[$FUNCATTR]]
-// NOINTERNALIZE: define dso_local double @do_f64_stuff({{.*}}) #[[$FUNCATTR]]
-// NOINTERNALIZE: define weak float @weak_do_f32_stuff({{.*}}) #[[$WEAK_FUNCATTR:[0-9]+]]
+// NOINTERNALIZE: define dso_local {{(noundef )?}}half @do_f16_stuff({{.*}}) #[[$FUNCATTR:[0-9]+]]
+// NOINTERNALIZE: define dso_local {{(noundef )?}}float @do_f32_stuff({{.*}}) #[[$FUNCATTR]]
+// NOINTERNALIZE: define dso_local {{(noundef )?}}double @do_f64_stuff({{.*}}) #[[$FUNCATTR]]
+// NOINTERNALIZE: define weak {{(noundef )?}}float @weak_do_f32_stuff({{.*}}) #[[$WEAK_FUNCATTR:[0-9]+]]
diff --git a/clang/test/CodeGenOpenCL/as_type.cl b/clang/test/CodeGenOpenCL/as_type.cl
index d8e75db936f732..1fe26fbeafdb4b 100644
--- a/clang/test/CodeGenOpenCL/as_type.cl
+++ b/clang/test/CodeGenOpenCL/as_type.cl
@@ -27,7 +27,7 @@ char3 f3(int x) {
return __builtin_astype(x, char3);
}
-//CHECK: define{{.*}} spir_func <4 x i8> @f4(i32 noundef %[[x:.*]])
+//CHECK: define{{.*}} spir_func noundef <4 x i8> @f4(i32 noundef %[[x:.*]])
//CHECK: %[[astype:.*]] = bitcast i32 %[[x]] to <4 x i8>
//CHECK-NOT: shufflevector
//CHECK: ret <4 x i8> %[[astype]]
@@ -43,7 +43,7 @@ int f5(char3 x) {
return __builtin_astype(x, int);
}
-//CHECK: define{{.*}} spir_func i32 @f6(<4 x i8> noundef %[[x:.*]])
+//CHECK: define{{.*}} spir_func noundef i32 @f6(<4 x i8> noundef %[[x:.*]])
//CHECK: %[[astype:.*]] = bitcast <4 x i8> %[[x]] to i32
//CHECK-NOT: shufflevector
//CHECK: ret i32 %[[astype]]
@@ -51,7 +51,7 @@ int f6(char4 x) {
return __builtin_astype(x, int);
}
-//CHECK: define{{.*}} spir_func <3 x i8> @f7(<3 x i8> noundef returned %[[x:.*]])
+//CHECK: define{{.*}} spir_func noundef <3 x i8> @f7(<3 x i8> noundef returned %[[x:.*]])
//CHECK-NOT: bitcast
//CHECK-NOT: shufflevector
//CHECK: ret <3 x i8> %[[x]]
@@ -67,21 +67,21 @@ int3 f8(char16 x) {
return __builtin_astype(x, int3);
}
-//CHECK: define{{.*}} spir_func ptr addrspace(1) @addr_cast(ptr noundef readnone %[[x:.*]])
+//CHECK: define{{.*}} spir_func noundef ptr addrspace(1) @addr_cast(ptr noundef readnone %[[x:.*]])
//CHECK: %[[cast:.*]] ={{.*}} addrspacecast ptr %[[x]] to ptr addrspace(1)
//CHECK: ret ptr addrspace(1) %[[cast]]
global int* addr_cast(int *x) {
return __builtin_astype(x, global int*);
}
-//CHECK: define{{.*}} spir_func ptr addrspace(1) @int_to_ptr(i32 noundef %[[x:.*]])
+//CHECK: define{{.*}} spir_func noundef ptr addrspace(1) @int_to_ptr(i32 noundef %[[x:.*]])
//CHECK: %[[cast:.*]] = inttoptr i32 %[[x]] to ptr addrspace(1)
//CHECK: ret ptr addrspace(1) %[[cast]]
global int* int_to_ptr(int x) {
return __builtin_astype(x, global int*);
}
-//CHECK: define{{.*}} spir_func i32 @ptr_to_int(ptr noundef %[[x:.*]])
+//CHECK: define{{.*}} spir_func noundef i32 @ptr_to_int(ptr noundef %[[x:.*]])
//CHECK: %[[cast:.*]] = ptrtoint ptr %[[x]] to i32
//CHECK: ret i32 %[[cast]]
int ptr_to_int(int *x) {
diff --git a/lld/test/COFF/savetemps.ll b/lld/test/COFF/savetemps.ll
index 46a4958d2f782c..64d0566108b824 100644
--- a/lld/test/COFF/savetemps.ll
+++ b/lld/test/COFF/savetemps.ll
@@ -18,7 +18,7 @@
; RUN: llvm-objdump -s %T/savetemps/savetemps.exe.lto.obj | \
; RUN: FileCheck --check-prefix=CHECK-OBJDUMP %s
-; CHECK: define i32 @main()
+; CHECK: define {{(noundef )?}}i32 @main()
; CHECK-OBJDUMP: file format coff
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
diff --git a/lld/test/ELF/lto/devirt_validate_vtable_typeinfos.ll b/lld/test/ELF/lto/devirt_validate_vtable_typeinfos.ll
index 74e437747df3b8..eb2e9970f72372 100644
--- a/lld/test/ELF/lto/devirt_validate_vtable_typeinfos.ll
+++ b/lld/test/ELF/lto/devirt_validate_vtable_typeinfos.ll
@@ -183,7 +183,7 @@ target triple = "x86_64-unknown-linux-gnu"
;; Prevent the vtables from being dead code eliminated.
@llvm.used = appending global [3 x ptr] [ ptr @_ZTV1B, ptr @_ZTV1C, ptr @_ZTV1D ]
-; CHECK-COMMON-IR-LABEL: define dso_local i32 @_start
+; CHECK-COMMON-IR-LABEL: define dso_local {{(noundef )?}}i32 @_start
define i32 @_start(ptr %obj, ptr %obj2, i32 %a) {
entry:
%vtable = load ptr, ptr %obj
diff --git a/lld/test/ELF/lto/devirt_validate_vtable_typeinfos_mixed_lto.ll b/lld/test/ELF/lto/devirt_validate_vtable_typeinfos_mixed_lto.ll
index 15040b8707aede..9dacbc32175a7d 100644
--- a/lld/test/ELF/lto/devirt_validate_vtable_typeinfos_mixed_lto.ll
+++ b/lld/test/ELF/lto/devirt_validate_vtable_typeinfos_mixed_lto.ll
@@ -53,7 +53,7 @@ target triple = "x86_64-unknown-linux-gnu"
;; Prevent the vtables from being dead code eliminated.
@llvm.used = appending global [3 x ptr] [ ptr @_ZTV1B, ptr @_ZTV1C, ptr @_ZTV1D ], section "llvm.metadata"
-; CHECK-COMMON-IR-LABEL: define dso_local i32 @_start
+; CHECK-COMMON-IR-LABEL: define dso_local noundef i32 @_start
define i32 @_start(ptr %obj, ptr %obj2, i32 %a) {
;; Call function built with RegularLTO
%RegularLTOResult = call i32 @RegularLTO(ptr %obj, i32 %a)
diff --git a/lld/test/ELF/lto/devirt_validate_vtable_typeinfos_no_rtti.ll b/lld/test/ELF/lto/devirt_validate_vtable_typeinfos_no_rtti.ll
index 3f3ea2cc5a3755..2c6f63f7552938 100644
--- a/lld/test/ELF/lto/devirt_validate_vtable_typeinfos_no_rtti.ll
+++ b/lld/test/ELF/lto/devirt_validate_vtable_typeinfos_no_rtti.ll
@@ -67,7 +67,7 @@ target triple = "x86_64-unknown-linux-gnu"
;; Prevent the vtables from being dead code eliminated.
@llvm.used = appending global [3 x ptr] [ ptr @_ZTV1B, ptr @_ZTV1C, ptr @_ZTV1D ]
-; CHECK-COMMON-IR-LABEL: define dso_local i32 @_start
+; CHECK-COMMON-IR-LABEL: define dso_local {{(noundef )?}}i32 @_start
define i32 @_start(ptr %obj, ptr %obj2, i32 %a) {
entry:
%vtable = load ptr, ptr %obj
diff --git a/lld/test/ELF/lto/devirt_vcall_vis_export_dynamic.ll b/lld/test/ELF/lto/devirt_vcall_vis_export_dynamic.ll
index 7686fa978d4d2c..2a52c5ad8ae42d 100644
--- a/lld/test/ELF/lto/devirt_vcall_vis_export_dynamic.ll
+++ b/lld/test/ELF/lto/devirt_vcall_vis_export_dynamic.ll
@@ -130,7 +130,7 @@ target triple = "x86_64-grtev4-linux-gnu"
;; Prevent the vtables from being dead code eliminated.
@llvm.used = appending global [3 x ptr] [ ptr @_ZTV1B, ptr @_ZTV1C, ptr @_ZTV1D]
-; CHECK-IR-LABEL: define dso_local i32 @_start
+; CHECK-IR-LABEL: define dso_local {{(noundef )?}}i32 @_start
define i32 @_start(ptr %obj, ptr %obj2, i32 %a) {
entry:
%vtable = load ptr, ptr %obj
diff --git a/lld/test/ELF/lto/devirt_vcall_vis_public.ll b/lld/test/ELF/lto/devirt_vcall_vis_public.ll
index 1c0d55f7d73acb..a827fea465fd7f 100644
--- a/lld/test/ELF/lto/devirt_vcall_vis_public.ll
+++ b/lld/test/ELF/lto/devirt_vcall_vis_public.ll
@@ -65,7 +65,7 @@ target triple = "x86_64-grtev4-linux-gnu"
; Prevent the vtables from being dead code eliminated.
@llvm.used = appending global [3 x ptr] [ ptr @_ZTV1B, ptr @_ZTV1C, ptr @_ZTV1D]
-; CHECK-IR-LABEL: define dso_local i32 @_start
+; CHECK-IR-LABEL: define dso_local {{(noundef )?}}i32 @_start
define i32 @_start(ptr %obj, ptr %obj2, i32 %a) {
entry:
%vtable = load ptr, ptr %obj
diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
index 9ce9f8451a95fa..ce083979afc63a 100644
--- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -76,6 +76,7 @@ STATISTIC(NumReadOnlyArg, "Number of arguments marked readonly");
STATISTIC(NumWriteOnlyArg, "Number of arguments marked writeonly");
STATISTIC(NumNoAlias, "Number of function returns marked noalias");
STATISTIC(NumNonNullReturn, "Number of function returns marked nonnull");
+STATISTIC(NumNoUndefReturn, "Number of function returns marked noundef");
STATISTIC(NumNoRecurse, "Number of functions marked as norecurse");
STATISTIC(NumNoUnwind, "Number of functions marked as nounwind");
STATISTIC(NumNoFree, "Number of functions marked as nofree");
@@ -1279,6 +1280,39 @@ static void addNonNullAttrs(const SCCNodeSet &SCCNodes,
}
}
+/// Deduce noundef attributes for the SCC.
+static void addNoUndefAttrs(const SCCNodeSet &SCCNodes,
+ SmallSet<Function *, 8> &Changed) {
+ // Check each function in turn, determining which functions return noundef
+ // values.
+ for (Function *F : SCCNodes) {
+ // Already noundef.
+ if (F->getAttributes().hasRetAttr(Attribute::NoUndef))
+ continue;
+
+ // We can infer and propagate function attributes only when we know that the
+ // definition we'll get at link time is *exactly* the definition we see now.
+ // For more details, see GlobalValue::mayBeDerefined.
+ if (!F->hasExactDefinition())
+ return;
+
+ if (F->getReturnType()->isVoidTy())
+ continue;
+
+ if (all_of(*F, [](BasicBlock &BB) {
+ if (auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator())) {
+ // TODO: perform context-sensitive analysis?
+ return isGuaranteedNotToBeUndefOrPoison(Ret->getReturnValue());
+ }
+ return true;
+ })) {
+ F->addRetAttr(Attribute::NoUndef);
+ ++NumNoUndefReturn;
+ Changed.insert(F);
+ }
+ }
+}
+
namespace {
/// Collects a set of attribute inference requests and performs them all in one
@@ -1788,6 +1822,7 @@ deriveAttrsInPostOrder(ArrayRef<Function *> Functions, AARGetterT &&AARGetter,
inferConvergent(Nodes.SCCNodes, Changed);
addNoReturnAttrs(Nodes.SCCNodes, Changed);
addWillReturn(Nodes.SCCNodes, Changed);
+ addNoUndefAttrs(Nodes.SCCNodes, Changed);
// If we have no external nodes participating in the SCC, we can deduce some
// more precise attributes as well.
diff --git a/llvm/test/DebugInfo/X86/array2.ll b/llvm/test/DebugInfo/X86/array2.ll
index 8b386ca44c5fb1..4fe9c9feb86ed1 100644
--- a/llvm/test/DebugInfo/X86/array2.ll
+++ b/llvm/test/DebugInfo/X86/array2.ll
@@ -16,7 +16,7 @@
; RUN: opt --try-experimental-debuginfo-iterators %s -O2 -S -o - | FileCheck %s
; Test that we correctly lower dbg.declares for arrays.
;
-; CHECK: define i32 @main
+; CHECK: define noundef i32 @main
; CHECK: call void @llvm.dbg.value(metadata i32 42, metadata ![[ARRAY:[0-9]+]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32))
; CHECK: ![[ARRAY]] = !DILocalVariable(name: "array",{{.*}} line: 6
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
diff --git a/llvm/test/ThinLTO/X86/devirt.ll b/llvm/test/ThinLTO/X86/devirt.ll
index 3bb5d6b2e4e0df..472e43d776803a 100644
--- a/llvm/test/ThinLTO/X86/devirt.ll
+++ b/llvm/test/ThinLTO/X86/devirt.ll
@@ -100,7 +100,7 @@ target triple = "x86_64-grtev4-linux-gnu"
@_ZTV1D = constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr undef, ptr @_ZN1D1mEi] }, !type !3
-; CHECK-IR-LABEL: define i32 @test
+; CHECK-IR-LABEL: define {{(noundef )?}}i32 @test
define i32 @test(ptr %obj, ptr %obj2, i32 %a) {
entry:
%vtable = load ptr, ptr %obj
diff --git a/llvm/test/ThinLTO/X86/devirt2.ll b/llvm/test/ThinLTO/X86/devirt2.ll
index 1b33741d37bdd0..9e91efeba0da44 100644
--- a/llvm/test/ThinLTO/X86/devirt2.ll
+++ b/llvm/test/ThinLTO/X86/devirt2.ll
@@ -202,7 +202,7 @@ entry:
; CHECK-IR1-LABEL: ret i32
; CHECK-IR1-LABEL: }
-; CHECK-IR2: define i32 @test2
+; CHECK-IR2: define noundef i32 @test2
; CHECK-IR2-NEXT: entry:
; Check that the call was devirtualized. Ignore extra character before
; symbol name which would happen if it was promoted during module
diff --git a/llvm/test/ThinLTO/X86/devirt_check.ll b/llvm/test/ThinLTO/X86/devirt_check.ll
index bf03afa0d8c61c..74f1dfd6ac012a 100644
--- a/llvm/test/ThinLTO/X86/devirt_check.ll
+++ b/llvm/test/ThinLTO/X86/devirt_check.ll
@@ -40,7 +40,7 @@ target triple = "x86_64-grtev4-linux-gnu"
@_ZTV1B = constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* undef, i8* bitcast (i32 (%struct.B*, i32)* @_ZN1B1fEi to i8*), i8* bitcast (i32 (%struct.A*, i32)* @_ZN1A1nEi to i8*)] }, !type !0, !type !1, !vcall_visibility !5
-; CHECK-LABEL: define i32 @test
+; CHECK-LABEL: define {{(noundef )?}}i32 @test
define i32 @test(%struct.A* %obj, i32 %a) {
entry:
%0 = bitcast %struct.A* %obj to i8***
diff --git a/llvm/test/ThinLTO/X86/devirt_promote.ll b/llvm/test/ThinLTO/X86/devirt_promote.ll
index fc2b41f215af1a..d00701be3a1757 100644
--- a/llvm/test/ThinLTO/X86/devirt_promote.ll
+++ b/llvm/test/ThinLTO/X86/devirt_promote.ll
@@ -63,7 +63,7 @@ entry:
; CHECK-IR1-LABEL: ret i32
; CHECK-IR1-LABEL: }
-; CHECK-IR2: define i32 @test2
+; CHECK-IR2: define noundef i32 @test2
; Check that the call was devirtualized.
; CHECK-IR2: %call4 = tail call i32 @_ZN1A1nEi
diff --git a/llvm/test/ThinLTO/X86/devirt_promote_legacy.ll b/llvm/test/ThinLTO/X86/devirt_promote_legacy.ll
index 9d7a40204ba829..542c1e85b6dde4 100644
--- a/llvm/test/ThinLTO/X86/devirt_promote_legacy.ll
+++ b/llvm/test/ThinLTO/X86/devirt_promote_legacy.ll
@@ -45,7 +45,7 @@ entry:
; CHECK-IR1-LABEL: ret i32
; CHECK-IR1-LABEL: }
-; CHECK-IR2: define i32 @test2
+; CHECK-IR2: define noundef i32 @test2
; Check that the call was devirtualized.
; CHECK-IR2: = tail call i32 @_ZN1A1nEi
diff --git a/llvm/test/ThinLTO/X86/devirt_pure_virtual_base.ll b/llvm/test/ThinLTO/X86/devirt_pure_virtual_base.ll
index cff616091e03dd..ea69eedb6e353a 100644
--- a/llvm/test/ThinLTO/X86/devirt_pure_virtual_base.ll
+++ b/llvm/test/ThinLTO/X86/devirt_pure_virtual_base.ll
@@ -66,7 +66,7 @@ target triple = "x86_64-grtev4-linux-gnu"
;; Prevent the vtables from being dead code eliminated.
@llvm.used = appending global [2 x ptr] [ ptr @_ZTV1A, ptr @_ZTV1B]
-; CHECK-IR-LABEL: define dso_local i32 @_start
+; CHECK-IR-LABEL: define dso_local {{(noundef )?}}i32 @_start
define i32 @_start(ptr %obj, i32 %a) {
entry:
%vtable = load ptr, ptr %obj
diff --git a/llvm/test/ThinLTO/X86/devirt_single_hybrid.ll b/llvm/test/ThinLTO/X86/devirt_single_hybrid.ll
index f5a37551085ab6..90fdf0d7dfa090 100644
--- a/llvm/test/ThinLTO/X86/devirt_single_hybrid.ll
+++ b/llvm/test/ThinLTO/X86/devirt_single_hybrid.ll
@@ -24,11 +24,11 @@
; REMARK-COUNT-3: single-impl: devirtualized a call to _ZNK1A1fEv
-; IMPORT: define available_externally hidden i32 @_ZNK1A1fEv(ptr %this)
+; IMPORT: define available_externally hidden {{(noundef )?}}i32 @_ZNK1A1fEv(ptr %this)
; IMPORT-NEXT: entry:
; IMPORT-NEXT: ret i32 3
-; CODEGEN: define hidden i32 @main()
+; CODEGEN: define hidden {{(noundef )?}}i32 @main()
; CODEGEN-NEXT: entry:
; CODEGEN-NEXT: ret i32 23
diff --git a/llvm/test/ThinLTO/X86/devirt_vcall_vis_hidden.ll b/llvm/test/ThinLTO/X86/devirt_vcall_vis_hidden.ll
index 7ebb22c6f98c89..7c007e15a8045d 100644
--- a/llvm/test/ThinLTO/X86/devirt_vcall_vis_hidden.ll
+++ b/llvm/test/ThinLTO/X86/devirt_vcall_vis_hidden.ll
@@ -71,7 +71,7 @@ target triple = "x86_64-grtev4-linux-gnu"
@_ZTV1D = constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr undef, ptr @_ZN1D1mEi] }, !type !3, !vcall_visibility !5
-; CHECK-IR-LABEL: define i32 @test
+; CHECK-IR-LABEL: define {{(noundef )?}}i32 @test
define i32 @test(ptr %obj, ptr %obj2, i32 %a) {
entry:
%vtable = load ptr, ptr %obj
diff --git a/llvm/test/ThinLTO/X86/devirt_vcall_vis_public.ll b/llvm/test/ThinLTO/X86/devirt_vcall_vis_public.ll
index 10dda3fab0baa0..dfb2f8f033d658 100644
--- a/llvm/test/ThinLTO/X86/devirt_vcall_vis_public.ll
+++ b/llvm/test/ThinLTO/X86/devirt_vcall_vis_public.ll
@@ -157,7 +157,7 @@ target triple = "x86_64-grtev4-linux-gnu"
@_ZTV1D = constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr undef, ptr @_ZN1D1mEi] }, !type !3, !vcall_visibility !5
-; CHECK-IR-LABEL: define i32 @test
+; CHECK-IR-LABEL: define {{(noundef )?}}i32 @test
define i32 @test(ptr %obj, ptr %obj2, i32 %a) {
entry:
%vtable = load ptr, ptr %obj
@@ -193,7 +193,7 @@ entry:
; CHECK-IR-LABEL: ret i32
; CHECK-IR-LABEL: }
-; CHECK-IR-LABEL: define i32 @test_public
+; CHECK-IR-LABEL: define {{(noundef )?}}i32 @test_public
define i32 @test_public(ptr %obj, ptr %obj2, i32 %a) {
entry:
%vtable = load ptr, ptr %obj
diff --git a/llvm/test/ThinLTO/X86/funcimport.ll b/llvm/test/ThinLTO/X86/funcimport.ll
index 63a83b6a33b93f..3f7941bb764883 100644
--- a/llvm/test/ThinLTO/X86/funcimport.ll
+++ b/llvm/test/ThinLTO/X86/funcimport.ll
@@ -33,7 +33,7 @@
; Verify that the optimizer run
; RUN: llvm-lto -thinlto-action=optimize %t2.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=OPTIMIZED
-; OPTIMIZED: define i32 @main()
+; OPTIMIZED: define noundef i32 @main()
; Verify that the codegen run
; RUN: llvm-lto -thinlto-action=codegen %t2.bc -o - | llvm-nm -o - | FileCheck %s --check-prefix=CODEGEN
diff --git a/llvm/test/ThinLTO/X86/globals-import-const-fold.ll b/llvm/test/ThinLTO/X86/globals-import-const-fold.ll
index ec94719abfa1f9..caa0103f9f82b2 100644
--- a/llvm/test/ThinLTO/X86/globals-import-const-fold.ll
+++ b/llvm/test/ThinLTO/X86/globals-import-const-fold.ll
@@ -9,7 +9,7 @@
; IMPORT: @baz = internal local_unnamed_addr constant i32 10
-; OPTIMIZE: define i32 @main()
+; OPTIMIZE: define noundef i32 @main()
; OPTIMIZE-NEXT: ret i32 10
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
diff --git a/llvm/test/ThinLTO/X86/import-constant.ll b/llvm/test/ThinLTO/X86/import-constant.ll
index 79d0ef53673337..a614fd9f09d246 100644
--- a/llvm/test/ThinLTO/X86/import-constant.ll
+++ b/llvm/test/ThinLTO/X86/import-constant.ll
@@ -35,7 +35,7 @@
; @outer is a write-only variable that's stored to once, so the store and the global can be removed.
; OPT-NOT: @outer
-; OPT: define dso_local i32 @main()
+; OPT: define dso_local noundef i32 @main()
; OPT-NEXT: entry:
; OPT-NEXT: ret i32 12
diff --git a/llvm/test/ThinLTO/X86/index-const-prop-alias.ll b/llvm/test/ThinLTO/X86/index-const-prop-alias.ll
index 1e4855aa840cd2..91d311853a57ac 100644
--- a/llvm/test/ThinLTO/X86/index-const-prop-alias.ll
+++ b/llvm/test/ThinLTO/X86/index-const-prop-alias.ll
@@ -20,7 +20,7 @@
; IMPORT-NEXT: @g = internal global i32 42, align 4 #0
; IMPORT: attributes #0 = { "thinlto-internalize" }
-; CODEGEN: define dso_local i32 @main
+; CODEGEN: define dso_local noundef i32 @main
; CODEGEN-NEXT: ret i32 42
; PRESERVED: @g.alias = external global i32
diff --git a/llvm/test/ThinLTO/X86/index-const-prop.ll b/llvm/test/ThinLTO/X86/index-const-prop.ll
index 5087ec6ad5cab3..f55fc23d1f32b8 100644
--- a/llvm/test/ThinLTO/X86/index-const-prop.ll
+++ b/llvm/test/ThinLTO/X86/index-const-prop.ll
@@ -23,7 +23,7 @@
; IMPORT-NEXT: @gFoo.llvm.0 = internal unnamed_addr global i32 1, align 4, !dbg !5
; IMPORT: !DICompileUnit({{.*}})
-; OPTIMIZE: define i32 @main
+; OPTIMIZE: define noundef i32 @main
; OPTIMIZE-NEXT: ret i32 3
; IMPORT2: @gBar = available_externally local_unnamed_addr global i32 2, align 4, !dbg !0
diff --git a/llvm/test/Transforms/FunctionAttrs/nocapture.ll b/llvm/test/Transforms/FunctionAttrs/nocapture.ll
index eb999d69d95f1e..3d483f671b1af7 100644
--- a/llvm/test/Transforms/FunctionAttrs/nocapture.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nocapture.ll
@@ -55,7 +55,7 @@ define void @c3(ptr %q) {
define i1 @c4(ptr %q, i32 %bitno) {
; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
-; FNATTRS-LABEL: define i1 @c4
+; FNATTRS-LABEL: define noundef i1 @c4
; FNATTRS-SAME: (ptr [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR0]] {
; FNATTRS-NEXT: [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32
; FNATTRS-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]]
@@ -91,7 +91,7 @@ l1:
; c4b is c4 but without the escaping part
define i1 @c4b(ptr %q, i32 %bitno) {
; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
-; FNATTRS-LABEL: define i1 @c4b
+; FNATTRS-LABEL: define noundef i1 @c4b
; FNATTRS-SAME: (ptr [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR0]] {
; FNATTRS-NEXT: [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32
; FNATTRS-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]]
@@ -160,7 +160,7 @@ declare void @throw_if_bit_set(ptr, i8) readonly
define i1 @c6(ptr %q, i8 %bit) personality ptr @__gxx_personality_v0 {
; FNATTRS: Function Attrs: nofree memory(read)
-; FNATTRS-LABEL: define i1 @c6
+; FNATTRS-LABEL: define noundef i1 @c6
; FNATTRS-SAME: (ptr readonly [[Q:%.*]], i8 [[BIT:%.*]]) #[[ATTR5:[0-9]+]] personality ptr @__gxx_personality_v0 {
; FNATTRS-NEXT: invoke void @throw_if_bit_set(ptr [[Q]], i8 [[BIT]])
; FNATTRS-NEXT: to label [[RET0:%.*]] unwind label [[RET1:%.*]]
@@ -813,7 +813,7 @@ define i1 @nocaptureInboundsGEPICmpRev(ptr %x) {
define i1 @nocaptureDereferenceableOrNullICmp(ptr dereferenceable_or_null(4) %x) {
; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
-; FNATTRS-LABEL: define i1 @nocaptureDereferenceableOrNullICmp
+; FNATTRS-LABEL: define noundef i1 @nocaptureDereferenceableOrNullICmp
; FNATTRS-SAME: (ptr nocapture readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR0]] {
; FNATTRS-NEXT: [[TMP1:%.*]] = icmp eq ptr [[X]], null
; FNATTRS-NEXT: ret i1 [[TMP1]]
@@ -830,7 +830,7 @@ define i1 @nocaptureDereferenceableOrNullICmp(ptr dereferenceable_or_null(4) %x)
define i1 @captureDereferenceableOrNullICmp(ptr dereferenceable_or_null(4) %x) null_pointer_is_valid {
; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none)
-; FNATTRS-LABEL: define i1 @captureDereferenceableOrNullICmp
+; FNATTRS-LABEL: define noundef i1 @captureDereferenceableOrNullICmp
; FNATTRS-SAME: (ptr readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR16:[0-9]+]] {
; FNATTRS-NEXT: [[TMP1:%.*]] = icmp eq ptr [[X]], null
; FNATTRS-NEXT: ret i1 [[TMP1]]
diff --git a/llvm/test/Transforms/FunctionAttrs/nonnull.ll b/llvm/test/Transforms/FunctionAttrs/nonnull.ll
index 7ca07e549346d6..d9bdb6298ed0fd 100644
--- a/llvm/test/Transforms/FunctionAttrs/nonnull.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nonnull.ll
@@ -32,14 +32,23 @@ define ptr @test2(ptr nonnull %p) {
; Given an SCC where one of the functions can not be marked nonnull,
; can we still mark the other one which is trivially nonnull
define ptr @scc_binder(i1 %c) {
-; COMMON-LABEL: define ptr @scc_binder(
-; COMMON-SAME: i1 [[C:%.*]]) {
-; COMMON-NEXT: br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]
-; COMMON: rec:
-; COMMON-NEXT: [[TMP1:%.*]] = call ptr @test3(i1 [[C]])
-; COMMON-NEXT: br label [[END]]
-; COMMON: end:
-; COMMON-NEXT: ret ptr null
+; FNATTRS-LABEL: define noundef ptr @scc_binder(
+; FNATTRS-SAME: i1 [[C:%.*]]) {
+; FNATTRS-NEXT: br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]
+; FNATTRS: rec:
+; FNATTRS-NEXT: [[TMP1:%.*]] = call ptr @test3(i1 [[C]])
+; FNATTRS-NEXT: br label [[END]]
+; FNATTRS: end:
+; FNATTRS-NEXT: ret ptr null
+;
+; ATTRIBUTOR-LABEL: define ptr @scc_binder(
+; ATTRIBUTOR-SAME: i1 [[C:%.*]]) {
+; ATTRIBUTOR-NEXT: br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]
+; ATTRIBUTOR: rec:
+; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = call ptr @test3(i1 [[C]])
+; ATTRIBUTOR-NEXT: br label [[END]]
+; ATTRIBUTOR: end:
+; ATTRIBUTOR-NEXT: ret ptr null
;
br i1 %c, label %rec, label %end
rec:
@@ -97,7 +106,7 @@ define ptr @test4() {
; Given a mutual recursive set of functions which *can* return null
; make sure we haven't marked them as nonnull.
define ptr @test5_helper(i1 %c) {
-; FNATTRS-LABEL: define noalias ptr @test5_helper(
+; FNATTRS-LABEL: define noalias noundef ptr @test5_helper(
; FNATTRS-SAME: i1 [[C:%.*]]) #[[ATTR1]] {
; FNATTRS-NEXT: br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]
; FNATTRS: rec:
@@ -124,7 +133,7 @@ end:
}
define ptr @test5(i1 %c) {
-; FNATTRS-LABEL: define noalias ptr @test5(
+; FNATTRS-LABEL: define noalias noundef ptr @test5(
; FNATTRS-SAME: i1 [[C:%.*]]) #[[ATTR1]] {
; FNATTRS-NEXT: [[RET:%.*]] = call ptr @test5_helper(i1 [[C]])
; FNATTRS-NEXT: ret ptr [[RET]]
@@ -892,7 +901,7 @@ define i8 @parent7(ptr %a) {
declare i32 @esfp(...)
define i1 @parent8(ptr %a, ptr %bogus1, ptr %b) personality ptr @esfp{
-; FNATTRS-LABEL: define i1 @parent8(
+; FNATTRS-LABEL: define noundef i1 @parent8(
; FNATTRS-SAME: ptr nonnull [[A:%.*]], ptr nocapture readnone [[BOGUS1:%.*]], ptr nonnull [[B:%.*]]) #[[ATTR7]] personality ptr @esfp {
; FNATTRS-NEXT: entry:
; FNATTRS-NEXT: invoke void @use2nonnull(ptr [[A]], ptr [[B]])
@@ -981,7 +990,7 @@ define ptr addrspace(3) @gep2(ptr addrspace(3) %p) {
; FIXME: We should propagate dereferenceable here but *not* nonnull
define ptr addrspace(3) @as(ptr addrspace(3) dereferenceable(4) %p) {
-; FNATTRS-LABEL: define ptr addrspace(3) @as(
+; FNATTRS-LABEL: define noundef ptr addrspace(3) @as(
; FNATTRS-SAME: ptr addrspace(3) readnone returned dereferenceable(4) [[P:%.*]]) #[[ATTR0]] {
; FNATTRS-NEXT: ret ptr addrspace(3) [[P]]
;
@@ -993,7 +1002,7 @@ define ptr addrspace(3) @as(ptr addrspace(3) dereferenceable(4) %p) {
}
define internal ptr @g2() {
-; FNATTRS-LABEL: define internal nonnull ptr @g2(
+; FNATTRS-LABEL: define internal noundef nonnull ptr @g2(
; FNATTRS-SAME: ) #[[ATTR0]] {
; FNATTRS-NEXT: ret ptr inttoptr (i64 4 to ptr)
;
@@ -1005,7 +1014,7 @@ define internal ptr @g2() {
}
define ptr @g1() {
-; FNATTRS-LABEL: define nonnull ptr @g1(
+; FNATTRS-LABEL: define noundef nonnull ptr @g1(
; FNATTRS-SAME: ) #[[ATTR0]] {
; FNATTRS-NEXT: [[C:%.*]] = call ptr @g2()
; FNATTRS-NEXT: ret ptr [[C]]
diff --git a/llvm/test/Transforms/FunctionAttrs/noundef.ll b/llvm/test/Transforms/FunctionAttrs/noundef.ll
index 9eca495e111e8f..b357587cc12394 100644
--- a/llvm/test/Transforms/FunctionAttrs/noundef.ll
+++ b/llvm/test/Transforms/FunctionAttrs/noundef.ll
@@ -2,7 +2,7 @@
; RUN: opt < %s -passes='function-attrs' -S | FileCheck %s
define i32 @test_ret_constant() {
-; CHECK-LABEL: define i32 @test_ret_constant(
+; CHECK-LABEL: define noundef i32 @test_ret_constant(
; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: ret i32 0
;
@@ -34,7 +34,7 @@ define i32 @test_ret_param(i32 %x) {
}
define i32 @test_ret_noundef_param(i32 noundef %x) {
-; CHECK-LABEL: define i32 @test_ret_noundef_param(
+; CHECK-LABEL: define noundef i32 @test_ret_noundef_param(
; CHECK-SAME: i32 noundef returned [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: ret i32 [[X]]
;
@@ -42,7 +42,7 @@ define i32 @test_ret_noundef_param(i32 noundef %x) {
}
define i32 @test_ret_noundef_expr(i32 noundef %x) {
-; CHECK-LABEL: define i32 @test_ret_noundef_expr(
+; CHECK-LABEL: define noundef i32 @test_ret_noundef_expr(
; CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[Y:%.*]] = add i32 [[X]], 1
; CHECK-NEXT: ret i32 [[Y]]
@@ -62,7 +62,7 @@ define i32 @test_ret_create_poison_expr(i32 noundef %x) {
}
define i32 @test_ret_freezed(i32 noundef %x) {
-; CHECK-LABEL: define i32 @test_ret_freezed(
+; CHECK-LABEL: define noundef i32 @test_ret_freezed(
; CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[Y:%.*]] = add nsw i32 [[X]], 1
; CHECK-NEXT: [[Z:%.*]] = freeze i32 [[Y]]
@@ -74,7 +74,7 @@ define i32 @test_ret_freezed(i32 noundef %x) {
}
define i32 @test_ret_control_flow(i32 noundef %x) {
-; CHECK-LABEL: define i32 @test_ret_control_flow(
+; CHECK-LABEL: define noundef i32 @test_ret_control_flow(
; CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[X]], 0
; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
@@ -135,7 +135,7 @@ if.else:
}
define i32 @test_noundef_prop() {
-; CHECK-LABEL: define i32 @test_noundef_prop(
+; CHECK-LABEL: define noundef i32 @test_noundef_prop(
; CHECK-SAME: ) #[[ATTR0]] {
; CHECK-NEXT: [[RET:%.*]] = call i32 @test_ret_constant()
; CHECK-NEXT: ret i32 [[RET]]
diff --git a/llvm/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll b/llvm/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll
index 4b23583b8754df..6209ddc8317e86 100644
--- a/llvm/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll
+++ b/llvm/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll
@@ -17,7 +17,7 @@ define void @va_func(ptr readonly %b, ...) readonly nounwind {
}
define i32 @caller(ptr %x) {
-; CHECK-LABEL: define i32 @caller(ptr nocapture readonly %x)
+; CHECK-LABEL: define noundef i32 @caller(ptr nocapture readonly %x)
entry:
call void(ptr,...) @va_func(ptr null, i32 0, i32 0, i32 0, ptr %x)
ret i32 42
@@ -34,7 +34,7 @@ define void @va_func2(ptr readonly %b, ...) {
}
define i32 @caller2(ptr %x, ptr %y) {
-; CHECK-LABEL: define i32 @caller2(ptr nocapture readonly %x, ptr %y)
+; CHECK-LABEL: define noundef i32 @caller2(ptr nocapture readonly %x, ptr %y)
entry:
call void(ptr,...) @va_func2(ptr %x, i32 0, i32 0, i32 0, ptr %y)
ret i32 42
diff --git a/llvm/test/Transforms/Inline/devirtualize-3.ll b/llvm/test/Transforms/Inline/devirtualize-3.ll
index b4f80072391ade..8ef20301a4e0e8 100644
--- a/llvm/test/Transforms/Inline/devirtualize-3.ll
+++ b/llvm/test/Transforms/Inline/devirtualize-3.ll
@@ -1,7 +1,7 @@
; RUN: opt -aa-pipeline=basic-aa -S -passes='default<O2>' < %s | FileCheck %s
; PR5009
-; CHECK: define i32 @main()
+; CHECK: define noundef i32 @main()
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @exit(i32 38)
diff --git a/llvm/test/Transforms/Inline/devirtualize-5.ll b/llvm/test/Transforms/Inline/devirtualize-5.ll
index dbfe445e898c75..298113dbaec2e9 100644
--- a/llvm/test/Transforms/Inline/devirtualize-5.ll
+++ b/llvm/test/Transforms/Inline/devirtualize-5.ll
@@ -5,7 +5,7 @@ define i32 @i() alwaysinline {
ret i32 45
}
-; CHECK-LABEL: define i32 @main
+; CHECK-LABEL: define {{(noundef )?}}i32 @main
; CHECK-NEXT: ret i32 45
define i32 @main() {
diff --git a/llvm/test/Transforms/Inline/launder.invariant.group.ll b/llvm/test/Transforms/Inline/launder.invariant.group.ll
index 71df7965136976..9c1ddf7b5666ed 100644
--- a/llvm/test/Transforms/Inline/launder.invariant.group.ll
+++ b/llvm/test/Transforms/Inline/launder.invariant.group.ll
@@ -7,7 +7,7 @@
; This test checks if value returned from the launder is considered aliasing
; with its argument. Due to bug caused by handling launder in capture tracking
; sometimes it would be considered noalias.
-; CHECK-LABEL: define i32 @bar(ptr noalias
+; CHECK-LABEL: define {{(noundef )?}}i32 @bar(ptr noalias
define i32 @bar(ptr noalias) {
; CHECK-NOT: noalias
%2 = call ptr @llvm.launder.invariant.group.p0(ptr %0)
@@ -18,7 +18,7 @@ define i32 @bar(ptr noalias) {
ret i32 %5
}
-; CHECK-LABEL: define i32 @foo(ptr noalias
+; CHECK-LABEL: define {{(noundef )?}}i32 @foo(ptr noalias
define i32 @foo(ptr noalias) {
; CHECK-NOT: call i32 @bar(
; CHECK-NOT: !noalias
diff --git a/llvm/test/Transforms/PhaseOrdering/AArch64/constraint-elimination-placement.ll b/llvm/test/Transforms/PhaseOrdering/AArch64/constraint-elimination-placement.ll
index eb813bdb8c4ee9..ad4d4cf28ace64 100644
--- a/llvm/test/Transforms/PhaseOrdering/AArch64/constraint-elimination-placement.ll
+++ b/llvm/test/Transforms/PhaseOrdering/AArch64/constraint-elimination-placement.ll
@@ -5,7 +5,7 @@ target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
target triple = "arm64-apple-macosx"
define i1 @test_order_1(ptr %this, ptr noalias %other, i1 %tobool9.not, i32 %call) {
-; CHECK-LABEL: define i1 @test_order_1(
+; CHECK-LABEL: define noundef i1 @test_order_1(
; CHECK-SAME: ptr nocapture writeonly [[THIS:%.*]], ptr noalias [[OTHER:%.*]], i1 [[TOBOOL9_NOT:%.*]], i32 [[CALL:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[TOBOOL9_NOT]], label [[EXIT:%.*]], label [[FOR_COND_PREHEADER:%.*]]
@@ -105,14 +105,14 @@ define void @test2(ptr %this) #0 {
; CHECK-NEXT: i64 17, label [[IF_END_I31:%.*]]
; CHECK-NEXT: ]
; CHECK: if.end.i:
-; CHECK-NEXT: [[CALL8_I_I:%.*]] = tail call fastcc i32 @test2_fn6()
+; CHECK-NEXT: [[CALL8_I_I:%.*]] = tail call fastcc noundef i32 @test2_fn6()
; CHECK-NEXT: [[TRUNC_I_I:%.*]] = trunc i32 [[CALL8_I_I]] to i8
; CHECK-NEXT: [[CALL1_I1_I:%.*]] = tail call i1 @test2_fn4(i8 [[TRUNC_I_I]])
; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[CALL1_I1_I]], true
; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP0]])
; CHECK-NEXT: br label [[COMMON_RET]]
; CHECK: test2_fn2.exit12:
-; CHECK-NEXT: [[CALL8_I_I8:%.*]] = tail call fastcc i32 @test2_fn6()
+; CHECK-NEXT: [[CALL8_I_I8:%.*]] = tail call fastcc noundef i32 @test2_fn6()
; CHECK-NEXT: [[TRUNC_I_I9:%.*]] = trunc i32 [[CALL8_I_I8]] to i8
; CHECK-NEXT: [[CALL1_I1_I10:%.*]] = tail call i1 @test2_fn4(i8 [[TRUNC_I_I9]])
; CHECK-NEXT: [[TMP1:%.*]] = xor i1 [[CALL1_I1_I10]], true
@@ -125,11 +125,11 @@ define void @test2(ptr %this) #0 {
; CHECK-NEXT: store i8 0, ptr [[THIS]], align 4
; CHECK-NEXT: br label [[COMMON_RET]]
; CHECK: if.end.i31:
-; CHECK-NEXT: [[DOTPRE:%.*]] = tail call fastcc i32 @test2_fn6()
-; CHECK-NEXT: [[DOTPRE38:%.*]] = trunc i32 [[DOTPRE]] to i8
-; CHECK-NEXT: [[DOTPRE39:%.*]] = tail call i1 @test2_fn4(i8 [[DOTPRE38]])
-; CHECK-NEXT: [[DOTPRE40:%.*]] = xor i1 [[DOTPRE39]], true
-; CHECK-NEXT: tail call void @llvm.assume(i1 [[DOTPRE40]])
+; CHECK-NEXT: [[CALL8_I_I32:%.*]] = tail call fastcc noundef i32 @test2_fn6()
+; CHECK-NEXT: [[TRUNC_I_I33:%.*]] = trunc i32 [[CALL8_I_I32]] to i8
+; CHECK-NEXT: [[CALL1_I1_I34:%.*]] = tail call i1 @test2_fn4(i8 [[TRUNC_I_I33]])
+; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[CALL1_I1_I34]], true
+; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP2]])
; CHECK-NEXT: br label [[COMMON_RET]]
;
entry:
@@ -152,7 +152,7 @@ if.else21: ; preds = %entry
}
define i1 @test2_fn2(ptr %__rhs) #0 {
-; CHECK-LABEL: define i1 @test2_fn2(
+; CHECK-LABEL: define noundef i1 @test2_fn2(
; CHECK-SAME: ptr nocapture readonly [[__RHS:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[__RHS]])
@@ -162,7 +162,7 @@ define i1 @test2_fn2(ptr %__rhs) #0 {
; CHECK-NEXT: [[CMP2_NOT:%.*]] = icmp eq i64 [[CALL]], [[COND_I]]
; CHECK-NEXT: br i1 [[CMP2_NOT]], label [[IF_END:%.*]], label [[CLEANUP:%.*]]
; CHECK: if.end:
-; CHECK-NEXT: [[CALL8_I:%.*]] = tail call fastcc i32 @test2_fn6()
+; CHECK-NEXT: [[CALL8_I:%.*]] = tail call fastcc noundef i32 @test2_fn6()
; CHECK-NEXT: [[TRUNC_I:%.*]] = trunc i32 [[CALL8_I]] to i8
; CHECK-NEXT: [[CALL1_I1:%.*]] = tail call i1 @test2_fn4(i8 [[TRUNC_I]])
; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[CALL1_I1]], true
@@ -231,7 +231,7 @@ entry:
}
define internal i32 @test2_fn6() {
-; CHECK-LABEL: define internal fastcc i32 @test2_fn6(
+; CHECK-LABEL: define internal fastcc noundef i32 @test2_fn6(
; CHECK-SAME: ) unnamed_addr #[[ATTR5]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i32 0
diff --git a/llvm/test/Transforms/PhaseOrdering/X86/merge-functions.ll b/llvm/test/Transforms/PhaseOrdering/X86/merge-functions.ll
index 0e751ce4e55a5a..8f1c52c591631f 100644
--- a/llvm/test/Transforms/PhaseOrdering/X86/merge-functions.ll
+++ b/llvm/test/Transforms/PhaseOrdering/X86/merge-functions.ll
@@ -90,7 +90,7 @@ bb3: ; preds = %bb1, %bb2
define i1 @test2(i32 %c) {
; CHECK-LABEL: @test2(
-; CHECK-NEXT: [[TMP2:%.*]] = tail call i1 @test1(i32 [[TMP0:%.*]]) #[[ATTR0:[0-9]+]]
+; CHECK-NEXT: [[TMP2:%.*]] = tail call noundef i1 @test1(i32 [[TMP0:%.*]]) #[[ATTR0:[0-9]+]]
; CHECK-NEXT: ret i1 [[TMP2]]
;
entry:
diff --git a/llvm/test/Transforms/PhaseOrdering/bitcast-store-branch.ll b/llvm/test/Transforms/PhaseOrdering/bitcast-store-branch.ll
index 678ac59a694b3a..4c9cd3090681eb 100644
--- a/llvm/test/Transforms/PhaseOrdering/bitcast-store-branch.ll
+++ b/llvm/test/Transforms/PhaseOrdering/bitcast-store-branch.ll
@@ -11,7 +11,7 @@ entry:
}
define ptr @parent(ptr align 8 dereferenceable(72) %f, half %val1, i16 %val2, i32 %val3) align 2 {
-; CHECK-LABEL: define nonnull ptr @parent
+; CHECK-LABEL: define noundef nonnull ptr @parent
; CHECK-SAME: (ptr readonly returned align 8 dereferenceable(72) [[F:%.*]], half [[VAL1:%.*]], i16 [[VAL2:%.*]], i32 [[VAL3:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] align 2 {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[F]], i64 64
diff --git a/llvm/test/Transforms/PhaseOrdering/dce-after-argument-promotion-loads.ll b/llvm/test/Transforms/PhaseOrdering/dce-after-argument-promotion-loads.ll
index ee913d299aaab7..a3d111fffbbf6d 100644
--- a/llvm/test/Transforms/PhaseOrdering/dce-after-argument-promotion-loads.ll
+++ b/llvm/test/Transforms/PhaseOrdering/dce-after-argument-promotion-loads.ll
@@ -13,7 +13,7 @@ entry:
}
define ptr @parent(ptr align 8 dereferenceable(72) %f, i16 %val1, i16 %val2, i32 %val3) align 2 {
-; CHECK-LABEL: define nonnull ptr @parent
+; CHECK-LABEL: define noundef nonnull ptr @parent
; CHECK-SAME: (ptr readonly returned align 8 dereferenceable(72) [[F:%.*]], i16 [[VAL1:%.*]], i16 [[VAL2:%.*]], i32 [[VAL3:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] align 2 {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[F]], i64 64
diff --git a/llvm/test/Transforms/PhaseOrdering/early-arg-attrs-inference.ll b/llvm/test/Transforms/PhaseOrdering/early-arg-attrs-inference.ll
index a42e4dd75d9fc9..ba4583160b137b 100644
--- a/llvm/test/Transforms/PhaseOrdering/early-arg-attrs-inference.ll
+++ b/llvm/test/Transforms/PhaseOrdering/early-arg-attrs-inference.ll
@@ -2,7 +2,7 @@
; RUN: opt -S -O3 -memssa-check-limit=1 -memdep-block-scan-limit=1 < %s | FileCheck %s
define i32 @f(ptr noalias %p, i32 %c) {
-; CHECK-LABEL: define i32 @f
+; CHECK-LABEL: define noundef i32 @f
; CHECK-SAME: (ptr noalias nocapture readonly [[P:%.*]], i32 [[C:%.*]]) local_unnamed_addr {
; CHECK-NEXT: tail call void @g()
; CHECK-NEXT: tail call void @g()
diff --git a/llvm/test/Transforms/PhaseOrdering/gep-null-compare-in-loop.ll b/llvm/test/Transforms/PhaseOrdering/gep-null-compare-in-loop.ll
index 545e203c5e2c95..fba3c1c154d80e 100644
--- a/llvm/test/Transforms/PhaseOrdering/gep-null-compare-in-loop.ll
+++ b/llvm/test/Transforms/PhaseOrdering/gep-null-compare-in-loop.ll
@@ -33,7 +33,7 @@ bb12:
}
define i32 @using_alloca() {
-; CHECK-LABEL: define i32 @using_alloca
+; CHECK-LABEL: define noundef i32 @using_alloca
; CHECK-SAME: () local_unnamed_addr #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: bb:
; CHECK-NEXT: ret i32 6
@@ -51,7 +51,7 @@ bb:
}
define i32 @using_malloc() {
-; CHECK-LABEL: define i32 @using_malloc
+; CHECK-LABEL: define noundef i32 @using_malloc
; CHECK-SAME: () local_unnamed_addr #[[ATTR0]] {
; CHECK-NEXT: bb:
; CHECK-NEXT: ret i32 6
diff --git a/llvm/test/Transforms/SampleProfile/ctxsplit.ll b/llvm/test/Transforms/SampleProfile/ctxsplit.ll
index 0b105e1aa703b1..46e088a63e941f 100644
--- a/llvm/test/Transforms/SampleProfile/ctxsplit.ll
+++ b/llvm/test/Transforms/SampleProfile/ctxsplit.ll
@@ -10,16 +10,16 @@
; be read in non-thinlto mode.
; RUN: opt < %s -passes='default<O2>' -pgo-kind=pgo-sample-use-pipeline -use-profiled-call-graph=0 -profile-file=%S/Inputs/ctxsplit.extbinary.afdo -S | FileCheck %s --check-prefix=NOTHINLTO
-; POSTLINK: define dso_local i32 @goo() {{.*}} !prof ![[ENTRY1:[0-9]+]] {
-; POSTLINK: define dso_local i32 @foo() {{.*}} !prof ![[ENTRY2:[0-9]+]] {
+; POSTLINK: define dso_local noundef i32 @goo() {{.*}} !prof ![[ENTRY1:[0-9]+]] {
+; POSTLINK: define dso_local noundef i32 @foo() {{.*}} !prof ![[ENTRY2:[0-9]+]] {
; POSTLINK: ![[ENTRY1]] = !{!"function_entry_count", i64 1001}
; POSTLINK: ![[ENTRY2]] = !{!"function_entry_count", i64 -1}
-; PRELINK: define dso_local i32 @goo() {{.*}} !prof ![[ENTRY1:[0-9]+]] {
-; PRELINK: define dso_local i32 @foo() {{.*}} !prof ![[ENTRY2:[0-9]+]] {
+; PRELINK: define dso_local noundef i32 @goo() {{.*}} !prof ![[ENTRY1:[0-9]+]] {
+; PRELINK: define dso_local noundef i32 @foo() {{.*}} !prof ![[ENTRY2:[0-9]+]] {
; PRELINK: ![[ENTRY1]] = !{!"function_entry_count", i64 1001}
; PRELINK: ![[ENTRY2]] = !{!"function_entry_count", i64 3001}
-; NOTHINLTO: define dso_local i32 @goo() {{.*}} !prof ![[ENTRY1:[0-9]+]] {
-; NOTHINLTO: define dso_local i32 @foo() {{.*}} !prof ![[ENTRY2:[0-9]+]] {
+; NOTHINLTO: define dso_local noundef i32 @goo() {{.*}} !prof ![[ENTRY1:[0-9]+]] {
+; NOTHINLTO: define dso_local noundef i32 @foo() {{.*}} !prof ![[ENTRY2:[0-9]+]] {
; NOTHINLTO: ![[ENTRY1]] = !{!"function_entry_count", i64 1001}
; NOTHINLTO: ![[ENTRY2]] = !{!"function_entry_count", i64 3001}
More information about the cfe-commits
mailing list