1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals 2; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT 3; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC 4 5; FIXME: CGSCC is not looking at callees and calleers even though it could be allowed. 6 7define i32 @test0(ptr %p) { 8; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) 9; CHECK-LABEL: define {{[^@]+}}@test0 10; CHECK-SAME: (ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR0:[0-9]+]] { 11; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG0:![0-9]+]] 12; CHECK-NEXT: ret i32 [[A]] 13; 14 %a = load i32, ptr %p, !range !0 15 ret i32 %a 16} 17 18define i32 @test0-range-check(ptr %p) { 19; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) 20; TUNIT-LABEL: define {{[^@]+}}@test0-range-check 21; TUNIT-SAME: (ptr nofree readonly align 4 captures(none) [[P:%.*]]) #[[ATTR0]] { 22; TUNIT-NEXT: [[A:%.*]] = tail call i32 @test0(ptr nofree noundef readonly align 4 captures(none) [[P]]) #[[ATTR3:[0-9]+]], !range [[RNG0]] 23; TUNIT-NEXT: ret i32 [[A]] 24; 25; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: read) 26; CGSCC-LABEL: define {{[^@]+}}@test0-range-check 27; CGSCC-SAME: (ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR1:[0-9]+]] { 28; CGSCC-NEXT: [[A:%.*]] = tail call i32 @test0(ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[P]]) #[[ATTR5:[0-9]+]] 29; CGSCC-NEXT: ret i32 [[A]] 30; 31 %a = tail call i32 @test0(ptr %p) 32 ret i32 %a 33} 34 35declare void @use3-dummy(i1, i1, i1) 36define void @use3(i1, i1, i1) { 37; CHECK-LABEL: define {{[^@]+}}@use3 38; CHECK-SAME: (i1 [[TMP0:%.*]], i1 [[TMP1:%.*]], i1 [[TMP2:%.*]]) { 39; CHECK-NEXT: tail call void @use3-dummy(i1 [[TMP0]], i1 [[TMP1]], i1 [[TMP2]]) 40; CHECK-NEXT: ret void 41; 42 tail call void @use3-dummy(i1 %0, i1 %1, i1 %2) 43 ret void 44} 45 46; TEST0 icmp test 47define void @test0-icmp-check(ptr %p){ 48 ; ret = [0, 10) 49; TUNIT-LABEL: define {{[^@]+}}@test0-icmp-check 50; TUNIT-SAME: (ptr nofree readonly align 4 captures(none) [[P:%.*]]) { 51; TUNIT-NEXT: [[RET:%.*]] = tail call i32 @test0(ptr nofree noundef readonly align 4 captures(none) [[P]]) #[[ATTR3]], !range [[RNG0]] 52; TUNIT-NEXT: [[CMP_EQ_1:%.*]] = icmp eq i32 [[RET]], 10 53; TUNIT-NEXT: [[CMP_EQ_2:%.*]] = icmp eq i32 [[RET]], 9 54; TUNIT-NEXT: [[CMP_EQ_3:%.*]] = icmp eq i32 [[RET]], 8 55; TUNIT-NEXT: [[CMP_EQ_4:%.*]] = icmp eq i32 [[RET]], 1 56; TUNIT-NEXT: [[CMP_EQ_5:%.*]] = icmp eq i32 [[RET]], 0 57; TUNIT-NEXT: [[CMP_EQ_6:%.*]] = icmp eq i32 [[RET]], -1 58; TUNIT-NEXT: tail call void @use3(i1 [[CMP_EQ_1]], i1 [[CMP_EQ_2]], i1 [[CMP_EQ_3]]) 59; TUNIT-NEXT: tail call void @use3(i1 [[CMP_EQ_4]], i1 [[CMP_EQ_5]], i1 [[CMP_EQ_6]]) 60; TUNIT-NEXT: [[CMP_NE_1:%.*]] = icmp ne i32 [[RET]], 10 61; TUNIT-NEXT: [[CMP_NE_2:%.*]] = icmp ne i32 [[RET]], 9 62; TUNIT-NEXT: [[CMP_NE_3:%.*]] = icmp ne i32 [[RET]], 8 63; TUNIT-NEXT: [[CMP_NE_4:%.*]] = icmp ne i32 [[RET]], 1 64; TUNIT-NEXT: [[CMP_NE_5:%.*]] = icmp ne i32 [[RET]], 0 65; TUNIT-NEXT: [[CMP_NE_6:%.*]] = icmp ne i32 [[RET]], -1 66; TUNIT-NEXT: tail call void @use3(i1 [[CMP_NE_1]], i1 [[CMP_NE_2]], i1 [[CMP_NE_3]]) 67; TUNIT-NEXT: tail call void @use3(i1 [[CMP_NE_4]], i1 [[CMP_NE_5]], i1 [[CMP_NE_6]]) 68; TUNIT-NEXT: [[CMP_UGT_1:%.*]] = icmp ugt i32 [[RET]], 10 69; TUNIT-NEXT: [[CMP_UGT_2:%.*]] = icmp ugt i32 [[RET]], 9 70; TUNIT-NEXT: [[CMP_UGT_3:%.*]] = icmp ugt i32 [[RET]], 8 71; TUNIT-NEXT: [[CMP_UGT_4:%.*]] = icmp ugt i32 [[RET]], 1 72; TUNIT-NEXT: [[CMP_UGT_5:%.*]] = icmp ugt i32 [[RET]], 0 73; TUNIT-NEXT: tail call void @use3(i1 [[CMP_UGT_1]], i1 [[CMP_UGT_2]], i1 [[CMP_UGT_3]]) 74; TUNIT-NEXT: tail call void @use3(i1 [[CMP_UGT_4]], i1 [[CMP_UGT_5]], i1 noundef false) 75; TUNIT-NEXT: [[CMP_UGE_1:%.*]] = icmp uge i32 [[RET]], 10 76; TUNIT-NEXT: [[CMP_UGE_2:%.*]] = icmp uge i32 [[RET]], 9 77; TUNIT-NEXT: [[CMP_UGE_3:%.*]] = icmp uge i32 [[RET]], 8 78; TUNIT-NEXT: [[CMP_UGE_4:%.*]] = icmp uge i32 [[RET]], 1 79; TUNIT-NEXT: [[CMP_UGE_6:%.*]] = icmp uge i32 [[RET]], -1 80; TUNIT-NEXT: tail call void @use3(i1 [[CMP_UGE_1]], i1 [[CMP_UGE_2]], i1 [[CMP_UGE_3]]) 81; TUNIT-NEXT: tail call void @use3(i1 [[CMP_UGE_4]], i1 noundef true, i1 [[CMP_UGE_6]]) 82; TUNIT-NEXT: [[CMP_SGT_1:%.*]] = icmp sgt i32 [[RET]], 10 83; TUNIT-NEXT: [[CMP_SGT_2:%.*]] = icmp sgt i32 [[RET]], 9 84; TUNIT-NEXT: [[CMP_SGT_3:%.*]] = icmp sgt i32 [[RET]], 8 85; TUNIT-NEXT: [[CMP_SGT_4:%.*]] = icmp sgt i32 [[RET]], 1 86; TUNIT-NEXT: [[CMP_SGT_5:%.*]] = icmp sgt i32 [[RET]], 0 87; TUNIT-NEXT: [[CMP_SGT_6:%.*]] = icmp sgt i32 [[RET]], -1 88; TUNIT-NEXT: tail call void @use3(i1 [[CMP_SGT_1]], i1 [[CMP_SGT_2]], i1 [[CMP_SGT_3]]) 89; TUNIT-NEXT: tail call void @use3(i1 [[CMP_SGT_4]], i1 [[CMP_SGT_5]], i1 [[CMP_SGT_6]]) 90; TUNIT-NEXT: [[CMP_GTE_1:%.*]] = icmp sge i32 [[RET]], 10 91; TUNIT-NEXT: [[CMP_GTE_2:%.*]] = icmp sge i32 [[RET]], 9 92; TUNIT-NEXT: [[CMP_GTE_3:%.*]] = icmp sge i32 [[RET]], 8 93; TUNIT-NEXT: [[CMP_GTE_4:%.*]] = icmp sge i32 [[RET]], 1 94; TUNIT-NEXT: [[CMP_GTE_5:%.*]] = icmp sge i32 [[RET]], 0 95; TUNIT-NEXT: [[CMP_GTE_6:%.*]] = icmp sge i32 [[RET]], -1 96; TUNIT-NEXT: tail call void @use3(i1 [[CMP_GTE_1]], i1 [[CMP_GTE_2]], i1 [[CMP_GTE_3]]) 97; TUNIT-NEXT: tail call void @use3(i1 [[CMP_GTE_4]], i1 [[CMP_GTE_5]], i1 [[CMP_GTE_6]]) 98; TUNIT-NEXT: [[CMP_SLT_1:%.*]] = icmp slt i32 [[RET]], 10 99; TUNIT-NEXT: [[CMP_SLT_2:%.*]] = icmp slt i32 [[RET]], 9 100; TUNIT-NEXT: [[CMP_SLT_3:%.*]] = icmp slt i32 [[RET]], 8 101; TUNIT-NEXT: [[CMP_SLT_4:%.*]] = icmp slt i32 [[RET]], 1 102; TUNIT-NEXT: [[CMP_SLT_5:%.*]] = icmp slt i32 [[RET]], 0 103; TUNIT-NEXT: [[CMP_SLT_6:%.*]] = icmp slt i32 [[RET]], -1 104; TUNIT-NEXT: tail call void @use3(i1 [[CMP_SLT_1]], i1 [[CMP_SLT_2]], i1 [[CMP_SLT_3]]) 105; TUNIT-NEXT: tail call void @use3(i1 [[CMP_SLT_4]], i1 [[CMP_SLT_5]], i1 [[CMP_SLT_6]]) 106; TUNIT-NEXT: [[CMP_LTE_1:%.*]] = icmp sle i32 [[RET]], 10 107; TUNIT-NEXT: [[CMP_LTE_2:%.*]] = icmp sle i32 [[RET]], 9 108; TUNIT-NEXT: [[CMP_LTE_3:%.*]] = icmp sle i32 [[RET]], 8 109; TUNIT-NEXT: [[CMP_LTE_4:%.*]] = icmp sle i32 [[RET]], 1 110; TUNIT-NEXT: [[CMP_LTE_5:%.*]] = icmp sle i32 [[RET]], 0 111; TUNIT-NEXT: [[CMP_LTE_6:%.*]] = icmp sle i32 [[RET]], -1 112; TUNIT-NEXT: tail call void @use3(i1 [[CMP_LTE_1]], i1 [[CMP_LTE_2]], i1 [[CMP_LTE_3]]) 113; TUNIT-NEXT: tail call void @use3(i1 [[CMP_LTE_4]], i1 [[CMP_LTE_5]], i1 [[CMP_LTE_6]]) 114; TUNIT-NEXT: ret void 115; 116; CGSCC-LABEL: define {{[^@]+}}@test0-icmp-check 117; CGSCC-SAME: (ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[P:%.*]]) { 118; CGSCC-NEXT: [[RET:%.*]] = tail call i32 @test0(ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[P]]) #[[ATTR5]] 119; CGSCC-NEXT: [[CMP_EQ_1:%.*]] = icmp eq i32 [[RET]], 10 120; CGSCC-NEXT: [[CMP_EQ_2:%.*]] = icmp eq i32 [[RET]], 9 121; CGSCC-NEXT: [[CMP_EQ_3:%.*]] = icmp eq i32 [[RET]], 8 122; CGSCC-NEXT: [[CMP_EQ_4:%.*]] = icmp eq i32 [[RET]], 1 123; CGSCC-NEXT: [[CMP_EQ_5:%.*]] = icmp eq i32 [[RET]], 0 124; CGSCC-NEXT: [[CMP_EQ_6:%.*]] = icmp eq i32 [[RET]], -1 125; CGSCC-NEXT: tail call void @use3(i1 [[CMP_EQ_1]], i1 [[CMP_EQ_2]], i1 [[CMP_EQ_3]]) 126; CGSCC-NEXT: tail call void @use3(i1 [[CMP_EQ_4]], i1 [[CMP_EQ_5]], i1 [[CMP_EQ_6]]) 127; CGSCC-NEXT: [[CMP_NE_1:%.*]] = icmp ne i32 [[RET]], 10 128; CGSCC-NEXT: [[CMP_NE_2:%.*]] = icmp ne i32 [[RET]], 9 129; CGSCC-NEXT: [[CMP_NE_3:%.*]] = icmp ne i32 [[RET]], 8 130; CGSCC-NEXT: [[CMP_NE_4:%.*]] = icmp ne i32 [[RET]], 1 131; CGSCC-NEXT: [[CMP_NE_5:%.*]] = icmp ne i32 [[RET]], 0 132; CGSCC-NEXT: [[CMP_NE_6:%.*]] = icmp ne i32 [[RET]], -1 133; CGSCC-NEXT: tail call void @use3(i1 [[CMP_NE_1]], i1 [[CMP_NE_2]], i1 [[CMP_NE_3]]) 134; CGSCC-NEXT: tail call void @use3(i1 [[CMP_NE_4]], i1 [[CMP_NE_5]], i1 [[CMP_NE_6]]) 135; CGSCC-NEXT: [[CMP_UGT_1:%.*]] = icmp ugt i32 [[RET]], 10 136; CGSCC-NEXT: [[CMP_UGT_2:%.*]] = icmp ugt i32 [[RET]], 9 137; CGSCC-NEXT: [[CMP_UGT_3:%.*]] = icmp ugt i32 [[RET]], 8 138; CGSCC-NEXT: [[CMP_UGT_4:%.*]] = icmp ugt i32 [[RET]], 1 139; CGSCC-NEXT: [[CMP_UGT_5:%.*]] = icmp ugt i32 [[RET]], 0 140; CGSCC-NEXT: tail call void @use3(i1 [[CMP_UGT_1]], i1 [[CMP_UGT_2]], i1 [[CMP_UGT_3]]) 141; CGSCC-NEXT: tail call void @use3(i1 [[CMP_UGT_4]], i1 [[CMP_UGT_5]], i1 noundef false) 142; CGSCC-NEXT: [[CMP_UGE_1:%.*]] = icmp uge i32 [[RET]], 10 143; CGSCC-NEXT: [[CMP_UGE_2:%.*]] = icmp uge i32 [[RET]], 9 144; CGSCC-NEXT: [[CMP_UGE_3:%.*]] = icmp uge i32 [[RET]], 8 145; CGSCC-NEXT: [[CMP_UGE_4:%.*]] = icmp uge i32 [[RET]], 1 146; CGSCC-NEXT: [[CMP_UGE_6:%.*]] = icmp uge i32 [[RET]], -1 147; CGSCC-NEXT: tail call void @use3(i1 [[CMP_UGE_1]], i1 [[CMP_UGE_2]], i1 [[CMP_UGE_3]]) 148; CGSCC-NEXT: tail call void @use3(i1 [[CMP_UGE_4]], i1 noundef true, i1 [[CMP_UGE_6]]) 149; CGSCC-NEXT: [[CMP_SGT_1:%.*]] = icmp sgt i32 [[RET]], 10 150; CGSCC-NEXT: [[CMP_SGT_2:%.*]] = icmp sgt i32 [[RET]], 9 151; CGSCC-NEXT: [[CMP_SGT_3:%.*]] = icmp sgt i32 [[RET]], 8 152; CGSCC-NEXT: [[CMP_SGT_4:%.*]] = icmp sgt i32 [[RET]], 1 153; CGSCC-NEXT: [[CMP_SGT_5:%.*]] = icmp sgt i32 [[RET]], 0 154; CGSCC-NEXT: [[CMP_SGT_6:%.*]] = icmp sgt i32 [[RET]], -1 155; CGSCC-NEXT: tail call void @use3(i1 [[CMP_SGT_1]], i1 [[CMP_SGT_2]], i1 [[CMP_SGT_3]]) 156; CGSCC-NEXT: tail call void @use3(i1 [[CMP_SGT_4]], i1 [[CMP_SGT_5]], i1 [[CMP_SGT_6]]) 157; CGSCC-NEXT: [[CMP_GTE_1:%.*]] = icmp sge i32 [[RET]], 10 158; CGSCC-NEXT: [[CMP_GTE_2:%.*]] = icmp sge i32 [[RET]], 9 159; CGSCC-NEXT: [[CMP_GTE_3:%.*]] = icmp sge i32 [[RET]], 8 160; CGSCC-NEXT: [[CMP_GTE_4:%.*]] = icmp sge i32 [[RET]], 1 161; CGSCC-NEXT: [[CMP_GTE_5:%.*]] = icmp sge i32 [[RET]], 0 162; CGSCC-NEXT: [[CMP_GTE_6:%.*]] = icmp sge i32 [[RET]], -1 163; CGSCC-NEXT: tail call void @use3(i1 [[CMP_GTE_1]], i1 [[CMP_GTE_2]], i1 [[CMP_GTE_3]]) 164; CGSCC-NEXT: tail call void @use3(i1 [[CMP_GTE_4]], i1 [[CMP_GTE_5]], i1 [[CMP_GTE_6]]) 165; CGSCC-NEXT: [[CMP_SLT_1:%.*]] = icmp slt i32 [[RET]], 10 166; CGSCC-NEXT: [[CMP_SLT_2:%.*]] = icmp slt i32 [[RET]], 9 167; CGSCC-NEXT: [[CMP_SLT_3:%.*]] = icmp slt i32 [[RET]], 8 168; CGSCC-NEXT: [[CMP_SLT_4:%.*]] = icmp slt i32 [[RET]], 1 169; CGSCC-NEXT: [[CMP_SLT_5:%.*]] = icmp slt i32 [[RET]], 0 170; CGSCC-NEXT: [[CMP_SLT_6:%.*]] = icmp slt i32 [[RET]], -1 171; CGSCC-NEXT: tail call void @use3(i1 [[CMP_SLT_1]], i1 [[CMP_SLT_2]], i1 [[CMP_SLT_3]]) 172; CGSCC-NEXT: tail call void @use3(i1 [[CMP_SLT_4]], i1 [[CMP_SLT_5]], i1 [[CMP_SLT_6]]) 173; CGSCC-NEXT: [[CMP_LTE_1:%.*]] = icmp sle i32 [[RET]], 10 174; CGSCC-NEXT: [[CMP_LTE_2:%.*]] = icmp sle i32 [[RET]], 9 175; CGSCC-NEXT: [[CMP_LTE_3:%.*]] = icmp sle i32 [[RET]], 8 176; CGSCC-NEXT: [[CMP_LTE_4:%.*]] = icmp sle i32 [[RET]], 1 177; CGSCC-NEXT: [[CMP_LTE_5:%.*]] = icmp sle i32 [[RET]], 0 178; CGSCC-NEXT: [[CMP_LTE_6:%.*]] = icmp sle i32 [[RET]], -1 179; CGSCC-NEXT: tail call void @use3(i1 [[CMP_LTE_1]], i1 [[CMP_LTE_2]], i1 [[CMP_LTE_3]]) 180; CGSCC-NEXT: tail call void @use3(i1 [[CMP_LTE_4]], i1 [[CMP_LTE_5]], i1 [[CMP_LTE_6]]) 181; CGSCC-NEXT: ret void 182; 183 %ret = tail call i32 @test0(ptr %p) 184 185 ; ret = [0, 10), eq 186 %cmp-eq-1 = icmp eq i32 %ret, 10 187 %cmp-eq-2 = icmp eq i32 %ret, 9 188 %cmp-eq-3 = icmp eq i32 %ret, 8 189 %cmp-eq-4 = icmp eq i32 %ret, 1 190 %cmp-eq-5 = icmp eq i32 %ret, 0 191 %cmp-eq-6 = icmp eq i32 %ret, -1 192 tail call void @use3(i1 %cmp-eq-1, i1 %cmp-eq-2, i1 %cmp-eq-3) 193 tail call void @use3(i1 %cmp-eq-4, i1 %cmp-eq-5, i1 %cmp-eq-6) 194 195 ; ret = [0, 10), ne 196 %cmp-ne-1 = icmp ne i32 %ret, 10 197 %cmp-ne-2 = icmp ne i32 %ret, 9 198 %cmp-ne-3 = icmp ne i32 %ret, 8 199 %cmp-ne-4 = icmp ne i32 %ret, 1 200 %cmp-ne-5 = icmp ne i32 %ret, 0 201 %cmp-ne-6 = icmp ne i32 %ret, -1 202 tail call void @use3(i1 %cmp-ne-1, i1 %cmp-ne-2, i1 %cmp-ne-3) 203 tail call void @use3(i1 %cmp-ne-4, i1 %cmp-ne-5, i1 %cmp-ne-6) 204 205 ; ret = [0, 10), ugt 206 %cmp-ugt-1 = icmp ugt i32 %ret, 10 207 %cmp-ugt-2 = icmp ugt i32 %ret, 9 208 %cmp-ugt-3 = icmp ugt i32 %ret, 8 209 %cmp-ugt-4 = icmp ugt i32 %ret, 1 210 %cmp-ugt-5 = icmp ugt i32 %ret, 0 211 %cmp-ugt-6 = icmp ugt i32 %ret, -1 212 tail call void @use3(i1 %cmp-ugt-1, i1 %cmp-ugt-2, i1 %cmp-ugt-3) 213 tail call void @use3(i1 %cmp-ugt-4, i1 %cmp-ugt-5, i1 %cmp-ugt-6) 214 215 ; ret = [0, 10), uge 216 %cmp-uge-1 = icmp uge i32 %ret, 10 217 %cmp-uge-2 = icmp uge i32 %ret, 9 218 %cmp-uge-3 = icmp uge i32 %ret, 8 219 %cmp-uge-4 = icmp uge i32 %ret, 1 220 %cmp-uge-5 = icmp uge i32 %ret, 0 221 %cmp-uge-6 = icmp uge i32 %ret, -1 222 tail call void @use3(i1 %cmp-uge-1, i1 %cmp-uge-2, i1 %cmp-uge-3) 223 tail call void @use3(i1 %cmp-uge-4, i1 %cmp-uge-5, i1 %cmp-uge-6) 224 225 ; ret = [0, 10), sgt 226 %cmp-sgt-1 = icmp sgt i32 %ret, 10 227 %cmp-sgt-2 = icmp sgt i32 %ret, 9 228 %cmp-sgt-3 = icmp sgt i32 %ret, 8 229 %cmp-sgt-4 = icmp sgt i32 %ret, 1 230 %cmp-sgt-5 = icmp sgt i32 %ret, 0 231 %cmp-sgt-6 = icmp sgt i32 %ret, -1 232 tail call void @use3(i1 %cmp-sgt-1, i1 %cmp-sgt-2, i1 %cmp-sgt-3) 233 tail call void @use3(i1 %cmp-sgt-4, i1 %cmp-sgt-5, i1 %cmp-sgt-6) 234 235 ; ret = [0, 10), sge 236 %cmp-gte-1 = icmp sge i32 %ret, 10 237 %cmp-gte-2 = icmp sge i32 %ret, 9 238 %cmp-gte-3 = icmp sge i32 %ret, 8 239 %cmp-gte-4 = icmp sge i32 %ret, 1 240 %cmp-gte-5 = icmp sge i32 %ret, 0 241 %cmp-gte-6 = icmp sge i32 %ret, -1 242 tail call void @use3(i1 %cmp-gte-1, i1 %cmp-gte-2, i1 %cmp-gte-3) 243 tail call void @use3(i1 %cmp-gte-4, i1 %cmp-gte-5, i1 %cmp-gte-6) 244 245 ; ret = [0, 10), slt 246 %cmp-slt-1 = icmp slt i32 %ret, 10 247 %cmp-slt-2 = icmp slt i32 %ret, 9 248 %cmp-slt-3 = icmp slt i32 %ret, 8 249 %cmp-slt-4 = icmp slt i32 %ret, 1 250 %cmp-slt-5 = icmp slt i32 %ret, 0 251 %cmp-slt-6 = icmp slt i32 %ret, -1 252 tail call void @use3(i1 %cmp-slt-1, i1 %cmp-slt-2, i1 %cmp-slt-3) 253 tail call void @use3(i1 %cmp-slt-4, i1 %cmp-slt-5, i1 %cmp-slt-6) 254 255 ; ret = [0, 10), sle 256 %cmp-lte-1 = icmp sle i32 %ret, 10 257 %cmp-lte-2 = icmp sle i32 %ret, 9 258 %cmp-lte-3 = icmp sle i32 %ret, 8 259 %cmp-lte-4 = icmp sle i32 %ret, 1 260 %cmp-lte-5 = icmp sle i32 %ret, 0 261 %cmp-lte-6 = icmp sle i32 %ret, -1 262 tail call void @use3(i1 %cmp-lte-1, i1 %cmp-lte-2, i1 %cmp-lte-3) 263 tail call void @use3(i1 %cmp-lte-4, i1 %cmp-lte-5, i1 %cmp-lte-6) 264 265 ret void 266} 267define i32 @test1(ptr %p) { 268; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) 269; CHECK-LABEL: define {{[^@]+}}@test1 270; CHECK-SAME: (ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR0]] { 271; CHECK-NEXT: [[LOAD_10_100:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG1:![0-9]+]] 272; CHECK-NEXT: [[ADD_10_THEN_20_110:%.*]] = add i32 [[LOAD_10_100]], 10 273; CHECK-NEXT: [[MUL_10_THEN_200_1091:%.*]] = mul i32 [[ADD_10_THEN_20_110]], 10 274; CHECK-NEXT: ret i32 [[MUL_10_THEN_200_1091]] 275; 276 %load-10-100 = load i32, ptr %p, !range !1 277 %add-10-then-20-110 = add i32 %load-10-100, 10 278 %mul-10-then-200-1091 = mul i32 %add-10-then-20-110, 10 279 ret i32 %mul-10-then-200-1091 280} 281 282define i1 @test1-check(ptr %p) { 283; 284; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) 285; TUNIT-LABEL: define {{[^@]+}}@test1-check 286; TUNIT-SAME: (ptr nofree readonly align 4 captures(none) [[P:%.*]]) #[[ATTR0]] { 287; TUNIT-NEXT: [[RES:%.*]] = tail call i32 @test1(ptr nofree noundef readonly align 4 captures(none) [[P]]) #[[ATTR3]], !range [[RNG2:![0-9]+]] 288; TUNIT-NEXT: [[CMP:%.*]] = icmp eq i32 [[RES]], 500 289; TUNIT-NEXT: ret i1 [[CMP]] 290; 291; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: read) 292; CGSCC-LABEL: define {{[^@]+}}@test1-check 293; CGSCC-SAME: (ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR1]] { 294; CGSCC-NEXT: [[RES:%.*]] = tail call i32 @test1(ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[P]]) #[[ATTR5]] 295; CGSCC-NEXT: [[CMP:%.*]] = icmp eq i32 [[RES]], 500 296; CGSCC-NEXT: ret i1 [[CMP]] 297; 298 %res = tail call i32 @test1(ptr %p) 299 %cmp = icmp eq i32 %res, 500 300 ret i1 %cmp 301} 302 303; TEST2 304; int test2(int *p) { return *p == 0 ? 4 : 3; } 305; int test2_check(int *p) { 306; int call = test2(p); 307; if (call == 5) { 308; // dead block 309; return 2; 310; } else { 311; return 3; 312; } 313; } 314 315define i32 @test2(ptr %p) { 316; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) 317; CHECK-LABEL: define {{[^@]+}}@test2 318; CHECK-SAME: (ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR0]] { 319; CHECK-NEXT: entry: 320; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[P]], align 4 321; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0 322; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 4, i32 3 323; CHECK-NEXT: ret i32 [[COND]] 324; 325entry: 326 %0 = load i32, ptr %p, align 4 327 %tobool = icmp eq i32 %0, 0 328 %cond = select i1 %tobool, i32 4, i32 3 329 ret i32 %cond 330} 331 332define i32 @test2_check(ptr %p) { 333; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 334; TUNIT-LABEL: define {{[^@]+}}@test2_check 335; TUNIT-SAME: (ptr nofree readnone align 4 captures(none) [[P:%.*]]) #[[ATTR1:[0-9]+]] { 336; TUNIT-NEXT: entry: 337; TUNIT-NEXT: br label [[IF_THEN:%.*]] 338; TUNIT: if.then: 339; TUNIT-NEXT: br label [[RETURN:%.*]] 340; TUNIT: if.end: 341; TUNIT-NEXT: unreachable 342; TUNIT: return: 343; TUNIT-NEXT: ret i32 2 344; 345; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: read) 346; CGSCC-LABEL: define {{[^@]+}}@test2_check 347; CGSCC-SAME: (ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR1]] { 348; CGSCC-NEXT: entry: 349; CGSCC-NEXT: [[CALL:%.*]] = tail call i32 @test2(ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[P]]) #[[ATTR5]] 350; CGSCC-NEXT: [[CMP:%.*]] = icmp slt i32 [[CALL]], 5 351; CGSCC-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 352; CGSCC: if.then: 353; CGSCC-NEXT: br label [[RETURN:%.*]] 354; CGSCC: if.end: 355; CGSCC-NEXT: br label [[RETURN]] 356; CGSCC: return: 357; CGSCC-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 2, [[IF_THEN]] ], [ 3, [[IF_END]] ] 358; CGSCC-NEXT: ret i32 [[RETVAL_0]] 359; 360entry: 361 %call = tail call i32 @test2(ptr %p) 362 %cmp = icmp slt i32 %call, 5 363 br i1 %cmp, label %if.then, label %if.end 364 365if.then: ; preds = %entry 366 br label %return 367 368if.end: ; preds = %entry 369 br label %return 370 371return: ; preds = %if.end, %if.then 372 %retval.0 = phi i32 [ 2, %if.then ], [ 3, %if.end ] 373 ret i32 %retval.0 374} 375 376; TEST 3 SECV test 377 378; void unkown(); 379; int r1(unsigned int u){ 380; int sum = 0; 381; for(int i = 0; i<100;i++){ 382; sum += i; 383; } 384; // sum = 50 * 49 / 2 385; if(sum > 10000){ 386; // dead block 387; return 20; 388; }else { 389; return 10; 390; } 391; } 392; void f1(int u){ 393; if(r1(u) > 15){ 394; // deadblock 395; unkown(); 396; }else { 397; return; 398; } 399; } 400 401declare dso_local void @unkown() 402 403define internal i32 @r1(i32) local_unnamed_addr { 404; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 405; TUNIT-LABEL: define {{[^@]+}}@r1 406; TUNIT-SAME: () local_unnamed_addr #[[ATTR1]] { 407; TUNIT-NEXT: br label [[TMP4:%.*]] 408; TUNIT: 1: 409; TUNIT-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP7:%.*]], 10000 410; TUNIT-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[F:%.*]] 411; TUNIT: 3: 412; TUNIT-NEXT: ret i32 20 413; TUNIT: f: 414; TUNIT-NEXT: ret i32 10 415; TUNIT: 4: 416; TUNIT-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP8:%.*]], [[TMP4]] ] 417; TUNIT-NEXT: [[TMP6:%.*]] = phi i32 [ 0, [[TMP0]] ], [ [[TMP7]], [[TMP4]] ] 418; TUNIT-NEXT: [[TMP7]] = add nuw nsw i32 [[TMP5]], [[TMP6]] 419; TUNIT-NEXT: [[TMP8]] = add nuw nsw i32 [[TMP5]], 1 420; TUNIT-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 100 421; TUNIT-NEXT: br i1 [[TMP9]], label [[TMP1:%.*]], label [[TMP4]] 422; 423; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 424; CGSCC-LABEL: define {{[^@]+}}@r1 425; CGSCC-SAME: () local_unnamed_addr #[[ATTR2:[0-9]+]] { 426; CGSCC-NEXT: br label [[TMP4:%.*]] 427; CGSCC: 1: 428; CGSCC-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP7:%.*]], 10000 429; CGSCC-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[F:%.*]] 430; CGSCC: 3: 431; CGSCC-NEXT: ret i32 20 432; CGSCC: f: 433; CGSCC-NEXT: ret i32 10 434; CGSCC: 4: 435; CGSCC-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP8:%.*]], [[TMP4]] ] 436; CGSCC-NEXT: [[TMP6:%.*]] = phi i32 [ 0, [[TMP0]] ], [ [[TMP7]], [[TMP4]] ] 437; CGSCC-NEXT: [[TMP7]] = add nuw nsw i32 [[TMP5]], [[TMP6]] 438; CGSCC-NEXT: [[TMP8]] = add nuw nsw i32 [[TMP5]], 1 439; CGSCC-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 100 440; CGSCC-NEXT: br i1 [[TMP9]], label [[TMP1:%.*]], label [[TMP4]] 441; 442 br label %5 443 4442: ; preds = %5 445 %3 = icmp sgt i32 %8, 10000 446 br i1 %3, label %4, label %f 4474: 448 ret i32 20 449f: 450 ret i32 10 4515: ; preds = %5, %1 452 %6 = phi i32 [ 0, %1 ], [ %9, %5 ] 453 %7 = phi i32 [ 0, %1 ], [ %8, %5 ] 454 %8 = add nuw nsw i32 %6, %7 455 %9 = add nuw nsw i32 %6, 1 456 %10 = icmp eq i32 %9, 100 457 br i1 %10, label %2, label %5 458} 459 460define void @f1(i32){ 461; TUNIT-LABEL: define {{[^@]+}}@f1 462; TUNIT-SAME: (i32 [[TMP0:%.*]]) { 463; TUNIT-NEXT: [[TMP2:%.*]] = tail call i32 @r1() #[[ATTR4:[0-9]+]] 464; TUNIT-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 15 465; TUNIT-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]] 466; TUNIT: 4: 467; TUNIT-NEXT: tail call void @unkown() 468; TUNIT-NEXT: br label [[TMP5]] 469; TUNIT: 5: 470; TUNIT-NEXT: ret void 471; 472; CGSCC-LABEL: define {{[^@]+}}@f1 473; CGSCC-SAME: (i32 [[TMP0:%.*]]) { 474; CGSCC-NEXT: [[TMP2:%.*]] = tail call i32 @r1() #[[ATTR6:[0-9]+]] 475; CGSCC-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 15 476; CGSCC-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]] 477; CGSCC: 4: 478; CGSCC-NEXT: tail call void @unkown() 479; CGSCC-NEXT: br label [[TMP5]] 480; CGSCC: 5: 481; CGSCC-NEXT: ret void 482; 483 %2 = tail call i32 @r1(i32 %0) 484 %3 = icmp sgt i32 %2, 15 485 br i1 %3, label %4, label %5 486 4874: ; preds = %1 488 tail call void @unkown() 489 br label %5 490 4915: ; preds = %1, %4 492 ret void 493} 494 495; TEST4 LVI test 496 497; f1 498; int test4-f1(int u){ 499; if(u>=0) { 500; return u; 501; }else{ 502; return 0; 503; } 504; } 505define dso_local i32 @test4-f1(i32 %u) { 506; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 507; TUNIT-LABEL: define {{[^@]+}}@test4-f1 508; TUNIT-SAME: (i32 [[U:%.*]]) #[[ATTR1]] { 509; TUNIT-NEXT: entry: 510; TUNIT-NEXT: [[CMP:%.*]] = icmp sgt i32 [[U]], -1 511; TUNIT-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]] 512; TUNIT: if.then: 513; TUNIT-NEXT: br label [[RETURN]] 514; TUNIT: return: 515; TUNIT-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[U]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ] 516; TUNIT-NEXT: ret i32 [[RETVAL_0]] 517; 518; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 519; CGSCC-LABEL: define {{[^@]+}}@test4-f1 520; CGSCC-SAME: (i32 [[U:%.*]]) #[[ATTR2]] { 521; CGSCC-NEXT: entry: 522; CGSCC-NEXT: [[CMP:%.*]] = icmp sgt i32 [[U]], -1 523; CGSCC-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]] 524; CGSCC: if.then: 525; CGSCC-NEXT: br label [[RETURN]] 526; CGSCC: return: 527; CGSCC-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[U]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ] 528; CGSCC-NEXT: ret i32 [[RETVAL_0]] 529; 530; FIXME: RETVAL_0 >= 0 531entry: 532 %cmp = icmp sgt i32 %u, -1 533 br i1 %cmp, label %if.then, label %return 534 535if.then: ; preds = %entry 536 br label %return 537 538return: ; preds = %entry, %if.then 539 %retval.0 = phi i32 [ %u, %if.then ], [ 0, %entry ] 540 ret i32 %retval.0 541} 542 543 544define dso_local i32 @test4-g1(i32 %u) { 545; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 546; TUNIT-LABEL: define {{[^@]+}}@test4-g1 547; TUNIT-SAME: (i32 [[U:%.*]]) #[[ATTR1]] { 548; TUNIT-NEXT: entry: 549; TUNIT-NEXT: [[CALL:%.*]] = tail call i32 @test4-f1(i32 [[U]]) #[[ATTR4]] 550; TUNIT-NEXT: ret i32 [[CALL]] 551; 552; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 553; CGSCC-LABEL: define {{[^@]+}}@test4-g1 554; CGSCC-SAME: (i32 [[U:%.*]]) #[[ATTR3:[0-9]+]] { 555; CGSCC-NEXT: entry: 556; CGSCC-NEXT: [[CALL:%.*]] = tail call i32 @test4-f1(i32 [[U]]) #[[ATTR7:[0-9]+]] 557; CGSCC-NEXT: ret i32 [[CALL]] 558; 559; FIXME: %call should have range [0, inf] 560 561entry: 562 %call = tail call i32 @test4-f1(i32 %u) 563 ret i32 %call 564} 565 566; f2 567; int test4-f1(int u){ 568; if(u>-1) { 569; return u+1; 570; }else{ 571; return 1; 572; } 573; } 574define dso_local i32 @test4-f2(i32 %u) { 575; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 576; TUNIT-LABEL: define {{[^@]+}}@test4-f2 577; TUNIT-SAME: (i32 [[U:%.*]]) #[[ATTR1]] { 578; TUNIT-NEXT: entry: 579; TUNIT-NEXT: [[CMP:%.*]] = icmp sgt i32 [[U]], -1 580; TUNIT-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 581; TUNIT: if.then: 582; TUNIT-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[U]], 1 583; TUNIT-NEXT: br label [[RETURN:%.*]] 584; TUNIT: if.else: 585; TUNIT-NEXT: br label [[RETURN]] 586; TUNIT: return: 587; TUNIT-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[ADD]], [[IF_THEN]] ], [ 1, [[IF_ELSE]] ] 588; TUNIT-NEXT: ret i32 [[RETVAL_0]] 589; 590; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 591; CGSCC-LABEL: define {{[^@]+}}@test4-f2 592; CGSCC-SAME: (i32 [[U:%.*]]) #[[ATTR2]] { 593; CGSCC-NEXT: entry: 594; CGSCC-NEXT: [[CMP:%.*]] = icmp sgt i32 [[U]], -1 595; CGSCC-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 596; CGSCC: if.then: 597; CGSCC-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[U]], 1 598; CGSCC-NEXT: br label [[RETURN:%.*]] 599; CGSCC: if.else: 600; CGSCC-NEXT: br label [[RETURN]] 601; CGSCC: return: 602; CGSCC-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[ADD]], [[IF_THEN]] ], [ 1, [[IF_ELSE]] ] 603; CGSCC-NEXT: ret i32 [[RETVAL_0]] 604; 605entry: 606 %cmp = icmp sgt i32 %u, -1 607 br i1 %cmp, label %if.then, label %if.else 608 609if.then: ; preds = %entry 610 %add = add nuw nsw i32 %u, 1 611 br label %return 612 613if.else: ; preds = %entry 614 br label %return 615 616return: ; preds = %if.else, %if.then 617 %retval.0 = phi i32 [ %add, %if.then ], [ 1, %if.else ] 618 ret i32 %retval.0 619} 620 621 622define dso_local i32 @test4-g2(i32 %u) { 623; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 624; TUNIT-LABEL: define {{[^@]+}}@test4-g2 625; TUNIT-SAME: (i32 [[U:%.*]]) #[[ATTR1]] { 626; TUNIT-NEXT: entry: 627; TUNIT-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]]) #[[ATTR4]], !range [[RNG3:![0-9]+]] 628; TUNIT-NEXT: ret i32 [[CALL]] 629; 630; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 631; CGSCC-LABEL: define {{[^@]+}}@test4-g2 632; CGSCC-SAME: (i32 [[U:%.*]]) #[[ATTR3]] { 633; CGSCC-NEXT: entry: 634; CGSCC-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]]) #[[ATTR7]] 635; CGSCC-NEXT: ret i32 [[CALL]] 636; 637entry: 638 %call = tail call i32 @test4-f2(i32 %u) 639 ret i32 %call 640} 641 642define dso_local i32 @test-5() { 643; TUNIT-LABEL: define {{[^@]+}}@test-5() { 644; TUNIT-NEXT: entry: 645; TUNIT-NEXT: [[CALL:%.*]] = call i32 @rec(i32 noundef 0) 646; TUNIT-NEXT: ret i32 [[CALL]] 647; 648; CGSCC-LABEL: define {{[^@]+}}@test-5() { 649; CGSCC-NEXT: entry: 650; CGSCC-NEXT: [[CALL:%.*]] = call noundef i32 @rec(i32 noundef 0) 651; CGSCC-NEXT: ret i32 [[CALL]] 652; 653entry: 654 %call = call i32 @rec(i32 0) 655 ret i32 %call 656} 657define internal i32 @rec(i32 %depth) { 658; CHECK-LABEL: define {{[^@]+}}@rec 659; CHECK-SAME: (i32 [[DEPTH:%.*]]) { 660; CHECK-NEXT: entry: 661; CHECK-NEXT: [[CALL:%.*]] = call i32 @foo(i32 [[DEPTH]]) 662; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[CALL]], 0 663; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 664; CHECK: if.then: 665; CHECK-NEXT: br label [[RETURN:%.*]] 666; CHECK: if.end: 667; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[DEPTH]], 10 668; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN1:%.*]], label [[IF_END3:%.*]] 669; CHECK: if.then1: 670; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[DEPTH]], 1 671; CHECK-NEXT: [[CALL2:%.*]] = call i32 @rec(i32 [[ADD]]) 672; CHECK-NEXT: br label [[IF_END3]] 673; CHECK: if.end3: 674; CHECK-NEXT: br label [[RETURN]] 675; CHECK: return: 676; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 0, [[IF_THEN]] ], [ 1, [[IF_END3]] ] 677; CHECK-NEXT: ret i32 [[RETVAL_0]] 678; 679entry: 680 %call = call i32 @foo(i32 %depth) 681 %tobool = icmp ne i32 %call, 0 682 br i1 %tobool, label %if.then, label %if.end 683 684if.then: ; preds = %entry 685 br label %return 686 687if.end: ; preds = %entry 688 %cmp = icmp slt i32 %depth, 10 689 br i1 %cmp, label %if.then1, label %if.end3 690 691if.then1: ; preds = %if.end 692 %add = add nsw i32 %depth, 1 693 %call2 = call i32 @rec(i32 %add) 694 br label %if.end3 695 696if.end3: ; preds = %if.then1, %if.end 697 br label %return 698 699return: ; preds = %if.end3, %if.then 700 %retval.0 = phi i32 [ 0, %if.then ], [ 1, %if.end3 ] 701 ret i32 %retval.0 702} 703declare dso_local i32 @foo(i32) 704 705 706; Examples taken from https://llvm.discourse.group/t/impossible-condition-optimization/461/1 707; 708; The important part is that we return a constant (false) 709; 710; { 711 712; FIXME: All but the return is not needed anymore 713define dso_local zeroext i1 @phi(i32 %arg) { 714; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 715; TUNIT-LABEL: define {{[^@]+}}@phi 716; TUNIT-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] { 717; TUNIT-NEXT: bb: 718; TUNIT-NEXT: [[TMP:%.*]] = icmp sgt i32 [[ARG]], 5 719; TUNIT-NEXT: br i1 [[TMP]], label [[BB1:%.*]], label [[BB2:%.*]] 720; TUNIT: bb1: 721; TUNIT-NEXT: br label [[BB3:%.*]] 722; TUNIT: bb2: 723; TUNIT-NEXT: br label [[BB3]] 724; TUNIT: bb3: 725; TUNIT-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[ARG]], 10 726; TUNIT-NEXT: br i1 [[TMP4]], label [[BB5:%.*]], label [[BB7:%.*]] 727; TUNIT: bb5: 728; TUNIT-NEXT: br label [[BB9:%.*]] 729; TUNIT: bb7: 730; TUNIT-NEXT: br label [[BB9]] 731; TUNIT: bb9: 732; TUNIT-NEXT: br label [[BB12:%.*]] 733; TUNIT: bb11: 734; TUNIT-NEXT: unreachable 735; TUNIT: bb12: 736; TUNIT-NEXT: br label [[BB13:%.*]] 737; TUNIT: bb13: 738; TUNIT-NEXT: ret i1 false 739; 740; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 741; CGSCC-LABEL: define {{[^@]+}}@phi 742; CGSCC-SAME: (i32 [[ARG:%.*]]) #[[ATTR2]] { 743; CGSCC-NEXT: bb: 744; CGSCC-NEXT: [[TMP:%.*]] = icmp sgt i32 [[ARG]], 5 745; CGSCC-NEXT: br i1 [[TMP]], label [[BB1:%.*]], label [[BB2:%.*]] 746; CGSCC: bb1: 747; CGSCC-NEXT: br label [[BB3:%.*]] 748; CGSCC: bb2: 749; CGSCC-NEXT: br label [[BB3]] 750; CGSCC: bb3: 751; CGSCC-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[ARG]], 10 752; CGSCC-NEXT: br i1 [[TMP4]], label [[BB5:%.*]], label [[BB7:%.*]] 753; CGSCC: bb5: 754; CGSCC-NEXT: br label [[BB9:%.*]] 755; CGSCC: bb7: 756; CGSCC-NEXT: br label [[BB9]] 757; CGSCC: bb9: 758; CGSCC-NEXT: br label [[BB12:%.*]] 759; CGSCC: bb11: 760; CGSCC-NEXT: unreachable 761; CGSCC: bb12: 762; CGSCC-NEXT: br label [[BB13:%.*]] 763; CGSCC: bb13: 764; CGSCC-NEXT: ret i1 false 765; 766bb: 767 %tmp = icmp sgt i32 %arg, 5 768 br i1 %tmp, label %bb1, label %bb2 769 770bb1: ; preds = %bb 771 br label %bb3 772 773bb2: ; preds = %bb 774 br label %bb3 775 776bb3: ; preds = %bb2, %bb1 777 %.02 = phi i32 [ 1, %bb1 ], [ 2, %bb2 ] 778 %tmp4 = icmp sgt i32 %arg, 10 779 br i1 %tmp4, label %bb5, label %bb7 780 781bb5: ; preds = %bb3 782 %tmp6 = add nsw i32 %.02, 1 783 br label %bb9 784 785bb7: ; preds = %bb3 786 %tmp8 = add nsw i32 %.02, 2 787 br label %bb9 788 789bb9: ; preds = %bb7, %bb5 790 %.01 = phi i32 [ %tmp6, %bb5 ], [ %tmp8, %bb7 ] 791 %tmp10 = icmp eq i32 %.01, 5 792 br i1 %tmp10, label %bb11, label %bb12 793 794bb11: ; preds = %bb9 795 br label %bb13 796 797bb12: ; preds = %bb9 798 br label %bb13 799 800bb13: ; preds = %bb12, %bb11 801 %.0 = phi i1 [ true, %bb11 ], [ false, %bb12 ] 802 ret i1 %.0 803} 804 805define dso_local i1 @select(i32 %a) local_unnamed_addr #0 { 806; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 807; TUNIT-LABEL: define {{[^@]+}}@select 808; TUNIT-SAME: (i32 [[A:%.*]]) local_unnamed_addr #[[ATTR1]] { 809; TUNIT-NEXT: entry: 810; TUNIT-NEXT: ret i1 false 811; 812; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 813; CGSCC-LABEL: define {{[^@]+}}@select 814; CGSCC-SAME: (i32 [[A:%.*]]) local_unnamed_addr #[[ATTR2]] { 815; CGSCC-NEXT: entry: 816; CGSCC-NEXT: ret i1 false 817; 818entry: 819 %cmp = icmp sgt i32 %a, 5 820 %. = select i1 %cmp, i32 1, i32 2 821 %cmp1 = icmp sgt i32 %a, 10 822 %y.0.v = select i1 %cmp1, i32 1, i32 2 823 %y.0 = add nuw nsw i32 %., %y.0.v 824 %cmp6 = icmp eq i32 %y.0, 5 825 ret i1 %cmp6 826} 827 828define dso_local i32 @select_zext(i32 %a) local_unnamed_addr #0 { 829; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 830; TUNIT-LABEL: define {{[^@]+}}@select_zext 831; TUNIT-SAME: (i32 [[A:%.*]]) local_unnamed_addr #[[ATTR1]] { 832; TUNIT-NEXT: entry: 833; TUNIT-NEXT: ret i32 0 834; 835; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 836; CGSCC-LABEL: define {{[^@]+}}@select_zext 837; CGSCC-SAME: (i32 [[A:%.*]]) local_unnamed_addr #[[ATTR2]] { 838; CGSCC-NEXT: entry: 839; CGSCC-NEXT: ret i32 0 840; 841entry: 842 %cmp = icmp sgt i32 %a, 5 843 %. = select i1 %cmp, i32 1, i32 2 844 %cmp1 = icmp sgt i32 %a, 10 845 %y.0.v = select i1 %cmp1, i32 1, i32 2 846 %y.0 = add nuw nsw i32 %., %y.0.v 847 %cmp6 = icmp eq i32 %y.0, 5 848 %.13 = zext i1 %cmp6 to i32 849 ret i32 %.13 850} 851 852define dso_local i64 @select_int2ptr_bitcast_ptr2int(i32 %a) local_unnamed_addr #0 { 853; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 854; TUNIT-LABEL: define {{[^@]+}}@select_int2ptr_bitcast_ptr2int 855; TUNIT-SAME: (i32 [[A:%.*]]) local_unnamed_addr #[[ATTR1]] { 856; TUNIT-NEXT: entry: 857; TUNIT-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], 5 858; TUNIT-NEXT: [[DOT:%.*]] = select i1 [[CMP]], i32 1, i32 2 859; TUNIT-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[A]], 10 860; TUNIT-NEXT: [[Y_0_V:%.*]] = select i1 [[CMP1]], i32 1, i32 2 861; TUNIT-NEXT: [[Y_0:%.*]] = add nuw nsw i32 [[DOT]], [[Y_0_V]] 862; TUNIT-NEXT: [[CMP6:%.*]] = icmp eq i32 [[Y_0]], 5 863; TUNIT-NEXT: [[I2P:%.*]] = inttoptr i1 [[CMP6]] to ptr 864; TUNIT-NEXT: [[P2I:%.*]] = ptrtoint ptr [[I2P]] to i64 865; TUNIT-NEXT: ret i64 [[P2I]] 866; 867; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 868; CGSCC-LABEL: define {{[^@]+}}@select_int2ptr_bitcast_ptr2int 869; CGSCC-SAME: (i32 [[A:%.*]]) local_unnamed_addr #[[ATTR2]] { 870; CGSCC-NEXT: entry: 871; CGSCC-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], 5 872; CGSCC-NEXT: [[DOT:%.*]] = select i1 [[CMP]], i32 1, i32 2 873; CGSCC-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[A]], 10 874; CGSCC-NEXT: [[Y_0_V:%.*]] = select i1 [[CMP1]], i32 1, i32 2 875; CGSCC-NEXT: [[Y_0:%.*]] = add nuw nsw i32 [[DOT]], [[Y_0_V]] 876; CGSCC-NEXT: [[CMP6:%.*]] = icmp eq i32 [[Y_0]], 5 877; CGSCC-NEXT: [[I2P:%.*]] = inttoptr i1 [[CMP6]] to ptr 878; CGSCC-NEXT: [[P2I:%.*]] = ptrtoint ptr [[I2P]] to i64 879; CGSCC-NEXT: ret i64 [[P2I]] 880; 881entry: 882 %cmp = icmp sgt i32 %a, 5 883 %. = select i1 %cmp, i32 1, i32 2 884 %cmp1 = icmp sgt i32 %a, 10 885 %y.0.v = select i1 %cmp1, i32 1, i32 2 886 %y.0 = add nuw nsw i32 %., %y.0.v 887 %cmp6 = icmp eq i32 %y.0, 5 888 %i2p = inttoptr i1 %cmp6 to ptr 889 %p2i = ptrtoint ptr %i2p to i64 890 ret i64 %p2i 891} 892 893; } 894 895define i1 @f_fcmp(float %a, float %b) { 896; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 897; TUNIT-LABEL: define {{[^@]+}}@f_fcmp 898; TUNIT-SAME: (float [[A:%.*]], float [[B:%.*]]) #[[ATTR1]] { 899; TUNIT-NEXT: [[R:%.*]] = fcmp uge float [[A]], [[B]] 900; TUNIT-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false 901; TUNIT-NEXT: ret i1 [[S]] 902; 903; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 904; CGSCC-LABEL: define {{[^@]+}}@f_fcmp 905; CGSCC-SAME: (float [[A:%.*]], float [[B:%.*]]) #[[ATTR2]] { 906; CGSCC-NEXT: [[R:%.*]] = fcmp uge float [[A]], [[B]] 907; CGSCC-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false 908; CGSCC-NEXT: ret i1 [[S]] 909; 910 %r = fcmp uge float %a, %b 911 %s = select i1 %r, i1 %r, i1 0 912 ret i1 %s 913} 914define i1 @d_fcmp(double %a, double %b) { 915; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 916; TUNIT-LABEL: define {{[^@]+}}@d_fcmp 917; TUNIT-SAME: (double [[A:%.*]], double [[B:%.*]]) #[[ATTR1]] { 918; TUNIT-NEXT: [[R:%.*]] = fcmp oeq double [[A]], [[B]] 919; TUNIT-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false 920; TUNIT-NEXT: ret i1 [[S]] 921; 922; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 923; CGSCC-LABEL: define {{[^@]+}}@d_fcmp 924; CGSCC-SAME: (double [[A:%.*]], double [[B:%.*]]) #[[ATTR2]] { 925; CGSCC-NEXT: [[R:%.*]] = fcmp oeq double [[A]], [[B]] 926; CGSCC-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false 927; CGSCC-NEXT: ret i1 [[S]] 928; 929 %r = fcmp oeq double %a, %b 930 %s = select i1 %r, i1 %r, i1 0 931 ret i1 %s 932} 933define i1 @dp_icmp(ptr %a, ptr %b) { 934; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 935; TUNIT-LABEL: define {{[^@]+}}@dp_icmp 936; TUNIT-SAME: (ptr nofree readnone [[A:%.*]], ptr nofree readnone [[B:%.*]]) #[[ATTR1]] { 937; TUNIT-NEXT: [[R:%.*]] = icmp sge ptr [[A]], [[B]] 938; TUNIT-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false 939; TUNIT-NEXT: ret i1 [[S]] 940; 941; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 942; CGSCC-LABEL: define {{[^@]+}}@dp_icmp 943; CGSCC-SAME: (ptr nofree readnone [[A:%.*]], ptr nofree readnone [[B:%.*]]) #[[ATTR2]] { 944; CGSCC-NEXT: [[R:%.*]] = icmp sge ptr [[A]], [[B]] 945; CGSCC-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false 946; CGSCC-NEXT: ret i1 [[S]] 947; 948 %r = icmp sge ptr %a, %b 949 %s = select i1 %r, i1 %r, i1 0 950 ret i1 %s 951} 952define i1 @ip_icmp(ptr %a, ptr %b) { 953; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 954; TUNIT-LABEL: define {{[^@]+}}@ip_icmp 955; TUNIT-SAME: (ptr nofree readnone [[A:%.*]], ptr nofree readnone [[B:%.*]]) #[[ATTR1]] { 956; TUNIT-NEXT: [[R:%.*]] = icmp ult ptr [[A]], [[B]] 957; TUNIT-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false 958; TUNIT-NEXT: ret i1 [[S]] 959; 960; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 961; CGSCC-LABEL: define {{[^@]+}}@ip_icmp 962; CGSCC-SAME: (ptr nofree readnone [[A:%.*]], ptr nofree readnone [[B:%.*]]) #[[ATTR2]] { 963; CGSCC-NEXT: [[R:%.*]] = icmp ult ptr [[A]], [[B]] 964; CGSCC-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false 965; CGSCC-NEXT: ret i1 [[S]] 966; 967 %r = icmp ult ptr %a, %b 968 %s = select i1 %r, i1 %r, i1 0 969 ret i1 %s 970} 971define i1 @fcmp_caller(float %fa, float %fb, double %da, double %db, ptr %dpa, ptr %dpb, ptr %ipa, ptr %ipb) { 972; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 973; TUNIT-LABEL: define {{[^@]+}}@fcmp_caller 974; TUNIT-SAME: (float [[FA:%.*]], float [[FB:%.*]], double [[DA:%.*]], double [[DB:%.*]], ptr nofree readnone [[DPA:%.*]], ptr nofree readnone [[DPB:%.*]], ptr nofree readnone [[IPA:%.*]], ptr nofree readnone [[IPB:%.*]]) #[[ATTR1]] { 975; TUNIT-NEXT: [[R1:%.*]] = call i1 @f_fcmp(float [[FA]], float [[FB]]) #[[ATTR4]] 976; TUNIT-NEXT: [[R2:%.*]] = call i1 @d_fcmp(double [[DA]], double [[DB]]) #[[ATTR4]] 977; TUNIT-NEXT: [[R3:%.*]] = call i1 @dp_icmp(ptr noalias nofree readnone [[DPA]], ptr noalias nofree readnone [[DPB]]) #[[ATTR4]] 978; TUNIT-NEXT: [[R4:%.*]] = call i1 @ip_icmp(ptr noalias nofree readnone [[IPA]], ptr noalias nofree readnone [[IPB]]) #[[ATTR4]] 979; TUNIT-NEXT: [[O1:%.*]] = or i1 [[R1]], [[R2]] 980; TUNIT-NEXT: [[O2:%.*]] = or i1 [[R3]], [[R4]] 981; TUNIT-NEXT: [[O3:%.*]] = or i1 [[O1]], [[O2]] 982; TUNIT-NEXT: ret i1 [[O3]] 983; 984; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 985; CGSCC-LABEL: define {{[^@]+}}@fcmp_caller 986; CGSCC-SAME: (float [[FA:%.*]], float [[FB:%.*]], double [[DA:%.*]], double [[DB:%.*]], ptr nofree readnone [[DPA:%.*]], ptr nofree readnone [[DPB:%.*]], ptr nofree readnone [[IPA:%.*]], ptr nofree readnone [[IPB:%.*]]) #[[ATTR3]] { 987; CGSCC-NEXT: [[R1:%.*]] = call i1 @f_fcmp(float [[FA]], float [[FB]]) #[[ATTR7]] 988; CGSCC-NEXT: [[R2:%.*]] = call i1 @d_fcmp(double [[DA]], double [[DB]]) #[[ATTR7]] 989; CGSCC-NEXT: [[R3:%.*]] = call i1 @dp_icmp(ptr noalias nofree readnone [[DPA]], ptr noalias nofree readnone [[DPB]]) #[[ATTR7]] 990; CGSCC-NEXT: [[R4:%.*]] = call i1 @ip_icmp(ptr noalias nofree readnone [[IPA]], ptr noalias nofree readnone [[IPB]]) #[[ATTR7]] 991; CGSCC-NEXT: [[O1:%.*]] = or i1 [[R1]], [[R2]] 992; CGSCC-NEXT: [[O2:%.*]] = or i1 [[R3]], [[R4]] 993; CGSCC-NEXT: [[O3:%.*]] = or i1 [[O1]], [[O2]] 994; CGSCC-NEXT: ret i1 [[O3]] 995; 996 %r1 = call i1 @f_fcmp(float %fa, float %fb) 997 %r2 = call i1 @d_fcmp(double %da, double %db) 998 %r3 = call i1 @dp_icmp(ptr %dpa, ptr %dpb) 999 %r4 = call i1 @ip_icmp(ptr %ipa, ptr %ipb) 1000 %o1 = or i1 %r1, %r2 1001 %o2 = or i1 %r3, %r4 1002 %o3 = or i1 %o1, %o2 1003 ret i1 %o3 1004} 1005 1006define i8 @ret_two() { 1007; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1008; TUNIT-LABEL: define {{[^@]+}}@ret_two 1009; TUNIT-SAME: () #[[ATTR1]] { 1010; TUNIT-NEXT: ret i8 2 1011; 1012; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1013; CGSCC-LABEL: define {{[^@]+}}@ret_two 1014; CGSCC-SAME: () #[[ATTR2]] { 1015; CGSCC-NEXT: ret i8 2 1016; 1017 ret i8 2 1018} 1019define i8 @ret_undef() { 1020; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1021; TUNIT-LABEL: define {{[^@]+}}@ret_undef 1022; TUNIT-SAME: () #[[ATTR1]] { 1023; TUNIT-NEXT: ret i8 undef 1024; 1025; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1026; CGSCC-LABEL: define {{[^@]+}}@ret_undef 1027; CGSCC-SAME: () #[[ATTR2]] { 1028; CGSCC-NEXT: ret i8 undef 1029; 1030 ret i8 undef 1031} 1032 1033; Verify we collapse undef to a value and return something non-undef here. 1034define i8 @undef_collapse_1() { 1035; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1036; TUNIT-LABEL: define {{[^@]+}}@undef_collapse_1 1037; TUNIT-SAME: () #[[ATTR1]] { 1038; TUNIT-NEXT: ret i8 0 1039; 1040; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 1041; CGSCC-LABEL: define {{[^@]+}}@undef_collapse_1 1042; CGSCC-SAME: () #[[ATTR3]] { 1043; CGSCC-NEXT: [[C:%.*]] = call i8 @ret_undef() #[[ATTR7]] 1044; CGSCC-NEXT: [[S:%.*]] = shl i8 [[C]], 2 1045; CGSCC-NEXT: ret i8 [[S]] 1046; 1047 %c = call i8 @ret_undef() 1048 %s = shl i8 %c, 2 1049 ret i8 %s 1050} 1051 1052; Verify we collapse undef to a value and return something non-undef here. 1053define i8 @undef_collapse_2() { 1054; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1055; TUNIT-LABEL: define {{[^@]+}}@undef_collapse_2 1056; TUNIT-SAME: () #[[ATTR1]] { 1057; TUNIT-NEXT: ret i8 0 1058; 1059; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 1060; CGSCC-LABEL: define {{[^@]+}}@undef_collapse_2 1061; CGSCC-SAME: () #[[ATTR3]] { 1062; CGSCC-NEXT: [[C:%.*]] = call i8 @ret_two() #[[ATTR7]] 1063; CGSCC-NEXT: [[S:%.*]] = shl i8 undef, [[C]] 1064; CGSCC-NEXT: ret i8 [[S]] 1065; 1066 %c = call i8 @ret_two() 1067 %s = shl i8 undef, %c 1068 ret i8 %s 1069} 1070 1071define i8 @undef_collapse_caller() { 1072; 1073; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1074; TUNIT-LABEL: define {{[^@]+}}@undef_collapse_caller 1075; TUNIT-SAME: () #[[ATTR1]] { 1076; TUNIT-NEXT: ret i8 0 1077; 1078; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 1079; CGSCC-LABEL: define {{[^@]+}}@undef_collapse_caller 1080; CGSCC-SAME: () #[[ATTR3]] { 1081; CGSCC-NEXT: [[C1:%.*]] = call i8 @undef_collapse_1() #[[ATTR7]] 1082; CGSCC-NEXT: [[C2:%.*]] = call i8 @undef_collapse_2() #[[ATTR7]] 1083; CGSCC-NEXT: [[A:%.*]] = add i8 [[C1]], [[C2]] 1084; CGSCC-NEXT: ret i8 [[A]] 1085; 1086 %c1 = call i8 @undef_collapse_1() 1087 %c2 = call i8 @undef_collapse_2() 1088 %a = add i8 %c1, %c2 1089 ret i8 %a 1090} 1091 1092define i32 @ret1or2(i1 %c) { 1093; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1094; TUNIT-LABEL: define {{[^@]+}}@ret1or2 1095; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { 1096; TUNIT-NEXT: [[S:%.*]] = select i1 [[C]], i32 1, i32 2 1097; TUNIT-NEXT: ret i32 [[S]] 1098; 1099; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1100; CGSCC-LABEL: define {{[^@]+}}@ret1or2 1101; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR2]] { 1102; CGSCC-NEXT: [[S:%.*]] = select i1 [[C]], i32 1, i32 2 1103; CGSCC-NEXT: ret i32 [[S]] 1104; 1105 %s = select i1 %c, i32 1, i32 2 1106 ret i32 %s 1107} 1108define i1 @callee_range_1(i1 %c1, i1 %c2, i1 %c3) { 1109; 1110; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1111; TUNIT-LABEL: define {{[^@]+}}@callee_range_1 1112; TUNIT-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) #[[ATTR1]] { 1113; TUNIT-NEXT: [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) #[[ATTR4]] 1114; TUNIT-NEXT: [[R2:%.*]] = call i32 @ret1or2(i1 [[C2]]) #[[ATTR4]] 1115; TUNIT-NEXT: [[INDIRECTION:%.*]] = select i1 [[C3]], i32 [[R1]], i32 [[R2]] 1116; TUNIT-NEXT: [[A:%.*]] = add i32 [[R1]], [[INDIRECTION]] 1117; TUNIT-NEXT: [[I1:%.*]] = icmp sle i32 [[A]], 4 1118; TUNIT-NEXT: [[I2:%.*]] = icmp sge i32 [[A]], 2 1119; TUNIT-NEXT: [[F:%.*]] = and i1 [[I1]], [[I2]] 1120; TUNIT-NEXT: ret i1 [[F]] 1121; 1122; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 1123; CGSCC-LABEL: define {{[^@]+}}@callee_range_1 1124; CGSCC-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) #[[ATTR3]] { 1125; CGSCC-NEXT: [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) #[[ATTR7]] 1126; CGSCC-NEXT: [[R2:%.*]] = call i32 @ret1or2(i1 [[C2]]) #[[ATTR7]] 1127; CGSCC-NEXT: [[INDIRECTION:%.*]] = select i1 [[C3]], i32 [[R1]], i32 [[R2]] 1128; CGSCC-NEXT: [[A:%.*]] = add i32 [[R1]], [[INDIRECTION]] 1129; CGSCC-NEXT: [[I1:%.*]] = icmp sle i32 [[A]], 4 1130; CGSCC-NEXT: [[I2:%.*]] = icmp sge i32 [[A]], 2 1131; CGSCC-NEXT: [[F:%.*]] = and i1 [[I1]], [[I2]] 1132; CGSCC-NEXT: ret i1 [[F]] 1133; 1134 %r1 = call i32 @ret1or2(i1 %c1) 1135 %r2 = call i32 @ret1or2(i1 %c2) 1136 %indirection = select i1 %c3, i32 %r1, i32 %r2 1137 %a = add i32 %r1, %indirection 1138 %i1 = icmp sle i32 %a, 4 1139 %i2 = icmp sge i32 %a, 2 1140 %f = and i1 %i1, %i2 1141 ret i1 %f 1142} 1143 1144define i1 @callee_range_2(i1 %c1, i1 %c2) { 1145; 1146; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1147; TUNIT-LABEL: define {{[^@]+}}@callee_range_2 1148; TUNIT-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR1]] { 1149; TUNIT-NEXT: [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) #[[ATTR4]] 1150; TUNIT-NEXT: [[R2:%.*]] = call i32 @ret1or2(i1 [[C2]]) #[[ATTR4]] 1151; TUNIT-NEXT: [[A:%.*]] = add i32 [[R1]], [[R2]] 1152; TUNIT-NEXT: [[I1:%.*]] = icmp sle i32 [[A]], 3 1153; TUNIT-NEXT: [[I2:%.*]] = icmp sge i32 [[A]], 2 1154; TUNIT-NEXT: [[F:%.*]] = and i1 [[I1]], [[I2]] 1155; TUNIT-NEXT: ret i1 [[F]] 1156; 1157; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 1158; CGSCC-LABEL: define {{[^@]+}}@callee_range_2 1159; CGSCC-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR3]] { 1160; CGSCC-NEXT: [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) #[[ATTR7]] 1161; CGSCC-NEXT: [[R2:%.*]] = call i32 @ret1or2(i1 [[C2]]) #[[ATTR7]] 1162; CGSCC-NEXT: [[A:%.*]] = add i32 [[R1]], [[R2]] 1163; CGSCC-NEXT: [[I1:%.*]] = icmp sle i32 [[A]], 3 1164; CGSCC-NEXT: [[I2:%.*]] = icmp sge i32 [[A]], 2 1165; CGSCC-NEXT: [[F:%.*]] = and i1 [[I1]], [[I2]] 1166; CGSCC-NEXT: ret i1 [[F]] 1167; 1168 %r1 = call i32 @ret1or2(i1 %c1) 1169 %r2 = call i32 @ret1or2(i1 %c2) 1170 %a = add i32 %r1, %r2 1171 %i1 = icmp sle i32 %a, 3 1172 %i2 = icmp sge i32 %a, 2 1173 %f = and i1 %i1, %i2 1174 ret i1 %f 1175} 1176 1177 1178define i32 @ret100() { 1179; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1180; TUNIT-LABEL: define {{[^@]+}}@ret100 1181; TUNIT-SAME: () #[[ATTR1]] { 1182; TUNIT-NEXT: ret i32 100 1183; 1184; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1185; CGSCC-LABEL: define {{[^@]+}}@ret100 1186; CGSCC-SAME: () #[[ATTR2]] { 1187; CGSCC-NEXT: ret i32 100 1188; 1189 ret i32 100 1190} 1191 1192define i1 @ctx_adjustment(i32 %V) { 1193; 1194; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1195; TUNIT-LABEL: define {{[^@]+}}@ctx_adjustment 1196; TUNIT-SAME: (i32 [[V:%.*]]) #[[ATTR1]] { 1197; TUNIT-NEXT: [[C1:%.*]] = icmp sge i32 [[V]], 100 1198; TUNIT-NEXT: br i1 [[C1]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 1199; TUNIT: if.true: 1200; TUNIT-NEXT: br label [[END:%.*]] 1201; TUNIT: if.false: 1202; TUNIT-NEXT: br label [[END]] 1203; TUNIT: end: 1204; TUNIT-NEXT: [[PHI:%.*]] = phi i32 [ [[V]], [[IF_TRUE]] ], [ 100, [[IF_FALSE]] ] 1205; TUNIT-NEXT: [[C2:%.*]] = icmp sge i32 [[PHI]], 100 1206; TUNIT-NEXT: ret i1 [[C2]] 1207; 1208; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 1209; CGSCC-LABEL: define {{[^@]+}}@ctx_adjustment 1210; CGSCC-SAME: (i32 [[V:%.*]]) #[[ATTR3]] { 1211; CGSCC-NEXT: [[C1:%.*]] = icmp sge i32 [[V]], 100 1212; CGSCC-NEXT: br i1 [[C1]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 1213; CGSCC: if.true: 1214; CGSCC-NEXT: br label [[END:%.*]] 1215; CGSCC: if.false: 1216; CGSCC-NEXT: [[CALL:%.*]] = call i32 @ret100() #[[ATTR7]] 1217; CGSCC-NEXT: br label [[END]] 1218; CGSCC: end: 1219; CGSCC-NEXT: [[PHI:%.*]] = phi i32 [ [[V]], [[IF_TRUE]] ], [ [[CALL]], [[IF_FALSE]] ] 1220; CGSCC-NEXT: [[C2:%.*]] = icmp sge i32 [[PHI]], 100 1221; CGSCC-NEXT: ret i1 [[C2]] 1222; 1223 %c1 = icmp sge i32 %V, 100 1224 br i1 %c1, label %if.true, label %if.false 1225if.true: 1226 br label %end 1227if.false: 1228 %call = call i32 @ret100() 1229 br label %end 1230end: 1231 %phi = phi i32 [ %V, %if.true ], [ %call, %if.false ] 1232 %c2 = icmp sge i32 %phi, 100 1233 ret i1 %c2 1234} 1235 1236 1237define i32 @func(i1 %c) { 1238; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1239; TUNIT-LABEL: define {{[^@]+}}@func 1240; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { 1241; TUNIT-NEXT: [[RET:%.*]] = select i1 [[C]], i32 0, i32 1 1242; TUNIT-NEXT: ret i32 [[RET]] 1243; 1244; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1245; CGSCC-LABEL: define {{[^@]+}}@func 1246; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR2]] { 1247; CGSCC-NEXT: [[RET:%.*]] = select i1 [[C]], i32 0, i32 1 1248; CGSCC-NEXT: ret i32 [[RET]] 1249; 1250 %ret = select i1 %c, i32 0, i32 1 1251 ret i32 %ret 1252} 1253 1254define i32 @simplify_callsite_argument(i1 %d) { 1255; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1256; TUNIT-LABEL: define {{[^@]+}}@simplify_callsite_argument 1257; TUNIT-SAME: (i1 [[D:%.*]]) #[[ATTR1]] { 1258; TUNIT-NEXT: [[C:%.*]] = select i1 [[D]], i1 true, i1 false 1259; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 1260; TUNIT: t: 1261; TUNIT-NEXT: [[RET1:%.*]] = call i32 @func(i1 noundef [[C]]) #[[ATTR4]] 1262; TUNIT-NEXT: ret i32 [[RET1]] 1263; TUNIT: f: 1264; TUNIT-NEXT: [[RET2:%.*]] = call i32 @func(i1 noundef false) #[[ATTR4]] 1265; TUNIT-NEXT: ret i32 [[RET2]] 1266; 1267; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 1268; CGSCC-LABEL: define {{[^@]+}}@simplify_callsite_argument 1269; CGSCC-SAME: (i1 [[D:%.*]]) #[[ATTR3]] { 1270; CGSCC-NEXT: [[C:%.*]] = select i1 [[D]], i1 true, i1 false 1271; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 1272; CGSCC: t: 1273; CGSCC-NEXT: [[RET1:%.*]] = call noundef i32 @func(i1 noundef [[C]]) #[[ATTR7]] 1274; CGSCC-NEXT: ret i32 [[RET1]] 1275; CGSCC: f: 1276; CGSCC-NEXT: [[RET2:%.*]] = call noundef i32 @func(i1 noundef false) #[[ATTR7]] 1277; CGSCC-NEXT: ret i32 [[RET2]] 1278; 1279 %c = select i1 %d, i1 true, i1 false 1280 br i1 %c, label %t, label %f 1281t: 1282 %ret1 = call i32 @func(i1 %c) 1283 ret i32 %ret1 1284f: 1285 %ret2 = call i32 @func(i1 false) 1286 ret i32 %ret2 1287} 1288 1289define internal i32 @less_than_65536(i32 %arg) { 1290; 1291; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1292; CGSCC-LABEL: define {{[^@]+}}@less_than_65536 1293; CGSCC-SAME: (i32 [[ARG:%.*]]) #[[ATTR2]] { 1294; CGSCC-NEXT: [[SHRINKED:%.*]] = udiv i32 [[ARG]], 65536 1295; CGSCC-NEXT: ret i32 [[SHRINKED]] 1296; 1297 %shrinked = udiv i32 %arg, 65536 1298 ret i32 %shrinked 1299} 1300 1301define internal i1 @is_less_than_65536(i32 %arg) { 1302; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1303; CGSCC-LABEL: define {{[^@]+}}@is_less_than_65536 1304; CGSCC-SAME: (i32 [[ARG:%.*]]) #[[ATTR2]] { 1305; CGSCC-NEXT: [[CMP:%.*]] = icmp ult i32 [[ARG]], 65536 1306; CGSCC-NEXT: ret i1 [[CMP]] 1307; 1308 %cmp = icmp ult i32 %arg, 65536 1309 ret i1 %cmp 1310} 1311 1312define i1 @check_divided_range(i32 %arg) { 1313; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1314; TUNIT-LABEL: define {{[^@]+}}@check_divided_range 1315; TUNIT-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] { 1316; TUNIT-NEXT: ret i1 true 1317; 1318; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 1319; CGSCC-LABEL: define {{[^@]+}}@check_divided_range 1320; CGSCC-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] { 1321; CGSCC-NEXT: [[CSRET1:%.*]] = call i32 @less_than_65536(i32 noundef 0) #[[ATTR7]] 1322; CGSCC-NEXT: [[CSRET2:%.*]] = call i32 @less_than_65536(i32 [[ARG]]) #[[ATTR7]] 1323; CGSCC-NEXT: [[TRUE1:%.*]] = call i1 @is_less_than_65536(i32 [[CSRET1]]) #[[ATTR7]] 1324; CGSCC-NEXT: [[TRUE2:%.*]] = call i1 @is_less_than_65536(i32 [[CSRET2]]) #[[ATTR7]] 1325; CGSCC-NEXT: [[RET:%.*]] = and i1 [[TRUE1]], [[TRUE2]] 1326; CGSCC-NEXT: ret i1 [[RET]] 1327; 1328 %csret1 = call i32 @less_than_65536(i32 0) 1329 %csret2 = call i32 @less_than_65536(i32 %arg) 1330 %true1 = call i1 @is_less_than_65536(i32 %csret1) 1331 %true2 = call i1 @is_less_than_65536(i32 %csret2) 1332 %ret = and i1 %true1, %true2 1333 ret i1 %ret 1334} 1335 1336define internal i32 @cast_and_return(i1 %c) { 1337; 1338; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1339; CGSCC-LABEL: define {{[^@]+}}@cast_and_return 1340; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR2]] { 1341; CGSCC-NEXT: [[RET:%.*]] = zext i1 [[C]] to i32 1342; CGSCC-NEXT: ret i32 [[RET]] 1343; 1344 %ret = zext i1 %c to i32 1345 ret i32 %ret 1346} 1347 1348define internal i1 @is_less_than_3(i32 %c) { 1349; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1350; CGSCC-LABEL: define {{[^@]+}}@is_less_than_3 1351; CGSCC-SAME: (i32 [[C:%.*]]) #[[ATTR2]] { 1352; CGSCC-NEXT: [[CMP:%.*]] = icmp slt i32 [[C]], 3 1353; CGSCC-NEXT: ret i1 [[CMP]] 1354; 1355 %cmp = icmp slt i32 %c, 3 1356 ret i1 %cmp 1357} 1358 1359define i1 @check_casted_range(i1 %c) { 1360; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1361; TUNIT-LABEL: define {{[^@]+}}@check_casted_range 1362; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { 1363; TUNIT-NEXT: ret i1 true 1364; 1365; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 1366; CGSCC-LABEL: define {{[^@]+}}@check_casted_range 1367; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR3]] { 1368; CGSCC-NEXT: [[CSRET1:%.*]] = call i32 @cast_and_return(i1 noundef true) #[[ATTR7]] 1369; CGSCC-NEXT: [[CSRET2:%.*]] = call i32 @cast_and_return(i1 [[C]]) #[[ATTR7]] 1370; CGSCC-NEXT: [[ADD:%.*]] = add i32 [[CSRET1]], [[CSRET2]] 1371; CGSCC-NEXT: [[RET:%.*]] = call i1 @is_less_than_3(i32 [[ADD]]) #[[ATTR7]] 1372; CGSCC-NEXT: ret i1 [[RET]] 1373; 1374 %csret1 = call i32 @cast_and_return(i1 true) 1375 %csret2 = call i32 @cast_and_return(i1 %c) 1376 %add = add i32 %csret1, %csret2 1377 %ret = call i1 @is_less_than_3(i32 %add) 1378 ret i1 %ret 1379} 1380 1381define internal i32 @less_than_100_1(i32 %c) { 1382; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1383; CGSCC-LABEL: define {{[^@]+}}@less_than_100_1 1384; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR2]] { 1385; CGSCC-NEXT: switch i32 [[C]], label [[OTHERWISE:%.*]] [ 1386; CGSCC-NEXT: i32 0, label [[ONZERO:%.*]] 1387; CGSCC-NEXT: i32 1, label [[ONONE:%.*]] 1388; CGSCC-NEXT: i32 2, label [[ONTWO:%.*]] 1389; CGSCC-NEXT: i32 3, label [[ONTHREE:%.*]] 1390; CGSCC-NEXT: i32 4, label [[ONFOUR:%.*]] 1391; CGSCC-NEXT: i32 5, label [[ONFIVE:%.*]] 1392; CGSCC-NEXT: i32 6, label [[ONSIX:%.*]] 1393; CGSCC-NEXT: ] 1394; CGSCC: onzero: 1395; CGSCC-NEXT: ret i32 0 1396; CGSCC: onone: 1397; CGSCC-NEXT: ret i32 1 1398; CGSCC: ontwo: 1399; CGSCC-NEXT: ret i32 2 1400; CGSCC: onthree: 1401; CGSCC-NEXT: ret i32 3 1402; CGSCC: onfour: 1403; CGSCC-NEXT: ret i32 4 1404; CGSCC: onfive: 1405; CGSCC-NEXT: ret i32 5 1406; CGSCC: onsix: 1407; CGSCC-NEXT: ret i32 6 1408; CGSCC: otherwise: 1409; CGSCC-NEXT: ret i32 99 1410; 1411 switch i32 %c, label %otherwise [ i32 0, label %onzero 1412 i32 1, label %onone 1413 i32 2, label %ontwo 1414 i32 3, label %onthree 1415 i32 4, label %onfour 1416 i32 5, label %onfive 1417 i32 6, label %onsix] 1418onzero: 1419 ret i32 0 1420onone: 1421 ret i32 1 1422ontwo: 1423 ret i32 2 1424onthree: 1425 ret i32 3 1426onfour: 1427 ret i32 4 1428onfive: 1429 ret i32 5 1430onsix: 1431 ret i32 6 1432otherwise: 1433 ret i32 99 1434} 1435 1436define internal i1 @is_less_than_100_1(i32 %c) { 1437; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1438; CGSCC-LABEL: define {{[^@]+}}@is_less_than_100_1 1439; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR2]] { 1440; CGSCC-NEXT: [[CMP:%.*]] = icmp slt i32 [[C]], 100 1441; CGSCC-NEXT: ret i1 [[CMP]] 1442; 1443 %cmp = icmp slt i32 %c, 100 1444 ret i1 %cmp 1445} 1446 1447define i1 @propagate_range1(i32 %c){ 1448; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1449; TUNIT-LABEL: define {{[^@]+}}@propagate_range1 1450; TUNIT-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { 1451; TUNIT-NEXT: ret i1 true 1452; 1453; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 1454; CGSCC-LABEL: define {{[^@]+}}@propagate_range1 1455; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR3]] { 1456; CGSCC-NEXT: [[CSRET:%.*]] = call i32 @less_than_100_1(i32 noundef [[C]]) #[[ATTR7]] 1457; CGSCC-NEXT: [[TRUE:%.*]] = call i1 @is_less_than_100_1(i32 noundef [[CSRET]]) #[[ATTR7]] 1458; CGSCC-NEXT: ret i1 [[TRUE]] 1459; 1460 %csret = call i32 @less_than_100_1(i32 %c) 1461 %true = call i1 @is_less_than_100_1(i32 %csret) 1462 ret i1 %true 1463} 1464 1465define internal i32 @less_than_100_2(i32 %c) { 1466; 1467; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1468; TUNIT-LABEL: define {{[^@]+}}@less_than_100_2 1469; TUNIT-SAME: (i32 noundef [[C:%.*]]) #[[ATTR1]] { 1470; TUNIT-NEXT: switch i32 [[C]], label [[OTHERWISE:%.*]] [ 1471; TUNIT-NEXT: i32 0, label [[ONZERO:%.*]] 1472; TUNIT-NEXT: i32 1, label [[ONONE:%.*]] 1473; TUNIT-NEXT: i32 2, label [[ONTWO:%.*]] 1474; TUNIT-NEXT: i32 3, label [[ONTHREE:%.*]] 1475; TUNIT-NEXT: i32 4, label [[ONFOUR:%.*]] 1476; TUNIT-NEXT: i32 5, label [[ONFIVE:%.*]] 1477; TUNIT-NEXT: i32 6, label [[ONSIX:%.*]] 1478; TUNIT-NEXT: ] 1479; TUNIT: onzero: 1480; TUNIT-NEXT: ret i32 0 1481; TUNIT: onone: 1482; TUNIT-NEXT: ret i32 1 1483; TUNIT: ontwo: 1484; TUNIT-NEXT: ret i32 2 1485; TUNIT: onthree: 1486; TUNIT-NEXT: ret i32 3 1487; TUNIT: onfour: 1488; TUNIT-NEXT: ret i32 4 1489; TUNIT: onfive: 1490; TUNIT-NEXT: ret i32 5 1491; TUNIT: onsix: 1492; TUNIT-NEXT: ret i32 6 1493; TUNIT: otherwise: 1494; TUNIT-NEXT: ret i32 99 1495; 1496; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1497; CGSCC-LABEL: define {{[^@]+}}@less_than_100_2 1498; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR2]] { 1499; CGSCC-NEXT: switch i32 [[C]], label [[OTHERWISE:%.*]] [ 1500; CGSCC-NEXT: i32 0, label [[ONZERO:%.*]] 1501; CGSCC-NEXT: i32 1, label [[ONONE:%.*]] 1502; CGSCC-NEXT: i32 2, label [[ONTWO:%.*]] 1503; CGSCC-NEXT: i32 3, label [[ONTHREE:%.*]] 1504; CGSCC-NEXT: i32 4, label [[ONFOUR:%.*]] 1505; CGSCC-NEXT: i32 5, label [[ONFIVE:%.*]] 1506; CGSCC-NEXT: i32 6, label [[ONSIX:%.*]] 1507; CGSCC-NEXT: ] 1508; CGSCC: onzero: 1509; CGSCC-NEXT: ret i32 0 1510; CGSCC: onone: 1511; CGSCC-NEXT: ret i32 1 1512; CGSCC: ontwo: 1513; CGSCC-NEXT: ret i32 2 1514; CGSCC: onthree: 1515; CGSCC-NEXT: ret i32 3 1516; CGSCC: onfour: 1517; CGSCC-NEXT: ret i32 4 1518; CGSCC: onfive: 1519; CGSCC-NEXT: ret i32 5 1520; CGSCC: onsix: 1521; CGSCC-NEXT: ret i32 6 1522; CGSCC: otherwise: 1523; CGSCC-NEXT: ret i32 99 1524; 1525 switch i32 %c, label %otherwise [ i32 0, label %onzero 1526 i32 1, label %onone 1527 i32 2, label %ontwo 1528 i32 3, label %onthree 1529 i32 4, label %onfour 1530 i32 5, label %onfive 1531 i32 6, label %onsix] 1532onzero: 1533 ret i32 0 1534onone: 1535 ret i32 1 1536ontwo: 1537 ret i32 2 1538onthree: 1539 ret i32 3 1540onfour: 1541 ret i32 4 1542onfive: 1543 ret i32 5 1544onsix: 1545 ret i32 6 1546otherwise: 1547 ret i32 99 1548} 1549 1550define internal i1 @is_less_than_100_2(i32 %c) { 1551; 1552; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1553; TUNIT-LABEL: define {{[^@]+}}@is_less_than_100_2 1554; TUNIT-SAME: (i32 noundef [[C:%.*]]) #[[ATTR1]] { 1555; TUNIT-NEXT: [[CMP:%.*]] = icmp slt i32 [[C]], 100 1556; TUNIT-NEXT: ret i1 [[CMP]] 1557; 1558; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1559; CGSCC-LABEL: define {{[^@]+}}@is_less_than_100_2 1560; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR2]] { 1561; CGSCC-NEXT: [[CMP:%.*]] = icmp slt i32 [[C]], 100 1562; CGSCC-NEXT: ret i1 [[CMP]] 1563; 1564 %cmp = icmp slt i32 %c, 100 1565 ret i1 %cmp 1566} 1567 1568define i1 @propagate_range2(i32 %c) { 1569; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1570; TUNIT-LABEL: define {{[^@]+}}@propagate_range2 1571; TUNIT-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { 1572; TUNIT-NEXT: [[CSRET1:%.*]] = call noundef i32 @less_than_100_2(i32 noundef 0) #[[ATTR4]] 1573; TUNIT-NEXT: [[TRUE1:%.*]] = call i1 @is_less_than_100_2(i32 noundef [[CSRET1]]) #[[ATTR4]] 1574; TUNIT-NEXT: [[CSRET2:%.*]] = call noundef i32 @less_than_100_2(i32 noundef [[C]]) #[[ATTR4]] 1575; TUNIT-NEXT: [[TRUE2:%.*]] = call i1 @is_less_than_100_2(i32 noundef [[CSRET2]]) #[[ATTR4]] 1576; TUNIT-NEXT: [[TRUE:%.*]] = and i1 [[TRUE1]], [[TRUE2]] 1577; TUNIT-NEXT: ret i1 [[TRUE]] 1578; 1579; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 1580; CGSCC-LABEL: define {{[^@]+}}@propagate_range2 1581; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR3]] { 1582; CGSCC-NEXT: [[CSRET1:%.*]] = call i32 @less_than_100_2(i32 noundef 0) #[[ATTR7]] 1583; CGSCC-NEXT: [[TRUE1:%.*]] = call i1 @is_less_than_100_2(i32 noundef [[CSRET1]]) #[[ATTR7]] 1584; CGSCC-NEXT: [[CSRET2:%.*]] = call i32 @less_than_100_2(i32 noundef [[C]]) #[[ATTR7]] 1585; CGSCC-NEXT: [[TRUE2:%.*]] = call i1 @is_less_than_100_2(i32 noundef [[CSRET2]]) #[[ATTR7]] 1586; CGSCC-NEXT: [[TRUE:%.*]] = and i1 [[TRUE1]], [[TRUE2]] 1587; CGSCC-NEXT: ret i1 [[TRUE]] 1588; 1589 %csret1 = call i32 @less_than_100_2(i32 0) 1590 %true1 = call i1 @is_less_than_100_2(i32 %csret1) 1591 %csret2 = call i32 @less_than_100_2(i32 %c) 1592 %true2 = call i1 @is_less_than_100_2(i32 %csret2) 1593 %true = and i1 %true1, %true2 1594 ret i1 %true 1595} 1596 1597define internal i1 @non_zero(i8 %v) { 1598; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1599; TUNIT-LABEL: define {{[^@]+}}@non_zero 1600; TUNIT-SAME: (i8 [[V:%.*]]) #[[ATTR1]] { 1601; TUNIT-NEXT: [[R:%.*]] = icmp ne i8 [[V]], 0 1602; TUNIT-NEXT: ret i1 [[R]] 1603; 1604; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 1605; CGSCC-LABEL: define {{[^@]+}}@non_zero 1606; CGSCC-SAME: (i8 [[V:%.*]]) #[[ATTR2]] { 1607; CGSCC-NEXT: ret i1 true 1608; 1609 %r = icmp ne i8 %v, 0 1610 ret i1 %r 1611} 1612 1613; Avoid range metadata for %l below 1614define i1 @context(ptr %p) { 1615; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) 1616; TUNIT-LABEL: define {{[^@]+}}@context 1617; TUNIT-SAME: (ptr nofree noundef nonnull readonly captures(none) dereferenceable(1) [[P:%.*]]) #[[ATTR0]] { 1618; TUNIT-NEXT: [[L:%.*]] = load i8, ptr [[P]], align 1 1619; TUNIT-NEXT: [[C:%.*]] = icmp slt i8 0, [[L]] 1620; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 1621; TUNIT: t: 1622; TUNIT-NEXT: [[R:%.*]] = call i1 @non_zero(i8 [[L]]) #[[ATTR4]] 1623; TUNIT-NEXT: ret i1 [[R]] 1624; TUNIT: f: 1625; TUNIT-NEXT: ret i1 false 1626; 1627; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: read) 1628; CGSCC-LABEL: define {{[^@]+}}@context 1629; CGSCC-SAME: (ptr nofree noundef nonnull readonly captures(none) dereferenceable(1) [[P:%.*]]) #[[ATTR1]] { 1630; CGSCC-NEXT: [[L:%.*]] = load i8, ptr [[P]], align 1 1631; CGSCC-NEXT: [[C:%.*]] = icmp slt i8 0, [[L]] 1632; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 1633; CGSCC: t: 1634; CGSCC-NEXT: [[R:%.*]] = call noundef i1 @non_zero(i8 [[L]]) #[[ATTR7]] 1635; CGSCC-NEXT: ret i1 [[R]] 1636; CGSCC: f: 1637; CGSCC-NEXT: ret i1 false 1638; 1639 %l = load i8, ptr %p 1640 %c = icmp slt i8 0, %l 1641 br i1 %c, label %t, label %f 1642t: 1643 %r = call i1 @non_zero(i8 %l) 1644 ret i1 %r 1645f: 1646 ret i1 false 1647} 1648 1649 1650define void @spam(ptr %arg, ptr %arg1) { 1651; CHECK-LABEL: define {{[^@]+}}@spam 1652; CHECK-SAME: (ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[ARG:%.*]], ptr nofree readnone captures(none) [[ARG1:%.*]]) { 1653; CHECK-NEXT: bb: 1654; CHECK-NEXT: [[TMP:%.*]] = load i32, ptr [[ARG]], align 8 1655; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[TMP]], 4 1656; CHECK-NEXT: br i1 [[TMP2]], label [[BB3:%.*]], label [[BB4:%.*]] 1657; CHECK: bb3: 1658; CHECK-NEXT: call fastcc void @wobble(i32 signext [[TMP]]) 1659; CHECK-NEXT: br label [[BB5:%.*]] 1660; CHECK: bb4: 1661; CHECK-NEXT: call void @ham(i32 [[TMP]]) 1662; CHECK-NEXT: br label [[BB5]] 1663; CHECK: bb5: 1664; CHECK-NEXT: ret void 1665; 1666bb: 1667 %tmp = load i32, ptr %arg, align 8 1668 %tmp2 = icmp ult i32 %tmp, 4 1669 br i1 %tmp2, label %bb3, label %bb4 1670 1671bb3: ; preds = %bb 1672 call fastcc void @wobble(i32 signext %tmp) 1673 br label %bb5 1674 1675bb4: ; preds = %bb 1676 call void @ham(i32 %tmp) 1677 br label %bb5 1678 1679bb5: ; preds = %bb4, %bb3 1680 ret void 1681} 1682 1683define internal fastcc void @wobble(i32 signext %arg) { 1684; CHECK-LABEL: define {{[^@]+}}@wobble 1685; CHECK-SAME: (i32 signext [[ARG:%.*]]) { 1686; CHECK-NEXT: bb: 1687; CHECK-NEXT: [[TMP:%.*]] = icmp ult i32 [[ARG]], 2 1688; CHECK-NEXT: br i1 [[TMP]], label [[BB1:%.*]], label [[BB2:%.*]] 1689; CHECK: bb1: 1690; CHECK-NEXT: call void @barney(i32 noundef signext 32, i32 noundef signext 0) 1691; CHECK-NEXT: br label [[BB3:%.*]] 1692; CHECK: bb2: 1693; CHECK-NEXT: br label [[BB3]] 1694; CHECK: bb3: 1695; CHECK-NEXT: ret void 1696; 1697bb: 1698 %tmp = icmp ult i32 %arg, 2 1699 br i1 %tmp, label %bb1, label %bb2 1700 1701bb1: ; preds = %bb 1702 call void @barney(i32 signext 32, i32 signext 0) 1703 br label %bb3 1704 1705bb2: ; preds = %bb 1706 br label %bb3 1707 1708bb3: ; preds = %bb2, %bb1 1709 ret void 1710} 1711 1712define i1 @loop_1(i32 %N) { 1713; TUNIT: Function Attrs: nofree norecurse nosync nounwind memory(none) 1714; TUNIT-LABEL: define {{[^@]+}}@loop_1 1715; TUNIT-SAME: (i32 [[N:%.*]]) #[[ATTR2:[0-9]+]] { 1716; TUNIT-NEXT: entry: 1717; TUNIT-NEXT: br label [[HEADER:%.*]] 1718; TUNIT: header: 1719; TUNIT-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[AND:%.*]], [[HEADER]] ] 1720; TUNIT-NEXT: [[INC:%.*]] = add i32 [[I]], 1 1721; TUNIT-NEXT: [[AND]] = and i32 [[INC]], 9999 1722; TUNIT-NEXT: [[CMP:%.*]] = icmp ne i32 [[N]], [[AND]] 1723; TUNIT-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]] 1724; TUNIT: exit: 1725; TUNIT-NEXT: [[R:%.*]] = icmp sle i32 [[I]], 5 1726; TUNIT-NEXT: ret i1 [[R]] 1727; 1728; CGSCC: Function Attrs: nofree norecurse nosync nounwind memory(none) 1729; CGSCC-LABEL: define {{[^@]+}}@loop_1 1730; CGSCC-SAME: (i32 [[N:%.*]]) #[[ATTR4:[0-9]+]] { 1731; CGSCC-NEXT: entry: 1732; CGSCC-NEXT: br label [[HEADER:%.*]] 1733; CGSCC: header: 1734; CGSCC-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[AND:%.*]], [[HEADER]] ] 1735; CGSCC-NEXT: [[INC:%.*]] = add i32 [[I]], 1 1736; CGSCC-NEXT: [[AND]] = and i32 [[INC]], 9999 1737; CGSCC-NEXT: [[CMP:%.*]] = icmp ne i32 [[N]], [[AND]] 1738; CGSCC-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]] 1739; CGSCC: exit: 1740; CGSCC-NEXT: [[R:%.*]] = icmp sle i32 [[I]], 5 1741; CGSCC-NEXT: ret i1 [[R]] 1742; 1743entry: 1744 br label %header 1745header: 1746 %i = phi i32 [0, %entry], [%and, %header] 1747 %inc = add i32 %i, 1 1748 %and = and i32 %inc, 9999 1749 %cmp = icmp ne i32 %N, %and 1750 br i1 %cmp, label %header, label %exit 1751exit: 1752 %r = icmp sle i32 %i, 5 1753 ret i1 %r 1754} 1755 1756declare void @ham(i32) 1757 1758declare void @barney(i32 signext, i32 signext) 1759 1760 1761!0 = !{i32 0, i32 10} 1762!1 = !{i32 10, i32 100} 1763;. 1764; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) } 1765; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } 1766; TUNIT: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind memory(none) } 1767; TUNIT: attributes #[[ATTR3]] = { nofree nosync nounwind willreturn memory(read) } 1768; TUNIT: attributes #[[ATTR4]] = { nofree nosync nounwind willreturn memory(none) } 1769;. 1770; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) } 1771; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree nosync nounwind willreturn memory(argmem: read) } 1772; CGSCC: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } 1773; CGSCC: attributes #[[ATTR3]] = { mustprogress nofree nosync nounwind willreturn memory(none) } 1774; CGSCC: attributes #[[ATTR4]] = { nofree norecurse nosync nounwind memory(none) } 1775; CGSCC: attributes #[[ATTR5]] = { nofree willreturn memory(read) } 1776; CGSCC: attributes #[[ATTR6]] = { nofree willreturn } 1777; CGSCC: attributes #[[ATTR7]] = { nofree nosync willreturn } 1778;. 1779; TUNIT: [[RNG0]] = !{i32 0, i32 10} 1780; TUNIT: [[RNG1]] = !{i32 10, i32 100} 1781; TUNIT: [[RNG2]] = !{i32 200, i32 1091} 1782; TUNIT: [[RNG3]] = !{i32 1, i32 -2147483648} 1783;. 1784; CGSCC: [[RNG0]] = !{i32 0, i32 10} 1785; CGSCC: [[RNG1]] = !{i32 10, i32 100} 1786;. 1787