[llvm] bf8d039 - [Inliner] Add some additional tests for progagating attributes before inlining; NFC

Noah Goldstein via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 28 15:27:54 PDT 2023


Author: Noah Goldstein
Date: 2023-09-28T17:27:41-05:00
New Revision: bf8d03921d3cb599eebcd77e1c0f7d7dd59d42d5

URL: https://github.com/llvm/llvm-project/commit/bf8d03921d3cb599eebcd77e1c0f7d7dd59d42d5
DIFF: https://github.com/llvm/llvm-project/commit/bf8d03921d3cb599eebcd77e1c0f7d7dd59d42d5.diff

LOG: [Inliner] Add some additional tests for progagating attributes before inlining; NFC

Added: 
    llvm/test/Transforms/Inline/access-attributes-prop.ll
    llvm/test/Transforms/Inline/ret_attr_align_and_noundef.ll

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/Inline/access-attributes-prop.ll b/llvm/test/Transforms/Inline/access-attributes-prop.ll
new file mode 100644
index 000000000000000..3b4a59897c5694a
--- /dev/null
+++ b/llvm/test/Transforms/Inline/access-attributes-prop.ll
@@ -0,0 +1,498 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes
+; RUN: opt -S -passes=inline %s | FileCheck %s
+; RUN: opt -S -passes='cgscc(inline)' %s | FileCheck %s
+; RUN: opt -S -passes='module-inline' %s | FileCheck %s
+
+declare void @bar1(ptr %p)
+declare void @bar2(ptr %p, ptr %p2)
+
+define dso_local void @foo1_rdonly(ptr readonly %p) {
+; CHECK-LABEL: define {{[^@]+}}@foo1_rdonly
+; CHECK-SAME: (ptr readonly [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @bar1(ptr %p)
+  ret void
+}
+
+define dso_local void @foo1(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@foo1
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @bar1(ptr %p)
+  ret void
+}
+
+define dso_local void @foo1_bar_aligned64_deref512(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@foo1_bar_aligned64_deref512
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr align 64 dereferenceable(512) [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @bar1(ptr align 64 dereferenceable(512) %p)
+  ret void
+}
+
+define dso_local void @foo1_bar_aligned512_deref_or_null512(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@foo1_bar_aligned512_deref_or_null512
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr align 512 dereferenceable_or_null(512) [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @bar1(ptr align 512 dereferenceable_or_null(512) %p)
+  ret void
+}
+
+define dso_local void @foo2(ptr %p, ptr %p2) {
+; CHECK-LABEL: define {{[^@]+}}@foo2
+; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @bar2(ptr %p, ptr %p)
+  ret void
+}
+
+define dso_local void @foo2_2(ptr %p, ptr %p2) {
+; CHECK-LABEL: define {{[^@]+}}@foo2_2
+; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT:    call void @bar2(ptr [[P2]], ptr [[P2]])
+; CHECK-NEXT:    ret void
+;
+  call void @bar2(ptr %p2, ptr %p2)
+  ret void
+}
+
+define dso_local void @foo2_3(ptr %p, ptr readnone %p2) {
+; CHECK-LABEL: define {{[^@]+}}@foo2_3
+; CHECK-SAME: (ptr [[P:%.*]], ptr readnone [[P2:%.*]]) {
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[P2]])
+; CHECK-NEXT:    ret void
+;
+  call void @bar2(ptr %p, ptr %p2)
+  ret void
+}
+
+define dso_local void @buz1_wronly(ptr %p) writeonly {
+; CHECK: Function Attrs: memory(write)
+; CHECK-LABEL: define {{[^@]+}}@buz1_wronly
+; CHECK-SAME: (ptr [[P:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @bar1(ptr %p)
+  ret void
+}
+
+define dso_local void @buz1(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@buz1
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @bar1(ptr %p)
+  ret void
+}
+
+define dso_local void @buz1_wronly_fail_alloca(ptr %p) writeonly {
+; CHECK: Function Attrs: memory(write)
+; CHECK-LABEL: define {{[^@]+}}@buz1_wronly_fail_alloca
+; CHECK-SAME: (ptr [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[A]])
+; CHECK-NEXT:    ret void
+;
+  %a = alloca i32, align 4
+  call void @bar2(ptr %p, ptr %a)
+  ret void
+}
+
+define dso_local void @buz1_fail_alloca(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@buz1_fail_alloca
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[A]])
+; CHECK-NEXT:    ret void
+;
+  %a = alloca i32, align 4
+  call void @bar2(ptr %p, ptr %a)
+  ret void
+}
+
+define dso_local void @buz1_wronly_partially_okay_alloca(ptr %p) writeonly {
+; CHECK: Function Attrs: memory(write)
+; CHECK-LABEL: define {{[^@]+}}@buz1_wronly_partially_okay_alloca
+; CHECK-SAME: (ptr [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[A]])
+; CHECK-NEXT:    ret void
+;
+  call void @bar1(ptr %p)
+  %a = alloca i32, align 4
+  call void @bar2(ptr %p, ptr %a)
+  ret void
+}
+
+define dso_local void @buz1_partially_okay_alloca(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@buz1_partially_okay_alloca
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[A]])
+; CHECK-NEXT:    ret void
+;
+  call void @bar1(ptr %p)
+  %a = alloca i32, align 4
+  call void @bar2(ptr %p, ptr %a)
+  ret void
+}
+
+define dso_local void @foo2_through_obj(ptr %p, ptr %p2) {
+; CHECK-LABEL: define {{[^@]+}}@foo2_through_obj
+; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT:    [[PP:%.*]] = getelementptr i8, ptr [[P]], i64 9
+; CHECK-NEXT:    [[P2P:%.*]] = getelementptr i8, ptr [[P2]], i64 123
+; CHECK-NEXT:    call void @bar2(ptr [[P2P]], ptr [[PP]])
+; CHECK-NEXT:    ret void
+;
+  %pp = getelementptr i8, ptr %p, i64 9
+  %p2p = getelementptr i8, ptr %p2, i64 123
+  call void @bar2(ptr %p2p, ptr %pp)
+  ret void
+}
+
+define void @prop_param_func_decl(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_param_func_decl
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1_rdonly(ptr %p)
+  ret void
+}
+
+define void @prop_param_callbase_def(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1(ptr readonly %p)
+  call void @bar1(ptr %p)
+  ret void
+}
+
+define void @prop_param_callbase_def_2x(ptr %p, ptr %p2) {
+; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_2x
+; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo2(ptr readonly %p, ptr %p)
+  ret void
+}
+
+define void @prop_param_callbase_def_2x_2(ptr %p, ptr %p2) {
+; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_2x_2
+; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT:    [[PP_I:%.*]] = getelementptr i8, ptr [[P]], i64 9
+; CHECK-NEXT:    [[P2P_I:%.*]] = getelementptr i8, ptr [[P2]], i64 123
+; CHECK-NEXT:    call void @bar2(ptr [[P2P_I]], ptr [[PP_I]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo2_through_obj(ptr readonly %p, ptr writeonly %p2)
+  ret void
+}
+
+define void @prop_param_callbase_def_2x_incompat(ptr %p, ptr %p2) {
+; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_2x_incompat
+; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT:    [[PP_I:%.*]] = getelementptr i8, ptr [[P]], i64 9
+; CHECK-NEXT:    [[P2P_I:%.*]] = getelementptr i8, ptr [[P]], i64 123
+; CHECK-NEXT:    call void @bar2(ptr [[P2P_I]], ptr [[PP_I]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo2_through_obj(ptr readnone %p, ptr readonly %p)
+  ret void
+}
+
+define void @prop_param_callbase_def_2x_incompat_2(ptr %p, ptr %p2) {
+; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_2x_incompat_2
+; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo2(ptr readonly %p, ptr readnone %p)
+  ret void
+}
+
+define void @prop_param_callbase_def_2x_incompat_3(ptr %p, ptr %p2) {
+; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_2x_incompat_3
+; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo2_2(ptr readonly %p, ptr readnone %p)
+  ret void
+}
+
+define void @prop_param_callbase_def_1x_partial(ptr %p, ptr %p2) {
+; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_1x_partial
+; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo2(ptr readonly %p, ptr %p)
+  ret void
+}
+
+define void @prop_param_callbase_def_1x_partial_2(ptr %p, ptr %p2) {
+; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_1x_partial_2
+; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo2_2(ptr readonly %p, ptr %p)
+  ret void
+}
+
+define void @prop_param_callbase_def_1x_partial_3(ptr %p, ptr %p2) {
+; CHECK-LABEL: define {{[^@]+}}@prop_param_callbase_def_1x_partial_3
+; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo2_3(ptr readonly %p, ptr %p)
+  ret void
+}
+
+define void @prop_deref(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_deref
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1(ptr dereferenceable(16) %p)
+  ret void
+}
+
+define void @prop_deref_or_null(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_deref_or_null
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1(ptr dereferenceable_or_null(256) %p)
+  ret void
+}
+
+define void @prop_param_nonnull_and_align(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_param_nonnull_and_align
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1(ptr nonnull align 32 %p)
+  ret void
+}
+
+define void @prop_param_deref_align_no_update(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_param_deref_align_no_update
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr align 64 dereferenceable(512) [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1_bar_aligned64_deref512(ptr align 4 dereferenceable(64) %p)
+  ret void
+}
+
+define void @prop_param_deref_align_update(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_param_deref_align_update
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr align 64 dereferenceable(512) [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1_bar_aligned64_deref512(ptr align 128 dereferenceable(1024) %p)
+  ret void
+}
+
+define void @prop_param_deref_or_null_update(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_param_deref_or_null_update
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr align 512 dereferenceable_or_null(512) [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1_bar_aligned512_deref_or_null512(ptr dereferenceable_or_null(1024) %p)
+  ret void
+}
+
+define void @prop_param_deref_or_null_no_update(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_param_deref_or_null_no_update
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr align 512 dereferenceable_or_null(512) [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1_bar_aligned512_deref_or_null512(ptr dereferenceable_or_null(32) %p)
+  ret void
+}
+
+define void @prop_fn_decl(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_fn_decl
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @buz1_wronly(ptr %p)
+  call void @bar1(ptr %p)
+  ret void
+}
+
+define void @prop_cb_def_wr(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_cb_def_wr
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @buz1(ptr %p) writeonly
+  call void @bar1(ptr %p)
+  ret void
+}
+
+define void @prop_fn_decl_fail_alloca(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_fn_decl_fail_alloca
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    [[A_I:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr [[A_I]])
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[A_I]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr [[A_I]])
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @buz1_wronly_fail_alloca(ptr %p)
+  call void @bar1(ptr %p)
+  ret void
+}
+
+define void @prop_cb_def_wr_fail_alloca(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_cb_def_wr_fail_alloca
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    [[A_I:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr [[A_I]])
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[A_I]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr [[A_I]])
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @buz1_fail_alloca(ptr %p) writeonly
+  call void @bar1(ptr %p)
+  ret void
+}
+
+define void @prop_fn_decl_partially_okay_alloca(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_fn_decl_partially_okay_alloca
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    [[A_I:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr [[A_I]])
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[A_I]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr [[A_I]])
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @buz1_wronly_partially_okay_alloca(ptr %p)
+  call void @bar1(ptr %p)
+  ret void
+}
+
+define void @prop_cb_def_wr_partially_okay_alloca(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_cb_def_wr_partially_okay_alloca
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    [[A_I:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr [[A_I]])
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    call void @bar2(ptr [[P]], ptr [[A_I]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr [[A_I]])
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @buz1_partially_okay_alloca(ptr %p) writeonly
+  call void @bar1(ptr %p)
+  ret void
+}
+
+define void @prop_cb_def_readonly(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_cb_def_readonly
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1(ptr %p) readonly
+  ret void
+}
+
+define void @prop_cb_def_readnone(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_cb_def_readnone
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1(ptr %p) readnone
+  ret void
+}
+
+define void @prop_cb_def_argmem_readonly_fail(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_cb_def_argmem_readonly_fail
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1(ptr %p) memory(argmem:read)
+  ret void
+}
+
+define void @prop_cb_def_inaccessible_none(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_cb_def_inaccessible_none
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1(ptr %p) memory(inaccessiblemem:none)
+  ret void
+}
+
+define void @prop_cb_def_inaccessible_none_argmem_none(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_cb_def_inaccessible_none_argmem_none
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1(ptr %p) memory(inaccessiblemem:none, argmem:none)
+  ret void
+}
+
+define void @prop_cb_def_willreturn(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_cb_def_willreturn
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1(ptr %p) willreturn
+  ret void
+}
+
+define void @prop_cb_def_mustprogress(ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@prop_cb_def_mustprogress
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @bar1(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+  call void @foo1(ptr %p) mustprogress
+  ret void
+}

diff  --git a/llvm/test/Transforms/Inline/ret_attr_align_and_noundef.ll b/llvm/test/Transforms/Inline/ret_attr_align_and_noundef.ll
new file mode 100644
index 000000000000000..f7dccc75ba4e029
--- /dev/null
+++ b/llvm/test/Transforms/Inline/ret_attr_align_and_noundef.ll
@@ -0,0 +1,339 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
+; RUN: opt -S -passes=inline %s | FileCheck %s
+; RUN: opt -S -passes='cgscc(inline)' %s | FileCheck %s
+; RUN: opt -S -passes='module-inline' %s | FileCheck %s
+
+declare ptr @foo()
+declare void @use.ptr(ptr) willreturn nounwind
+declare void @bar()
+declare void @baz()
+declare ptr @llvm.ptrmask.p0.i64(ptr, i64)
+declare i1 @val()
+
+define ptr @callee0123() {
+; CHECK-LABEL: define ptr @callee0123() {
+; CHECK-NEXT:    [[R:%.*]] = call ptr @foo()
+; CHECK-NEXT:    ret ptr [[R]]
+;
+  %r = call ptr @foo()
+  ret ptr %r
+}
+
+define ptr @caller0() {
+; CHECK-LABEL: define ptr @caller0() {
+; CHECK-NEXT:    [[R_I:%.*]] = call dereferenceable(16) ptr @foo()
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call dereferenceable(16) ptr @callee0123()
+  ret ptr %r
+}
+
+define ptr @caller1() {
+; CHECK-LABEL: define ptr @caller1() {
+; CHECK-NEXT:    [[R_I:%.*]] = call ptr @foo()
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call align(16) ptr @callee0123()
+  ret ptr %r
+}
+
+define ptr @caller2() {
+; CHECK-LABEL: define ptr @caller2() {
+; CHECK-NEXT:    [[R_I:%.*]] = call ptr @foo()
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call noundef ptr @callee0123()
+  ret ptr %r
+}
+
+define ptr @caller3() {
+; CHECK-LABEL: define ptr @caller3() {
+; CHECK-NEXT:    [[R_I:%.*]] = call dereferenceable_or_null(32) ptr @foo()
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call dereferenceable_or_null(32) ptr @callee0123()
+  ret ptr %r
+}
+
+define ptr @caller_0123_dornull() {
+; CHECK-LABEL: define ptr @caller_0123_dornull() {
+; CHECK-NEXT:    [[R_I:%.*]] = call dereferenceable_or_null(16) ptr @foo()
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call noundef align(32) dereferenceable_or_null(16) ptr @callee0123()
+  ret ptr %r
+}
+
+define ptr @caller_0123_d() {
+; CHECK-LABEL: define ptr @caller_0123_d() {
+; CHECK-NEXT:    [[R_I:%.*]] = call dereferenceable(16) ptr @foo()
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call noundef align(32) dereferenceable(16) ptr @callee0123()
+  ret ptr %r
+}
+
+define ptr @callee4() {
+; CHECK-LABEL: define ptr @callee4() {
+; CHECK-NEXT:    [[R:%.*]] = call ptr @foo()
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    ret ptr [[R]]
+;
+  %r = call ptr @foo()
+  call void @bar()
+  ret ptr %r
+}
+
+define ptr @caller4_fail() {
+; CHECK-LABEL: define ptr @caller4_fail() {
+; CHECK-NEXT:    [[R_I:%.*]] = call ptr @foo()
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call noundef align(256) ptr @callee4()
+  ret ptr %r
+}
+
+define ptr @callee5() {
+; CHECK-LABEL: define ptr @callee5() {
+; CHECK-NEXT:    [[R:%.*]] = call align 64 ptr @foo()
+; CHECK-NEXT:    ret ptr [[R]]
+;
+  %r = call align(64) ptr @foo()
+  ret ptr %r
+}
+
+define ptr @caller5_fail() {
+; CHECK-LABEL: define ptr @caller5_fail() {
+; CHECK-NEXT:    [[R_I:%.*]] = call align 64 ptr @foo()
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call noundef align(32) ptr @callee5()
+  ret ptr %r
+}
+
+define ptr @caller5_okay() {
+; CHECK-LABEL: define ptr @caller5_okay() {
+; CHECK-NEXT:    [[R_I:%.*]] = call align 64 ptr @foo()
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call noundef align(128) ptr @callee5()
+  ret ptr %r
+}
+
+define ptr @callee6() {
+; CHECK-LABEL: define ptr @callee6() {
+; CHECK-NEXT:    [[R:%.*]] = call dereferenceable(16) ptr @foo()
+; CHECK-NEXT:    ret ptr [[R]]
+;
+  %r = call dereferenceable(16) ptr @foo()
+  ret ptr %r
+}
+
+define ptr @caller6_fail() {
+; CHECK-LABEL: define ptr @caller6_fail() {
+; CHECK-NEXT:    [[R_I:%.*]] = call dereferenceable(8) ptr @foo()
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call dereferenceable(8) ptr @callee6()
+  ret ptr %r
+}
+
+define ptr @caller6_okay() {
+; CHECK-LABEL: define ptr @caller6_okay() {
+; CHECK-NEXT:    [[R_I:%.*]] = call dereferenceable(32) ptr @foo()
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call dereferenceable(32) ptr @callee6()
+  ret ptr %r
+}
+
+define ptr @callee7() {
+; CHECK-LABEL: define ptr @callee7() {
+; CHECK-NEXT:    [[R:%.*]] = call dereferenceable_or_null(16) ptr @foo()
+; CHECK-NEXT:    ret ptr [[R]]
+;
+  %r = call dereferenceable_or_null(16) ptr @foo()
+  ret ptr %r
+}
+
+define ptr @caller7_fail() {
+; CHECK-LABEL: define ptr @caller7_fail() {
+; CHECK-NEXT:    [[R_I:%.*]] = call dereferenceable_or_null(8) ptr @foo()
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call dereferenceable_or_null(8) ptr @callee7()
+  ret ptr %r
+}
+
+define ptr @caller7_okay() {
+; CHECK-LABEL: define ptr @caller7_okay() {
+; CHECK-NEXT:    [[R_I:%.*]] = call dereferenceable_or_null(32) ptr @foo()
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call dereferenceable_or_null(32) ptr @callee7()
+  ret ptr %r
+}
+
+define ptr @callee8() {
+; CHECK-LABEL: define ptr @callee8() {
+; CHECK-NEXT:    [[R:%.*]] = call ptr @foo()
+; CHECK-NEXT:    ret ptr [[R]]
+;
+  %r = call ptr @foo()
+  ret ptr %r
+}
+
+define ptr @caller8_okay_use_after_poison_anyways() {
+; CHECK-LABEL: define ptr @caller8_okay_use_after_poison_anyways() {
+; CHECK-NEXT:    [[R_I:%.*]] = call nonnull ptr @foo()
+; CHECK-NEXT:    call void @use.ptr(ptr [[R_I]])
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call nonnull ptr @callee8()
+  call void @use.ptr(ptr %r)
+  ret ptr %r
+}
+
+define ptr @callee9() {
+; CHECK-LABEL: define ptr @callee9() {
+; CHECK-NEXT:    [[R:%.*]] = call noundef ptr @foo()
+; CHECK-NEXT:    ret ptr [[R]]
+;
+  %r = call noundef ptr @foo()
+  ret ptr %r
+}
+
+define ptr @caller9_fail_creates_ub() {
+; CHECK-LABEL: define ptr @caller9_fail_creates_ub() {
+; CHECK-NEXT:    [[R_I:%.*]] = call noundef nonnull ptr @foo()
+; CHECK-NEXT:    call void @use.ptr(ptr [[R_I]])
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call nonnull ptr @callee9()
+  call void @use.ptr(ptr %r)
+  ret ptr %r
+}
+
+define ptr @caller9_okay_is_ub_anyways() {
+; CHECK-LABEL: define ptr @caller9_okay_is_ub_anyways() {
+; CHECK-NEXT:    [[R_I:%.*]] = call noundef nonnull ptr @foo()
+; CHECK-NEXT:    call void @use.ptr(ptr [[R_I]])
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call noundef nonnull ptr @callee9()
+  call void @use.ptr(ptr %r)
+  ret ptr %r
+}
+
+define ptr @callee10() {
+; CHECK-LABEL: define ptr @callee10() {
+; CHECK-NEXT:    [[R:%.*]] = call ptr @foo()
+; CHECK-NEXT:    call void @use.ptr(ptr [[R]])
+; CHECK-NEXT:    ret ptr [[R]]
+;
+  %r = call ptr @foo()
+  call void @use.ptr(ptr %r)
+  ret ptr %r
+}
+
+define ptr @caller10_fail_maybe_poison() {
+; CHECK-LABEL: define ptr @caller10_fail_maybe_poison() {
+; CHECK-NEXT:    [[R_I:%.*]] = call nonnull ptr @foo()
+; CHECK-NEXT:    call void @use.ptr(ptr [[R_I]])
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call nonnull ptr @callee10()
+  ret ptr %r
+}
+
+define ptr @caller10_okay_will_be_ub() {
+; CHECK-LABEL: define ptr @caller10_okay_will_be_ub() {
+; CHECK-NEXT:    [[R_I:%.*]] = call nonnull ptr @foo()
+; CHECK-NEXT:    call void @use.ptr(ptr [[R_I]])
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call noundef nonnull ptr @callee10()
+  ret ptr %r
+}
+
+define noundef ptr @caller10_okay_will_be_ub_todo() {
+; CHECK-LABEL: define noundef ptr @caller10_okay_will_be_ub_todo() {
+; CHECK-NEXT:    [[R_I:%.*]] = call nonnull ptr @foo()
+; CHECK-NEXT:    call void @use.ptr(ptr [[R_I]])
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call nonnull ptr @callee10()
+  ret ptr %r
+}
+
+define ptr @callee11() {
+; CHECK-LABEL: define ptr @callee11() {
+; CHECK-NEXT:    [[R:%.*]] = call ptr @foo()
+; CHECK-NEXT:    [[COND:%.*]] = call i1 @val() #[[ATTR0:[0-9]+]]
+; CHECK-NEXT:    br i1 [[COND]], label [[TRUE:%.*]], label [[FALSE:%.*]]
+; CHECK:       True:
+; CHECK-NEXT:    call void @baz() #[[ATTR0]]
+; CHECK-NEXT:    ret ptr [[R]]
+; CHECK:       False:
+; CHECK-NEXT:    call void @bar() #[[ATTR0]]
+; CHECK-NEXT:    [[COND2:%.*]] = call i1 @val()
+; CHECK-NEXT:    ret ptr [[R]]
+;
+  %r = call ptr @foo()
+  %cond = call i1 @val() nounwind willreturn
+  br i1 %cond, label %True, label %False
+True:
+  call void @baz() nounwind willreturn
+  ret ptr %r
+False:
+  call void @bar() nounwind willreturn
+  %cond2 = call i1 @val()
+  ret ptr %r
+}
+
+define ptr @caller11_todo() {
+; CHECK-LABEL: define ptr @caller11_todo() {
+; CHECK-NEXT:    [[R_I:%.*]] = call ptr @foo()
+; CHECK-NEXT:    [[COND_I:%.*]] = call i1 @val() #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[COND_I]], label [[TRUE_I:%.*]], label [[FALSE_I:%.*]]
+; CHECK:       True.i:
+; CHECK-NEXT:    call void @baz() #[[ATTR0]]
+; CHECK-NEXT:    br label [[CALLEE11_EXIT:%.*]]
+; CHECK:       False.i:
+; CHECK-NEXT:    call void @bar() #[[ATTR0]]
+; CHECK-NEXT:    [[COND2_I:%.*]] = call i1 @val()
+; CHECK-NEXT:    br label [[CALLEE11_EXIT]]
+; CHECK:       callee11.exit:
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call nonnull ptr @callee11()
+  ret ptr %r
+}
+
+define ptr @callee12() {
+; CHECK-LABEL: define ptr @callee12() {
+; CHECK-NEXT:    [[P:%.*]] = call ptr @foo()
+; CHECK-NEXT:    [[COND:%.*]] = call i1 @val() #[[ATTR0]]
+; CHECK-NEXT:    [[PP:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -4)
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[COND]], ptr [[P]], ptr [[PP]]
+; CHECK-NEXT:    ret ptr [[R]]
+;
+  %p = call ptr @foo()
+  %cond = call i1 @val() nounwind willreturn
+  %pp = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -4)
+  %r = select i1 %cond, ptr %p, ptr %pp
+  ret ptr %r
+}
+
+define ptr @caller12_todo() {
+; CHECK-LABEL: define ptr @caller12_todo() {
+; CHECK-NEXT:    [[P_I:%.*]] = call ptr @foo()
+; CHECK-NEXT:    [[COND_I:%.*]] = call i1 @val() #[[ATTR0]]
+; CHECK-NEXT:    [[PP_I:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P_I]], i64 -4)
+; CHECK-NEXT:    [[R_I:%.*]] = select i1 [[COND_I]], ptr [[P_I]], ptr [[PP_I]]
+; CHECK-NEXT:    ret ptr [[R_I]]
+;
+  %r = call nonnull ptr @callee12()
+  ret ptr %r
+}


        


More information about the llvm-commits mailing list