1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature 2; RUN: opt -ipsccp -S %s | FileCheck %s 3 4%t1 = type opaque 5 6@e = common global i32 0, align 4 7 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_m 12; CHECK-SAME: (i32 [[H:%.*]]) 13; CHECK-NEXT: entry: 14; CHECK-NEXT: [[CONV:%.*]] = trunc i32 [[H]] to i8 15; CHECK-NEXT: [[CALL:%.*]] = call i32 @test1_k(i8 [[CONV]], i32 0) 16; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[H]] to i64 17; CHECK-NEXT: [[TMP0:%.*]] = inttoptr i64 [[CONV1]] to %t1* 18; CHECK-NEXT: [[CALL2:%.*]] = call i1 @test1_g(%t1* [[TMP0]], i32 1) 19; CHECK-NEXT: ret i32 undef 20; 21entry: 22 %conv = trunc i32 %h to i8 23 %call = call i32 @test1_k(i8 %conv, i32 0) 24 %conv1 = sext i32 %h to i64 25 %0 = inttoptr i64 %conv1 to %t1* 26 %call2 = call i1 @test1_g(%t1* %0, i32 1) 27 ret i32 undef 28 29; uselistorder directives 30 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_k 37; CHECK-SAME: (i8 [[H:%.*]], i32 [[I:%.*]]) 38; CHECK-NEXT: entry: 39; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @e, align 4 40; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64 41; CHECK-NEXT: [[TMP1:%.*]] = inttoptr i64 [[CONV]] to %t1* 42; CHECK-NEXT: [[CALL:%.*]] = call i1 @test1_g(%t1* [[TMP1]], i32 0) 43; CHECK-NEXT: call void @use.1(i1 false) 44; CHECK-NEXT: ret i32 undef 45; 46entry: 47 %0 = load i32, i32* @e, align 4 48 %conv = sext i32 %0 to i64 49 %1 = inttoptr i64 %conv to %t1* 50 %call = call i1 @test1_g(%t1* %1, i32 %i) 51 %frombool.1 = zext i1 %call to i8 52 %tobool.1 = trunc i8 %frombool.1 to i1 53 call void @use.1(i1 %tobool.1) 54 ret i32 undef 55} 56 57define internal i1 @test1_g(%t1* %h, i32 %i) #0 { 58; CHECK-LABEL: define {{[^@]+}}@test1_g 59; CHECK-SAME: (%t1* [[H:%.*]], i32 [[I:%.*]]) 60; CHECK-NEXT: entry: 61; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[I]], 0 62; 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]], 0 66; 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 undef 70; 71entry: 72 %tobool = icmp ne i32 %i, 0 73 br i1 %tobool, label %land.rhs, label %land.end 74 75land.rhs: ; preds = %entry 76 %call = call i32 (...) @test1_j() 77 %tobool1 = icmp ne i32 %call, 0 78 br label %land.end 79 80land.end: ; preds = %land.rhs, %entry 81 %0 = phi i1 [ false, %entry ], [ %tobool1, %land.rhs ] 82 ret i1 false 83} 84 85declare i32 @test1_j(...) 86 87define i32 @test2_m(i32 %h) #0 { 88; CHECK-LABEL: define {{[^@]+}}@test2_m 89; CHECK-SAME: (i32 [[H:%.*]]) 90; CHECK-NEXT: entry: 91; CHECK-NEXT: [[CONV:%.*]] = trunc i32 [[H]] to i8 92; CHECK-NEXT: [[CALL:%.*]] = call i32 @test2_k(i8 [[CONV]], i32 0) 93; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[H]] to i64 94; CHECK-NEXT: [[TMP0:%.*]] = inttoptr i64 [[CONV1]] to %t1* 95; CHECK-NEXT: [[CALL2:%.*]] = call i1 @test2_g(%t1* [[TMP0]], i32 1) 96; CHECK-NEXT: ret i32 undef 97; 98entry: 99 %conv = trunc i32 %h to i8 100 %call = call i32 @test2_k(i8 %conv, i32 0) 101 %conv1 = sext i32 %h to i64 102 %0 = inttoptr i64 %conv1 to %t1* 103 %call2 = call i1 @test2_g(%t1* %0, i32 1) 104 ret i32 undef 105 106; uselistorder directives 107 uselistorder i32 %h, { 1, 0 } 108} 109 110; TODO: We could do better for the return value of call i1 @test3_g, if we 111; resolve the unknown values there first. 112define internal i32 @test2_k(i8 %h, i32 %i) { 113; CHECK-LABEL: define {{[^@]+}}@test2_k 114; CHECK-SAME: (i8 [[H:%.*]], i32 [[I:%.*]]) 115; CHECK-NEXT: entry: 116; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @e, align 4 117; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64 118; CHECK-NEXT: [[TMP1:%.*]] = inttoptr i64 [[CONV]] to %t1* 119; CHECK-NEXT: [[CALL:%.*]] = call i1 @test3_g(%t1* [[TMP1]], i32 0) 120; CHECK-NEXT: call void @use.1(i1 false) 121; CHECK-NEXT: ret i32 undef 122; 123entry: 124 %0 = load i32, i32* @e, align 4 125 %conv = sext i32 %0 to i64 126 %1 = inttoptr i64 %conv to %t1* 127 %call = call i1 @test3_g(%t1* %1, i32 %i) 128 %frombool = icmp slt i1 %call, 1 129 %add = add i1 %frombool, %frombool 130 call void @use.1(i1 %frombool) 131 ret i32 undef 132 133} 134 135define internal i1 @test2_g(%t1* %h, i32 %i) { 136; CHECK-LABEL: define {{[^@]+}}@test2_g 137; CHECK-SAME: (%t1* [[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]], 0 143; CHECK-NEXT: br label [[LAND_END:%.*]] 144; CHECK: land.end: 145; CHECK-NEXT: ret i1 undef 146; 147entry: 148 %tobool = icmp ne i32 %i, 0 149 br i1 %tobool, label %land.rhs, label %land.end 150 151land.rhs: ; preds = %entry 152 %call = call i32 (...) @test2_j() 153 %tobool1 = icmp ne i32 %call, 0 154 br label %land.end 155 156land.end: ; preds = %land.rhs, %entry 157 %0 = phi i1 [ false, %entry ], [ %tobool1, %land.rhs ] 158 ret i1 false 159} 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_m 168; CHECK-SAME: (i32 [[H:%.*]]) 169; CHECK-NEXT: entry: 170; CHECK-NEXT: [[CONV:%.*]] = trunc i32 [[H]] to i8 171; CHECK-NEXT: [[CALL:%.*]] = call i32 @test3_k(i8 [[CONV]], i32 0) 172; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[H]] to i64 173; CHECK-NEXT: [[TMP0:%.*]] = inttoptr i64 [[CONV1]] to %t1* 174; CHECK-NEXT: [[CALL2:%.*]] = call i1 @test3_g(%t1* [[TMP0]], i32 1) 175; CHECK-NEXT: ret i32 undef 176; 177entry: 178 %conv = trunc i32 %h to i8 179 %call = call i32 @test3_k(i8 %conv, i32 0) 180 %conv1 = sext i32 %h to i64 181 %0 = inttoptr i64 %conv1 to %t1* 182 %call2 = call i1 @test3_g(%t1* %0, i32 1) 183 ret i32 undef 184 185; uselistorder directives 186 uselistorder i32 %h, { 1, 0 } 187} 188 189define internal i32 @test3_k(i8 %h, i32 %i) { 190; CHECK-LABEL: define {{[^@]+}}@test3_k 191; CHECK-SAME: (i8 [[H:%.*]], i32 [[I:%.*]]) 192; CHECK-NEXT: entry: 193; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @e, align 4 194; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64 195; CHECK-NEXT: [[TMP1:%.*]] = inttoptr i64 [[CONV]] to %t1* 196; CHECK-NEXT: br label [[LOOP:%.*]] 197; CHECK: loop: 198; CHECK-NEXT: [[CALL:%.*]] = call i1 @test3_g(%t1* [[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 undef 203; 204entry: 205 %0 = load i32, i32* @e, align 4 206 %conv = sext i32 %0 to i64 207 %1 = inttoptr i64 %conv to %t1* 208 br label %loop 209 210loop: 211 %phi = phi i1 [ undef, %entry], [ %call, %loop ] 212 %call = call i1 @test3_g(%t1* %1, i32 %i) 213 %frombool = icmp slt i1 %call, 1 214 %add = add i1 %frombool, %frombool 215 call void @use.1(i1 %frombool) 216 br i1 %call, label %loop, label %exit 217 218exit: 219 ret i32 undef 220} 221 222define internal i1 @test3_g(%t1* %h, i32 %i) { 223; CHECK-LABEL: define {{[^@]+}}@test3_g 224; CHECK-SAME: (%t1* [[H:%.*]], i32 [[I:%.*]]) 225; CHECK-NEXT: entry: 226; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[I]], 0 227; 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]], 0 231; 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 undef 235; 236entry: 237 %tobool = icmp ne i32 %i, 0 238 br i1 %tobool, label %land.rhs, label %land.end 239 240land.rhs: ; preds = %entry 241 %call = call i32 (...) @test3_j() 242 %tobool1 = icmp ne i32 %call, 0 243 br label %land.end 244 245land.end: ; preds = %land.rhs, %entry 246 %0 = phi i1 [ false, %entry ], [ %tobool1, %land.rhs ] 247 ret i1 false 248} 249 250declare i32 @test3_j(...) 251 252 253; TODO: We can eliminate the bitcast, if we resolve the unknown argument of 254; @test4_b first. 255 256declare void @use.16(i16*) 257declare void @use.8(i8*) 258 259define void @test4_a() { 260; CHECK-LABEL: define {{[^@]+}}@test4_a() 261; CHECK-NEXT: bb: 262; CHECK-NEXT: [[TMP:%.*]] = call i8* @test4_c(i8* null) 263; CHECK-NEXT: call void @test4_b(i8* null) 264; CHECK-NEXT: ret void 265; 266bb: 267 %tmp = call i8* @test4_c(i8* null) 268 call void @test4_b(i8* %tmp) 269 ret void 270} 271 272define internal void @test4_b(i8* %arg) { 273; CHECK-LABEL: define {{[^@]+}}@test4_b 274; CHECK-SAME: (i8* [[ARG:%.*]]) 275; CHECK-NEXT: bb: 276; CHECK-NEXT: [[TMP:%.*]] = bitcast i8* null to i16* 277; CHECK-NEXT: [[SEL:%.*]] = select i1 false, i8* null, i8* null 278; CHECK-NEXT: call void @use.16(i16* [[TMP]]) 279; CHECK-NEXT: call void @use.8(i8* [[SEL]]) 280; CHECK-NEXT: ret void 281; 282bb: 283 %tmp = bitcast i8* %arg to i16* 284 %sel = select i1 false, i8* %arg, i8* %arg 285 call void @use.16(i16* %tmp) 286 call void @use.8(i8* %sel) 287 ret void 288} 289 290define internal i8* @test4_c(i8* %arg) { 291; CHECK-LABEL: define {{[^@]+}}@test4_c 292; CHECK-SAME: (i8* [[ARG:%.*]]) 293; CHECK-NEXT: bb1: 294; CHECK-NEXT: [[TMP:%.*]] = and i1 undef, undef 295; CHECK-NEXT: br i1 [[TMP]], label [[BB3:%.*]], label [[BB2:%.*]] 296; CHECK: bb2: 297; CHECK-NEXT: unreachable 298; CHECK: bb3: 299; CHECK-NEXT: ret i8* undef 300; 301bb1: ; preds = %bb 302 %tmp = and i1 undef, undef 303 br i1 %tmp, label %bb3, label %bb2 304 305bb2: ; preds = %bb1 306 unreachable 307 308bb3: ; preds = %bb1 309 ret i8* null 310} 311 312; TODO: Same as test4, but with a select instead of a bitcast. 313 314define void @test5_a() { 315; CHECK-LABEL: define {{[^@]+}}@test5_a() 316; CHECK-NEXT: bb: 317; CHECK-NEXT: [[TMP:%.*]] = call i8* @test5_c(i8* null) 318; CHECK-NEXT: call void @test5_b(i8* null) 319; CHECK-NEXT: ret void 320; 321bb: 322 %tmp = call i8* @test5_c(i8* null) 323 call void @test5_b(i8* %tmp) 324 ret void 325} 326 327define internal void @test5_b(i8* %arg) { 328; CHECK-LABEL: define {{[^@]+}}@test5_b 329; CHECK-SAME: (i8* [[ARG:%.*]]) 330; CHECK-NEXT: bb: 331; CHECK-NEXT: [[SEL:%.*]] = select i1 false, i8* null, i8* null 332; CHECK-NEXT: call void @use.8(i8* [[SEL]]) 333; CHECK-NEXT: ret void 334; 335bb: 336 %sel = select i1 false, i8* %arg, i8* %arg 337 call void @use.8(i8* %sel) 338 ret void 339} 340 341define internal i8* @test5_c(i8* %arg) { 342; CHECK-LABEL: define {{[^@]+}}@test5_c 343; CHECK-SAME: (i8* [[ARG:%.*]]) 344; CHECK-NEXT: bb1: 345; CHECK-NEXT: [[TMP:%.*]] = and i1 undef, undef 346; CHECK-NEXT: br i1 [[TMP]], label [[BB3:%.*]], label [[BB2:%.*]] 347; CHECK: bb2: 348; CHECK-NEXT: unreachable 349; CHECK: bb3: 350; CHECK-NEXT: ret i8* undef 351; 352bb1: ; preds = %bb 353 %tmp = and i1 undef, undef 354 br i1 %tmp, label %bb3, label %bb2 355 356bb2: ; preds = %bb1 357 unreachable 358 359bb3: ; preds = %bb1 360 ret i8* null 361} 362 363 364 365@contextsize = external dso_local local_unnamed_addr global i32, align 4 366@pcount = internal local_unnamed_addr global i32 0, align 4 367@maxposslen = external dso_local local_unnamed_addr global i32, align 4 368 369define void @test3() { 370; CHECK-LABEL: define {{[^@]+}}@test3() 371; CHECK-NEXT: entry: 372; CHECK-NEXT: br label [[IF_END16:%.*]] 373; CHECK: if.end16: 374; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @contextsize, align 4 375; CHECK-NEXT: [[SUB18:%.*]] = sub i32 undef, [[TMP0]] 376; CHECK-NEXT: [[SUB19:%.*]] = sub i32 [[SUB18]], undef 377; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @maxposslen, align 4 378; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP1]], 8 379; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 undef, [[ADD]] 380; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* @pcount, align 4 381; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[DIV]], [[SUB19]] 382; CHECK-NEXT: [[CMP20:%.*]] = icmp sgt i32 [[TMP2]], [[MUL]] 383; CHECK-NEXT: br i1 [[CMP20]], label [[IF_THEN22:%.*]], label [[IF_END24:%.*]] 384; CHECK: if.then22: 385; CHECK-NEXT: store i32 [[MUL]], i32* @pcount, align 4 386; CHECK-NEXT: ret void 387; CHECK: if.end24: 388; CHECK-NEXT: [[CMP25474:%.*]] = icmp sgt i32 [[TMP2]], 0 389; CHECK-NEXT: br i1 [[CMP25474]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] 390; CHECK: for.body: 391; CHECK-NEXT: ret void 392; CHECK: for.end: 393; CHECK-NEXT: ret void 394; 395entry: 396 br label %if.end16 397 398if.end16: ; preds = %entry 399 %0 = load i32, i32* @contextsize, align 4 400 %sub18 = sub i32 undef, %0 401 %sub19 = sub i32 %sub18, undef 402 %1 = load i32, i32* @maxposslen, align 4 403 %add = add nsw i32 %1, 8 404 %div = sdiv i32 undef, %add 405 %2 = load i32, i32* @pcount, align 4 406 %mul = mul nsw i32 %div, %sub19 407 %cmp20 = icmp sgt i32 %2, %mul 408 br i1 %cmp20, label %if.then22, label %if.end24 409 410if.then22: ; preds = %if.end16 411 store i32 %mul, i32* @pcount, align 4 412 ret void 413 414if.end24: ; preds = %if.end16 415 %cmp25474 = icmp sgt i32 %2, 0 416 br i1 %cmp25474, label %for.body, label %for.end 417 418for.body: ; preds = %if.end24 419 %3 = trunc i64 0 to i32 420 %div30 = sdiv i32 %3, %sub19 421 ret void 422 423for.end: ; preds = %if.end24 424 ret void 425} 426