1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals 2; RUN: opt -enable-new-pm=0 -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=20 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM 3; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=20 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM 4; RUN: opt -enable-new-pm=0 -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM 5; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM 6; 7; Test for multiple potential values 8; 9; potential-test 1 10; bool iszero(int c) { return c == 0; } 11; bool potential_test1(bool c) { return iszero(c ? 1 : -1); } 12 13define internal i1 @iszero1(i32 %c) { 14; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 15; IS__CGSCC____-LABEL: define {{[^@]+}}@iszero1 16; IS__CGSCC____-SAME: () #[[ATTR0:[0-9]+]] { 17; IS__CGSCC____-NEXT: ret i1 false 18; 19 %cmp = icmp eq i32 %c, 0 20 ret i1 %cmp 21} 22 23define i1 @potential_test1(i1 %c) { 24; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 25; CHECK-LABEL: define {{[^@]+}}@potential_test1 26; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0:[0-9]+]] { 27; CHECK-NEXT: ret i1 false 28; 29 %arg = select i1 %c, i32 -1, i32 1 30 %ret = call i1 @iszero1(i32 %arg) 31 ret i1 %ret 32} 33 34 35; potential-test 2 36; 37; potential values of argument of iszero are {1,-1} 38; potential value of returned value of iszero is 0 39; 40; int call_with_two_values(int x) { return iszero(x) + iszero(-x); } 41; int potential_test2(int x) { return call_with_two_values(1) + call_with_two_values(-1); } 42 43define internal i32 @iszero2(i32 %c) { 44; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 45; IS__CGSCC____-LABEL: define {{[^@]+}}@iszero2 46; IS__CGSCC____-SAME: () #[[ATTR0]] { 47; IS__CGSCC____-NEXT: ret i32 0 48; 49 %cmp = icmp eq i32 %c, 0 50 %ret = zext i1 %cmp to i32 51 ret i32 %ret 52} 53 54define internal i32 @call_with_two_values(i32 %c) { 55; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 56; IS__CGSCC____-LABEL: define {{[^@]+}}@call_with_two_values 57; IS__CGSCC____-SAME: () #[[ATTR0]] { 58; IS__CGSCC____-NEXT: ret i32 0 59; 60 %csret1 = call i32 @iszero2(i32 %c) 61 %minusc = sub i32 0, %c 62 %csret2 = call i32 @iszero2(i32 %minusc) 63 %ret = add i32 %csret1, %csret2 64 ret i32 %ret 65} 66 67define i32 @potential_test2(i1 %c) { 68; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 69; CHECK-LABEL: define {{[^@]+}}@potential_test2 70; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 71; CHECK-NEXT: ret i32 0 72; 73 %csret1 = call i32 @call_with_two_values(i32 1) 74 %csret2 = call i32 @call_with_two_values(i32 -1) 75 %ret = add i32 %csret1, %csret2 76 ret i32 %ret 77} 78 79 80; potential-test 3 81; 82; potential values of returned value of f are {0,1} 83; potential values of argument of g are {0,1} 84; potential value of returned value of g is 1 85; then returned value of g can be simplified 86; 87; int zero_or_one(int c) { return c < 2; } 88; int potential_test3() { return zero_or_one(iszero(0))+zero_or_one(iszero(1)); } 89 90define internal i32 @iszero3(i32 %c) { 91; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 92; IS__CGSCC____-LABEL: define {{[^@]+}}@iszero3 93; IS__CGSCC____-SAME: (i32 noundef [[C:%.*]]) #[[ATTR0]] { 94; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32 [[C]], 0 95; IS__CGSCC____-NEXT: [[RET:%.*]] = zext i1 [[CMP]] to i32 96; IS__CGSCC____-NEXT: ret i32 [[RET]] 97; 98 %cmp = icmp eq i32 %c, 0 99 %ret = zext i1 %cmp to i32 100 ret i32 %ret 101} 102 103define internal i32 @less_than_two(i32 %c) { 104; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 105; IS__CGSCC____-LABEL: define {{[^@]+}}@less_than_two 106; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 107; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp slt i32 [[C]], 2 108; IS__CGSCC____-NEXT: [[RET:%.*]] = zext i1 [[CMP]] to i32 109; IS__CGSCC____-NEXT: ret i32 [[RET]] 110; 111 %cmp = icmp slt i32 %c, 2 112 %ret = zext i1 %cmp to i32 113 ret i32 %ret 114} 115 116define i32 @potential_test3() { 117; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 118; CHECK-LABEL: define {{[^@]+}}@potential_test3 119; CHECK-SAME: () #[[ATTR0]] { 120; CHECK-NEXT: ret i32 2 121; 122 %cmp1 = call i32 @iszero3(i32 0) 123 %true1 = call i32 @less_than_two(i32 %cmp1) 124 %cmp2 = call i32 @iszero3(i32 1) 125 %true2 = call i32 @less_than_two(i32 %cmp2) 126 %ret = add i32 %true1, %true2 127 ret i32 %ret 128} 129 130 131; potential-test 4,5 132; 133; simplified 134; int potential_test4(int c) { return return1or3(c) == 2; } 135; int potential_test5(int c) { return return1or3(c) == return2or4(c); } 136; 137; not simplified 138; int potential_test6(int c) { return return1or3(c) == 3; } 139; int potential_test7(int c) { return return1or3(c) == return3or4(c); } 140 141define i32 @potential_test4(i32 %c) { 142; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 143; CHECK-LABEL: define {{[^@]+}}@potential_test4 144; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 145; CHECK-NEXT: ret i32 0 146; 147 %csret = call i32 @return1or3(i32 %c) 148 %false = icmp eq i32 %csret, 2 149 %ret = zext i1 %false to i32 150 ret i32 %ret 151} 152 153define i32 @potential_test5(i32 %c) { 154; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 155; CHECK-LABEL: define {{[^@]+}}@potential_test5 156; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 157; CHECK-NEXT: ret i32 0 158; 159 %csret1 = call i32 @return1or3(i32 %c) 160 %csret2 = call i32 @return2or4(i32 %c) 161 %false = icmp eq i32 %csret1, %csret2 162 %ret = zext i1 %false to i32 163 ret i32 %ret 164} 165 166define i1 @potential_test6(i32 %c) { 167; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 168; IS________OPM-LABEL: define {{[^@]+}}@potential_test6 169; IS________OPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 170; IS________OPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2:[0-9]+]], !range [[RNG0:![0-9]+]] 171; IS________OPM-NEXT: [[RET:%.*]] = icmp eq i32 [[CSRET1]], 3 172; IS________OPM-NEXT: ret i1 [[RET]] 173; 174; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 175; IS________NPM-LABEL: define {{[^@]+}}@potential_test6 176; IS________NPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 177; IS________NPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]] 178; IS________NPM-NEXT: [[RET:%.*]] = icmp eq i32 [[CSRET1]], 3 179; IS________NPM-NEXT: ret i1 [[RET]] 180; 181 %csret1 = call i32 @return1or3(i32 %c) 182 %ret = icmp eq i32 %csret1, 3 183 ret i1 %ret 184} 185 186define i1 @potential_test7(i32 %c) { 187; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 188; IS________OPM-LABEL: define {{[^@]+}}@potential_test7 189; IS________OPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 190; IS________OPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]], !range [[RNG0]] 191; IS________OPM-NEXT: [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR2]], !range [[RNG1:![0-9]+]] 192; IS________OPM-NEXT: [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]] 193; IS________OPM-NEXT: ret i1 [[RET]] 194; 195; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 196; IS________NPM-LABEL: define {{[^@]+}}@potential_test7 197; IS________NPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 198; IS________NPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR1]], !range [[RNG0]] 199; IS________NPM-NEXT: [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR1]], !range [[RNG1:![0-9]+]] 200; IS________NPM-NEXT: [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]] 201; IS________NPM-NEXT: ret i1 [[RET]] 202; 203 %csret1 = call i32 @return1or3(i32 %c) 204 %csret2 = call i32 @return3or4(i32 %c) 205 %ret = icmp eq i32 %csret1, %csret2 206 ret i1 %ret 207} 208 209define internal i32 @return1or3(i32 %c) { 210; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 211; CHECK-LABEL: define {{[^@]+}}@return1or3 212; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 213; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C]], 0 214; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 1, i32 3 215; CHECK-NEXT: ret i32 [[RET]] 216; 217 %cmp = icmp eq i32 %c, 0 218 %ret = select i1 %cmp, i32 1, i32 3 219 ret i32 %ret 220} 221 222define internal i32 @return2or4(i32 %c) { 223; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 224; IS__CGSCC____-LABEL: define {{[^@]+}}@return2or4 225; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 226; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32 [[C]], 0 227; IS__CGSCC____-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 2, i32 4 228; IS__CGSCC____-NEXT: ret i32 [[RET]] 229; 230 %cmp = icmp eq i32 %c, 0 231 %ret = select i1 %cmp, i32 2, i32 4 232 ret i32 %ret 233} 234 235define internal i32 @return3or4(i32 %c) { 236; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 237; CHECK-LABEL: define {{[^@]+}}@return3or4 238; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 239; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C]], 0 240; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 3, i32 4 241; CHECK-NEXT: ret i32 [[RET]] 242; 243 %cmp = icmp eq i32 %c, 0 244 %ret = select i1 %cmp, i32 3, i32 4 245 ret i32 %ret 246} 247 248; potential-test 8 249; 250; propagate argument to callsite argument 251 252define internal i1 @cmp_with_four(i32 %c) { 253; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 254; IS__CGSCC____-LABEL: define {{[^@]+}}@cmp_with_four 255; IS__CGSCC____-SAME: () #[[ATTR0]] { 256; IS__CGSCC____-NEXT: ret i1 false 257; 258 %cmp = icmp eq i32 %c, 4 259 ret i1 %cmp 260} 261 262define internal i1 @wrapper(i32 %c) { 263; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 264; IS__CGSCC____-LABEL: define {{[^@]+}}@wrapper 265; IS__CGSCC____-SAME: () #[[ATTR0]] { 266; IS__CGSCC____-NEXT: ret i1 false 267; 268 %ret = call i1 @cmp_with_four(i32 %c) 269 ret i1 %ret 270} 271 272define i1 @potential_test8() { 273; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 274; CHECK-LABEL: define {{[^@]+}}@potential_test8 275; CHECK-SAME: () #[[ATTR0]] { 276; CHECK-NEXT: ret i1 false 277; 278 %res1 = call i1 @wrapper(i32 1) 279 %res3 = call i1 @wrapper(i32 3) 280 %res5 = call i1 @wrapper(i32 5) 281 %res13 = or i1 %res1, %res3 282 %res135 = or i1 %res13, %res5 283 ret i1 %res135 284} 285 286define i1 @potential_test9() { 287; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone 288; IS________OPM-LABEL: define {{[^@]+}}@potential_test9 289; IS________OPM-SAME: () #[[ATTR1:[0-9]+]] { 290; IS________OPM-NEXT: entry: 291; IS________OPM-NEXT: br label [[COND:%.*]] 292; IS________OPM: cond: 293; IS________OPM-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_1:%.*]], [[INC:%.*]] ] 294; IS________OPM-NEXT: [[C_0:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[C_1:%.*]], [[INC]] ] 295; IS________OPM-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 10 296; IS________OPM-NEXT: br i1 [[CMP]], label [[BODY:%.*]], label [[END:%.*]] 297; IS________OPM: body: 298; IS________OPM-NEXT: [[C_1]] = mul i32 [[C_0]], -1 299; IS________OPM-NEXT: br label [[INC]] 300; IS________OPM: inc: 301; IS________OPM-NEXT: [[I_1]] = add i32 [[I_0]], 1 302; IS________OPM-NEXT: br label [[COND]] 303; IS________OPM: end: 304; IS________OPM-NEXT: ret i1 false 305; 306; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 307; IS________NPM-LABEL: define {{[^@]+}}@potential_test9 308; IS________NPM-SAME: () #[[ATTR0]] { 309; IS________NPM-NEXT: entry: 310; IS________NPM-NEXT: br label [[COND:%.*]] 311; IS________NPM: cond: 312; IS________NPM-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_1:%.*]], [[INC:%.*]] ] 313; IS________NPM-NEXT: [[C_0:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[C_1:%.*]], [[INC]] ] 314; IS________NPM-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 10 315; IS________NPM-NEXT: br i1 [[CMP]], label [[BODY:%.*]], label [[END:%.*]] 316; IS________NPM: body: 317; IS________NPM-NEXT: [[C_1]] = mul i32 [[C_0]], -1 318; IS________NPM-NEXT: br label [[INC]] 319; IS________NPM: inc: 320; IS________NPM-NEXT: [[I_1]] = add i32 [[I_0]], 1 321; IS________NPM-NEXT: br label [[COND]] 322; IS________NPM: end: 323; IS________NPM-NEXT: ret i1 false 324; 325entry: 326 br label %cond 327cond: 328 %i.0 = phi i32 [0, %entry], [%i.1, %inc] 329 %c.0 = phi i32 [1, %entry], [%c.1, %inc] 330 %cmp = icmp slt i32 %i.0, 10 331 br i1 %cmp, label %body, label %end 332body: 333 %c.1 = mul i32 %c.0, -1 334 br label %inc 335inc: 336 %i.1 = add i32 %i.0, 1 337 br label %cond 338end: 339 %ret = icmp eq i32 %c.0, 0 340 ret i1 %ret 341} 342 343; Test 10 344; FIXME: potential returned values of @may_return_undef is {1, -1} 345; and returned value of @potential_test10 can be simplified to 0(false) 346 347define internal i32 @may_return_undef(i32 %c) { 348; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 349; IS__CGSCC____-LABEL: define {{[^@]+}}@may_return_undef 350; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 351; IS__CGSCC____-NEXT: switch i32 [[C]], label [[OTHERWISE:%.*]] [ 352; IS__CGSCC____-NEXT: i32 1, label [[A:%.*]] 353; IS__CGSCC____-NEXT: i32 -1, label [[B:%.*]] 354; IS__CGSCC____-NEXT: ] 355; IS__CGSCC____: a: 356; IS__CGSCC____-NEXT: ret i32 1 357; IS__CGSCC____: b: 358; IS__CGSCC____-NEXT: ret i32 -1 359; IS__CGSCC____: otherwise: 360; IS__CGSCC____-NEXT: ret i32 undef 361; 362 switch i32 %c, label %otherwise [i32 1, label %a 363 i32 -1, label %b] 364a: 365 ret i32 1 366b: 367 ret i32 -1 368otherwise: 369 ret i32 undef 370} 371 372define i1 @potential_test10(i32 %c) { 373; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 374; CHECK-LABEL: define {{[^@]+}}@potential_test10 375; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 376; CHECK-NEXT: ret i1 false 377; 378 %ret = call i32 @may_return_undef(i32 %c) 379 %cmp = icmp eq i32 %ret, 0 380 ret i1 %cmp 381} 382 383define i32 @optimize_undef_1(i1 %c) { 384; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 385; CHECK-LABEL: define {{[^@]+}}@optimize_undef_1 386; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 387; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 388; CHECK: t: 389; CHECK-NEXT: ret i32 0 390; CHECK: f: 391; CHECK-NEXT: ret i32 1 392; 393 br i1 %c, label %t, label %f 394t: 395 ret i32 0 396f: 397 %undef = add i32 undef, 1 398 ret i32 %undef 399} 400 401define i32 @optimize_undef_2(i1 %c) { 402; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 403; CHECK-LABEL: define {{[^@]+}}@optimize_undef_2 404; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 405; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 406; CHECK: t: 407; CHECK-NEXT: ret i32 0 408; CHECK: f: 409; CHECK-NEXT: ret i32 -1 410; 411 br i1 %c, label %t, label %f 412t: 413 ret i32 0 414f: 415 %undef = sub i32 undef, 1 416 ret i32 %undef 417} 418 419define i32 @optimize_undef_3(i1 %c) { 420; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 421; CHECK-LABEL: define {{[^@]+}}@optimize_undef_3 422; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 423; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 424; CHECK: t: 425; CHECK-NEXT: ret i32 0 426; CHECK: f: 427; CHECK-NEXT: ret i32 1 428; 429 br i1 %c, label %t, label %f 430t: 431 ret i32 0 432f: 433 %undef = icmp eq i32 undef, 0 434 %undef2 = zext i1 %undef to i32 435 ret i32 %undef2 436} 437 438 439; FIXME: returned value can be simplified to 0 440define i32 @potential_test11(i1 %c) { 441; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 442; IS________OPM-LABEL: define {{[^@]+}}@potential_test11 443; IS________OPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 444; IS________OPM-NEXT: [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) #[[ATTR2]], !range [[RNG2:![0-9]+]] 445; IS________OPM-NEXT: [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) #[[ATTR2]], !range [[RNG3:![0-9]+]] 446; IS________OPM-NEXT: [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]]) #[[ATTR2]], !range [[RNG2]] 447; IS________OPM-NEXT: [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]] 448; IS________OPM-NEXT: [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]] 449; IS________OPM-NEXT: ret i32 [[ACC2]] 450; 451; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 452; IS________NPM-LABEL: define {{[^@]+}}@potential_test11 453; IS________NPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 454; IS________NPM-NEXT: [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) #[[ATTR1]], !range [[RNG2:![0-9]+]] 455; IS________NPM-NEXT: [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) #[[ATTR1]], !range [[RNG3:![0-9]+]] 456; IS________NPM-NEXT: [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]]) #[[ATTR1]], !range [[RNG2]] 457; IS________NPM-NEXT: [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]] 458; IS________NPM-NEXT: [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]] 459; IS________NPM-NEXT: ret i32 [[ACC2]] 460; 461 %zero1 = call i32 @optimize_undef_1(i1 %c) 462 %zero2 = call i32 @optimize_undef_2(i1 %c) 463 %zero3 = call i32 @optimize_undef_3(i1 %c) 464 %acc1 = add i32 %zero1, %zero2 465 %acc2 = add i32 %acc1, %zero3 466 ret i32 %acc2 467} 468 469define i32 @optimize_poison_1(i1 %c) { 470; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 471; IS________OPM-LABEL: define {{[^@]+}}@optimize_poison_1 472; IS________OPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 473; IS________OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 474; IS________OPM: t: 475; IS________OPM-NEXT: ret i32 0 476; IS________OPM: f: 477; IS________OPM-NEXT: ret i32 -1 478; 479; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 480; IS________NPM-LABEL: define {{[^@]+}}@optimize_poison_1 481; IS________NPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 482; IS________NPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 483; IS________NPM: t: 484; IS________NPM-NEXT: ret i32 0 485; IS________NPM: f: 486; IS________NPM-NEXT: ret i32 undef 487; 488 br i1 %c, label %t, label %f 489t: 490 ret i32 0 491f: 492 %poison = sub nuw i32 0, 1 493 ret i32 %poison 494} 495 496; FIXME: returned value can be simplified to 0 497define i32 @potential_test12(i1 %c) { 498; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 499; IS________OPM-LABEL: define {{[^@]+}}@potential_test12 500; IS________OPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 501; IS________OPM-NEXT: [[ZERO:%.*]] = call noundef i32 @optimize_poison_1(i1 [[C]]) #[[ATTR2]], !range [[RNG3]] 502; IS________OPM-NEXT: ret i32 [[ZERO]] 503; 504; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 505; IS________NPM-LABEL: define {{[^@]+}}@potential_test12 506; IS________NPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 507; IS________NPM-NEXT: ret i32 0 508; 509 %zero = call i32 @optimize_poison_1(i1 %c) 510 ret i32 %zero 511} 512 513; Test 13 514; Do not simplify %ret in the callee to `%c`. 515; The potential value of %c is {0, 1} (undef is merged). 516; However, we should not simplify `and i32 %c, 3` to `%c` 517 518define internal i32 @potential_test13_callee(i32 %c) { 519; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 520; CHECK-LABEL: define {{[^@]+}}@potential_test13_callee 521; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 522; CHECK-NEXT: [[RET:%.*]] = and i32 [[C]], 3 523; CHECK-NEXT: ret i32 [[RET]] 524; 525 %ret = and i32 %c, 3 526 ret i32 %ret 527} 528 529define i32 @potential_test13_caller1() { 530; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 531; IS________OPM-LABEL: define {{[^@]+}}@potential_test13_caller1 532; IS________OPM-SAME: () #[[ATTR0]] { 533; IS________OPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 0) #[[ATTR2]], !range [[RNG2]] 534; IS________OPM-NEXT: ret i32 [[RET]] 535; 536; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 537; IS________NPM-LABEL: define {{[^@]+}}@potential_test13_caller1 538; IS________NPM-SAME: () #[[ATTR0]] { 539; IS________NPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 0) #[[ATTR1]], !range [[RNG2]] 540; IS________NPM-NEXT: ret i32 [[RET]] 541; 542 %ret = call i32 @potential_test13_callee(i32 0) 543 ret i32 %ret 544} 545 546define i32 @potential_test13_caller2() { 547; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 548; IS________OPM-LABEL: define {{[^@]+}}@potential_test13_caller2 549; IS________OPM-SAME: () #[[ATTR0]] { 550; IS________OPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 1) #[[ATTR2]], !range [[RNG2]] 551; IS________OPM-NEXT: ret i32 [[RET]] 552; 553; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 554; IS________NPM-LABEL: define {{[^@]+}}@potential_test13_caller2 555; IS________NPM-SAME: () #[[ATTR0]] { 556; IS________NPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 1) #[[ATTR1]], !range [[RNG2]] 557; IS________NPM-NEXT: ret i32 [[RET]] 558; 559 %ret = call i32 @potential_test13_callee(i32 1) 560 ret i32 %ret 561} 562 563define i32 @potential_test13_caller3() { 564; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 565; IS________OPM-LABEL: define {{[^@]+}}@potential_test13_caller3 566; IS________OPM-SAME: () #[[ATTR0]] { 567; IS________OPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR2]], !range [[RNG2]] 568; IS________OPM-NEXT: ret i32 [[RET]] 569; 570; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 571; IS________NPM-LABEL: define {{[^@]+}}@potential_test13_caller3 572; IS________NPM-SAME: () #[[ATTR0]] { 573; IS________NPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR1]], !range [[RNG2]] 574; IS________NPM-NEXT: ret i32 [[RET]] 575; 576 %ret = call i32 @potential_test13_callee(i32 undef) 577 ret i32 %ret 578} 579 580define i1 @potential_test14(i1 %c0, i1 %c1, i1 %c2, i1 %c3) { 581; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 582; CHECK-LABEL: define {{[^@]+}}@potential_test14 583; CHECK-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) #[[ATTR0]] { 584; CHECK-NEXT: [[X0:%.*]] = select i1 [[C0]], i32 0, i32 1 585; CHECK-NEXT: [[X1:%.*]] = select i1 [[C1]], i32 [[X0]], i32 undef 586; CHECK-NEXT: [[Y2:%.*]] = select i1 [[C2]], i32 0, i32 7 587; CHECK-NEXT: [[Z3:%.*]] = select i1 [[C3]], i32 [[X1]], i32 [[Y2]] 588; CHECK-NEXT: [[RET:%.*]] = icmp slt i32 [[Z3]], 7 589; CHECK-NEXT: ret i1 [[RET]] 590; 591 %x0 = select i1 %c0, i32 0, i32 1 592 %x1 = select i1 %c1, i32 %x0, i32 undef 593 %y2 = select i1 %c2, i32 0, i32 7 594 %z3 = select i1 %c3, i32 %x1, i32 %y2 595 %ret = icmp slt i32 %z3, 7 596 ret i1 %ret 597} 598 599define i1 @potential_test15(i1 %c0, i1 %c1) { 600; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 601; CHECK-LABEL: define {{[^@]+}}@potential_test15 602; CHECK-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]]) #[[ATTR0]] { 603; CHECK-NEXT: ret i1 false 604; 605 %x0 = select i1 %c0, i32 0, i32 1 606 %x1 = select i1 %c1, i32 %x0, i32 undef 607 %ret = icmp eq i32 %x1, 7 608 ret i1 %ret 609} 610 611define i1 @potential_test16(i1 %c0, i1 %c1) { 612; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 613; CHECK-LABEL: define {{[^@]+}}@potential_test16 614; CHECK-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]]) #[[ATTR0]] { 615; CHECK-NEXT: ret i1 false 616; 617 %x0 = select i1 %c0, i32 0, i32 undef 618 %x1 = select i1 %c1, i32 %x0, i32 1 619 %ret = icmp eq i32 %x1, 7 620 ret i1 %ret 621} 622 623;. 624; IS__TUNIT_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } 625; IS__TUNIT_OPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone } 626; IS__TUNIT_OPM: attributes #[[ATTR2]] = { nofree nosync nounwind readnone willreturn } 627;. 628; IS__TUNIT_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } 629; IS__TUNIT_NPM: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn } 630;. 631; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } 632; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone } 633; IS__CGSCC_OPM: attributes #[[ATTR2]] = { readnone willreturn } 634;. 635; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } 636; IS__CGSCC_NPM: attributes #[[ATTR1]] = { readnone willreturn } 637;. 638; CHECK: [[META0:![0-9]+]] = !{i32 1, i32 4} 639; CHECK: [[META1:![0-9]+]] = !{i32 3, i32 5} 640; CHECK: [[META2:![0-9]+]] = !{i32 0, i32 2} 641; CHECK: [[META3:![0-9]+]] = !{i32 -1, i32 1} 642;. 643