645 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; CHECK-LABEL: test16; Simple loop where the IV's is constant7define i32 @test1(i32 %val, ptr nocapture %A) {8entry:9 br label %for.body10; CHECK: entry:11; CHECK: %flatten.tripcount = mul i32 20, 1012; CHECK: br label %for.body13 14for.body: ; preds = %entry, %for.inc615 %i.018 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]16 %mul = mul nuw nsw i32 %i.018, 2017 br label %for.body318; CHECK: for.body:19; CHECK: %i.018 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]20; CHECK: %mul = mul nuw nsw i32 %i.018, 2021; CHECK: br label %for.body322 23for.body3: ; preds = %for.body, %for.body324 %j.017 = phi i32 [ 0, %for.body ], [ %inc, %for.body3 ]25 %add = add nuw nsw i32 %j.017, %mul26 %arrayidx = getelementptr inbounds i16, ptr %A, i32 %add27 %0 = load i16, ptr %arrayidx, align 228 %conv16 = zext i16 %0 to i3229 %add4 = add i32 %conv16, %val30 %conv5 = trunc i32 %add4 to i1631 store i16 %conv5, ptr %arrayidx, align 232 %inc = add nuw nsw i32 %j.017, 133 %exitcond = icmp ne i32 %inc, 2034 br i1 %exitcond, label %for.body3, label %for.inc635; CHECK: for.body3:36; CHECK: %j.017 = phi i32 [ 0, %for.body ]37; CHECK: %add = add nuw nsw i32 %j.017, %mul38; CHECK: %arrayidx = getelementptr inbounds i16, ptr %A, i32 %i.01839; CHECK: %0 = load i16, ptr %arrayidx, align 240; CHECK: %conv16 = zext i16 %0 to i3241; CHECK: %add4 = add i32 %conv16, %val42; CHECK: %conv5 = trunc i32 %add4 to i1643; CHECK: store i16 %conv5, ptr %arrayidx, align 244; CHECK: %inc = add nuw nsw i32 %j.017, 145; CHECK: %exitcond = icmp ne i32 %inc, 2046; CHECK: br label %for.inc647 48for.inc6: ; preds = %for.body349 %inc7 = add nuw nsw i32 %i.018, 150 %exitcond19 = icmp ne i32 %inc7, 1051 br i1 %exitcond19, label %for.body, label %for.end852; CHECK: for.inc6:53; CHECK: %inc7 = add nuw nsw i32 %i.018, 154; CHECK: %exitcond19 = icmp ne i32 %inc7, %flatten.tripcount55; CHECK: br i1 %exitcond19, label %for.body, label %for.end856 57for.end8: ; preds = %for.inc658 ret i32 1059}60 61 62; CHECK-LABEL: test263; Same as above but non constant IV (which still cannot overflow)64define i32 @test2(i8 zeroext %I, i32 %val, ptr nocapture %A) {65entry:66 %conv = zext i8 %I to i3267 %cmp26 = icmp eq i8 %I, 068 br i1 %cmp26, label %for.end13, label %for.body.lr.ph.split.us69 70for.body.lr.ph.split.us: ; preds = %entry71 br label %for.body.us72; CHECK: for.body.lr.ph.split.us:73; CHECK: %flatten.tripcount = mul i32 %conv, %conv74; CHECK: br label %for.body.us75 76for.body.us: ; preds = %for.cond2.for.inc11_crit_edge.us, %for.body.lr.ph.split.us77 %i.027.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc12.us, %for.cond2.for.inc11_crit_edge.us ]78 %mul.us = mul nuw nsw i32 %i.027.us, %conv79 br label %for.body6.us80; CHECK: for.body.us:81; CHECK: %i.027.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc12.us, %for.cond2.for.inc11_crit_edge.us ]82; CHECK: %mul.us = mul nuw nsw i32 %i.027.us, %conv83; CHECK: br label %for.body6.us84 85for.body6.us: ; preds = %for.body.us, %for.body6.us86 %j.025.us = phi i32 [ 0, %for.body.us ], [ %inc.us, %for.body6.us ]87 %add.us = add nuw nsw i32 %j.025.us, %mul.us88 %arrayidx.us = getelementptr inbounds i16, ptr %A, i32 %add.us89 %0 = load i16, ptr %arrayidx.us, align 290 %conv823.us = zext i16 %0 to i3291 %add9.us = add i32 %conv823.us, %val92 %conv10.us = trunc i32 %add9.us to i1693 store i16 %conv10.us, ptr %arrayidx.us, align 294 %inc.us = add nuw nsw i32 %j.025.us, 195 %exitcond = icmp ne i32 %inc.us, %conv96 br i1 %exitcond, label %for.body6.us, label %for.cond2.for.inc11_crit_edge.us97; CHECK: for.body6.us:98; CHECK: %j.025.us = phi i32 [ 0, %for.body.us ]99; CHECK: %add.us = add nuw nsw i32 %j.025.us, %mul.us100; CHECK: %arrayidx.us = getelementptr inbounds i16, ptr %A, i32 %i.027.us101; CHECK: %0 = load i16, ptr %arrayidx.us, align 2102; CHECK: %conv823.us = zext i16 %0 to i32103; CHECK: %add9.us = add i32 %conv823.us, %val104; CHECK: %conv10.us = trunc i32 %add9.us to i16105; CHECK: store i16 %conv10.us, ptr %arrayidx.us, align 2106; CHECK: %inc.us = add nuw nsw i32 %j.025.us, 1107; CHECK: %exitcond = icmp ne i32 %inc.us, %conv108; CHECK: br label %for.cond2.for.inc11_crit_edge.us109 110for.cond2.for.inc11_crit_edge.us: ; preds = %for.body6.us111 %inc12.us = add nuw nsw i32 %i.027.us, 1112 %exitcond28 = icmp ne i32 %inc12.us, %conv113 br i1 %exitcond28, label %for.body.us, label %for.end13.loopexit114; CHECK: for.cond2.for.inc11_crit_edge.us: ; preds = %for.body6.us115; CHECK: %inc12.us = add nuw nsw i32 %i.027.us, 1116; CHECK: %exitcond28 = icmp ne i32 %inc12.us, %flatten.tripcount117; CHECK: br i1 %exitcond28, label %for.body.us, label %for.end13.loopexit118 119for.end13.loopexit: ; preds = %for.cond2.for.inc11_crit_edge.us120 br label %for.end13121 122for.end13: ; preds = %for.end13.loopexit, %entry123 %i.0.lcssa = phi i32 [ 0, %entry ], [ %conv, %for.end13.loopexit ]124 ret i32 %i.0.lcssa125}126 127 128; CHECK-LABEL: test3129; Same as above, uses load to determine it can't overflow130define i32 @test3(i32 %N, i32 %val, ptr nocapture %A) local_unnamed_addr #0 {131entry:132 %cmp21 = icmp eq i32 %N, 0133 br i1 %cmp21, label %for.end8, label %for.body.lr.ph.split.us134 135for.body.lr.ph.split.us: ; preds = %entry136 br label %for.body.us137; CHECK: for.body.lr.ph.split.us:138; CHECK: %flatten.tripcount = mul i32 %N, %N139; CHECK: br label %for.body.us140 141for.body.us: ; preds = %for.cond1.for.inc6_crit_edge.us, %for.body.lr.ph.split.us142 %i.022.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc7.us, %for.cond1.for.inc6_crit_edge.us ]143 %mul.us = mul i32 %i.022.us, %N144 br label %for.body3.us145; CHECK: for.body.us:146; CHECK: %i.022.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc7.us, %for.cond1.for.inc6_crit_edge.us ]147; CHECK: %mul.us = mul i32 %i.022.us, %N148; CHECK: br label %for.body3.us149 150for.body3.us: ; preds = %for.body.us, %for.body3.us151 %j.020.us = phi i32 [ 0, %for.body.us ], [ %inc.us, %for.body3.us ]152 %add.us = add i32 %j.020.us, %mul.us153 %arrayidx.us = getelementptr inbounds i16, ptr %A, i32 %add.us154 %0 = load i16, ptr %arrayidx.us, align 2155 %conv18.us = zext i16 %0 to i32156 %add4.us = add i32 %conv18.us, %val157 %conv5.us = trunc i32 %add4.us to i16158 store i16 %conv5.us, ptr %arrayidx.us, align 2159 %inc.us = add nuw i32 %j.020.us, 1160 %exitcond = icmp ne i32 %inc.us, %N161 br i1 %exitcond, label %for.body3.us, label %for.cond1.for.inc6_crit_edge.us162; CHECK: for.body3.us:163; CHECK: %j.020.us = phi i32 [ 0, %for.body.us ]164; CHECK: %add.us = add i32 %j.020.us, %mul.us165; CHECK: %arrayidx.us = getelementptr inbounds i16, ptr %A, i32 %i.022.us166; CHECK: %0 = load i16, ptr %arrayidx.us, align 2167; CHECK: %conv18.us = zext i16 %0 to i32168; CHECK: %add4.us = add i32 %conv18.us, %val169; CHECK: %conv5.us = trunc i32 %add4.us to i16170; CHECK: store i16 %conv5.us, ptr %arrayidx.us, align 2171; CHECK: %inc.us = add nuw i32 %j.020.us, 1172; CHECK: %exitcond = icmp ne i32 %inc.us, %N173; CHECK: br label %for.cond1.for.inc6_crit_edge.us174 175for.cond1.for.inc6_crit_edge.us: ; preds = %for.body3.us176 %inc7.us = add nuw i32 %i.022.us, 1177 %exitcond23 = icmp ne i32 %inc7.us, %N178 br i1 %exitcond23, label %for.body.us, label %for.end8.loopexit179; CHECK: for.cond1.for.inc6_crit_edge.us:180; CHECK: %inc7.us = add nuw i32 %i.022.us, 1181; CHECK: %exitcond23 = icmp ne i32 %inc7.us, %flatten.tripcount182; CHECK: br i1 %exitcond23, label %for.body.us, label %for.end8.loopexit183 184for.end8.loopexit: ; preds = %for.cond1.for.inc6_crit_edge.us185 br label %for.end8186 187for.end8: ; preds = %for.end8.loopexit, %entry188 %i.0.lcssa = phi i32 [ 0, %entry ], [ %N, %for.end8.loopexit ]189 ret i32 %i.0.lcssa190}191 192 193; CHECK-LABEL: test4194; Multiplication cannot overflow, so we can replace the original loop.195define void @test4(i16 zeroext %N, ptr nocapture %C, ptr nocapture readonly %A, i32 %scale) {196entry:197 %conv = zext i16 %N to i32198 %cmp30 = icmp eq i16 %N, 0199 br i1 %cmp30, label %for.cond.cleanup, label %for.body.lr.ph.split.us200; CHECK: entry:201; CHECK: %[[LIMIT:.*]] = zext i16 %N to i32202; CHECK: br i1 %{{.*}} label %for.cond.cleanup, label %for.body.lr.ph.split.us203 204for.body.lr.ph.split.us: ; preds = %entry205 br label %for.body.us206; CHECK: for.body.lr.ph.split.us:207; CHECK: %[[TRIPCOUNT:.*]] = mul i32 %[[LIMIT]], %[[LIMIT]]208; CHECK: br label %for.body.us209 210for.body.us: ; preds = %for.cond2.for.cond.cleanup6_crit_edge.us, %for.body.lr.ph.split.us211 %i.031.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc15.us, %for.cond2.for.cond.cleanup6_crit_edge.us ]212 %mul.us = mul nuw nsw i32 %i.031.us, %conv213 br label %for.body7.us214; CHECK: for.body.us:215; CHECK: %[[OUTER_IV:.*]] = phi i32216; CHECK: br label %for.body7.us217 218for.body7.us: ; preds = %for.body.us, %for.body7.us219; CHECK: for.body7.us:220 %j.029.us = phi i32 [ 0, %for.body.us ], [ %inc.us, %for.body7.us ]221 %add.us = add nuw nsw i32 %j.029.us, %mul.us222 %arrayidx.us = getelementptr inbounds i32, ptr %A, i32 %add.us223; CHECK: getelementptr inbounds i32, ptr %A, i32 %[[OUTER_IV]]224 %0 = load i32, ptr %arrayidx.us, align 4225 %mul9.us = mul nsw i32 %0, %scale226; CHECK: getelementptr inbounds i32, ptr %C, i32 %[[OUTER_IV]]227 %arrayidx13.us = getelementptr inbounds i32, ptr %C, i32 %add.us228 store i32 %mul9.us, ptr %arrayidx13.us, align 4229 %inc.us = add nuw nsw i32 %j.029.us, 1230 %exitcond = icmp ne i32 %inc.us, %conv231 br i1 %exitcond, label %for.body7.us, label %for.cond2.for.cond.cleanup6_crit_edge.us232; CHECK: br label %for.cond2.for.cond.cleanup6_crit_edge.us233 234for.cond2.for.cond.cleanup6_crit_edge.us: ; preds = %for.body7.us235 %inc15.us = add nuw nsw i32 %i.031.us, 1236 %exitcond32 = icmp ne i32 %inc15.us, %conv237 br i1 %exitcond32, label %for.body.us, label %for.cond.cleanup.loopexit238; CHECK: for.cond2.for.cond.cleanup6_crit_edge.us:239; CHECK: br i1 %exitcond32, label %for.body.us, label %for.cond.cleanup.loopexit240 241for.cond.cleanup.loopexit: ; preds = %for.cond2.for.cond.cleanup6_crit_edge.us242 br label %for.cond.cleanup243; CHECK: for.cond.cleanup.loopexit:244; CHECK: br label %for.cond.cleanup245 246for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry247 ret void248; CHECK: for.cond.cleanup:249; CHECK: ret void250}251 252 253; CHECK-LABEL: test5254define i32 @test5(i8 zeroext %I, i16 zeroext %J) {255entry:256 %0 = lshr i8 %I, 1257 %div = zext i8 %0 to i32258 %cmp30 = icmp eq i8 %0, 0259 br i1 %cmp30, label %for.cond.cleanup, label %for.body.lr.ph260 261for.body.lr.ph: ; preds = %entry262 %1 = lshr i16 %J, 1263 %div5 = zext i16 %1 to i32264 %cmp627 = icmp eq i16 %1, 0265 br i1 %cmp627, label %for.body.lr.ph.split, label %for.body.lr.ph.split.us266 267for.body.lr.ph.split.us: ; preds = %for.body.lr.ph268 br label %for.body.us269; CHECK: for.body.lr.ph.split.us:270; CHECK: %flatten.tripcount = mul i32 %div5, %div271; CHECK: br label %for.body.us272 273for.body.us: ; preds = %for.cond3.for.cond.cleanup8_crit_edge.us, %for.body.lr.ph.split.us274 %i.032.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc13.us, %for.cond3.for.cond.cleanup8_crit_edge.us ]275 %x.031.us = phi i32 [ 1, %for.body.lr.ph.split.us ], [ %xor.us.lcssa, %for.cond3.for.cond.cleanup8_crit_edge.us ]276 br label %for.body9.us277; CHECK: for.body.us:278; CHECK: %i.032.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc13.us, %for.cond3.for.cond.cleanup8_crit_edge.us ]279; CHECK: %x.031.us = phi i32 [ 1, %for.body.lr.ph.split.us ], [ %xor.us.lcssa, %for.cond3.for.cond.cleanup8_crit_edge.us ]280; CHECK: br label %for.body9.us281 282for.body9.us: ; preds = %for.body.us, %for.body9.us283 %j.029.us = phi i32 [ 0, %for.body.us ], [ %inc.us, %for.body9.us ]284 %x.128.us = phi i32 [ %x.031.us, %for.body.us ], [ %xor.us, %for.body9.us ]285 %call.us = tail call i32 @func(i32 1)286 %sub.us = sub nsw i32 %call.us, %x.128.us287 %xor.us = xor i32 %sub.us, %x.128.us288 %inc.us = add nuw nsw i32 %j.029.us, 1289 %cmp6.us = icmp ult i32 %inc.us, %div5290 br i1 %cmp6.us, label %for.body9.us, label %for.cond3.for.cond.cleanup8_crit_edge.us291; CHECK: for.body9.us:292; CHECK: %j.029.us = phi i32 [ 0, %for.body.us ]293; CHECK: %x.128.us = phi i32 [ %x.031.us, %for.body.us ]294; CHECK: %call.us = tail call i32 @func(i32 1)295; CHECK: %sub.us = sub nsw i32 %call.us, %x.128.us296; CHECK: %xor.us = xor i32 %sub.us, %x.128.us297; CHECK: %inc.us = add nuw nsw i32 %j.029.us, 1298; CHECK: %cmp6.us = icmp ult i32 %inc.us, %div5299; CHECK: br label %for.cond3.for.cond.cleanup8_crit_edge.us300 301for.cond3.for.cond.cleanup8_crit_edge.us: ; preds = %for.body9.us302 %xor.us.lcssa = phi i32 [ %xor.us, %for.body9.us ]303 %inc13.us = add nuw nsw i32 %i.032.us, 1304 %cmp.us = icmp ult i32 %inc13.us, %div305 br i1 %cmp.us, label %for.body.us, label %for.cond.cleanup.loopexit306; CHECK: for.cond3.for.cond.cleanup8_crit_edge.us:307; CHECK: %xor.us.lcssa = phi i32 [ %xor.us, %for.body9.us ]308; CHECK: %inc13.us = add nuw nsw i32 %i.032.us, 1309; CHECK: %cmp.us = icmp ult i32 %inc13.us, %flatten.tripcount310; CHECK: br i1 %cmp.us, label %for.body.us, label %for.cond.cleanup.loopexit311 312for.body.lr.ph.split: ; preds = %for.body.lr.ph313 br label %for.body314 315for.cond.cleanup.loopexit: ; preds = %for.cond3.for.cond.cleanup8_crit_edge.us316 %xor.us.lcssa.lcssa = phi i32 [ %xor.us.lcssa, %for.cond3.for.cond.cleanup8_crit_edge.us ]317 br label %for.cond.cleanup318 319for.cond.cleanup.loopexit34: ; preds = %for.body320 br label %for.cond.cleanup321 322for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit34, %for.cond.cleanup.loopexit, %entry323 %x.0.lcssa = phi i32 [ 1, %entry ], [ %xor.us.lcssa.lcssa, %for.cond.cleanup.loopexit ], [ 1, %for.cond.cleanup.loopexit34 ]324 ret i32 %x.0.lcssa325 326for.body: ; preds = %for.body.lr.ph.split, %for.body327 %i.032 = phi i32 [ 0, %for.body.lr.ph.split ], [ %inc13, %for.body ]328 %inc13 = add nuw nsw i32 %i.032, 1329 %cmp = icmp ult i32 %inc13, %div330 br i1 %cmp, label %for.body, label %for.cond.cleanup.loopexit34331}332 333 334; CHECK-LABEL: test6335define i32 @test6(i8 zeroext %I, i16 zeroext %J) {336entry:337 %0 = lshr i8 %I, 1338 %div = zext i8 %0 to i32339 %cmp30 = icmp eq i8 %0, 0340 br i1 %cmp30, label %for.cond.cleanup, label %for.body.lr.ph341 342for.body.lr.ph: ; preds = %entry343 %1 = lshr i16 %J, 1344 %div5 = zext i16 %1 to i32345 %cmp627 = icmp eq i16 %1, 0346 br i1 %cmp627, label %for.body.lr.ph.split, label %for.body.lr.ph.split.us347 348for.body.lr.ph.split.us: ; preds = %for.body.lr.ph349 br label %for.body.us350; CHECK: for.body.lr.ph.split.us:351; CHECK: %flatten.tripcount = mul i32 %div5, %div352; CHECK: br label %for.body.us353 354for.body.us: ; preds = %for.cond3.for.cond.cleanup8_crit_edge.us, %for.body.lr.ph.split.us355 %i.032.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc13.us, %for.cond3.for.cond.cleanup8_crit_edge.us ]356 %x.031.us = phi i32 [ 1, %for.body.lr.ph.split.us ], [ %xor.us.lcssa, %for.cond3.for.cond.cleanup8_crit_edge.us ]357 %mul.us = mul nuw nsw i32 %i.032.us, %div5358 br label %for.body9.us359; CHECK: for.body.us:360; CHECK: %i.032.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc13.us, %for.cond3.for.cond.cleanup8_crit_edge.us ]361; CHECK: %x.031.us = phi i32 [ 1, %for.body.lr.ph.split.us ], [ %xor.us.lcssa, %for.cond3.for.cond.cleanup8_crit_edge.us ]362; CHECK: %mul.us = mul nuw nsw i32 %i.032.us, %div5363; CHECK: br label %for.body9.us364 365for.body9.us: ; preds = %for.body.us, %for.body9.us366 %j.029.us = phi i32 [ 0, %for.body.us ], [ %inc.us, %for.body9.us ]367 %x.128.us = phi i32 [ %x.031.us, %for.body.us ], [ %xor.us, %for.body9.us ]368 %add.us = add nuw nsw i32 %j.029.us, %mul.us369 %call.us = tail call i32 @func(i32 %add.us)370 %sub.us = sub nsw i32 %call.us, %x.128.us371 %xor.us = xor i32 %sub.us, %x.128.us372 %inc.us = add nuw nsw i32 %j.029.us, 1373 %cmp6.us = icmp ult i32 %inc.us, %div5374 br i1 %cmp6.us, label %for.body9.us, label %for.cond3.for.cond.cleanup8_crit_edge.us375; CHECK: for.body9.us:376; CHECK: %j.029.us = phi i32 [ 0, %for.body.us ]377; CHECK: %x.128.us = phi i32 [ %x.031.us, %for.body.us ]378; CHECK: %add.us = add nuw nsw i32 %j.029.us, %mul.us379; CHECK: %call.us = tail call i32 @func(i32 %i.032.us)380; CHECK: %sub.us = sub nsw i32 %call.us, %x.128.us381; CHECK: %xor.us = xor i32 %sub.us, %x.128.us382; CHECK: %inc.us = add nuw nsw i32 %j.029.us, 1383; CHECK: %cmp6.us = icmp ult i32 %inc.us, %div5384; CHECK: br label %for.cond3.for.cond.cleanup8_crit_edge.us385 386for.cond3.for.cond.cleanup8_crit_edge.us: ; preds = %for.body9.us387 %xor.us.lcssa = phi i32 [ %xor.us, %for.body9.us ]388 %inc13.us = add nuw nsw i32 %i.032.us, 1389 %cmp.us = icmp ult i32 %inc13.us, %div390 br i1 %cmp.us, label %for.body.us, label %for.cond.cleanup.loopexit391; CHECK: for.cond3.for.cond.cleanup8_crit_edge.us:392; CHECK: %xor.us.lcssa = phi i32 [ %xor.us, %for.body9.us ]393; CHECK: %inc13.us = add nuw nsw i32 %i.032.us, 1394; CHECK: %cmp.us = icmp ult i32 %inc13.us, %flatten.tripcount395; CHECK: br i1 %cmp.us, label %for.body.us, label %for.cond.cleanup.loopexit396 397for.body.lr.ph.split: ; preds = %for.body.lr.ph398 br label %for.body399 400for.cond.cleanup.loopexit: ; preds = %for.cond3.for.cond.cleanup8_crit_edge.us401 %xor.us.lcssa.lcssa = phi i32 [ %xor.us.lcssa, %for.cond3.for.cond.cleanup8_crit_edge.us ]402 br label %for.cond.cleanup403 404for.cond.cleanup.loopexit34: ; preds = %for.body405 br label %for.cond.cleanup406 407for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit34, %for.cond.cleanup.loopexit, %entry408 %x.0.lcssa = phi i32 [ 1, %entry ], [ %xor.us.lcssa.lcssa, %for.cond.cleanup.loopexit ], [ 1, %for.cond.cleanup.loopexit34 ]409 ret i32 %x.0.lcssa410 411for.body: ; preds = %for.body.lr.ph.split, %for.body412 %i.032 = phi i32 [ 0, %for.body.lr.ph.split ], [ %inc13, %for.body ]413 %inc13 = add nuw nsw i32 %i.032, 1414 %cmp = icmp ult i32 %inc13, %div415 br i1 %cmp, label %for.body, label %for.cond.cleanup.loopexit34416}417 418; CHECK-LABEL: test7419; Various inner phis and conditions which we can still work with420define signext i16 @test7(i32 %I, i32 %J, ptr nocapture readonly %C, i16 signext %limit) {421entry:422 %cmp43 = icmp eq i32 %J, 0423 br i1 %cmp43, label %for.end17, label %for.body.lr.ph424 425for.body.lr.ph: ; preds = %entry426 %conv = sext i16 %limit to i32427 br label %for.body.us428; CHECK: for.body.lr.ph:429; CHECK: %conv = sext i16 %limit to i32430; CHECK: %flatten.tripcount = mul i32 %J, %J431; CHECK: br label %for.body.us432 433for.body.us: ; preds = %for.cond1.for.inc15_crit_edge.us, %for.body.lr.ph434 %i.047.us = phi i32 [ 0, %for.body.lr.ph ], [ %inc16.us, %for.cond1.for.inc15_crit_edge.us ]435 %ret.046.us = phi i16 [ 0, %for.body.lr.ph ], [ %ret.2.us.lcssa, %for.cond1.for.inc15_crit_edge.us ]436 %prev.045.us = phi i32 [ 0, %for.body.lr.ph ], [ %.lcssa, %for.cond1.for.inc15_crit_edge.us ]437 %tmp.044.us = phi i32 [ 0, %for.body.lr.ph ], [ %tmp.2.us.lcssa, %for.cond1.for.inc15_crit_edge.us ]438 %mul.us = mul i32 %i.047.us, %J439 br label %for.body3.us440; CHECK: for.body.us:441; CHECK: %i.047.us = phi i32 [ 0, %for.body.lr.ph ], [ %inc16.us, %for.cond1.for.inc15_crit_edge.us ]442; CHECK: %ret.046.us = phi i16 [ 0, %for.body.lr.ph ], [ %ret.2.us.lcssa, %for.cond1.for.inc15_crit_edge.us ]443; CHECK: %prev.045.us = phi i32 [ 0, %for.body.lr.ph ], [ %.lcssa, %for.cond1.for.inc15_crit_edge.us ]444; CHECK: %tmp.044.us = phi i32 [ 0, %for.body.lr.ph ], [ %tmp.2.us.lcssa, %for.cond1.for.inc15_crit_edge.us ]445; CHECK: %mul.us = mul i32 %i.047.us, %J446; CHECK: br label %for.body3.us447 448for.body3.us: ; preds = %for.body.us, %if.end.us449 %j.040.us = phi i32 [ 0, %for.body.us ], [ %inc.us, %if.end.us ]450 %ret.139.us = phi i16 [ %ret.046.us, %for.body.us ], [ %ret.2.us, %if.end.us ]451 %prev.138.us = phi i32 [ %prev.045.us, %for.body.us ], [ %0, %if.end.us ]452 %tmp.137.us = phi i32 [ %tmp.044.us, %for.body.us ], [ %tmp.2.us, %if.end.us ]453 %add.us = add i32 %j.040.us, %mul.us454 %arrayidx.us = getelementptr inbounds i32, ptr %C, i32 %add.us455 %0 = load i32, ptr %arrayidx.us, align 4456 %add4.us = add nsw i32 %0, %tmp.137.us457 %cmp5.us = icmp sgt i32 %add4.us, %conv458 br i1 %cmp5.us, label %if.then.us, label %if.else.us459; CHECK: for.body3.us:460; CHECK: %j.040.us = phi i32 [ 0, %for.body.us ]461; CHECK: %ret.139.us = phi i16 [ %ret.046.us, %for.body.us ]462; CHECK: %prev.138.us = phi i32 [ %prev.045.us, %for.body.us ]463; CHECK: %tmp.137.us = phi i32 [ %tmp.044.us, %for.body.us ]464; CHECK: %add.us = add i32 %j.040.us, %mul.us465; CHECK: %arrayidx.us = getelementptr inbounds i32, ptr %C, i32 %i.047.us466; CHECK: %0 = load i32, ptr %arrayidx.us, align 4467; CHECK: %add4.us = add nsw i32 %0, %tmp.137.us468; CHECK: %cmp5.us = icmp sgt i32 %add4.us, %conv469; CHECK: br i1 %cmp5.us, label %if.then.us, label %if.else.us470 471if.else.us: ; preds = %for.body3.us472 %cmp10.us = icmp sgt i32 %0, %prev.138.us473 %cond.us = zext i1 %cmp10.us to i32474 %conv1235.us = zext i16 %ret.139.us to i32475 %add13.us = add nuw nsw i32 %cond.us, %conv1235.us476 br label %if.end.us477; CHECK: if.else.us:478; CHECK: %cmp10.us = icmp sgt i32 %0, %prev.138.us479; CHECK: %cond.us = zext i1 %cmp10.us to i32480; CHECK: %conv1235.us = zext i16 %ret.139.us to i32481; CHECK: %add13.us = add nuw nsw i32 %cond.us, %conv1235.us482; CHECK: br label %if.end.us483 484if.then.us: ; preds = %for.body3.us485 %conv7.us = sext i16 %ret.139.us to i32486 %add8.us = add nsw i32 %conv7.us, 10487 br label %if.end.us488; CHECK: if.then.us:489; CHECK: %conv7.us = sext i16 %ret.139.us to i32490; CHECK: %add8.us = add nsw i32 %conv7.us, 10491; CHECK: br label %if.end.us492 493if.end.us: ; preds = %if.then.us, %if.else.us494 %tmp.2.us = phi i32 [ 0, %if.then.us ], [ %add4.us, %if.else.us ]495 %ret.2.in.us = phi i32 [ %add8.us, %if.then.us ], [ %add13.us, %if.else.us ]496 %ret.2.us = trunc i32 %ret.2.in.us to i16497 %inc.us = add nuw i32 %j.040.us, 1498 %exitcond = icmp ne i32 %inc.us, %J499 br i1 %exitcond, label %for.body3.us, label %for.cond1.for.inc15_crit_edge.us500; CHECK: if.end.us:501; CHECK: %tmp.2.us = phi i32 [ 0, %if.then.us ], [ %add4.us, %if.else.us ]502; CHECK: %ret.2.in.us = phi i32 [ %add8.us, %if.then.us ], [ %add13.us, %if.else.us ]503; CHECK: %ret.2.us = trunc i32 %ret.2.in.us to i16504; CHECK: %inc.us = add nuw i32 %j.040.us, 1505; CHECK: %exitcond = icmp ne i32 %inc.us, %J506; CHECK: br label %for.cond1.for.inc15_crit_edge.us507 508for.cond1.for.inc15_crit_edge.us: ; preds = %if.end.us509 %tmp.2.us.lcssa = phi i32 [ %tmp.2.us, %if.end.us ]510 %ret.2.us.lcssa = phi i16 [ %ret.2.us, %if.end.us ]511 %.lcssa = phi i32 [ %0, %if.end.us ]512 %inc16.us = add nuw i32 %i.047.us, 1513 %exitcond49 = icmp ne i32 %inc16.us, %J514 br i1 %exitcond49, label %for.body.us, label %for.end17.loopexit515; CHECK: for.cond1.for.inc15_crit_edge.us:516; CHECK: %tmp.2.us.lcssa = phi i32 [ %tmp.2.us, %if.end.us ]517; CHECK: %ret.2.us.lcssa = phi i16 [ %ret.2.us, %if.end.us ]518; CHECK: %.lcssa = phi i32 [ %0, %if.end.us ]519; CHECK: %inc16.us = add nuw i32 %i.047.us, 1520; CHECK: %exitcond49 = icmp ne i32 %inc16.us, %flatten.tripcount521; CHECK: br i1 %exitcond49, label %for.body.us, label %for.end17.loopexit522 523for.end17.loopexit: ; preds = %for.cond1.for.inc15_crit_edge.us524 %ret.2.us.lcssa.lcssa = phi i16 [ %ret.2.us.lcssa, %for.cond1.for.inc15_crit_edge.us ]525 br label %for.end17526 527for.end17: ; preds = %for.end17.loopexit, %entry528 %ret.0.lcssa = phi i16 [ 0, %entry ], [ %ret.2.us.lcssa.lcssa, %for.end17.loopexit ]529 ret i16 %ret.0.lcssa530}531 532; CHECK-LABEL: test8533; Same as test1, but with different continue block order534; (uses icmp eq and loops on false)535define i32 @test8(i32 %val, ptr nocapture %A) {536entry:537 br label %for.body538; CHECK: entry:539; CHECK: %flatten.tripcount = mul i32 20, 10540; CHECK: br label %for.body541 542for.body: ; preds = %entry, %for.inc6543 %i.018 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]544 %mul = mul nuw nsw i32 %i.018, 20545 br label %for.body3546; CHECK: for.body:547; CHECK: %i.018 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]548; CHECK: %mul = mul nuw nsw i32 %i.018, 20549; CHECK: br label %for.body3550 551for.body3: ; preds = %for.body, %for.body3552 %j.017 = phi i32 [ 0, %for.body ], [ %inc, %for.body3 ]553 %add = add nuw nsw i32 %j.017, %mul554 %arrayidx = getelementptr inbounds i16, ptr %A, i32 %add555 %0 = load i16, ptr %arrayidx, align 2556 %conv16 = zext i16 %0 to i32557 %add4 = add i32 %conv16, %val558 %conv5 = trunc i32 %add4 to i16559 store i16 %conv5, ptr %arrayidx, align 2560 %inc = add nuw nsw i32 %j.017, 1561 %exitcond = icmp eq i32 %inc, 20562 br i1 %exitcond, label %for.inc6, label %for.body3563; CHECK: for.body3:564; CHECK: %j.017 = phi i32 [ 0, %for.body ]565; CHECK: %add = add nuw nsw i32 %j.017, %mul566; CHECK: %arrayidx = getelementptr inbounds i16, ptr %A, i32 %i.018567; CHECK: %0 = load i16, ptr %arrayidx, align 2568; CHECK: %conv16 = zext i16 %0 to i32569; CHECK: %add4 = add i32 %conv16, %val570; CHECK: %conv5 = trunc i32 %add4 to i16571; CHECK: store i16 %conv5, ptr %arrayidx, align 2572; CHECK: %inc = add nuw nsw i32 %j.017, 1573; CHECK: %exitcond = icmp eq i32 %inc, 20574; CHECK: br label %for.inc6575 576for.inc6: ; preds = %for.body3577 %inc7 = add nuw nsw i32 %i.018, 1578 %exitcond19 = icmp eq i32 %inc7, 10579 br i1 %exitcond19, label %for.end8, label %for.body580; CHECK: for.inc6:581; CHECK: %inc7 = add nuw nsw i32 %i.018, 1582; CHECK: %exitcond19 = icmp eq i32 %inc7, %flatten.tripcount583; CHECK: br i1 %exitcond19, label %for.end8, label %for.body584 585for.end8: ; preds = %for.inc6586 ret i32 10587}588 589; When the inner loop trip count is a constant and the step590; is 1, the InstCombine pass causes the transformation e.g.591; icmp ult i32 %inc, 20 -> icmp ult i32 %j, 19. This doesn't592; match the pattern (OuterPHI * InnerTripCount) + InnerPHI but593; we should still flatten the loop as the compare is removed594; later anyway.595define i32 @test9(ptr nocapture %A) {596entry:597 br label %for.cond1.preheader598; CHECK-LABEL: test9599; CHECK: entry:600; CHECK: %flatten.tripcount = mul i32 20, 11601; CHECK: br label %for.cond1.preheader602 603for.cond1.preheader:604 %i.017 = phi i32 [ 0, %entry ], [ %inc6, %for.cond.cleanup3 ]605 %mul = mul i32 %i.017, 20606 br label %for.body4607; CHECK: for.cond1.preheader:608; CHECK: %i.017 = phi i32 [ 0, %entry ], [ %inc6, %for.cond.cleanup3 ]609; CHECK: %mul = mul i32 %i.017, 20610; CHECK: br label %for.body4611 612for.cond.cleanup3:613 %inc6 = add i32 %i.017, 1614 %cmp = icmp ult i32 %inc6, 11615 br i1 %cmp, label %for.cond1.preheader, label %for.cond.cleanup616; CHECK: for.cond.cleanup3:617; CHECK: %inc6 = add i32 %i.017, 1618; CHECK: %cmp = icmp ult i32 %inc6, %flatten.tripcount619; CHECK: br i1 %cmp, label %for.cond1.preheader, label %for.cond.cleanup620 621for.body4:622 %j.016 = phi i32 [ 0, %for.cond1.preheader ], [ %inc, %for.body4 ]623 %add = add i32 %j.016, %mul624 %arrayidx = getelementptr inbounds i32, ptr %A, i32 %add625 store i32 30, ptr %arrayidx, align 4626 %inc = add nuw nsw i32 %j.016, 1627 %cmp2 = icmp ult i32 %j.016, 19628 br i1 %cmp2, label %for.body4, label %for.cond.cleanup3629; CHECK: for.body4630; CHECK: %j.016 = phi i32 [ 0, %for.cond1.preheader ]631; CHECK: %add = add i32 %j.016, %mul632; CHECK: %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.017633; CHECK: store i32 30, ptr %arrayidx, align 4634; CHECK: %inc = add nuw nsw i32 %j.016, 1635; CHECK: %cmp2 = icmp ult i32 %j.016, 19636; CHECK: br label %for.cond.cleanup3637 638for.cond.cleanup:639 %0 = load i32, ptr %A, align 4640 ret i32 %0641}642 643declare i32 @func(i32)644 645