196 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 42; RUN: opt -passes=ipsccp -S %s | FileCheck %s3 4; Test 1.5; Both arguments and return value of @callee can be tracked. The inferred range6; 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 %x13}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, %c225 ret i32 %a26}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]], 1532; CHECK-NEXT: [[C:%.*]] = call i32 @callee(i32 [[X_15]])33; CHECK-NEXT: ret i32 [[C]]34;35 %x.15 = and i32 %x, 1536 %c = call i32 @callee(i32 %x.15)37 ret i32 %c38}39 40; Test 2.41; The return value of @callee2 can be tracked, but arguments cannot, because42; it is passed to @use_cb1. We cannot infer a range for the return value, no43; 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 %x53}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 void61;62 %c1 = call i32 @callee2(i32 9)63 %c2 = call i32 @callee2(i32 10)64 call void @use_cb1(ptr @callee2)65 ret void66}67 68; Test 3.69; The return value can be tracked and it the result range ([500, 601) does not70; depend on the arguments, which cannot be tracked because @callee3 is passed71; 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]], 1079; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i32 500, i32 60080; CHECK-NEXT: ret i32 [[S]]81;82 %c = icmp eq i32 %x, 1083 %s = select i1 %c, i32 500, i32 60084 ret i32 %s85}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 void93;94 %c1 = call i32 @callee3(i32 9)95 %c2 = call i32 @callee3(i32 10)96 call void @use_cb2(ptr @callee3)97 ret void98}99 100; Test 4.101; The return value of @callee4 can be tracked, but depends on an argument which102; 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]], 10110; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i32 500, i32 [[Y]]111; CHECK-NEXT: ret i32 [[S]]112;113 %c = icmp eq i32 %x, 10114 %s = select i1 %c, i32 500, i32 %y115 ret i32 %s116}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 void124;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 void129}130 131; Test 5.132; Range for the return value of callee5 includes undef. No range metadata133; 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]], 15138; 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, 15148 br i1 %c, label %bb1, label %bb2149 150bb1:151 br label %exit152 153bb2:154 br label %exit155 156exit:157 %res = phi i32 [ %y, %bb1 ], [ undef, %bb2]158 ret i32 %res159}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, %c2171 ret i32 %a172}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> %res182}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> %res192}193 194declare <2 x i64> @llvm.ctlz.v2i64(<2 x i64>, i1)195 196