xref: /llvm-project/llvm/test/Transforms/Attributor/noundef.ll (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-annotate-decl-cs  -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
3; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
4
5declare void @unknown()
6
7declare void @bar(ptr)
8
9define void @foo() {
10; CHECK-LABEL: define {{[^@]+}}@foo() {
11; CHECK-NEXT:    [[X:%.*]] = alloca i32, align 4
12; CHECK-NEXT:    call void @unknown()
13; CHECK-NEXT:    call void @bar(ptr noundef nonnull align 4 dereferenceable(4) [[X]])
14; CHECK-NEXT:    ret void
15;
16  %x = alloca i32
17  call void @unknown()
18  call void @bar(ptr %x)
19  ret void
20}
21
22define internal ptr @returned_dead() {
23; CHECK-LABEL: define {{[^@]+}}@returned_dead() {
24; CHECK-NEXT:    call void @unknown()
25; CHECK-NEXT:    ret ptr undef
26;
27  call void @unknown()
28  ret ptr null
29}
30
31define void @caller1() {
32; CHECK-LABEL: define {{[^@]+}}@caller1() {
33; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @returned_dead()
34; CHECK-NEXT:    ret void
35;
36  call ptr @returned_dead()
37  ret void
38}
39
40define internal void @argument_dead_callback_callee(ptr %c) {
41; CHECK-LABEL: define {{[^@]+}}@argument_dead_callback_callee
42; CHECK-SAME: (ptr noalias nofree readnone align 4294967296 captures(none) [[C:%.*]]) {
43; CHECK-NEXT:    call void @unknown()
44; CHECK-NEXT:    ret void
45;
46  call void @unknown()
47  ret void
48}
49
50define void @callback_caller() {
51; TUNIT-LABEL: define {{[^@]+}}@callback_caller() {
52; TUNIT-NEXT:    call void @callback_broker(ptr noundef nonnull @argument_dead_callback_callee, ptr nofree readnone align 4294967296 undef)
53; TUNIT-NEXT:    ret void
54;
55; CGSCC-LABEL: define {{[^@]+}}@callback_caller() {
56; CGSCC-NEXT:    call void @callback_broker(ptr noundef nonnull @argument_dead_callback_callee, ptr nofree noundef readnone align 4294967296 null)
57; CGSCC-NEXT:    ret void
58;
59  call void @callback_broker(ptr @argument_dead_callback_callee, ptr null)
60  ret void
61}
62
63; Drop the noundef if when we replace the call argument with `undef`. We use a
64; varargs function as we cannot (yet) rewrite their signature. If we ever can,
65; try to come up with a different scheme to verify the `noundef` is dropped if
66; signature rewriting is not happening.
67define internal void @callee_with_dead_noundef_arg(i1 noundef %create, ...) {
68; TUNIT-LABEL: define {{[^@]+}}@callee_with_dead_noundef_arg
69; TUNIT-SAME: (i1 [[CREATE:%.*]], ...) {
70; TUNIT-NEXT:    call void @unknown()
71; TUNIT-NEXT:    ret void
72;
73; CGSCC-LABEL: define {{[^@]+}}@callee_with_dead_noundef_arg
74; CGSCC-SAME: (i1 noundef [[CREATE:%.*]], ...) {
75; CGSCC-NEXT:    call void @unknown()
76; CGSCC-NEXT:    ret void
77;
78  call void @unknown()
79  ret void
80}
81
82define void @caller_with_unused_arg(i1 %c) {
83; TUNIT-LABEL: define {{[^@]+}}@caller_with_unused_arg
84; TUNIT-SAME: (i1 noundef [[C:%.*]]) {
85; TUNIT-NEXT:    call void (i1, ...) @callee_with_dead_noundef_arg(i1 undef)
86; TUNIT-NEXT:    ret void
87;
88; CGSCC-LABEL: define {{[^@]+}}@caller_with_unused_arg
89; CGSCC-SAME: (i1 noundef [[C:%.*]]) {
90; CGSCC-NEXT:    call void (i1, ...) @callee_with_dead_noundef_arg(i1 noundef [[C]])
91; CGSCC-NEXT:    ret void
92;
93  call void (i1, ...) @callee_with_dead_noundef_arg(i1 %c)
94  ret void
95}
96
97define internal void @callee_with_dead_arg(i1 %create, ...) {
98;
99; TUNIT-LABEL: define {{[^@]+}}@callee_with_dead_arg
100; TUNIT-SAME: (i1 [[CREATE:%.*]], ...) {
101; TUNIT-NEXT:  entry:
102; TUNIT-NEXT:    br label [[IF_THEN3:%.*]]
103; TUNIT:       if.then:
104; TUNIT-NEXT:    unreachable
105; TUNIT:       if.then3:
106; TUNIT-NEXT:    call void @unknown()
107; TUNIT-NEXT:    ret void
108;
109; CGSCC-LABEL: define {{[^@]+}}@callee_with_dead_arg
110; CGSCC-SAME: (i1 noundef [[CREATE:%.*]], ...) {
111; CGSCC-NEXT:  entry:
112; CGSCC-NEXT:    br label [[IF_THEN3:%.*]]
113; CGSCC:       if.then:
114; CGSCC-NEXT:    unreachable
115; CGSCC:       if.then3:
116; CGSCC-NEXT:    call void @unknown()
117; CGSCC-NEXT:    ret void
118;
119entry:
120  br i1 %create, label %if.then3, label %if.then
121
122if.then:                                          ; preds = %entry
123  ret void
124
125if.then3:                                         ; preds = %entry
126  call void @unknown()
127  ret void
128}
129
130; Drop the noundef if when we replace the call argument with `undef`. We use a
131; varargs function as we cannot (yet) rewrite their signature. If we ever can,
132; try to come up with a different scheme to verify the `noundef` is dropped if
133; signature rewriting is not happening.
134define void @caller_with_noundef_arg() {
135;
136; TUNIT-LABEL: define {{[^@]+}}@caller_with_noundef_arg() {
137; TUNIT-NEXT:    call void (i1, ...) @callee_with_dead_arg(i1 undef)
138; TUNIT-NEXT:    ret void
139;
140; CGSCC-LABEL: define {{[^@]+}}@caller_with_noundef_arg() {
141; CGSCC-NEXT:    call void (i1, ...) @callee_with_dead_arg(i1 noundef true)
142; CGSCC-NEXT:    ret void
143;
144  call void (i1, ...) @callee_with_dead_arg(i1 noundef true)
145  ret void
146}
147
148declare !callback !0 void @callback_broker(ptr, ptr)
149!1 = !{i64 0, i64 1, i1 false}
150!0 = !{!1}
151;.
152; TUNIT: [[META0:![0-9]+]] = !{[[META1:![0-9]+]]}
153; TUNIT: [[META1]] = !{i64 0, i64 1, i1 false}
154;.
155; CGSCC: [[META0:![0-9]+]] = !{[[META1:![0-9]+]]}
156; CGSCC: [[META1]] = !{i64 0, i64 1, i1 false}
157;.
158