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
5 ; Both arguments and return value of @callee can be tracked. The inferred range
6 ; can be added to call sites.
7 define internal i32 @callee(i32 %x) {
8 ; CHECK-LABEL: define internal range(i32 0, 21) i32 @callee(
9 ; CHECK-SAME: i32 [[X:%.*]]) {
10 ; CHECK-NEXT: ret i32 [[X]]
15 define 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]]
22 %c1 = call i32 @callee(i32 10)
23 %c2 = call i32 @callee(i32 20)
28 define 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]]
35 %x.15 = and i32 %x, 15
36 %c = call i32 @callee(i32 %x.15)
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.
45 declare void @use_cb1(ptr)
47 define internal i32 @callee2(i32 %x) {
48 ; CHECK-LABEL: define internal i32 @callee2(
49 ; CHECK-SAME: i32 [[X:%.*]]) {
50 ; CHECK-NEXT: ret i32 [[X]]
55 define 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
62 %c1 = call i32 @callee2(i32 9)
63 %c2 = call i32 @callee2(i32 10)
64 call void @use_cb1(ptr @callee2)
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.
73 declare void @use_cb2(ptr)
75 define 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]]
82 %c = icmp eq i32 %x, 10
83 %s = select i1 %c, i32 500, i32 600
87 define 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
94 %c1 = call i32 @callee3(i32 9)
95 %c2 = call i32 @callee3(i32 10)
96 call void @use_cb2(ptr @callee3)
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.
104 declare void @use_cb3(ptr)
106 define 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]]
113 %c = icmp eq i32 %x, 10
114 %s = select i1 %c, i32 500, i32 %y
118 define 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
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)
132 ; Range for the return value of callee5 includes undef. No range metadata
133 ; should be added at call sites.
134 define internal i32 @callee5(i32 %x, i32 %y) {
135 ; CHECK-LABEL: define internal i32 @callee5(
136 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
137 ; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[X]], 15
138 ; CHECK-NEXT: br i1 [[C]], label [[BB1:%.*]], label [[BB2:%.*]]
140 ; CHECK-NEXT: br label [[EXIT:%.*]]
142 ; CHECK-NEXT: br label [[EXIT]]
144 ; CHECK-NEXT: [[RES:%.*]] = phi i32 [ [[Y]], [[BB1]] ], [ undef, [[BB2]] ]
145 ; CHECK-NEXT: ret i32 [[RES]]
147 %c = icmp slt i32 %x, 15
148 br i1 %c, label %bb1, label %bb2
157 %res = phi i32 [ %y, %bb1 ], [ undef, %bb2]
161 define 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]]
168 %c1 = call i32 @callee5(i32 10, i32 100)
169 %c2 = call i32 @callee5(i32 20, i32 200)
170 %a = add i32 %c1, %c2
174 define 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]]
180 %res = call <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %arg, i1 false)
184 define <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]]
190 %res = call <2 x i64> @ctlz(<2 x i64> %arg)
194 declare <2 x i64> @llvm.ctlz.v2i64(<2 x i64>, i1)