138 lines · plain
1; RUN: opt < %s -S -passes='loop(loop-flatten),verify' -verify-loop-info -verify-dom-info -verify-scev | FileCheck %s2 3target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"4 5; We should be able to flatten the loops and turn the two geps into one.6; CHECK-LABEL: test17define void @test1(i32 %N, ptr %A) {8entry:9 %cmp3 = icmp ult i32 0, %N10 br i1 %cmp3, label %for.outer.preheader, label %for.end11 12; CHECK-LABEL: for.outer.preheader:13; CHECK: %flatten.tripcount = mul i32 %N, %N14for.outer.preheader:15 br label %for.inner.preheader16 17; CHECK-LABEL: for.inner.preheader:18; CHECK: %flatten.arrayidx = getelementptr inbounds i32, ptr %A, i32 %i19for.inner.preheader:20 %i = phi i32 [ 0, %for.outer.preheader ], [ %inc2, %for.outer ]21 br label %for.inner22 23; CHECK-LABEL: for.inner:24; CHECK: store i32 0, ptr %flatten.arrayidx, align 425; CHECK: br label %for.outer26for.inner:27 %j = phi i32 [ 0, %for.inner.preheader ], [ %inc1, %for.inner ]28 %mul = mul i32 %i, %N29 %gep = getelementptr inbounds i32, ptr %A, i32 %mul30 %arrayidx = getelementptr inbounds i32, ptr %gep, i32 %j31 store i32 0, ptr %arrayidx, align 432 %inc1 = add nuw i32 %j, 133 %cmp2 = icmp ult i32 %inc1, %N34 br i1 %cmp2, label %for.inner, label %for.outer35 36; CHECK-LABEL: for.outer:37; CHECK: %cmp1 = icmp ult i32 %inc2, %flatten.tripcount38for.outer:39 %inc2 = add i32 %i, 140 %cmp1 = icmp ult i32 %inc2, %N41 br i1 %cmp1, label %for.inner.preheader, label %for.end.loopexit42 43for.end.loopexit:44 br label %for.end45 46for.end:47 ret void48}49 50; We can flatten, but the flattened gep has to be inserted after the load it51; depends on.52; CHECK-LABEL: test253define void @test2(i32 %N, ptr %A) {54entry:55 %cmp3 = icmp ult i32 0, %N56 br i1 %cmp3, label %for.outer.preheader, label %for.end57 58; CHECK-LABEL: for.outer.preheader:59; CHECK: %flatten.tripcount = mul i32 %N, %N60for.outer.preheader:61 br label %for.inner.preheader62 63; CHECK-LABEL: for.inner.preheader:64; CHECK-NOT: getelementptr inbounds i32, ptr %ptr, i32 %i65for.inner.preheader:66 %i = phi i32 [ 0, %for.outer.preheader ], [ %inc2, %for.outer ]67 br label %for.inner68 69; CHECK-LABEL: for.inner:70; CHECK: %flatten.arrayidx = getelementptr inbounds i32, ptr %ptr, i32 %i71; CHECK: store i32 0, ptr %flatten.arrayidx, align 472; CHECK: br label %for.outer73for.inner:74 %j = phi i32 [ 0, %for.inner.preheader ], [ %inc1, %for.inner ]75 %ptr = load volatile ptr, ptr %A, align 476 %mul = mul i32 %i, %N77 %gep = getelementptr inbounds i32, ptr %ptr, i32 %mul78 %arrayidx = getelementptr inbounds i32, ptr %gep, i32 %j79 store i32 0, ptr %arrayidx, align 480 %inc1 = add nuw i32 %j, 181 %cmp2 = icmp ult i32 %inc1, %N82 br i1 %cmp2, label %for.inner, label %for.outer83 84; CHECK-LABEL: for.outer:85; CHECK: %cmp1 = icmp ult i32 %inc2, %flatten.tripcount86for.outer:87 %inc2 = add i32 %i, 188 %cmp1 = icmp ult i32 %inc2, %N89 br i1 %cmp1, label %for.inner.preheader, label %for.end.loopexit90 91for.end.loopexit:92 br label %for.end93 94for.end:95 ret void96}97 98; We can't flatten if the gep offset is smaller than the pointer size.99; CHECK-LABEL: test3100define void @test3(i16 %N, ptr %A) {101entry:102 %cmp3 = icmp ult i16 0, %N103 br i1 %cmp3, label %for.outer.preheader, label %for.end104 105for.outer.preheader:106 br label %for.inner.preheader107 108; CHECK-LABEL: for.inner.preheader:109; CHECK-NOT: getelementptr i32, ptr %A, i16 %i110for.inner.preheader:111 %i = phi i16 [ 0, %for.outer.preheader ], [ %inc2, %for.outer ]112 br label %for.inner113 114; CHECK-LABEL: for.inner:115; CHECK-NOT: getelementptr i32, ptr %A, i16 %i116; CHECK: br i1 %cmp2, label %for.inner, label %for.outer117for.inner:118 %j = phi i16 [ 0, %for.inner.preheader ], [ %inc1, %for.inner ]119 %mul = mul i16 %i, %N120 %gep = getelementptr inbounds i32, ptr %A, i16 %mul121 %arrayidx = getelementptr inbounds i32, ptr %gep, i16 %j122 store i32 0, ptr %arrayidx, align 4123 %inc1 = add nuw i16 %j, 1124 %cmp2 = icmp ult i16 %inc1, %N125 br i1 %cmp2, label %for.inner, label %for.outer126 127for.outer:128 %inc2 = add i16 %i, 1129 %cmp1 = icmp ult i16 %inc2, %N130 br i1 %cmp1, label %for.inner.preheader, label %for.end.loopexit131 132for.end.loopexit:133 br label %for.end134 135for.end:136 ret void137}138