1ae978baaSJohn Brawn; RUN: opt < %s -S -passes='loop(loop-flatten),verify' -verify-loop-info -verify-dom-info -verify-scev | FileCheck %s 2ae978baaSJohn Brawn 3ae978baaSJohn Brawntarget datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" 4ae978baaSJohn Brawn 5ae978baaSJohn Brawn; We should be able to flatten the loops and turn the two geps into one. 6ae978baaSJohn Brawn; CHECK-LABEL: test1 7ae978baaSJohn Brawndefine void @test1(i32 %N, ptr %A) { 8ae978baaSJohn Brawnentry: 9ae978baaSJohn Brawn %cmp3 = icmp ult i32 0, %N 10ae978baaSJohn Brawn br i1 %cmp3, label %for.outer.preheader, label %for.end 11ae978baaSJohn Brawn 12ae978baaSJohn Brawn; CHECK-LABEL: for.outer.preheader: 13ae978baaSJohn Brawn; CHECK: %flatten.tripcount = mul i32 %N, %N 14ae978baaSJohn Brawnfor.outer.preheader: 15ae978baaSJohn Brawn br label %for.inner.preheader 16ae978baaSJohn Brawn 17ae978baaSJohn Brawn; CHECK-LABEL: for.inner.preheader: 18*4d1ecf19SAtariDreams; CHECK: %flatten.arrayidx = getelementptr inbounds i32, ptr %A, i32 %i 19ae978baaSJohn Brawnfor.inner.preheader: 20ae978baaSJohn Brawn %i = phi i32 [ 0, %for.outer.preheader ], [ %inc2, %for.outer ] 21ae978baaSJohn Brawn br label %for.inner 22ae978baaSJohn Brawn 23ae978baaSJohn Brawn; CHECK-LABEL: for.inner: 24ae978baaSJohn Brawn; CHECK: store i32 0, ptr %flatten.arrayidx, align 4 25ae978baaSJohn Brawn; CHECK: br label %for.outer 26ae978baaSJohn Brawnfor.inner: 27ae978baaSJohn Brawn %j = phi i32 [ 0, %for.inner.preheader ], [ %inc1, %for.inner ] 28ae978baaSJohn Brawn %mul = mul i32 %i, %N 29ae978baaSJohn Brawn %gep = getelementptr inbounds i32, ptr %A, i32 %mul 30ae978baaSJohn Brawn %arrayidx = getelementptr inbounds i32, ptr %gep, i32 %j 31ae978baaSJohn Brawn store i32 0, ptr %arrayidx, align 4 32ae978baaSJohn Brawn %inc1 = add nuw i32 %j, 1 33ae978baaSJohn Brawn %cmp2 = icmp ult i32 %inc1, %N 34ae978baaSJohn Brawn br i1 %cmp2, label %for.inner, label %for.outer 35ae978baaSJohn Brawn 36ae978baaSJohn Brawn; CHECK-LABEL: for.outer: 37ae978baaSJohn Brawn; CHECK: %cmp1 = icmp ult i32 %inc2, %flatten.tripcount 38ae978baaSJohn Brawnfor.outer: 39ae978baaSJohn Brawn %inc2 = add i32 %i, 1 40ae978baaSJohn Brawn %cmp1 = icmp ult i32 %inc2, %N 41ae978baaSJohn Brawn br i1 %cmp1, label %for.inner.preheader, label %for.end.loopexit 42ae978baaSJohn Brawn 43ae978baaSJohn Brawnfor.end.loopexit: 44ae978baaSJohn Brawn br label %for.end 45ae978baaSJohn Brawn 46ae978baaSJohn Brawnfor.end: 47ae978baaSJohn Brawn ret void 48ae978baaSJohn Brawn} 49ae978baaSJohn Brawn 50ae978baaSJohn Brawn; We can flatten, but the flattened gep has to be inserted after the load it 51ae978baaSJohn Brawn; depends on. 52ae978baaSJohn Brawn; CHECK-LABEL: test2 53ae978baaSJohn Brawndefine void @test2(i32 %N, ptr %A) { 54ae978baaSJohn Brawnentry: 55ae978baaSJohn Brawn %cmp3 = icmp ult i32 0, %N 56ae978baaSJohn Brawn br i1 %cmp3, label %for.outer.preheader, label %for.end 57ae978baaSJohn Brawn 58ae978baaSJohn Brawn; CHECK-LABEL: for.outer.preheader: 59ae978baaSJohn Brawn; CHECK: %flatten.tripcount = mul i32 %N, %N 60ae978baaSJohn Brawnfor.outer.preheader: 61ae978baaSJohn Brawn br label %for.inner.preheader 62ae978baaSJohn Brawn 63ae978baaSJohn Brawn; CHECK-LABEL: for.inner.preheader: 64*4d1ecf19SAtariDreams; CHECK-NOT: getelementptr inbounds i32, ptr %ptr, i32 %i 65ae978baaSJohn Brawnfor.inner.preheader: 66ae978baaSJohn Brawn %i = phi i32 [ 0, %for.outer.preheader ], [ %inc2, %for.outer ] 67ae978baaSJohn Brawn br label %for.inner 68ae978baaSJohn Brawn 69ae978baaSJohn Brawn; CHECK-LABEL: for.inner: 70*4d1ecf19SAtariDreams; CHECK: %flatten.arrayidx = getelementptr inbounds i32, ptr %ptr, i32 %i 71ae978baaSJohn Brawn; CHECK: store i32 0, ptr %flatten.arrayidx, align 4 72ae978baaSJohn Brawn; CHECK: br label %for.outer 73ae978baaSJohn Brawnfor.inner: 74ae978baaSJohn Brawn %j = phi i32 [ 0, %for.inner.preheader ], [ %inc1, %for.inner ] 75ae978baaSJohn Brawn %ptr = load volatile ptr, ptr %A, align 4 76ae978baaSJohn Brawn %mul = mul i32 %i, %N 77ae978baaSJohn Brawn %gep = getelementptr inbounds i32, ptr %ptr, i32 %mul 78ae978baaSJohn Brawn %arrayidx = getelementptr inbounds i32, ptr %gep, i32 %j 79ae978baaSJohn Brawn store i32 0, ptr %arrayidx, align 4 80ae978baaSJohn Brawn %inc1 = add nuw i32 %j, 1 81ae978baaSJohn Brawn %cmp2 = icmp ult i32 %inc1, %N 82ae978baaSJohn Brawn br i1 %cmp2, label %for.inner, label %for.outer 83ae978baaSJohn Brawn 84ae978baaSJohn Brawn; CHECK-LABEL: for.outer: 85ae978baaSJohn Brawn; CHECK: %cmp1 = icmp ult i32 %inc2, %flatten.tripcount 86ae978baaSJohn Brawnfor.outer: 87ae978baaSJohn Brawn %inc2 = add i32 %i, 1 88ae978baaSJohn Brawn %cmp1 = icmp ult i32 %inc2, %N 89ae978baaSJohn Brawn br i1 %cmp1, label %for.inner.preheader, label %for.end.loopexit 90ae978baaSJohn Brawn 91ae978baaSJohn Brawnfor.end.loopexit: 92ae978baaSJohn Brawn br label %for.end 93ae978baaSJohn Brawn 94ae978baaSJohn Brawnfor.end: 95ae978baaSJohn Brawn ret void 96ae978baaSJohn Brawn} 97ae978baaSJohn Brawn 98ae978baaSJohn Brawn; We can't flatten if the gep offset is smaller than the pointer size. 99ae978baaSJohn Brawn; CHECK-LABEL: test3 100ae978baaSJohn Brawndefine void @test3(i16 %N, ptr %A) { 101ae978baaSJohn Brawnentry: 102ae978baaSJohn Brawn %cmp3 = icmp ult i16 0, %N 103ae978baaSJohn Brawn br i1 %cmp3, label %for.outer.preheader, label %for.end 104ae978baaSJohn Brawn 105ae978baaSJohn Brawnfor.outer.preheader: 106ae978baaSJohn Brawn br label %for.inner.preheader 107ae978baaSJohn Brawn 108ae978baaSJohn Brawn; CHECK-LABEL: for.inner.preheader: 109ae978baaSJohn Brawn; CHECK-NOT: getelementptr i32, ptr %A, i16 %i 110ae978baaSJohn Brawnfor.inner.preheader: 111ae978baaSJohn Brawn %i = phi i16 [ 0, %for.outer.preheader ], [ %inc2, %for.outer ] 112ae978baaSJohn Brawn br label %for.inner 113ae978baaSJohn Brawn 114ae978baaSJohn Brawn; CHECK-LABEL: for.inner: 115ae978baaSJohn Brawn; CHECK-NOT: getelementptr i32, ptr %A, i16 %i 116ae978baaSJohn Brawn; CHECK: br i1 %cmp2, label %for.inner, label %for.outer 117ae978baaSJohn Brawnfor.inner: 118ae978baaSJohn Brawn %j = phi i16 [ 0, %for.inner.preheader ], [ %inc1, %for.inner ] 119ae978baaSJohn Brawn %mul = mul i16 %i, %N 120ae978baaSJohn Brawn %gep = getelementptr inbounds i32, ptr %A, i16 %mul 121ae978baaSJohn Brawn %arrayidx = getelementptr inbounds i32, ptr %gep, i16 %j 122ae978baaSJohn Brawn store i32 0, ptr %arrayidx, align 4 123ae978baaSJohn Brawn %inc1 = add nuw i16 %j, 1 124ae978baaSJohn Brawn %cmp2 = icmp ult i16 %inc1, %N 125ae978baaSJohn Brawn br i1 %cmp2, label %for.inner, label %for.outer 126ae978baaSJohn Brawn 127ae978baaSJohn Brawnfor.outer: 128ae978baaSJohn Brawn %inc2 = add i16 %i, 1 129ae978baaSJohn Brawn %cmp1 = icmp ult i16 %inc2, %N 130ae978baaSJohn Brawn br i1 %cmp1, label %for.inner.preheader, label %for.end.loopexit 131ae978baaSJohn Brawn 132ae978baaSJohn Brawnfor.end.loopexit: 133ae978baaSJohn Brawn br label %for.end 134ae978baaSJohn Brawn 135ae978baaSJohn Brawnfor.end: 136ae978baaSJohn Brawn ret void 137ae978baaSJohn Brawn} 138