1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt %s -S -passes='loop(loop-flatten),verify' -verify-loop-info -verify-dom-info -verify-scev -o - | FileCheck %s 3 4target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" 5 6; We need to version the loop as the GEPs are not inbounds 7define void @noinbounds_gep(i32 %N, ptr %A) { 8; CHECK-LABEL: define void @noinbounds_gep( 9; CHECK-SAME: i32 [[N:%.*]], ptr [[A:%.*]]) { 10; CHECK-NEXT: entry: 11; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i32 0, [[N]] 12; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_INNER_PREHEADER_LVER_CHECK:%.*]], label [[FOR_END:%.*]] 13; CHECK: for.inner.preheader.lver.check: 14; CHECK-NEXT: [[FLATTEN_MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[N]], i32 [[N]]) 15; CHECK-NEXT: [[FLATTEN_TRIPCOUNT:%.*]] = extractvalue { i32, i1 } [[FLATTEN_MUL]], 0 16; CHECK-NEXT: [[FLATTEN_OVERFLOW:%.*]] = extractvalue { i32, i1 } [[FLATTEN_MUL]], 1 17; CHECK-NEXT: br i1 [[FLATTEN_OVERFLOW]], label [[FOR_INNER_PREHEADER_PH_LVER_ORIG:%.*]], label [[FOR_INNER_PREHEADER_PH:%.*]] 18; CHECK: for.inner.preheader.ph.lver.orig: 19; CHECK-NEXT: br label [[FOR_INNER_PREHEADER_LVER_ORIG:%.*]] 20; CHECK: for.inner.preheader.lver.orig: 21; CHECK-NEXT: [[I_LVER_ORIG:%.*]] = phi i32 [ 0, [[FOR_INNER_PREHEADER_PH_LVER_ORIG]] ], [ [[INC2_LVER_ORIG:%.*]], [[FOR_OUTER_LVER_ORIG:%.*]] ] 22; CHECK-NEXT: br label [[FOR_INNER_LVER_ORIG:%.*]] 23; CHECK: for.inner.lver.orig: 24; CHECK-NEXT: [[J_LVER_ORIG:%.*]] = phi i32 [ 0, [[FOR_INNER_PREHEADER_LVER_ORIG]] ], [ [[INC1_LVER_ORIG:%.*]], [[FOR_INNER_LVER_ORIG]] ] 25; CHECK-NEXT: [[MUL_LVER_ORIG:%.*]] = mul i32 [[I_LVER_ORIG]], [[N]] 26; CHECK-NEXT: [[GEP_LVER_ORIG:%.*]] = getelementptr i32, ptr [[A]], i32 [[MUL_LVER_ORIG]] 27; CHECK-NEXT: [[ARRAYIDX_LVER_ORIG:%.*]] = getelementptr i32, ptr [[GEP_LVER_ORIG]], i32 [[J_LVER_ORIG]] 28; CHECK-NEXT: store i32 0, ptr [[ARRAYIDX_LVER_ORIG]], align 4 29; CHECK-NEXT: [[INC1_LVER_ORIG]] = add nuw i32 [[J_LVER_ORIG]], 1 30; CHECK-NEXT: [[CMP2_LVER_ORIG:%.*]] = icmp ult i32 [[INC1_LVER_ORIG]], [[N]] 31; CHECK-NEXT: br i1 [[CMP2_LVER_ORIG]], label [[FOR_INNER_LVER_ORIG]], label [[FOR_OUTER_LVER_ORIG]] 32; CHECK: for.outer.lver.orig: 33; CHECK-NEXT: [[INC2_LVER_ORIG]] = add i32 [[I_LVER_ORIG]], 1 34; CHECK-NEXT: [[CMP1_LVER_ORIG:%.*]] = icmp ult i32 [[INC2_LVER_ORIG]], [[N]] 35; CHECK-NEXT: br i1 [[CMP1_LVER_ORIG]], label [[FOR_INNER_PREHEADER_LVER_ORIG]], label [[FOR_END_LOOPEXIT_LOOPEXIT:%.*]] 36; CHECK: for.inner.preheader.ph: 37; CHECK-NEXT: br label [[FOR_INNER_PREHEADER:%.*]] 38; CHECK: for.inner.preheader: 39; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[FOR_INNER_PREHEADER_PH]] ], [ [[INC2:%.*]], [[FOR_OUTER:%.*]] ] 40; CHECK-NEXT: [[FLATTEN_ARRAYIDX:%.*]] = getelementptr i32, ptr [[A]], i32 [[I]] 41; CHECK-NEXT: br label [[FOR_INNER:%.*]] 42; CHECK: for.inner: 43; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[FOR_INNER_PREHEADER]] ] 44; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I]], [[N]] 45; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[A]], i32 [[MUL]] 46; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[GEP]], i32 [[J]] 47; CHECK-NEXT: store i32 0, ptr [[FLATTEN_ARRAYIDX]], align 4 48; CHECK-NEXT: [[INC1:%.*]] = add nuw i32 [[J]], 1 49; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[INC1]], [[N]] 50; CHECK-NEXT: br label [[FOR_OUTER]] 51; CHECK: for.outer: 52; CHECK-NEXT: [[INC2]] = add i32 [[I]], 1 53; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[INC2]], [[FLATTEN_TRIPCOUNT]] 54; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_INNER_PREHEADER]], label [[FOR_END_LOOPEXIT_LOOPEXIT1:%.*]] 55; CHECK: for.end.loopexit.loopexit: 56; CHECK-NEXT: br label [[FOR_END_LOOPEXIT:%.*]] 57; CHECK: for.end.loopexit.loopexit1: 58; CHECK-NEXT: br label [[FOR_END_LOOPEXIT]] 59; CHECK: for.end.loopexit: 60; CHECK-NEXT: br label [[FOR_END]] 61; CHECK: for.end: 62; CHECK-NEXT: ret void 63; 64entry: 65 %cmp3 = icmp ult i32 0, %N 66 br i1 %cmp3, label %for.outer.preheader, label %for.end 67 68for.outer.preheader: 69 br label %for.inner.preheader 70 71for.inner.preheader: 72 %i = phi i32 [ 0, %for.outer.preheader ], [ %inc2, %for.outer ] 73 br label %for.inner 74 75for.inner: 76 %j = phi i32 [ 0, %for.inner.preheader ], [ %inc1, %for.inner ] 77 %mul = mul i32 %i, %N 78 %gep = getelementptr i32, ptr %A, i32 %mul 79 %arrayidx = getelementptr i32, ptr %gep, i32 %j 80 store i32 0, ptr %arrayidx, align 4 81 %inc1 = add nuw i32 %j, 1 82 %cmp2 = icmp ult i32 %inc1, %N 83 br i1 %cmp2, label %for.inner, label %for.outer 84 85for.outer: 86 %inc2 = add i32 %i, 1 87 %cmp1 = icmp ult i32 %inc2, %N 88 br i1 %cmp1, label %for.inner.preheader, label %for.end.loopexit 89 90for.end.loopexit: 91 br label %for.end 92 93for.end: 94 ret void 95} 96 97; We shouldn't version the loop here as the multiply would use an illegal type. 98define void @noinbounds_gep_too_large_mul(i64 %N, ptr %A) { 99; CHECK-LABEL: define void @noinbounds_gep_too_large_mul( 100; CHECK-SAME: i64 [[N:%.*]], ptr [[A:%.*]]) { 101; CHECK-NEXT: entry: 102; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i64 0, [[N]] 103; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_OUTER_PREHEADER:%.*]], label [[FOR_END:%.*]] 104; CHECK: for.outer.preheader: 105; CHECK-NEXT: br label [[FOR_INNER_PREHEADER:%.*]] 106; CHECK: for.inner.preheader: 107; CHECK-NEXT: [[I:%.*]] = phi i64 [ 0, [[FOR_OUTER_PREHEADER]] ], [ [[INC2:%.*]], [[FOR_OUTER:%.*]] ] 108; CHECK-NEXT: br label [[FOR_INNER:%.*]] 109; CHECK: for.inner: 110; CHECK-NEXT: [[J:%.*]] = phi i64 [ 0, [[FOR_INNER_PREHEADER]] ], [ [[INC1:%.*]], [[FOR_INNER]] ] 111; CHECK-NEXT: [[MUL:%.*]] = mul i64 [[I]], [[N]] 112; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[A]], i64 [[MUL]] 113; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[GEP]], i64 [[J]] 114; CHECK-NEXT: store i32 0, ptr [[ARRAYIDX]], align 4 115; CHECK-NEXT: [[INC1]] = add nuw i64 [[J]], 1 116; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[INC1]], [[N]] 117; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_INNER]], label [[FOR_OUTER]] 118; CHECK: for.outer: 119; CHECK-NEXT: [[INC2]] = add i64 [[I]], 1 120; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[INC2]], [[N]] 121; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_INNER_PREHEADER]], label [[FOR_END_LOOPEXIT:%.*]] 122; CHECK: for.end.loopexit: 123; CHECK-NEXT: br label [[FOR_END]] 124; CHECK: for.end: 125; CHECK-NEXT: ret void 126; 127entry: 128 %cmp3 = icmp ult i64 0, %N 129 br i1 %cmp3, label %for.outer.preheader, label %for.end 130 131for.outer.preheader: 132 br label %for.inner.preheader 133 134for.inner.preheader: 135 %i = phi i64 [ 0, %for.outer.preheader ], [ %inc2, %for.outer ] 136 br label %for.inner 137 138for.inner: 139 %j = phi i64 [ 0, %for.inner.preheader ], [ %inc1, %for.inner ] 140 %mul = mul i64 %i, %N 141 %gep = getelementptr i32, ptr %A, i64 %mul 142 %arrayidx = getelementptr i32, ptr %gep, i64 %j 143 store i32 0, ptr %arrayidx, align 4 144 %inc1 = add nuw i64 %j, 1 145 %cmp2 = icmp ult i64 %inc1, %N 146 br i1 %cmp2, label %for.inner, label %for.outer 147 148for.outer: 149 %inc2 = add i64 %i, 1 150 %cmp1 = icmp ult i64 %inc2, %N 151 br i1 %cmp1, label %for.inner.preheader, label %for.end.loopexit 152 153for.end.loopexit: 154 br label %for.end 155 156for.end: 157 ret void 158} 159 160; A 3d loop corresponding to: 161; 162; for (int k = 0; k < N; ++k) 163; for (int i = 0; i < N; ++i) 164; for (int j = 0; j < M; ++j) 165; f(&A[i*M+j]); 166; 167define void @d3_2(ptr %A, i32 %N, i32 %M) { 168; CHECK-LABEL: define void @d3_2( 169; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]], i32 [[M:%.*]]) { 170; CHECK-NEXT: entry: 171; CHECK-NEXT: [[CMP30:%.*]] = icmp sgt i32 [[N]], 0 172; CHECK-NEXT: br i1 [[CMP30]], label [[FOR_COND1_PREHEADER_LR_PH:%.*]], label [[FOR_COND_CLEANUP:%.*]] 173; CHECK: for.cond1.preheader.lr.ph: 174; CHECK-NEXT: [[CMP625:%.*]] = icmp sgt i32 [[M]], 0 175; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_US:%.*]] 176; CHECK: for.cond1.preheader.us: 177; CHECK-NEXT: [[K_031_US:%.*]] = phi i32 [ 0, [[FOR_COND1_PREHEADER_LR_PH]] ], [ [[INC13_US:%.*]], [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US:%.*]] ] 178; CHECK-NEXT: br i1 [[CMP625]], label [[FOR_COND5_PREHEADER_US_US_LVER_CHECK:%.*]], label [[FOR_COND5_PREHEADER_US43_PREHEADER:%.*]] 179; CHECK: for.cond5.preheader.us43.preheader: 180; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_LOOPEXIT50:%.*]] 181; CHECK: for.cond5.preheader.us.us.lver.check: 182; CHECK-NEXT: [[FLATTEN_MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[N]], i32 [[M]]) 183; CHECK-NEXT: [[FLATTEN_TRIPCOUNT:%.*]] = extractvalue { i32, i1 } [[FLATTEN_MUL]], 0 184; CHECK-NEXT: [[FLATTEN_OVERFLOW:%.*]] = extractvalue { i32, i1 } [[FLATTEN_MUL]], 1 185; CHECK-NEXT: br i1 [[FLATTEN_OVERFLOW]], label [[FOR_COND5_PREHEADER_US_US_PH_LVER_ORIG:%.*]], label [[FOR_COND5_PREHEADER_US_US_PH:%.*]] 186; CHECK: for.cond5.preheader.us.us.ph.lver.orig: 187; CHECK-NEXT: br label [[FOR_COND5_PREHEADER_US_US_LVER_ORIG:%.*]] 188; CHECK: for.cond5.preheader.us.us.lver.orig: 189; CHECK-NEXT: [[I_028_US_US_LVER_ORIG:%.*]] = phi i32 [ [[INC10_US_US_LVER_ORIG:%.*]], [[FOR_COND5_FOR_COND_CLEANUP7_CRIT_EDGE_US_US_LVER_ORIG:%.*]] ], [ 0, [[FOR_COND5_PREHEADER_US_US_PH_LVER_ORIG]] ] 190; CHECK-NEXT: [[MUL_US_US_LVER_ORIG:%.*]] = mul nsw i32 [[I_028_US_US_LVER_ORIG]], [[M]] 191; CHECK-NEXT: br label [[FOR_BODY8_US_US_LVER_ORIG:%.*]] 192; CHECK: for.body8.us.us.lver.orig: 193; CHECK-NEXT: [[J_026_US_US_LVER_ORIG:%.*]] = phi i32 [ 0, [[FOR_COND5_PREHEADER_US_US_LVER_ORIG]] ], [ [[INC_US_US_LVER_ORIG:%.*]], [[FOR_BODY8_US_US_LVER_ORIG]] ] 194; CHECK-NEXT: [[ADD_US_US_LVER_ORIG:%.*]] = add nsw i32 [[J_026_US_US_LVER_ORIG]], [[MUL_US_US_LVER_ORIG]] 195; CHECK-NEXT: [[IDXPROM_US_US_LVER_ORIG:%.*]] = sext i32 [[ADD_US_US_LVER_ORIG]] to i64 196; CHECK-NEXT: [[ARRAYIDX_US_US_LVER_ORIG:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IDXPROM_US_US_LVER_ORIG]] 197; CHECK-NEXT: tail call void @f(ptr [[ARRAYIDX_US_US_LVER_ORIG]]) 198; CHECK-NEXT: [[INC_US_US_LVER_ORIG]] = add nuw nsw i32 [[J_026_US_US_LVER_ORIG]], 1 199; CHECK-NEXT: [[EXITCOND_LVER_ORIG:%.*]] = icmp ne i32 [[INC_US_US_LVER_ORIG]], [[M]] 200; CHECK-NEXT: br i1 [[EXITCOND_LVER_ORIG]], label [[FOR_BODY8_US_US_LVER_ORIG]], label [[FOR_COND5_FOR_COND_CLEANUP7_CRIT_EDGE_US_US_LVER_ORIG]] 201; CHECK: for.cond5.for.cond.cleanup7_crit_edge.us.us.lver.orig: 202; CHECK-NEXT: [[INC10_US_US_LVER_ORIG]] = add nuw nsw i32 [[I_028_US_US_LVER_ORIG]], 1 203; CHECK-NEXT: [[EXITCOND51_LVER_ORIG:%.*]] = icmp ne i32 [[INC10_US_US_LVER_ORIG]], [[N]] 204; CHECK-NEXT: br i1 [[EXITCOND51_LVER_ORIG]], label [[FOR_COND5_PREHEADER_US_US_LVER_ORIG]], label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_LOOPEXIT_LOOPEXIT:%.*]] 205; CHECK: for.cond5.preheader.us.us.ph: 206; CHECK-NEXT: br label [[FOR_COND5_PREHEADER_US_US:%.*]] 207; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us.loopexit.loopexit: 208; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_LOOPEXIT:%.*]] 209; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us.loopexit.loopexit1: 210; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_LOOPEXIT]] 211; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us.loopexit: 212; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]] 213; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us.loopexit50: 214; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]] 215; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us: 216; CHECK-NEXT: [[INC13_US]] = add nuw nsw i32 [[K_031_US]], 1 217; CHECK-NEXT: [[EXITCOND52:%.*]] = icmp ne i32 [[INC13_US]], [[N]] 218; CHECK-NEXT: br i1 [[EXITCOND52]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] 219; CHECK: for.cond5.preheader.us.us: 220; CHECK-NEXT: [[I_028_US_US:%.*]] = phi i32 [ [[INC10_US_US:%.*]], [[FOR_COND5_FOR_COND_CLEANUP7_CRIT_EDGE_US_US:%.*]] ], [ 0, [[FOR_COND5_PREHEADER_US_US_PH]] ] 221; CHECK-NEXT: [[MUL_US_US:%.*]] = mul nsw i32 [[I_028_US_US]], [[M]] 222; CHECK-NEXT: br label [[FOR_BODY8_US_US:%.*]] 223; CHECK: for.cond5.for.cond.cleanup7_crit_edge.us.us: 224; CHECK-NEXT: [[INC10_US_US]] = add nuw nsw i32 [[I_028_US_US]], 1 225; CHECK-NEXT: [[EXITCOND51:%.*]] = icmp ne i32 [[INC10_US_US]], [[FLATTEN_TRIPCOUNT]] 226; CHECK-NEXT: br i1 [[EXITCOND51]], label [[FOR_COND5_PREHEADER_US_US]], label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_LOOPEXIT_LOOPEXIT1:%.*]] 227; CHECK: for.body8.us.us: 228; CHECK-NEXT: [[J_026_US_US:%.*]] = phi i32 [ 0, [[FOR_COND5_PREHEADER_US_US]] ] 229; CHECK-NEXT: [[ADD_US_US:%.*]] = add nsw i32 [[J_026_US_US]], [[MUL_US_US]] 230; CHECK-NEXT: [[IDXPROM_US_US:%.*]] = sext i32 [[I_028_US_US]] to i64 231; CHECK-NEXT: [[ARRAYIDX_US_US:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IDXPROM_US_US]] 232; CHECK-NEXT: tail call void @f(ptr [[ARRAYIDX_US_US]]) 233; CHECK-NEXT: [[INC_US_US:%.*]] = add nuw nsw i32 [[J_026_US_US]], 1 234; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INC_US_US]], [[M]] 235; CHECK-NEXT: br label [[FOR_COND5_FOR_COND_CLEANUP7_CRIT_EDGE_US_US]] 236; CHECK: for.cond.cleanup.loopexit: 237; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 238; CHECK: for.cond.cleanup: 239; CHECK-NEXT: ret void 240; 241entry: 242 %cmp30 = icmp sgt i32 %N, 0 243 br i1 %cmp30, label %for.cond1.preheader.lr.ph, label %for.cond.cleanup 244 245for.cond1.preheader.lr.ph: 246 %cmp625 = icmp sgt i32 %M, 0 247 br label %for.cond1.preheader.us 248 249for.cond1.preheader.us: 250 %k.031.us = phi i32 [ 0, %for.cond1.preheader.lr.ph ], [ %inc13.us, %for.cond1.for.cond.cleanup3_crit_edge.us ] 251 br i1 %cmp625, label %for.cond5.preheader.us.us.preheader, label %for.cond5.preheader.us43.preheader 252 253for.cond5.preheader.us43.preheader: 254 br label %for.cond1.for.cond.cleanup3_crit_edge.us.loopexit50 255 256for.cond5.preheader.us.us.preheader: 257 br label %for.cond5.preheader.us.us 258 259for.cond1.for.cond.cleanup3_crit_edge.us.loopexit: 260 br label %for.cond1.for.cond.cleanup3_crit_edge.us 261 262for.cond1.for.cond.cleanup3_crit_edge.us.loopexit50: 263 br label %for.cond1.for.cond.cleanup3_crit_edge.us 264 265for.cond1.for.cond.cleanup3_crit_edge.us: 266 %inc13.us = add nuw nsw i32 %k.031.us, 1 267 %exitcond52 = icmp ne i32 %inc13.us, %N 268 br i1 %exitcond52, label %for.cond1.preheader.us, label %for.cond.cleanup.loopexit 269 270for.cond5.preheader.us.us: 271 %i.028.us.us = phi i32 [ %inc10.us.us, %for.cond5.for.cond.cleanup7_crit_edge.us.us ], [ 0, %for.cond5.preheader.us.us.preheader ] 272 %mul.us.us = mul nsw i32 %i.028.us.us, %M 273 br label %for.body8.us.us 274 275for.cond5.for.cond.cleanup7_crit_edge.us.us: 276 %inc10.us.us = add nuw nsw i32 %i.028.us.us, 1 277 %exitcond51 = icmp ne i32 %inc10.us.us, %N 278 br i1 %exitcond51, label %for.cond5.preheader.us.us, label %for.cond1.for.cond.cleanup3_crit_edge.us.loopexit 279 280for.body8.us.us: 281 %j.026.us.us = phi i32 [ 0, %for.cond5.preheader.us.us ], [ %inc.us.us, %for.body8.us.us ] 282 %add.us.us = add nsw i32 %j.026.us.us, %mul.us.us 283 %idxprom.us.us = sext i32 %add.us.us to i64 284 %arrayidx.us.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us.us 285 tail call void @f(ptr %arrayidx.us.us) #2 286 %inc.us.us = add nuw nsw i32 %j.026.us.us, 1 287 %exitcond = icmp ne i32 %inc.us.us, %M 288 br i1 %exitcond, label %for.body8.us.us, label %for.cond5.for.cond.cleanup7_crit_edge.us.us 289 290for.cond.cleanup.loopexit: 291 br label %for.cond.cleanup 292 293for.cond.cleanup: 294 ret void 295} 296 297; GEP doesn't dominate the loop latch so we need to check if N*M will overflow. 298@first = global i32 1, align 4 299@a = external global [0 x i8], align 1 300define void @overflow(i32 %lim, ptr %a) { 301; CHECK-LABEL: define void @overflow( 302; CHECK-SAME: i32 [[LIM:%.*]], ptr [[A:%.*]]) { 303; CHECK-NEXT: entry: 304; CHECK-NEXT: [[CMP17_NOT:%.*]] = icmp eq i32 [[LIM]], 0 305; CHECK-NEXT: br i1 [[CMP17_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_COND1_PREHEADER_LVER_CHECK:%.*]] 306; CHECK: for.cond1.preheader.lver.check: 307; CHECK-NEXT: [[FLATTEN_MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[LIM]], i32 100000) 308; CHECK-NEXT: [[FLATTEN_TRIPCOUNT:%.*]] = extractvalue { i32, i1 } [[FLATTEN_MUL]], 0 309; CHECK-NEXT: [[FLATTEN_OVERFLOW:%.*]] = extractvalue { i32, i1 } [[FLATTEN_MUL]], 1 310; CHECK-NEXT: br i1 [[FLATTEN_OVERFLOW]], label [[FOR_COND1_PREHEADER_PH_LVER_ORIG:%.*]], label [[FOR_COND1_PREHEADER_PH:%.*]] 311; CHECK: for.cond1.preheader.ph.lver.orig: 312; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_LVER_ORIG:%.*]] 313; CHECK: for.cond1.preheader.lver.orig: 314; CHECK-NEXT: [[I_018_LVER_ORIG:%.*]] = phi i32 [ [[INC6_LVER_ORIG:%.*]], [[FOR_COND_CLEANUP3_LVER_ORIG:%.*]] ], [ 0, [[FOR_COND1_PREHEADER_PH_LVER_ORIG]] ] 315; CHECK-NEXT: [[MUL_LVER_ORIG:%.*]] = mul i32 [[I_018_LVER_ORIG]], 100000 316; CHECK-NEXT: br label [[FOR_BODY4_LVER_ORIG:%.*]] 317; CHECK: for.body4.lver.orig: 318; CHECK-NEXT: [[J_016_LVER_ORIG:%.*]] = phi i32 [ 0, [[FOR_COND1_PREHEADER_LVER_ORIG]] ], [ [[INC_LVER_ORIG:%.*]], [[IF_END_LVER_ORIG:%.*]] ] 319; CHECK-NEXT: [[ADD_LVER_ORIG:%.*]] = add i32 [[J_016_LVER_ORIG]], [[MUL_LVER_ORIG]] 320; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @first, align 4 321; CHECK-NEXT: [[TOBOOL_NOT_LVER_ORIG:%.*]] = icmp eq i32 [[TMP0]], 0 322; CHECK-NEXT: br i1 [[TOBOOL_NOT_LVER_ORIG]], label [[IF_END_LVER_ORIG]], label [[IF_THEN_LVER_ORIG:%.*]] 323; CHECK: if.then.lver.orig: 324; CHECK-NEXT: [[ARRAYIDX_LVER_ORIG:%.*]] = getelementptr inbounds [0 x i8], ptr @a, i32 0, i32 [[ADD_LVER_ORIG]] 325; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX_LVER_ORIG]], align 1 326; CHECK-NEXT: tail call void asm sideeffect "", "r"(i8 [[TMP1]]) 327; CHECK-NEXT: store i32 0, ptr @first, align 4 328; CHECK-NEXT: br label [[IF_END_LVER_ORIG]] 329; CHECK: if.end.lver.orig: 330; CHECK-NEXT: tail call void asm sideeffect "", "r"(i32 [[ADD_LVER_ORIG]]) 331; CHECK-NEXT: [[INC_LVER_ORIG]] = add nuw nsw i32 [[J_016_LVER_ORIG]], 1 332; CHECK-NEXT: [[CMP2_LVER_ORIG:%.*]] = icmp ult i32 [[J_016_LVER_ORIG]], 99999 333; CHECK-NEXT: br i1 [[CMP2_LVER_ORIG]], label [[FOR_BODY4_LVER_ORIG]], label [[FOR_COND_CLEANUP3_LVER_ORIG]] 334; CHECK: for.cond.cleanup3.lver.orig: 335; CHECK-NEXT: [[INC6_LVER_ORIG]] = add i32 [[I_018_LVER_ORIG]], 1 336; CHECK-NEXT: [[CMP_LVER_ORIG:%.*]] = icmp ult i32 [[INC6_LVER_ORIG]], [[LIM]] 337; CHECK-NEXT: br i1 [[CMP_LVER_ORIG]], label [[FOR_COND1_PREHEADER_LVER_ORIG]], label [[FOR_COND_CLEANUP_LOOPEXIT_LOOPEXIT:%.*]] 338; CHECK: for.cond1.preheader.ph: 339; CHECK-NEXT: br label [[FOR_COND1_PREHEADER:%.*]] 340; CHECK: for.cond1.preheader: 341; CHECK-NEXT: [[I_018:%.*]] = phi i32 [ [[INC6:%.*]], [[FOR_COND_CLEANUP3:%.*]] ], [ 0, [[FOR_COND1_PREHEADER_PH]] ] 342; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I_018]], 100000 343; CHECK-NEXT: br label [[FOR_BODY4:%.*]] 344; CHECK: for.cond.cleanup.loopexit.loopexit: 345; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] 346; CHECK: for.cond.cleanup.loopexit.loopexit1: 347; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT]] 348; CHECK: for.cond.cleanup.loopexit: 349; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 350; CHECK: for.cond.cleanup: 351; CHECK-NEXT: ret void 352; CHECK: for.cond.cleanup3: 353; CHECK-NEXT: [[INC6]] = add i32 [[I_018]], 1 354; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[INC6]], [[FLATTEN_TRIPCOUNT]] 355; CHECK-NEXT: br i1 [[CMP]], label [[FOR_COND1_PREHEADER]], label [[FOR_COND_CLEANUP_LOOPEXIT_LOOPEXIT1:%.*]] 356; CHECK: for.body4: 357; CHECK-NEXT: [[J_016:%.*]] = phi i32 [ 0, [[FOR_COND1_PREHEADER]] ] 358; CHECK-NEXT: [[ADD:%.*]] = add i32 [[J_016]], [[MUL]] 359; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr @first, align 4 360; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[TMP2]], 0 361; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] 362; CHECK: if.then: 363; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr @a, i32 0, i32 [[I_018]] 364; CHECK-NEXT: [[TMP3:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 365; CHECK-NEXT: tail call void asm sideeffect "", "r"(i8 [[TMP3]]) 366; CHECK-NEXT: store i32 0, ptr @first, align 4 367; CHECK-NEXT: br label [[IF_END]] 368; CHECK: if.end: 369; CHECK-NEXT: tail call void asm sideeffect "", "r"(i32 [[I_018]]) 370; CHECK-NEXT: [[INC:%.*]] = add nuw nsw i32 [[J_016]], 1 371; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[J_016]], 99999 372; CHECK-NEXT: br label [[FOR_COND_CLEANUP3]] 373; 374entry: 375 %cmp17.not = icmp eq i32 %lim, 0 376 br i1 %cmp17.not, label %for.cond.cleanup, label %for.cond1.preheader.preheader 377 378for.cond1.preheader.preheader: 379 br label %for.cond1.preheader 380 381for.cond1.preheader: 382 %i.018 = phi i32 [ %inc6, %for.cond.cleanup3 ], [ 0, %for.cond1.preheader.preheader ] 383 %mul = mul i32 %i.018, 100000 384 br label %for.body4 385 386for.cond.cleanup.loopexit: 387 br label %for.cond.cleanup 388 389for.cond.cleanup: 390 ret void 391 392for.cond.cleanup3: 393 %inc6 = add i32 %i.018, 1 394 %cmp = icmp ult i32 %inc6, %lim 395 br i1 %cmp, label %for.cond1.preheader, label %for.cond.cleanup.loopexit 396 397for.body4: 398 %j.016 = phi i32 [ 0, %for.cond1.preheader ], [ %inc, %if.end ] 399 %add = add i32 %j.016, %mul 400 %0 = load i32, ptr @first, align 4 401 %tobool.not = icmp eq i32 %0, 0 402 br i1 %tobool.not, label %if.end, label %if.then 403 404if.then: 405 %arrayidx = getelementptr inbounds [0 x i8], ptr @a, i32 0, i32 %add 406 %1 = load i8, ptr %arrayidx, align 1 407 tail call void asm sideeffect "", "r"(i8 %1) 408 store i32 0, ptr @first, align 4 409 br label %if.end 410 411if.end: 412 tail call void asm sideeffect "", "r"(i32 %add) 413 %inc = add nuw nsw i32 %j.016, 1 414 %cmp2 = icmp ult i32 %j.016, 99999 415 br i1 %cmp2, label %for.body4, label %for.cond.cleanup3 416} 417 418declare dso_local void @f(ptr) 419