424 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature2; RUN: opt -passes=ipsccp -S %s | FileCheck %s3 4%t1 = type opaque5 6@e = common global i32 0, align 47 8; Test that we a skip unknown values depending on a unknown tracked call, until the call gets resolved. The @test1 and @test2 variants are very similar, they just check 2 different kinds of users (icmp and zext)9 10define i32 @test1_m(i32 %h) {11; CHECK-LABEL: define {{[^@]+}}@test1_m12; CHECK-SAME: (i32 [[H:%.*]]) {13; CHECK-NEXT: entry:14; CHECK-NEXT: [[CONV:%.*]] = trunc i32 [[H]] to i815; CHECK-NEXT: [[CALL:%.*]] = call i32 @test1_k(i8 [[CONV]], i32 0)16; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[H]] to i6417; CHECK-NEXT: [[TMP0:%.*]] = inttoptr i64 [[CONV1]] to ptr18; CHECK-NEXT: [[CALL2:%.*]] = call i1 @test1_g(ptr [[TMP0]], i32 1)19; CHECK-NEXT: ret i32 undef20;21entry:22 %conv = trunc i32 %h to i823 %call = call i32 @test1_k(i8 %conv, i32 0)24 %conv1 = sext i32 %h to i6425 %0 = inttoptr i64 %conv1 to ptr26 %call2 = call i1 @test1_g(ptr %0, i32 1)27 ret i32 undef28 29; uselistorder directives30 uselistorder i32 %h, { 1, 0 }31}32 33declare void @use.1(i1)34 35define internal i32 @test1_k(i8 %h, i32 %i) {36; CHECK-LABEL: define {{[^@]+}}@test1_k37; CHECK-SAME: (i8 [[H:%.*]], i32 [[I:%.*]]) {38; CHECK-NEXT: entry:39; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @e, align 440; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i6441; CHECK-NEXT: [[TMP1:%.*]] = inttoptr i64 [[CONV]] to ptr42; CHECK-NEXT: [[CALL:%.*]] = call i1 @test1_g(ptr [[TMP1]], i32 0)43; CHECK-NEXT: call void @use.1(i1 false)44; CHECK-NEXT: ret i32 undef45;46entry:47 %0 = load i32, ptr @e, align 448 %conv = sext i32 %0 to i6449 %1 = inttoptr i64 %conv to ptr50 %call = call i1 @test1_g(ptr %1, i32 %i)51 %frombool.1 = zext i1 %call to i852 %tobool.1 = trunc i8 %frombool.1 to i153 call void @use.1(i1 %tobool.1)54 ret i32 undef55}56 57define internal i1 @test1_g(ptr %h, i32 %i) #0 {58; CHECK-LABEL: define {{[^@]+}}@test1_g59; CHECK-SAME: (ptr [[H:%.*]], i32 range(i32 0, 2) [[I:%.*]]) {60; CHECK-NEXT: entry:61; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[I]], 062; CHECK-NEXT: br i1 [[TOBOOL]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]]63; CHECK: land.rhs:64; CHECK-NEXT: [[CALL:%.*]] = call i32 (...) @test1_j()65; CHECK-NEXT: [[TOBOOL1:%.*]] = icmp ne i32 [[CALL]], 066; CHECK-NEXT: br label [[LAND_END]]67; CHECK: land.end:68; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[TOBOOL1]], [[LAND_RHS]] ]69; CHECK-NEXT: ret i1 poison70;71entry:72 %tobool = icmp ne i32 %i, 073 br i1 %tobool, label %land.rhs, label %land.end74 75land.rhs: ; preds = %entry76 %call = call i32 (...) @test1_j()77 %tobool1 = icmp ne i32 %call, 078 br label %land.end79 80land.end: ; preds = %land.rhs, %entry81 %0 = phi i1 [ false, %entry ], [ %tobool1, %land.rhs ]82 ret i1 false83}84 85declare i32 @test1_j(...)86 87define i32 @test2_m(i32 %h) #0 {88; CHECK-LABEL: define {{[^@]+}}@test2_m89; CHECK-SAME: (i32 [[H:%.*]]) {90; CHECK-NEXT: entry:91; CHECK-NEXT: [[CONV:%.*]] = trunc i32 [[H]] to i892; CHECK-NEXT: [[CALL:%.*]] = call i32 @test2_k(i8 [[CONV]], i32 0)93; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[H]] to i6494; CHECK-NEXT: [[TMP0:%.*]] = inttoptr i64 [[CONV1]] to ptr95; CHECK-NEXT: [[CALL2:%.*]] = call i1 @test2_g(ptr [[TMP0]], i32 1)96; CHECK-NEXT: ret i32 undef97;98entry:99 %conv = trunc i32 %h to i8100 %call = call i32 @test2_k(i8 %conv, i32 0)101 %conv1 = sext i32 %h to i64102 %0 = inttoptr i64 %conv1 to ptr103 %call2 = call i1 @test2_g(ptr %0, i32 1)104 ret i32 undef105 106; uselistorder directives107 uselistorder i32 %h, { 1, 0 }108}109 110; TODO: We could do better for the return value of call i1 @test3_g, if we111; resolve the unknown values there first.112define internal i32 @test2_k(i8 %h, i32 %i) {113; CHECK-LABEL: define {{[^@]+}}@test2_k114; CHECK-SAME: (i8 [[H:%.*]], i32 [[I:%.*]]) {115; CHECK-NEXT: entry:116; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @e, align 4117; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64118; CHECK-NEXT: [[TMP1:%.*]] = inttoptr i64 [[CONV]] to ptr119; CHECK-NEXT: [[CALL:%.*]] = call i1 @test3_g(ptr [[TMP1]], i32 0)120; CHECK-NEXT: call void @use.1(i1 false)121; CHECK-NEXT: ret i32 undef122;123entry:124 %0 = load i32, ptr @e, align 4125 %conv = sext i32 %0 to i64126 %1 = inttoptr i64 %conv to ptr127 %call = call i1 @test3_g(ptr %1, i32 %i)128 %frombool = icmp slt i1 %call, 1129 %add = add i1 %frombool, %frombool130 call void @use.1(i1 %frombool)131 ret i32 undef132 133}134 135define internal i1 @test2_g(ptr %h, i32 %i) {136; CHECK-LABEL: define {{[^@]+}}@test2_g137; CHECK-SAME: (ptr [[H:%.*]], i32 [[I:%.*]]) {138; CHECK-NEXT: entry:139; CHECK-NEXT: br label [[LAND_RHS:%.*]]140; CHECK: land.rhs:141; CHECK-NEXT: [[CALL:%.*]] = call i32 (...) @test2_j()142; CHECK-NEXT: [[TOBOOL1:%.*]] = icmp ne i32 [[CALL]], 0143; CHECK-NEXT: br label [[LAND_END:%.*]]144; CHECK: land.end:145; CHECK-NEXT: ret i1 poison146;147entry:148 %tobool = icmp ne i32 %i, 0149 br i1 %tobool, label %land.rhs, label %land.end150 151land.rhs: ; preds = %entry152 %call = call i32 (...) @test2_j()153 %tobool1 = icmp ne i32 %call, 0154 br label %land.end155 156land.end: ; preds = %land.rhs, %entry157 %0 = phi i1 [ false, %entry ], [ %tobool1, %land.rhs ]158 ret i1 false159}160 161declare i32 @test2_j(...)162 163 164 165; Same as test_2*, but with a PHI node depending on a tracked call result.166define i32 @test3_m(i32 %h) #0 {167; CHECK-LABEL: define {{[^@]+}}@test3_m168; CHECK-SAME: (i32 [[H:%.*]]) {169; CHECK-NEXT: entry:170; CHECK-NEXT: [[CONV:%.*]] = trunc i32 [[H]] to i8171; CHECK-NEXT: [[CALL:%.*]] = call i32 @test3_k(i8 [[CONV]], i32 0)172; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[H]] to i64173; CHECK-NEXT: [[TMP0:%.*]] = inttoptr i64 [[CONV1]] to ptr174; CHECK-NEXT: [[CALL2:%.*]] = call i1 @test3_g(ptr [[TMP0]], i32 1)175; CHECK-NEXT: ret i32 undef176;177entry:178 %conv = trunc i32 %h to i8179 %call = call i32 @test3_k(i8 %conv, i32 0)180 %conv1 = sext i32 %h to i64181 %0 = inttoptr i64 %conv1 to ptr182 %call2 = call i1 @test3_g(ptr %0, i32 1)183 ret i32 undef184 185; uselistorder directives186 uselistorder i32 %h, { 1, 0 }187}188 189define internal i32 @test3_k(i8 %h, i32 %i) {190; CHECK-LABEL: define {{[^@]+}}@test3_k191; CHECK-SAME: (i8 [[H:%.*]], i32 [[I:%.*]]) {192; CHECK-NEXT: entry:193; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @e, align 4194; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64195; CHECK-NEXT: [[TMP1:%.*]] = inttoptr i64 [[CONV]] to ptr196; CHECK-NEXT: br label [[LOOP:%.*]]197; CHECK: loop:198; CHECK-NEXT: [[CALL:%.*]] = call i1 @test3_g(ptr [[TMP1]], i32 0)199; CHECK-NEXT: call void @use.1(i1 false)200; CHECK-NEXT: br label [[EXIT:%.*]]201; CHECK: exit:202; CHECK-NEXT: ret i32 undef203;204entry:205 %0 = load i32, ptr @e, align 4206 %conv = sext i32 %0 to i64207 %1 = inttoptr i64 %conv to ptr208 br label %loop209 210loop:211 %phi = phi i1 [ undef, %entry], [ %call, %loop ]212 %call = call i1 @test3_g(ptr %1, i32 %i)213 %frombool = icmp slt i1 %call, 1214 %add = add i1 %frombool, %frombool215 call void @use.1(i1 %frombool)216 br i1 %call, label %loop, label %exit217 218exit:219 ret i32 undef220}221 222define internal i1 @test3_g(ptr %h, i32 %i) {223; CHECK-LABEL: define {{[^@]+}}@test3_g224; CHECK-SAME: (ptr [[H:%.*]], i32 range(i32 0, 2) [[I:%.*]]) {225; CHECK-NEXT: entry:226; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[I]], 0227; CHECK-NEXT: br i1 [[TOBOOL]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]]228; CHECK: land.rhs:229; CHECK-NEXT: [[CALL:%.*]] = call i32 (...) @test3_j()230; CHECK-NEXT: [[TOBOOL1:%.*]] = icmp ne i32 [[CALL]], 0231; CHECK-NEXT: br label [[LAND_END]]232; CHECK: land.end:233; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[TOBOOL1]], [[LAND_RHS]] ]234; CHECK-NEXT: ret i1 poison235;236entry:237 %tobool = icmp ne i32 %i, 0238 br i1 %tobool, label %land.rhs, label %land.end239 240land.rhs: ; preds = %entry241 %call = call i32 (...) @test3_j()242 %tobool1 = icmp ne i32 %call, 0243 br label %land.end244 245land.end: ; preds = %land.rhs, %entry246 %0 = phi i1 [ false, %entry ], [ %tobool1, %land.rhs ]247 ret i1 false248}249 250declare i32 @test3_j(...)251 252 253; TODO: We can eliminate the bitcast, if we resolve the unknown argument of254; @test4_b first.255 256declare void @use.16(ptr)257declare void @use.8(ptr)258 259define void @test4_a() {260; CHECK-LABEL: define {{[^@]+}}@test4_a() {261; CHECK-NEXT: bb:262; CHECK-NEXT: [[TMP:%.*]] = call ptr @test4_c(ptr null)263; CHECK-NEXT: call void @test4_b(ptr null)264; CHECK-NEXT: ret void265;266bb:267 %tmp = call ptr @test4_c(ptr null)268 call void @test4_b(ptr %tmp)269 ret void270}271 272define internal void @test4_b(ptr %arg) {273; CHECK-LABEL: define {{[^@]+}}@test4_b274; CHECK-SAME: (ptr [[ARG:%.*]]) {275; CHECK-NEXT: bb:276; CHECK-NEXT: [[SEL:%.*]] = select i1 false, ptr null, ptr null277; CHECK-NEXT: call void @use.16(ptr null)278; CHECK-NEXT: call void @use.8(ptr [[SEL]])279; CHECK-NEXT: ret void280;281bb:282 %sel = select i1 false, ptr %arg, ptr %arg283 call void @use.16(ptr %arg)284 call void @use.8(ptr %sel)285 ret void286}287 288define internal ptr @test4_c(ptr %arg) {289; CHECK-LABEL: define {{[^@]+}}@test4_c290; CHECK-SAME: (ptr [[ARG:%.*]]) {291; CHECK-NEXT: bb1:292; CHECK-NEXT: [[TMP:%.*]] = and i1 undef, undef293; CHECK-NEXT: br i1 [[TMP]], label [[BB3:%.*]], label [[BB2:%.*]]294; CHECK: bb2:295; CHECK-NEXT: unreachable296; CHECK: bb3:297; CHECK-NEXT: ret ptr poison298;299bb1: ; preds = %bb300 %tmp = and i1 undef, undef301 br i1 %tmp, label %bb3, label %bb2302 303bb2: ; preds = %bb1304 unreachable305 306bb3: ; preds = %bb1307 ret ptr null308}309 310; TODO: Same as test4, but with a select instead of a bitcast.311 312define void @test5_a() {313; CHECK-LABEL: define {{[^@]+}}@test5_a() {314; CHECK-NEXT: bb:315; CHECK-NEXT: [[TMP:%.*]] = call ptr @test5_c(ptr null)316; CHECK-NEXT: call void @test5_b(ptr null)317; CHECK-NEXT: ret void318;319bb:320 %tmp = call ptr @test5_c(ptr null)321 call void @test5_b(ptr %tmp)322 ret void323}324 325define internal void @test5_b(ptr %arg) {326; CHECK-LABEL: define {{[^@]+}}@test5_b327; CHECK-SAME: (ptr [[ARG:%.*]]) {328; CHECK-NEXT: bb:329; CHECK-NEXT: [[SEL:%.*]] = select i1 false, ptr null, ptr null330; CHECK-NEXT: call void @use.8(ptr [[SEL]])331; CHECK-NEXT: ret void332;333bb:334 %sel = select i1 false, ptr %arg, ptr %arg335 call void @use.8(ptr %sel)336 ret void337}338 339define internal ptr @test5_c(ptr %arg) {340; CHECK-LABEL: define {{[^@]+}}@test5_c341; CHECK-SAME: (ptr [[ARG:%.*]]) {342; CHECK-NEXT: bb1:343; CHECK-NEXT: [[TMP:%.*]] = and i1 undef, undef344; CHECK-NEXT: br i1 [[TMP]], label [[BB3:%.*]], label [[BB2:%.*]]345; CHECK: bb2:346; CHECK-NEXT: unreachable347; CHECK: bb3:348; CHECK-NEXT: ret ptr poison349;350bb1: ; preds = %bb351 %tmp = and i1 undef, undef352 br i1 %tmp, label %bb3, label %bb2353 354bb2: ; preds = %bb1355 unreachable356 357bb3: ; preds = %bb1358 ret ptr null359}360 361 362 363@contextsize = external dso_local local_unnamed_addr global i32, align 4364@pcount = internal local_unnamed_addr global i32 0, align 4365@maxposslen = external dso_local local_unnamed_addr global i32, align 4366 367define void @test3() {368; CHECK-LABEL: define {{[^@]+}}@test3() {369; CHECK-NEXT: entry:370; CHECK-NEXT: br label [[IF_END16:%.*]]371; CHECK: if.end16:372; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @contextsize, align 4373; CHECK-NEXT: [[SUB18:%.*]] = sub i32 undef, [[TMP0]]374; CHECK-NEXT: [[SUB19:%.*]] = sub i32 [[SUB18]], undef375; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @maxposslen, align 4376; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP1]], 8377; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 undef, [[ADD]]378; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr @pcount, align 4379; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[DIV]], [[SUB19]]380; CHECK-NEXT: [[CMP20:%.*]] = icmp sgt i32 [[TMP2]], [[MUL]]381; CHECK-NEXT: br i1 [[CMP20]], label [[IF_THEN22:%.*]], label [[IF_END24:%.*]]382; CHECK: if.then22:383; CHECK-NEXT: store i32 [[MUL]], ptr @pcount, align 4384; CHECK-NEXT: ret void385; CHECK: if.end24:386; CHECK-NEXT: [[CMP25474:%.*]] = icmp sgt i32 [[TMP2]], 0387; CHECK-NEXT: br i1 [[CMP25474]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]388; CHECK: for.body:389; CHECK-NEXT: ret void390; CHECK: for.end:391; CHECK-NEXT: ret void392;393entry:394 br label %if.end16395 396if.end16: ; preds = %entry397 %0 = load i32, ptr @contextsize, align 4398 %sub18 = sub i32 undef, %0399 %sub19 = sub i32 %sub18, undef400 %1 = load i32, ptr @maxposslen, align 4401 %add = add nsw i32 %1, 8402 %div = sdiv i32 undef, %add403 %2 = load i32, ptr @pcount, align 4404 %mul = mul nsw i32 %div, %sub19405 %cmp20 = icmp sgt i32 %2, %mul406 br i1 %cmp20, label %if.then22, label %if.end24407 408if.then22: ; preds = %if.end16409 store i32 %mul, ptr @pcount, align 4410 ret void411 412if.end24: ; preds = %if.end16413 %cmp25474 = icmp sgt i32 %2, 0414 br i1 %cmp25474, label %for.body, label %for.end415 416for.body: ; preds = %if.end24417 %3 = trunc i64 0 to i32418 %div30 = sdiv i32 %3, %sub19419 ret void420 421for.end: ; preds = %if.end24422 ret void423}424