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