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=13 -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=13 -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: (i32 noundef [[C:%.*]]) #[[ATTR0:[0-9]+]] { 17; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32 [[C]], 0 18; IS__CGSCC____-NEXT: ret i1 [[CMP]] 19; 20 %cmp = icmp eq i32 %c, 0 21 ret i1 %cmp 22} 23 24define i1 @potential_test1(i1 %c) { 25; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 26; IS__TUNIT____-LABEL: define {{[^@]+}}@potential_test1 27; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR0:[0-9]+]] { 28; IS__TUNIT____-NEXT: ret i1 false 29; 30; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 31; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test1 32; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR1:[0-9]+]] { 33; IS__CGSCC_OPM-NEXT: [[ARG:%.*]] = select i1 [[C]], i32 -1, i32 1 34; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = call i1 @iszero1(i32 noundef [[ARG]]) #[[ATTR3:[0-9]+]] 35; IS__CGSCC_OPM-NEXT: ret i1 [[RET]] 36; 37; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 38; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test1 39; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR1:[0-9]+]] { 40; IS__CGSCC_NPM-NEXT: [[ARG:%.*]] = select i1 [[C]], i32 -1, i32 1 41; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = call i1 @iszero1(i32 noundef [[ARG]]) #[[ATTR2:[0-9]+]] 42; IS__CGSCC_NPM-NEXT: ret i1 [[RET]] 43; 44 %arg = select i1 %c, i32 -1, i32 1 45 %ret = call i1 @iszero1(i32 %arg) 46 ret i1 %ret 47} 48 49 50; potential-test 2 51; 52; potential values of argument of iszero are {1,-1} 53; potential value of returned value of iszero is 0 54; 55; int call_with_two_values(int x) { return iszero(x) + iszero(-x); } 56; int potential_test2(int x) { return call_with_two_values(1) + call_with_two_values(-1); } 57 58define internal i32 @iszero2(i32 %c) { 59; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 60; CHECK-LABEL: define {{[^@]+}}@iszero2 61; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0:[0-9]+]] { 62; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C]], 0 63; CHECK-NEXT: [[RET:%.*]] = zext i1 [[CMP]] to i32 64; CHECK-NEXT: ret i32 [[RET]] 65; 66 %cmp = icmp eq i32 %c, 0 67 %ret = zext i1 %cmp to i32 68 ret i32 %ret 69} 70 71define internal i32 @call_with_two_values(i32 %c) { 72; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 73; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@call_with_two_values 74; IS__TUNIT_OPM-SAME: (i32 noundef [[C:%.*]]) #[[ATTR0]] { 75; IS__TUNIT_OPM-NEXT: [[CSRET1:%.*]] = call i32 @iszero2(i32 noundef [[C]]) #[[ATTR2:[0-9]+]], !range [[RNG0:![0-9]+]] 76; IS__TUNIT_OPM-NEXT: [[MINUSC:%.*]] = sub i32 0, [[C]] 77; IS__TUNIT_OPM-NEXT: [[CSRET2:%.*]] = call i32 @iszero2(i32 [[MINUSC]]) #[[ATTR2]], !range [[RNG0]] 78; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]] 79; IS__TUNIT_OPM-NEXT: ret i32 [[RET]] 80; 81; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 82; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@call_with_two_values 83; IS__TUNIT_NPM-SAME: (i32 noundef [[C:%.*]]) #[[ATTR0]] { 84; IS__TUNIT_NPM-NEXT: [[CSRET1:%.*]] = call i32 @iszero2(i32 noundef [[C]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]] 85; IS__TUNIT_NPM-NEXT: [[MINUSC:%.*]] = sub i32 0, [[C]] 86; IS__TUNIT_NPM-NEXT: [[CSRET2:%.*]] = call i32 @iszero2(i32 [[MINUSC]]) #[[ATTR1]], !range [[RNG0]] 87; IS__TUNIT_NPM-NEXT: [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]] 88; IS__TUNIT_NPM-NEXT: ret i32 [[RET]] 89; 90; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 91; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@call_with_two_values 92; IS__CGSCC_OPM-SAME: (i32 noundef [[C:%.*]]) #[[ATTR1]] { 93; IS__CGSCC_OPM-NEXT: [[CSRET1:%.*]] = call i32 @iszero2(i32 noundef [[C]]) #[[ATTR3]] 94; IS__CGSCC_OPM-NEXT: [[MINUSC:%.*]] = sub i32 0, [[C]] 95; IS__CGSCC_OPM-NEXT: [[CSRET2:%.*]] = call i32 @iszero2(i32 [[MINUSC]]) #[[ATTR3]] 96; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]] 97; IS__CGSCC_OPM-NEXT: ret i32 [[RET]] 98; 99; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 100; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@call_with_two_values 101; IS__CGSCC_NPM-SAME: (i32 noundef [[C:%.*]]) #[[ATTR1]] { 102; IS__CGSCC_NPM-NEXT: [[CSRET1:%.*]] = call i32 @iszero2(i32 noundef [[C]]) #[[ATTR2]] 103; IS__CGSCC_NPM-NEXT: [[MINUSC:%.*]] = sub i32 0, [[C]] 104; IS__CGSCC_NPM-NEXT: [[CSRET2:%.*]] = call i32 @iszero2(i32 [[MINUSC]]) #[[ATTR2]] 105; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]] 106; IS__CGSCC_NPM-NEXT: ret i32 [[RET]] 107; 108 %csret1 = call i32 @iszero2(i32 %c) 109 %minusc = sub i32 0, %c 110 %csret2 = call i32 @iszero2(i32 %minusc) 111 %ret = add i32 %csret1, %csret2 112 ret i32 %ret 113} 114 115define i32 @potential_test2(i1 %c) { 116; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 117; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test2 118; IS__TUNIT_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 119; IS__TUNIT_OPM-NEXT: [[CSRET1:%.*]] = call i32 @call_with_two_values(i32 noundef 1) #[[ATTR2]], !range [[RNG1:![0-9]+]] 120; IS__TUNIT_OPM-NEXT: [[CSRET2:%.*]] = call i32 @call_with_two_values(i32 noundef -1) #[[ATTR2]], !range [[RNG1]] 121; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]] 122; IS__TUNIT_OPM-NEXT: ret i32 [[RET]] 123; 124; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 125; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test2 126; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 127; IS__TUNIT_NPM-NEXT: [[CSRET1:%.*]] = call i32 @call_with_two_values(i32 noundef 1) #[[ATTR1]], !range [[RNG1:![0-9]+]] 128; IS__TUNIT_NPM-NEXT: [[CSRET2:%.*]] = call i32 @call_with_two_values(i32 noundef -1) #[[ATTR1]], !range [[RNG1]] 129; IS__TUNIT_NPM-NEXT: [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]] 130; IS__TUNIT_NPM-NEXT: ret i32 [[RET]] 131; 132; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 133; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test2 134; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { 135; IS__CGSCC_OPM-NEXT: [[CSRET1:%.*]] = call i32 @call_with_two_values(i32 noundef 1) #[[ATTR3]] 136; IS__CGSCC_OPM-NEXT: [[CSRET2:%.*]] = call i32 @call_with_two_values(i32 noundef -1) #[[ATTR3]] 137; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]] 138; IS__CGSCC_OPM-NEXT: ret i32 [[RET]] 139; 140; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 141; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test2 142; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { 143; IS__CGSCC_NPM-NEXT: [[CSRET1:%.*]] = call i32 @call_with_two_values(i32 noundef 1) #[[ATTR2]] 144; IS__CGSCC_NPM-NEXT: [[CSRET2:%.*]] = call i32 @call_with_two_values(i32 noundef -1) #[[ATTR2]] 145; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]] 146; IS__CGSCC_NPM-NEXT: ret i32 [[RET]] 147; 148 %csret1 = call i32 @call_with_two_values(i32 1) 149 %csret2 = call i32 @call_with_two_values(i32 -1) 150 %ret = add i32 %csret1, %csret2 151 ret i32 %ret 152} 153 154 155; potential-test 3 156; 157; potential values of returned value of f are {0,1} 158; potential values of argument of g are {0,1} 159; potential value of returned value of g is 1 160; then returned value of g can be simplified 161; 162; int zero_or_one(int c) { return c < 2; } 163; int potential_test3() { return zero_or_one(iszero(0))+zero_or_one(iszero(1)); } 164 165define internal i32 @iszero3(i32 %c) { 166; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 167; IS__CGSCC____-LABEL: define {{[^@]+}}@iszero3 168; IS__CGSCC____-SAME: (i32 noundef [[C:%.*]]) #[[ATTR0]] { 169; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32 [[C]], 0 170; IS__CGSCC____-NEXT: [[RET:%.*]] = zext i1 [[CMP]] to i32 171; IS__CGSCC____-NEXT: ret i32 [[RET]] 172; 173 %cmp = icmp eq i32 %c, 0 174 %ret = zext i1 %cmp to i32 175 ret i32 %ret 176} 177 178define internal i32 @less_than_two(i32 %c) { 179; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 180; IS__CGSCC____-LABEL: define {{[^@]+}}@less_than_two 181; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 182; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp slt i32 [[C]], 2 183; IS__CGSCC____-NEXT: [[RET:%.*]] = zext i1 [[CMP]] to i32 184; IS__CGSCC____-NEXT: ret i32 [[RET]] 185; 186 %cmp = icmp slt i32 %c, 2 187 %ret = zext i1 %cmp to i32 188 ret i32 %ret 189} 190 191define i32 @potential_test3() { 192; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 193; IS__TUNIT____-LABEL: define {{[^@]+}}@potential_test3 194; IS__TUNIT____-SAME: () #[[ATTR0]] { 195; IS__TUNIT____-NEXT: ret i32 2 196; 197; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 198; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test3 199; IS__CGSCC_OPM-SAME: () #[[ATTR1]] { 200; IS__CGSCC_OPM-NEXT: [[CMP1:%.*]] = call i32 @iszero3(i32 noundef 0) #[[ATTR3]] 201; IS__CGSCC_OPM-NEXT: [[TRUE1:%.*]] = call i32 @less_than_two(i32 [[CMP1]]) #[[ATTR3]] 202; IS__CGSCC_OPM-NEXT: [[CMP2:%.*]] = call i32 @iszero3(i32 noundef 1) #[[ATTR3]] 203; IS__CGSCC_OPM-NEXT: [[TRUE2:%.*]] = call i32 @less_than_two(i32 [[CMP2]]) #[[ATTR3]] 204; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = add i32 [[TRUE1]], [[TRUE2]] 205; IS__CGSCC_OPM-NEXT: ret i32 [[RET]] 206; 207; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 208; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test3 209; IS__CGSCC_NPM-SAME: () #[[ATTR1]] { 210; IS__CGSCC_NPM-NEXT: [[CMP1:%.*]] = call i32 @iszero3(i32 noundef 0) #[[ATTR2]] 211; IS__CGSCC_NPM-NEXT: [[TRUE1:%.*]] = call i32 @less_than_two(i32 [[CMP1]]) #[[ATTR2]] 212; IS__CGSCC_NPM-NEXT: [[CMP2:%.*]] = call i32 @iszero3(i32 noundef 1) #[[ATTR2]] 213; IS__CGSCC_NPM-NEXT: [[TRUE2:%.*]] = call i32 @less_than_two(i32 [[CMP2]]) #[[ATTR2]] 214; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = add i32 [[TRUE1]], [[TRUE2]] 215; IS__CGSCC_NPM-NEXT: ret i32 [[RET]] 216; 217 %cmp1 = call i32 @iszero3(i32 0) 218 %true1 = call i32 @less_than_two(i32 %cmp1) 219 %cmp2 = call i32 @iszero3(i32 1) 220 %true2 = call i32 @less_than_two(i32 %cmp2) 221 %ret = add i32 %true1, %true2 222 ret i32 %ret 223} 224 225 226; potential-test 4,5 227; 228; simplified 229; int potential_test4(int c) { return return1or3(c) == 2; } 230; int potential_test5(int c) { return return1or3(c) == return2or4(c); } 231; 232; not simplified 233; int potential_test6(int c) { return return1or3(c) == 3; } 234; int potential_test7(int c) { return return1or3(c) == return3or4(c); } 235 236define i32 @potential_test4(i32 %c) { 237; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 238; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test4 239; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 240; IS__TUNIT_OPM-NEXT: [[CSRET:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]] 241; IS__TUNIT_OPM-NEXT: [[FALSE:%.*]] = icmp eq i32 [[CSRET]], 2 242; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = zext i1 [[FALSE]] to i32 243; IS__TUNIT_OPM-NEXT: ret i32 [[RET]] 244; 245; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 246; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test4 247; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 248; IS__TUNIT_NPM-NEXT: [[CSRET:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR1]] 249; IS__TUNIT_NPM-NEXT: [[FALSE:%.*]] = icmp eq i32 [[CSRET]], 2 250; IS__TUNIT_NPM-NEXT: [[RET:%.*]] = zext i1 [[FALSE]] to i32 251; IS__TUNIT_NPM-NEXT: ret i32 [[RET]] 252; 253; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 254; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test4 255; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { 256; IS__CGSCC_OPM-NEXT: [[CSRET:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR3]] 257; IS__CGSCC_OPM-NEXT: [[FALSE:%.*]] = icmp eq i32 [[CSRET]], 2 258; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = zext i1 [[FALSE]] to i32 259; IS__CGSCC_OPM-NEXT: ret i32 [[RET]] 260; 261; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 262; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test4 263; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { 264; IS__CGSCC_NPM-NEXT: [[CSRET:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]] 265; IS__CGSCC_NPM-NEXT: [[FALSE:%.*]] = icmp eq i32 [[CSRET]], 2 266; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = zext i1 [[FALSE]] to i32 267; IS__CGSCC_NPM-NEXT: ret i32 [[RET]] 268; 269 %csret = call i32 @return1or3(i32 %c) 270 %false = icmp eq i32 %csret, 2 271 %ret = zext i1 %false to i32 272 ret i32 %ret 273} 274 275define i32 @potential_test5(i32 %c) { 276; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 277; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test5 278; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 279; IS__TUNIT_OPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]] 280; IS__TUNIT_OPM-NEXT: [[CSRET2:%.*]] = call i32 @return2or4(i32 [[C]]) #[[ATTR2]] 281; IS__TUNIT_OPM-NEXT: [[FALSE:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]] 282; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = zext i1 [[FALSE]] to i32 283; IS__TUNIT_OPM-NEXT: ret i32 [[RET]] 284; 285; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 286; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test5 287; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 288; IS__TUNIT_NPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR1]] 289; IS__TUNIT_NPM-NEXT: [[CSRET2:%.*]] = call i32 @return2or4(i32 [[C]]) #[[ATTR1]] 290; IS__TUNIT_NPM-NEXT: [[FALSE:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]] 291; IS__TUNIT_NPM-NEXT: [[RET:%.*]] = zext i1 [[FALSE]] to i32 292; IS__TUNIT_NPM-NEXT: ret i32 [[RET]] 293; 294; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 295; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test5 296; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { 297; IS__CGSCC_OPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR3]] 298; IS__CGSCC_OPM-NEXT: [[CSRET2:%.*]] = call i32 @return2or4(i32 [[C]]) #[[ATTR3]] 299; IS__CGSCC_OPM-NEXT: [[FALSE:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]] 300; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = zext i1 [[FALSE]] to i32 301; IS__CGSCC_OPM-NEXT: ret i32 [[RET]] 302; 303; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 304; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test5 305; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { 306; IS__CGSCC_NPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]] 307; IS__CGSCC_NPM-NEXT: [[CSRET2:%.*]] = call i32 @return2or4(i32 [[C]]) #[[ATTR2]] 308; IS__CGSCC_NPM-NEXT: [[FALSE:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]] 309; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = zext i1 [[FALSE]] to i32 310; IS__CGSCC_NPM-NEXT: ret i32 [[RET]] 311; 312 %csret1 = call i32 @return1or3(i32 %c) 313 %csret2 = call i32 @return2or4(i32 %c) 314 %false = icmp eq i32 %csret1, %csret2 315 %ret = zext i1 %false to i32 316 ret i32 %ret 317} 318 319define i1 @potential_test6(i32 %c) { 320; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 321; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test6 322; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 323; IS__TUNIT_OPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]] 324; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = icmp eq i32 [[CSRET1]], 3 325; IS__TUNIT_OPM-NEXT: ret i1 [[RET]] 326; 327; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 328; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test6 329; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 330; IS__TUNIT_NPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR1]] 331; IS__TUNIT_NPM-NEXT: [[RET:%.*]] = icmp eq i32 [[CSRET1]], 3 332; IS__TUNIT_NPM-NEXT: ret i1 [[RET]] 333; 334; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 335; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test6 336; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { 337; IS__CGSCC_OPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR3]] 338; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = icmp eq i32 [[CSRET1]], 3 339; IS__CGSCC_OPM-NEXT: ret i1 [[RET]] 340; 341; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 342; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test6 343; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { 344; IS__CGSCC_NPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]] 345; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = icmp eq i32 [[CSRET1]], 3 346; IS__CGSCC_NPM-NEXT: ret i1 [[RET]] 347; 348 %csret1 = call i32 @return1or3(i32 %c) 349 %ret = icmp eq i32 %csret1, 3 350 ret i1 %ret 351} 352 353define i1 @potential_test7(i32 %c) { 354; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 355; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test7 356; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 357; IS__TUNIT_OPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]] 358; IS__TUNIT_OPM-NEXT: [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR2]] 359; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]] 360; IS__TUNIT_OPM-NEXT: ret i1 [[RET]] 361; 362; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 363; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test7 364; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 365; IS__TUNIT_NPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR1]] 366; IS__TUNIT_NPM-NEXT: [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR1]] 367; IS__TUNIT_NPM-NEXT: [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]] 368; IS__TUNIT_NPM-NEXT: ret i1 [[RET]] 369; 370; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 371; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test7 372; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { 373; IS__CGSCC_OPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR3]] 374; IS__CGSCC_OPM-NEXT: [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR3]] 375; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]] 376; IS__CGSCC_OPM-NEXT: ret i1 [[RET]] 377; 378; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 379; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test7 380; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { 381; IS__CGSCC_NPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]] 382; IS__CGSCC_NPM-NEXT: [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR2]] 383; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]] 384; IS__CGSCC_NPM-NEXT: ret i1 [[RET]] 385; 386 %csret1 = call i32 @return1or3(i32 %c) 387 %csret2 = call i32 @return3or4(i32 %c) 388 %ret = icmp eq i32 %csret1, %csret2 389 ret i1 %ret 390} 391 392define internal i32 @return1or3(i32 %c) { 393; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 394; CHECK-LABEL: define {{[^@]+}}@return1or3 395; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 396; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C]], 0 397; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 1, i32 3 398; CHECK-NEXT: ret i32 [[RET]] 399; 400 %cmp = icmp eq i32 %c, 0 401 %ret = select i1 %cmp, i32 1, i32 3 402 ret i32 %ret 403} 404 405define internal i32 @return2or4(i32 %c) { 406; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 407; CHECK-LABEL: define {{[^@]+}}@return2or4 408; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 409; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C]], 0 410; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 2, i32 4 411; CHECK-NEXT: ret i32 [[RET]] 412; 413 %cmp = icmp eq i32 %c, 0 414 %ret = select i1 %cmp, i32 2, i32 4 415 ret i32 %ret 416} 417 418define internal i32 @return3or4(i32 %c) { 419; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 420; CHECK-LABEL: define {{[^@]+}}@return3or4 421; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 422; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C]], 0 423; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 3, i32 4 424; CHECK-NEXT: ret i32 [[RET]] 425; 426 %cmp = icmp eq i32 %c, 0 427 %ret = select i1 %cmp, i32 3, i32 4 428 ret i32 %ret 429} 430 431; potential-test 8 432; 433; propagate argument to callsite argument 434 435define internal i1 @cmp_with_four(i32 %c) { 436; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 437; IS__CGSCC____-LABEL: define {{[^@]+}}@cmp_with_four 438; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 439; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32 [[C]], 4 440; IS__CGSCC____-NEXT: ret i1 [[CMP]] 441; 442 %cmp = icmp eq i32 %c, 4 443 ret i1 %cmp 444} 445 446define internal i1 @wrapper(i32 %c) { 447; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 448; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@wrapper 449; IS__CGSCC_OPM-SAME: (i32 noundef [[C:%.*]]) #[[ATTR1]] { 450; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = call i1 @cmp_with_four(i32 noundef [[C]]) #[[ATTR3]] 451; IS__CGSCC_OPM-NEXT: ret i1 [[RET]] 452; 453; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 454; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@wrapper 455; IS__CGSCC_NPM-SAME: (i32 noundef [[C:%.*]]) #[[ATTR1]] { 456; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = call i1 @cmp_with_four(i32 noundef [[C]]) #[[ATTR2]] 457; IS__CGSCC_NPM-NEXT: ret i1 [[RET]] 458; 459 %ret = call i1 @cmp_with_four(i32 %c) 460 ret i1 %ret 461} 462 463define i1 @potential_test8() { 464; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 465; IS__TUNIT____-LABEL: define {{[^@]+}}@potential_test8 466; IS__TUNIT____-SAME: () #[[ATTR0]] { 467; IS__TUNIT____-NEXT: ret i1 false 468; 469; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 470; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test8 471; IS__CGSCC_OPM-SAME: () #[[ATTR1]] { 472; IS__CGSCC_OPM-NEXT: [[RES1:%.*]] = call i1 @wrapper(i32 noundef 1) #[[ATTR3]] 473; IS__CGSCC_OPM-NEXT: [[RES3:%.*]] = call i1 @wrapper(i32 noundef 3) #[[ATTR3]] 474; IS__CGSCC_OPM-NEXT: [[RES5:%.*]] = call i1 @wrapper(i32 noundef 5) #[[ATTR3]] 475; IS__CGSCC_OPM-NEXT: [[RES13:%.*]] = or i1 [[RES1]], [[RES3]] 476; IS__CGSCC_OPM-NEXT: [[RES135:%.*]] = or i1 [[RES13]], [[RES5]] 477; IS__CGSCC_OPM-NEXT: ret i1 [[RES135]] 478; 479; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 480; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test8 481; IS__CGSCC_NPM-SAME: () #[[ATTR1]] { 482; IS__CGSCC_NPM-NEXT: [[RES1:%.*]] = call i1 @wrapper(i32 noundef 1) #[[ATTR2]] 483; IS__CGSCC_NPM-NEXT: [[RES3:%.*]] = call i1 @wrapper(i32 noundef 3) #[[ATTR2]] 484; IS__CGSCC_NPM-NEXT: [[RES5:%.*]] = call i1 @wrapper(i32 noundef 5) #[[ATTR2]] 485; IS__CGSCC_NPM-NEXT: [[RES13:%.*]] = or i1 [[RES1]], [[RES3]] 486; IS__CGSCC_NPM-NEXT: [[RES135:%.*]] = or i1 [[RES13]], [[RES5]] 487; IS__CGSCC_NPM-NEXT: ret i1 [[RES135]] 488; 489 %res1 = call i1 @wrapper(i32 1) 490 %res3 = call i1 @wrapper(i32 3) 491 %res5 = call i1 @wrapper(i32 5) 492 %res13 = or i1 %res1, %res3 493 %res135 = or i1 %res13, %res5 494 ret i1 %res135 495} 496 497define i1 @potential_test9() { 498; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone 499; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test9 500; IS__TUNIT_OPM-SAME: () #[[ATTR1:[0-9]+]] { 501; IS__TUNIT_OPM-NEXT: entry: 502; IS__TUNIT_OPM-NEXT: br label [[COND:%.*]] 503; IS__TUNIT_OPM: cond: 504; IS__TUNIT_OPM-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_1:%.*]], [[INC:%.*]] ] 505; IS__TUNIT_OPM-NEXT: [[C_0:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[C_1:%.*]], [[INC]] ] 506; IS__TUNIT_OPM-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 10 507; IS__TUNIT_OPM-NEXT: br i1 [[CMP]], label [[BODY:%.*]], label [[END:%.*]] 508; IS__TUNIT_OPM: body: 509; IS__TUNIT_OPM-NEXT: [[C_1]] = mul i32 [[C_0]], -1 510; IS__TUNIT_OPM-NEXT: br label [[INC]] 511; IS__TUNIT_OPM: inc: 512; IS__TUNIT_OPM-NEXT: [[I_1]] = add i32 [[I_0]], 1 513; IS__TUNIT_OPM-NEXT: br label [[COND]] 514; IS__TUNIT_OPM: end: 515; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = icmp eq i32 [[C_0]], 0 516; IS__TUNIT_OPM-NEXT: ret i1 [[RET]] 517; 518; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 519; IS________NPM-LABEL: define {{[^@]+}}@potential_test9 520; IS________NPM-SAME: () #[[ATTR0]] { 521; IS________NPM-NEXT: entry: 522; IS________NPM-NEXT: br label [[COND:%.*]] 523; IS________NPM: cond: 524; IS________NPM-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_1:%.*]], [[INC:%.*]] ] 525; IS________NPM-NEXT: [[C_0:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[C_1:%.*]], [[INC]] ] 526; IS________NPM-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 10 527; IS________NPM-NEXT: br i1 [[CMP]], label [[BODY:%.*]], label [[END:%.*]] 528; IS________NPM: body: 529; IS________NPM-NEXT: [[C_1]] = mul i32 [[C_0]], -1 530; IS________NPM-NEXT: br label [[INC]] 531; IS________NPM: inc: 532; IS________NPM-NEXT: [[I_1]] = add i32 [[I_0]], 1 533; IS________NPM-NEXT: br label [[COND]] 534; IS________NPM: end: 535; IS________NPM-NEXT: [[RET:%.*]] = icmp eq i32 [[C_0]], 0 536; IS________NPM-NEXT: ret i1 [[RET]] 537; 538; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone 539; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test9 540; IS__CGSCC_OPM-SAME: () #[[ATTR2:[0-9]+]] { 541; IS__CGSCC_OPM-NEXT: entry: 542; IS__CGSCC_OPM-NEXT: br label [[COND:%.*]] 543; IS__CGSCC_OPM: cond: 544; IS__CGSCC_OPM-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_1:%.*]], [[INC:%.*]] ] 545; IS__CGSCC_OPM-NEXT: [[C_0:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[C_1:%.*]], [[INC]] ] 546; IS__CGSCC_OPM-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 10 547; IS__CGSCC_OPM-NEXT: br i1 [[CMP]], label [[BODY:%.*]], label [[END:%.*]] 548; IS__CGSCC_OPM: body: 549; IS__CGSCC_OPM-NEXT: [[C_1]] = mul i32 [[C_0]], -1 550; IS__CGSCC_OPM-NEXT: br label [[INC]] 551; IS__CGSCC_OPM: inc: 552; IS__CGSCC_OPM-NEXT: [[I_1]] = add i32 [[I_0]], 1 553; IS__CGSCC_OPM-NEXT: br label [[COND]] 554; IS__CGSCC_OPM: end: 555; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = icmp eq i32 [[C_0]], 0 556; IS__CGSCC_OPM-NEXT: ret i1 [[RET]] 557; 558entry: 559 br label %cond 560cond: 561 %i.0 = phi i32 [0, %entry], [%i.1, %inc] 562 %c.0 = phi i32 [1, %entry], [%c.1, %inc] 563 %cmp = icmp slt i32 %i.0, 10 564 br i1 %cmp, label %body, label %end 565body: 566 %c.1 = mul i32 %c.0, -1 567 br label %inc 568inc: 569 %i.1 = add i32 %i.0, 1 570 br label %cond 571end: 572 %ret = icmp eq i32 %c.0, 0 573 ret i1 %ret 574} 575 576; Test 10 577; FIXME: potential returned values of @may_return_undef is {1, -1} 578; and returned value of @potential_test10 can be simplified to 0(false) 579 580define internal i32 @may_return_undef(i32 %c) { 581; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 582; CHECK-LABEL: define {{[^@]+}}@may_return_undef 583; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 584; CHECK-NEXT: switch i32 [[C]], label [[OTHERWISE:%.*]] [ 585; CHECK-NEXT: i32 1, label [[A:%.*]] 586; CHECK-NEXT: i32 -1, label [[B:%.*]] 587; CHECK-NEXT: ] 588; CHECK: a: 589; CHECK-NEXT: ret i32 1 590; CHECK: b: 591; CHECK-NEXT: ret i32 -1 592; CHECK: otherwise: 593; CHECK-NEXT: ret i32 undef 594; 595 switch i32 %c, label %otherwise [i32 1, label %a 596 i32 -1, label %b] 597a: 598 ret i32 1 599b: 600 ret i32 -1 601otherwise: 602 ret i32 undef 603} 604 605define i1 @potential_test10(i32 %c) { 606; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 607; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test10 608; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 609; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = call i32 @may_return_undef(i32 [[C]]) #[[ATTR2]] 610; IS__TUNIT_OPM-NEXT: [[CMP:%.*]] = icmp eq i32 [[RET]], 0 611; IS__TUNIT_OPM-NEXT: ret i1 [[CMP]] 612; 613; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 614; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test10 615; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 616; IS__TUNIT_NPM-NEXT: [[RET:%.*]] = call i32 @may_return_undef(i32 [[C]]) #[[ATTR1]] 617; IS__TUNIT_NPM-NEXT: [[CMP:%.*]] = icmp eq i32 [[RET]], 0 618; IS__TUNIT_NPM-NEXT: ret i1 [[CMP]] 619; 620; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 621; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test10 622; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { 623; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = call i32 @may_return_undef(i32 [[C]]) #[[ATTR3]] 624; IS__CGSCC_OPM-NEXT: [[CMP:%.*]] = icmp eq i32 [[RET]], 0 625; IS__CGSCC_OPM-NEXT: ret i1 [[CMP]] 626; 627; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 628; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test10 629; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { 630; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = call i32 @may_return_undef(i32 [[C]]) #[[ATTR2]] 631; IS__CGSCC_NPM-NEXT: [[CMP:%.*]] = icmp eq i32 [[RET]], 0 632; IS__CGSCC_NPM-NEXT: ret i1 [[CMP]] 633; 634 %ret = call i32 @may_return_undef(i32 %c) 635 %cmp = icmp eq i32 %ret, 0 636 ret i1 %cmp 637} 638 639define i32 @optimize_undef_1(i1 %c) { 640; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 641; CHECK-LABEL: define {{[^@]+}}@optimize_undef_1 642; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 643; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 644; CHECK: t: 645; CHECK-NEXT: ret i32 0 646; CHECK: f: 647; CHECK-NEXT: [[UNDEF:%.*]] = add i32 undef, 1 648; CHECK-NEXT: ret i32 [[UNDEF]] 649; 650 br i1 %c, label %t, label %f 651t: 652 ret i32 0 653f: 654 %undef = add i32 undef, 1 655 ret i32 %undef 656} 657 658define i32 @optimize_undef_2(i1 %c) { 659; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 660; CHECK-LABEL: define {{[^@]+}}@optimize_undef_2 661; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 662; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 663; CHECK: t: 664; CHECK-NEXT: ret i32 0 665; CHECK: f: 666; CHECK-NEXT: [[UNDEF:%.*]] = sub i32 undef, 1 667; CHECK-NEXT: ret i32 [[UNDEF]] 668; 669 br i1 %c, label %t, label %f 670t: 671 ret i32 0 672f: 673 %undef = sub i32 undef, 1 674 ret i32 %undef 675} 676 677define i32 @optimize_undef_3(i1 %c) { 678; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 679; CHECK-LABEL: define {{[^@]+}}@optimize_undef_3 680; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 681; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 682; CHECK: t: 683; CHECK-NEXT: ret i32 0 684; CHECK: f: 685; CHECK-NEXT: [[UNDEF:%.*]] = icmp eq i32 undef, 0 686; CHECK-NEXT: [[UNDEF2:%.*]] = zext i1 [[UNDEF]] to i32 687; CHECK-NEXT: ret i32 [[UNDEF2]] 688; 689 br i1 %c, label %t, label %f 690t: 691 ret i32 0 692f: 693 %undef = icmp eq i32 undef, 0 694 %undef2 = zext i1 %undef to i32 695 ret i32 %undef2 696} 697 698 699; FIXME: returned value can be simplified to 0 700define i32 @potential_test11(i1 %c) { 701; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 702; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test11 703; IS__TUNIT_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 704; IS__TUNIT_OPM-NEXT: [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) #[[ATTR2]], !range [[RNG0]] 705; IS__TUNIT_OPM-NEXT: [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) #[[ATTR2]], !range [[RNG2:![0-9]+]] 706; IS__TUNIT_OPM-NEXT: [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]]) #[[ATTR2]], !range [[RNG0]] 707; IS__TUNIT_OPM-NEXT: [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]] 708; IS__TUNIT_OPM-NEXT: [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]] 709; IS__TUNIT_OPM-NEXT: ret i32 [[ACC2]] 710; 711; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 712; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test11 713; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 714; IS__TUNIT_NPM-NEXT: [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) #[[ATTR1]], !range [[RNG0]] 715; IS__TUNIT_NPM-NEXT: [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) #[[ATTR1]], !range [[RNG2:![0-9]+]] 716; IS__TUNIT_NPM-NEXT: [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]]) #[[ATTR1]], !range [[RNG0]] 717; IS__TUNIT_NPM-NEXT: [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]] 718; IS__TUNIT_NPM-NEXT: [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]] 719; IS__TUNIT_NPM-NEXT: ret i32 [[ACC2]] 720; 721; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 722; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test11 723; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { 724; IS__CGSCC_OPM-NEXT: [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) #[[ATTR3]] 725; IS__CGSCC_OPM-NEXT: [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) #[[ATTR3]] 726; IS__CGSCC_OPM-NEXT: [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]]) #[[ATTR3]] 727; IS__CGSCC_OPM-NEXT: [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]] 728; IS__CGSCC_OPM-NEXT: [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]] 729; IS__CGSCC_OPM-NEXT: ret i32 [[ACC2]] 730; 731; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 732; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test11 733; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { 734; IS__CGSCC_NPM-NEXT: [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) #[[ATTR2]] 735; IS__CGSCC_NPM-NEXT: [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) #[[ATTR2]] 736; IS__CGSCC_NPM-NEXT: [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]]) #[[ATTR2]] 737; IS__CGSCC_NPM-NEXT: [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]] 738; IS__CGSCC_NPM-NEXT: [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]] 739; IS__CGSCC_NPM-NEXT: ret i32 [[ACC2]] 740; 741 %zero1 = call i32 @optimize_undef_1(i1 %c) 742 %zero2 = call i32 @optimize_undef_2(i1 %c) 743 %zero3 = call i32 @optimize_undef_3(i1 %c) 744 %acc1 = add i32 %zero1, %zero2 745 %acc2 = add i32 %acc1, %zero3 746 ret i32 %acc2 747} 748 749define i32 @optimize_poison_1(i1 %c) { 750; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 751; CHECK-LABEL: define {{[^@]+}}@optimize_poison_1 752; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 753; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 754; CHECK: t: 755; CHECK-NEXT: ret i32 0 756; CHECK: f: 757; CHECK-NEXT: [[POISON:%.*]] = sub nuw i32 0, 1 758; CHECK-NEXT: ret i32 [[POISON]] 759; 760 br i1 %c, label %t, label %f 761t: 762 ret i32 0 763f: 764 %poison = sub nuw i32 0, 1 765 ret i32 %poison 766} 767 768; FIXME: returned value can be simplified to 0 769define i32 @potential_test12(i1 %c) { 770; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 771; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test12 772; IS__TUNIT_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 773; IS__TUNIT_OPM-NEXT: [[ZERO:%.*]] = call i32 @optimize_poison_1(i1 [[C]]) #[[ATTR2]], !range [[RNG2]] 774; IS__TUNIT_OPM-NEXT: ret i32 [[ZERO]] 775; 776; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 777; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test12 778; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 779; IS__TUNIT_NPM-NEXT: ret i32 0 780; 781; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 782; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test12 783; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { 784; IS__CGSCC_OPM-NEXT: [[ZERO:%.*]] = call i32 @optimize_poison_1(i1 [[C]]) #[[ATTR3]] 785; IS__CGSCC_OPM-NEXT: ret i32 [[ZERO]] 786; 787; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 788; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test12 789; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { 790; IS__CGSCC_NPM-NEXT: [[ZERO:%.*]] = call i32 @optimize_poison_1(i1 [[C]]) #[[ATTR2]] 791; IS__CGSCC_NPM-NEXT: ret i32 [[ZERO]] 792; 793 %zero = call i32 @optimize_poison_1(i1 %c) 794 ret i32 %zero 795} 796 797; Test 13 798; Do not simplify %ret in the callee to `%c`. 799; The potential value of %c is {0, 1} (undef is merged). 800; However, we should not simplify `and i32 %c, 3` to `%c` 801 802define internal i32 @potential_test13_callee(i32 %c) { 803; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 804; CHECK-LABEL: define {{[^@]+}}@potential_test13_callee 805; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 806; CHECK-NEXT: [[RET:%.*]] = and i32 [[C]], 3 807; CHECK-NEXT: ret i32 [[RET]] 808; 809 %ret = and i32 %c, 3 810 ret i32 %ret 811} 812 813define i32 @potential_test13_caller1() { 814; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 815; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test13_caller1 816; IS__TUNIT_OPM-SAME: () #[[ATTR0]] { 817; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 0) #[[ATTR2]], !range [[RNG0]] 818; IS__TUNIT_OPM-NEXT: ret i32 [[RET]] 819; 820; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 821; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test13_caller1 822; IS__TUNIT_NPM-SAME: () #[[ATTR0]] { 823; IS__TUNIT_NPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 0) #[[ATTR1]], !range [[RNG0]] 824; IS__TUNIT_NPM-NEXT: ret i32 [[RET]] 825; 826; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 827; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test13_caller1 828; IS__CGSCC_OPM-SAME: () #[[ATTR1]] { 829; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 0) #[[ATTR3]] 830; IS__CGSCC_OPM-NEXT: ret i32 [[RET]] 831; 832; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 833; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test13_caller1 834; IS__CGSCC_NPM-SAME: () #[[ATTR1]] { 835; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 0) #[[ATTR2]] 836; IS__CGSCC_NPM-NEXT: ret i32 [[RET]] 837; 838 %ret = call i32 @potential_test13_callee(i32 0) 839 ret i32 %ret 840} 841 842define i32 @potential_test13_caller2() { 843; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 844; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test13_caller2 845; IS__TUNIT_OPM-SAME: () #[[ATTR0]] { 846; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 1) #[[ATTR2]], !range [[RNG0]] 847; IS__TUNIT_OPM-NEXT: ret i32 [[RET]] 848; 849; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 850; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test13_caller2 851; IS__TUNIT_NPM-SAME: () #[[ATTR0]] { 852; IS__TUNIT_NPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 1) #[[ATTR1]], !range [[RNG0]] 853; IS__TUNIT_NPM-NEXT: ret i32 [[RET]] 854; 855; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 856; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test13_caller2 857; IS__CGSCC_OPM-SAME: () #[[ATTR1]] { 858; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 1) #[[ATTR3]] 859; IS__CGSCC_OPM-NEXT: ret i32 [[RET]] 860; 861; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 862; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test13_caller2 863; IS__CGSCC_NPM-SAME: () #[[ATTR1]] { 864; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 1) #[[ATTR2]] 865; IS__CGSCC_NPM-NEXT: ret i32 [[RET]] 866; 867 %ret = call i32 @potential_test13_callee(i32 1) 868 ret i32 %ret 869} 870 871define i32 @potential_test13_caller3() { 872; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 873; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test13_caller3 874; IS__TUNIT_OPM-SAME: () #[[ATTR0]] { 875; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR2]], !range [[RNG0]] 876; IS__TUNIT_OPM-NEXT: ret i32 [[RET]] 877; 878; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 879; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test13_caller3 880; IS__TUNIT_NPM-SAME: () #[[ATTR0]] { 881; IS__TUNIT_NPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR1]], !range [[RNG0]] 882; IS__TUNIT_NPM-NEXT: ret i32 [[RET]] 883; 884; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 885; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test13_caller3 886; IS__CGSCC_OPM-SAME: () #[[ATTR1]] { 887; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR3]] 888; IS__CGSCC_OPM-NEXT: ret i32 [[RET]] 889; 890; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 891; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test13_caller3 892; IS__CGSCC_NPM-SAME: () #[[ATTR1]] { 893; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR2]] 894; IS__CGSCC_NPM-NEXT: ret i32 [[RET]] 895; 896 %ret = call i32 @potential_test13_callee(i32 undef) 897 ret i32 %ret 898} 899 900define i1 @potential_test14(i1 %c0, i1 %c1, i1 %c2, i1 %c3) { 901; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 902; CHECK-LABEL: define {{[^@]+}}@potential_test14 903; CHECK-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) #[[ATTR0]] { 904; CHECK-NEXT: [[X0:%.*]] = select i1 [[C0]], i32 0, i32 1 905; CHECK-NEXT: [[X1:%.*]] = select i1 [[C1]], i32 [[X0]], i32 undef 906; CHECK-NEXT: [[Y2:%.*]] = select i1 [[C2]], i32 0, i32 7 907; CHECK-NEXT: [[Z3:%.*]] = select i1 [[C3]], i32 [[X1]], i32 [[Y2]] 908; CHECK-NEXT: [[RET:%.*]] = icmp slt i32 [[Z3]], 7 909; CHECK-NEXT: ret i1 [[RET]] 910; 911 %x0 = select i1 %c0, i32 0, i32 1 912 %x1 = select i1 %c1, i32 %x0, i32 undef 913 %y2 = select i1 %c2, i32 0, i32 7 914 %z3 = select i1 %c3, i32 %x1, i32 %y2 915 %ret = icmp slt i32 %z3, 7 916 ret i1 %ret 917} 918 919define i1 @potential_test15(i1 %c0, i1 %c1) { 920; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 921; CHECK-LABEL: define {{[^@]+}}@potential_test15 922; CHECK-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]]) #[[ATTR0]] { 923; CHECK-NEXT: [[X0:%.*]] = select i1 [[C0]], i32 0, i32 1 924; CHECK-NEXT: [[X1:%.*]] = select i1 [[C1]], i32 [[X0]], i32 undef 925; CHECK-NEXT: [[RET:%.*]] = icmp eq i32 [[X1]], 7 926; CHECK-NEXT: ret i1 [[RET]] 927; 928 %x0 = select i1 %c0, i32 0, i32 1 929 %x1 = select i1 %c1, i32 %x0, i32 undef 930 %ret = icmp eq i32 %x1, 7 931 ret i1 %ret 932} 933 934define i1 @potential_test16(i1 %c0, i1 %c1) { 935; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 936; CHECK-LABEL: define {{[^@]+}}@potential_test16 937; CHECK-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]]) #[[ATTR0]] { 938; CHECK-NEXT: [[X1:%.*]] = select i1 [[C1]], i32 0, i32 1 939; CHECK-NEXT: [[RET:%.*]] = icmp eq i32 [[X1]], 7 940; CHECK-NEXT: ret i1 [[RET]] 941; 942 %x0 = select i1 %c0, i32 0, i32 undef 943 %x1 = select i1 %c1, i32 %x0, i32 1 944 %ret = icmp eq i32 %x1, 7 945 ret i1 %ret 946} 947 948;. 949; IS__TUNIT_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } 950; IS__TUNIT_OPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone } 951; IS__TUNIT_OPM: attributes #[[ATTR2]] = { nofree nosync nounwind readnone willreturn } 952;. 953; IS__TUNIT_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } 954; IS__TUNIT_NPM: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn } 955;. 956; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } 957; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn } 958; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone } 959; IS__CGSCC_OPM: attributes #[[ATTR3]] = { readnone willreturn } 960;. 961; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } 962; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn } 963; IS__CGSCC_NPM: attributes #[[ATTR2]] = { readnone willreturn } 964;. 965; IS__TUNIT____: [[META0:![0-9]+]] = !{i32 0, i32 2} 966; IS__TUNIT____: [[META1:![0-9]+]] = !{i32 0, i32 3} 967; IS__TUNIT____: [[META2:![0-9]+]] = !{i32 -1, i32 1} 968;. 969