xref: /llvm-project/llvm/test/Transforms/SCCP/ip-add-range-to-call.ll (revision b7e51b4f139ec18c498c818c6bcaa5a842cea83c)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt -passes=ipsccp -S %s | FileCheck %s
3
4; Test 1.
5; Both arguments and return value of @callee can be tracked. The inferred range
6; can be added to call sites.
7define internal i32 @callee(i32 %x) {
8; CHECK-LABEL: define internal range(i32 0, 21) i32 @callee(
9; CHECK-SAME: i32 range(i32 0, 21) [[X:%.*]]) {
10; CHECK-NEXT:    ret i32 [[X]]
11;
12  ret i32 %x
13}
14
15define i32 @caller1() {
16; CHECK-LABEL: define range(i32 0, 41) i32 @caller1() {
17; CHECK-NEXT:    [[C1:%.*]] = call i32 @callee(i32 10)
18; CHECK-NEXT:    [[C2:%.*]] = call i32 @callee(i32 20)
19; CHECK-NEXT:    [[A:%.*]] = add nuw nsw i32 [[C1]], [[C2]]
20; CHECK-NEXT:    ret i32 [[A]]
21;
22  %c1 = call i32 @callee(i32 10)
23  %c2 = call i32 @callee(i32 20)
24  %a = add i32 %c1, %c2
25  ret i32 %a
26}
27
28define i32 @caller2(i32 %x) {
29; CHECK-LABEL: define range(i32 0, 21) i32 @caller2(
30; CHECK-SAME: i32 [[X:%.*]]) {
31; CHECK-NEXT:    [[X_15:%.*]] = and i32 [[X]], 15
32; CHECK-NEXT:    [[C:%.*]] = call i32 @callee(i32 [[X_15]])
33; CHECK-NEXT:    ret i32 [[C]]
34;
35  %x.15 = and i32 %x, 15
36  %c = call i32 @callee(i32 %x.15)
37  ret i32 %c
38}
39
40; Test 2.
41; The return value of @callee2 can be tracked, but arguments cannot, because
42; it is passed to @use_cb1. We cannot infer a range for the return value, no
43; metadata should be added.
44
45declare void @use_cb1(ptr)
46
47define internal i32 @callee2(i32 %x) {
48; CHECK-LABEL: define internal i32 @callee2(
49; CHECK-SAME: i32 [[X:%.*]]) {
50; CHECK-NEXT:    ret i32 [[X]]
51;
52  ret i32 %x
53}
54
55define void @caller_cb1() {
56; CHECK-LABEL: define void @caller_cb1() {
57; CHECK-NEXT:    [[C1:%.*]] = call i32 @callee2(i32 9)
58; CHECK-NEXT:    [[C2:%.*]] = call i32 @callee2(i32 10)
59; CHECK-NEXT:    call void @use_cb1(ptr @callee2)
60; CHECK-NEXT:    ret void
61;
62  %c1 = call i32 @callee2(i32 9)
63  %c2 = call i32 @callee2(i32 10)
64  call void @use_cb1(ptr @callee2)
65  ret void
66}
67
68; Test 3.
69; The return value can be tracked and it the result range ([500, 601) does not
70; depend on the arguments, which cannot be tracked because @callee3 is passed
71; to @use_cb2. The result range can be added to the call sites of @callee.
72
73declare void @use_cb2(ptr)
74
75define internal i32 @callee3(i32 %x) {
76; CHECK-LABEL: define internal range(i32 500, 601) i32 @callee3(
77; CHECK-SAME: i32 [[X:%.*]]) {
78; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[X]], 10
79; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i32 500, i32 600
80; CHECK-NEXT:    ret i32 [[S]]
81;
82  %c = icmp eq i32 %x, 10
83  %s = select i1 %c, i32 500, i32 600
84  ret i32 %s
85}
86
87define void @caller_cb2() {
88; CHECK-LABEL: define void @caller_cb2() {
89; CHECK-NEXT:    [[C1:%.*]] = call i32 @callee3(i32 9)
90; CHECK-NEXT:    [[C2:%.*]] = call i32 @callee3(i32 10)
91; CHECK-NEXT:    call void @use_cb2(ptr @callee3)
92; CHECK-NEXT:    ret void
93;
94  %c1 = call i32 @callee3(i32 9)
95  %c2 = call i32 @callee3(i32 10)
96  call void @use_cb2(ptr @callee3)
97  ret void
98}
99
100; Test 4.
101; The return value of @callee4 can be tracked, but depends on an argument which
102; cannot be tracked. No result range can be inferred.
103
104declare void @use_cb3(ptr)
105
106define internal i32 @callee4(i32 %x, i32 %y) {
107; CHECK-LABEL: define internal i32 @callee4(
108; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
109; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[X]], 10
110; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i32 500, i32 [[Y]]
111; CHECK-NEXT:    ret i32 [[S]]
112;
113  %c = icmp eq i32 %x, 10
114  %s = select i1 %c, i32 500, i32 %y
115  ret i32 %s
116}
117
118define void @caller_cb3() {
119; CHECK-LABEL: define void @caller_cb3() {
120; CHECK-NEXT:    [[C1:%.*]] = call i32 @callee4(i32 11, i32 30)
121; CHECK-NEXT:    [[C2:%.*]] = call i32 @callee4(i32 12, i32 40)
122; CHECK-NEXT:    call void @use_cb3(ptr @callee4)
123; CHECK-NEXT:    ret void
124;
125  %c1 = call i32 @callee4(i32 11, i32 30)
126  %c2 = call i32 @callee4(i32 12, i32 40)
127  call void @use_cb3(ptr @callee4)
128  ret void
129}
130
131; Test 5.
132; Range for the return value of callee5 includes undef. No range metadata
133; should be added at call sites.
134define internal i32 @callee5(i32 %x, i32 %y) {
135; CHECK-LABEL: define internal i32 @callee5(
136; CHECK-SAME: i32 range(i32 10, 21) [[X:%.*]], i32 range(i32 100, 201) [[Y:%.*]]) {
137; CHECK-NEXT:    [[C:%.*]] = icmp slt i32 [[X]], 15
138; CHECK-NEXT:    br i1 [[C]], label [[BB1:%.*]], label [[BB2:%.*]]
139; CHECK:       bb1:
140; CHECK-NEXT:    br label [[EXIT:%.*]]
141; CHECK:       bb2:
142; CHECK-NEXT:    br label [[EXIT]]
143; CHECK:       exit:
144; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[Y]], [[BB1]] ], [ undef, [[BB2]] ]
145; CHECK-NEXT:    ret i32 [[RES]]
146;
147  %c = icmp slt i32 %x, 15
148  br i1 %c, label %bb1, label %bb2
149
150bb1:
151  br label %exit
152
153bb2:
154  br label %exit
155
156exit:
157  %res = phi i32 [ %y, %bb1 ], [ undef, %bb2]
158  ret i32 %res
159}
160
161define i32 @caller5() {
162; CHECK-LABEL: define i32 @caller5() {
163; CHECK-NEXT:    [[C1:%.*]] = call i32 @callee5(i32 10, i32 100)
164; CHECK-NEXT:    [[C2:%.*]] = call i32 @callee5(i32 20, i32 200)
165; CHECK-NEXT:    [[A:%.*]] = add i32 [[C1]], [[C2]]
166; CHECK-NEXT:    ret i32 [[A]]
167;
168  %c1 = call i32 @callee5(i32 10, i32 100)
169  %c2 = call i32 @callee5(i32 20, i32 200)
170  %a = add i32 %c1, %c2
171  ret i32 %a
172}
173
174define internal <2 x i64> @ctlz(<2 x i64> %arg) {
175; CHECK-LABEL: define internal range(i64 0, 65) <2 x i64> @ctlz(
176; CHECK-SAME: <2 x i64> [[ARG:%.*]]) {
177; CHECK-NEXT:    [[RES:%.*]] = call <2 x i64> @llvm.ctlz.v2i64(<2 x i64> [[ARG]], i1 false)
178; CHECK-NEXT:    ret <2 x i64> [[RES]]
179;
180  %res = call <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %arg, i1 false)
181  ret <2 x i64> %res
182}
183
184define <2 x i64> @ctlz_caller(<2 x i64> %arg) {
185; CHECK-LABEL: define range(i64 0, 65) <2 x i64> @ctlz_caller(
186; CHECK-SAME: <2 x i64> [[ARG:%.*]]) {
187; CHECK-NEXT:    [[RES:%.*]] = call <2 x i64> @ctlz(<2 x i64> [[ARG]])
188; CHECK-NEXT:    ret <2 x i64> [[RES]]
189;
190  %res = call <2 x i64> @ctlz(<2 x i64> %arg)
191  ret <2 x i64> %res
192}
193
194declare <2 x i64> @llvm.ctlz.v2i64(<2 x i64>, i1)
195
196