diff --git a/llvm/test/Transforms/LoopUnroll/unroll-unconditional-latch.ll b/llvm/test/Transforms/LoopUnroll/unroll-unconditional-latch.ll index da0d9ec4e8e4..89d1144314b4 100644 --- a/llvm/test/Transforms/LoopUnroll/unroll-unconditional-latch.ll +++ b/llvm/test/Transforms/LoopUnroll/unroll-unconditional-latch.ll @@ -1,36 +1,38 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -loop-unroll -S %s -verify-loop-info -verify-dom-info -verify-loop-lcssa | FileCheck %s %struct.spam = type { double, double, double, double, double, double, double } define void @test2(i32* %arg) { -; CHECK-LABEL: void @test2 -; CHECK-NEXT: entry: -; CHECK-NEXT: br label %for.header - -; CHECK-LABEL: for.header: ; preds = %entry -; CHECK-NEXT: store i32 0, i32* %arg, align 4 -; CHECK-NEXT: br label %for.latch - -; CHECK-LABEL: for.latch: ; preds = %for.header -; CHECK-NEXT: %ptr.1 = getelementptr inbounds i32, i32* %arg, i64 1 -; CHECK-NEXT: store i32 0, i32* %ptr.1, align 4 -; CHECK-NEXT: br label %for.latch.1 - -; CHECK-LABEL: if.end.loopexit: ; preds = %for.latch.2 +; CHECK-LABEL: @test2( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_HEADER:%.*]] +; CHECK: for.header: +; CHECK-NEXT: store i32 0, i32* [[ARG:%.*]], align 4 +; CHECK-NEXT: br label [[FOR_LATCH:%.*]] +; CHECK: for.latch: +; CHECK-NEXT: [[PTR_1:%.*]] = getelementptr inbounds i32, i32* [[ARG]], i64 1 +; CHECK-NEXT: store i32 0, i32* [[PTR_1]], align 4 +; CHECK-NEXT: br label [[FOR_LATCH_1:%.*]] +; CHECK: if.end.loopexit: ; CHECK-NEXT: ret void - -; CHECK-LABEL: for.latch.1: ; preds = %for.latch -; CHECK-NEXT: %ptr.2 = getelementptr inbounds i32, i32* %arg, i64 2 -; CHECK-NEXT: store i32 0, i32* %ptr.2, align 4 -; CHECK-NEXT: br label %for.latch.2 - -; CHECK-LABEL: for.latch.2: ; preds = %for.latch.1 -; CHECK-NEXT: %ptr.3 = getelementptr inbounds i32, i32* %arg, i64 3 -; CHECK-NEXT: store i32 0, i32* %ptr.3, align 4 -; CHECK-NEXT: br i1 true, label %if.end.loopexit, label %for.latch.3 - -; CHECK-LABEL: for.latch.3: ; preds = %for.latch.2 +; CHECK: for.latch.1: +; CHECK-NEXT: [[PTR_2:%.*]] = getelementptr inbounds i32, i32* [[ARG]], i64 2 +; CHECK-NEXT: store i32 0, i32* [[PTR_2]], align 4 +; CHECK-NEXT: br label [[FOR_LATCH_2:%.*]] +; CHECK: for.latch.2: +; CHECK-NEXT: [[PTR_3:%.*]] = getelementptr inbounds i32, i32* [[ARG]], i64 3 +; CHECK-NEXT: store i32 0, i32* [[PTR_3]], align 4 +; CHECK-NEXT: br i1 true, label [[IF_END_LOOPEXIT:%.*]], label [[FOR_LATCH_3:%.*]] +; CHECK: for.latch.3: ; CHECK-NEXT: unreachable +; + + + + + + entry: br label %for.header @@ -51,27 +53,28 @@ if.end.loopexit: ; preds = %for.header } define double @test_with_lcssa(double %arg1, double* %arg2) { -; CHECK-LABEL: define double @test_with_lcssa( -; CHECK-LABEL: entry: -; CHECK-NEXT: br label %loop.header - -; CHECK-LABEL: loop.header: ; preds = %entry -; CHECK-NEXT: %res = fsub double %arg1, 3.000000e+00 -; CHECK-NEXT: br label %loop.latch - -; CHECK-LABEL: loop.latch: ; preds = %loop.header -; CHECK-NEXT: %ptr = getelementptr inbounds double, double* %arg2, i64 1 -; CHECK-NEXT: %lv = load double, double* %ptr, align 8 -; CHECK-NEXT: %res.1 = fsub double %lv, %res -; CHECK-NEXT: br i1 true, label %loop.exit, label %loop.latch.1 - -; CHECK-LABEL: loop.exit: ; preds = %loop.latch -; CHECK-NEXT: %res.lcssa = phi double [ %res.1, %loop.latch ] -; CHECK-NEXT: ret double %res.lcssa - -; CHECK-LABEL: loop.latch.1: ; preds = %loop.latch -; CHECK-NEXT: %ptr.1 = getelementptr inbounds double, double* %arg2, i64 2 +; CHECK-LABEL: @test_with_lcssa( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[RES:%.*]] = fsub double [[ARG1:%.*]], 3.000000e+00 +; CHECK-NEXT: br label [[LOOP_LATCH:%.*]] +; CHECK: loop.latch: +; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds double, double* [[ARG2:%.*]], i64 1 +; CHECK-NEXT: [[LV:%.*]] = load double, double* [[PTR]], align 8 +; CHECK-NEXT: [[RES_1:%.*]] = fsub double [[LV]], [[RES]] +; CHECK-NEXT: br i1 true, label [[LOOP_EXIT:%.*]], label [[LOOP_LATCH_1:%.*]] +; CHECK: loop.exit: +; CHECK-NEXT: [[RES_LCSSA:%.*]] = phi double [ [[RES_1]], [[LOOP_LATCH]] ] +; CHECK-NEXT: ret double [[RES_LCSSA]] +; CHECK: loop.latch.1: +; CHECK-NEXT: [[PTR_1:%.*]] = getelementptr inbounds double, double* [[ARG2]], i64 2 ; CHECK-NEXT: unreachable +; + + + + entry: br label %loop.header @@ -97,60 +100,60 @@ loop.exit: ; preds = %bb366 ; We unroll the outer loop and need to preserve LI for the inner loop. define void @test_with_nested_loop(i32* %arg) { -; CHECK-LABEL: void @test_with_nested_loop -; CHECK-LABEL: entry: -; CHECK-NEXT: br label %outer.header - -; CHECK-DAG: outer.header: ; preds = %entry -; CHECK-NEXT: br label %inner.body.preheader - -; CHECK-DAG: inner.body.preheader: ; preds = %outer.header -; CHECK-NEXT: br label %inner.body - -; CHECK-LABEL: inner.body: ; preds = %inner.body.preheader, %inner.body -; CHECK-NEXT: %j.iv = phi i64 [ %j.iv.next, %inner.body ], [ 0, %inner.body.preheader ] -; CHECK-NEXT: %ptr = getelementptr inbounds i32, i32* %arg, i64 %j.iv -; CHECK-NEXT: store i32 0, i32* %ptr, align 4 -; CHECK-NEXT: %j.iv.next = add nuw nsw i64 %j.iv, 1 -; CHECK-NEXT: %inner.cond = icmp eq i64 %j.iv.next, 40000 -; CHECK-NEXT: br i1 %inner.cond, label %outer.latch, label %inner.body - -; CHECK-LABEL: outer.latch: ; preds = %inner.body -; CHECK-NEXT: br label %inner.body.preheader.1 - -; CHECK-LABEL: exit: ; preds = %outer.latch.1 +; CHECK-LABEL: @test_with_nested_loop( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] +; CHECK: outer.header: +; CHECK-NEXT: br label [[INNER_BODY_PREHEADER:%.*]] +; CHECK: inner.body.preheader: +; CHECK-NEXT: br label [[INNER_BODY:%.*]] +; CHECK: inner.body: +; CHECK-NEXT: [[J_IV:%.*]] = phi i64 [ [[J_IV_NEXT:%.*]], [[INNER_BODY]] ], [ 0, [[INNER_BODY_PREHEADER]] ] +; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds i32, i32* [[ARG:%.*]], i64 [[J_IV]] +; CHECK-NEXT: store i32 0, i32* [[PTR]], align 4 +; CHECK-NEXT: [[J_IV_NEXT]] = add nuw nsw i64 [[J_IV]], 1 +; CHECK-NEXT: [[INNER_COND:%.*]] = icmp eq i64 [[J_IV_NEXT]], 40000 +; CHECK-NEXT: br i1 [[INNER_COND]], label [[OUTER_LATCH:%.*]], label [[INNER_BODY]] +; CHECK: outer.latch: +; CHECK-NEXT: br label [[INNER_BODY_PREHEADER_1:%.*]] +; CHECK: exit: ; CHECK-NEXT: ret void - -; CHECK-LABEL: inner.body.preheader.1: ; preds = %outer.latch -; CHECK-NEXT: br label %inner.body.1 - -; CHECK-LABEL: inner.body.1: ; preds = %inner.body.1, %inner.body.preheader.1 -; CHECK-NEXT: %j.iv.1 = phi i64 [ %j.iv.next.1, %inner.body.1 ], [ 0, %inner.body.preheader.1 ] -; CHECK-NEXT: %idx.1 = add i64 1, %j.iv.1 -; CHECK-NEXT: %ptr.1 = getelementptr inbounds i32, i32* %arg, i64 %idx.1 -; CHECK-NEXT: store i32 0, i32* %ptr.1, align 4 -; CHECK-NEXT: %j.iv.next.1 = add nuw nsw i64 %j.iv.1, 1 -; CHECK-NEXT: %inner.cond.1 = icmp eq i64 %j.iv.next.1, 40000 -; CHECK-NEXT: br i1 %inner.cond.1, label %outer.latch.1, label %inner.body.1 - -; CHECK-LABEL: outer.latch.1: ; preds = %inner.body.1 -; CHECK-NEXT: br i1 true, label %exit, label %inner.body.preheader.2 - -; CHECK-LABEL: inner.body.preheader.2: ; preds = %outer.latch.1 -; CHECK-NEXT: br label %inner.body.2 - -; CHECK-LABEL: inner.body.2: ; preds = %inner.body.2, %inner.body.preheader.2 -; CHECK-NEXT: %j.iv.2 = phi i64 [ %j.iv.next.2, %inner.body.2 ], [ 0, %inner.body.preheader.2 ] -; CHECK-NEXT: %idx.2 = add i64 2, %j.iv.2 -; CHECK-NEXT: %ptr.2 = getelementptr inbounds i32, i32* %arg, i64 %idx.2 -; CHECK-NEXT: store i32 0, i32* %ptr.2, align 4 -; CHECK-NEXT: %j.iv.next.2 = add nuw nsw i64 %j.iv.2, 1 -; CHECK-NEXT: %inner.cond.2 = icmp eq i64 %j.iv.next.2, 40000 -; CHECK-NEXT: br i1 %inner.cond.2, label %outer.latch.2, label %inner.body.2 - -; CHECK-LABEL: outer.latch.2: ; preds = %inner.body.2 +; CHECK: inner.body.preheader.1: +; CHECK-NEXT: br label [[INNER_BODY_1:%.*]] +; CHECK: inner.body.1: +; CHECK-NEXT: [[J_IV_1:%.*]] = phi i64 [ [[J_IV_NEXT_1:%.*]], [[INNER_BODY_1]] ], [ 0, [[INNER_BODY_PREHEADER_1]] ] +; CHECK-NEXT: [[IDX_1:%.*]] = add i64 1, [[J_IV_1]] +; CHECK-NEXT: [[PTR_1:%.*]] = getelementptr inbounds i32, i32* [[ARG]], i64 [[IDX_1]] +; CHECK-NEXT: store i32 0, i32* [[PTR_1]], align 4 +; CHECK-NEXT: [[J_IV_NEXT_1]] = add nuw nsw i64 [[J_IV_1]], 1 +; CHECK-NEXT: [[INNER_COND_1:%.*]] = icmp eq i64 [[J_IV_NEXT_1]], 40000 +; CHECK-NEXT: br i1 [[INNER_COND_1]], label [[OUTER_LATCH_1:%.*]], label [[INNER_BODY_1]] +; CHECK: outer.latch.1: +; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[INNER_BODY_PREHEADER_2:%.*]] +; CHECK: inner.body.preheader.2: +; CHECK-NEXT: br label [[INNER_BODY_2:%.*]] +; CHECK: inner.body.2: +; CHECK-NEXT: [[J_IV_2:%.*]] = phi i64 [ [[J_IV_NEXT_2:%.*]], [[INNER_BODY_2]] ], [ 0, [[INNER_BODY_PREHEADER_2]] ] +; CHECK-NEXT: [[IDX_2:%.*]] = add i64 2, [[J_IV_2]] +; CHECK-NEXT: [[PTR_2:%.*]] = getelementptr inbounds i32, i32* [[ARG]], i64 [[IDX_2]] +; CHECK-NEXT: store i32 0, i32* [[PTR_2]], align 4 +; CHECK-NEXT: [[J_IV_NEXT_2]] = add nuw nsw i64 [[J_IV_2]], 1 +; CHECK-NEXT: [[INNER_COND_2:%.*]] = icmp eq i64 [[J_IV_NEXT_2]], 40000 +; CHECK-NEXT: br i1 [[INNER_COND_2]], label [[OUTER_LATCH_2:%.*]], label [[INNER_BODY_2]] +; CHECK: outer.latch.2: ; CHECK-NEXT: unreachable ; + + + + + + + + + + + entry: br label %outer.header @@ -178,30 +181,30 @@ exit: ; preds = %outer.header ; We unroll the inner loop and need to preserve LI for the outer loop. define void @test_with_nested_loop_unroll_inner(i32* %arg) { -; CHECK-LABEL: define void @test_with_nested_loop_unroll_inner( -; CHECK-LABEL: entry: -; CHECK-NEXT: br label %outer.header - -; CHECK-LABEL: outer.header: ; preds = %inner.body, %entry -; CHECK-NEXT: %outer.iv = phi i64 [ 0, %entry ], [ %outer.iv.next, %inner.body ] -; CHECK-NEXT: %outer.iv.next = add nuw nsw i64 %outer.iv, 1 -; CHECK-NEXT: %outer.cond = icmp eq i64 %outer.iv, 40000 -; CHECK-NEXT: br i1 %outer.cond, label %exit, label %inner.body.preheader - -; CHECK-LABEL: inner.body.preheader: ; preds = %outer.header -; CHECK-NEXT: br label %inner.body - -; CHECK-LABEL: inner.body: ; preds = %inner.body.preheader -; CHECK-NEXT: %ptr = getelementptr inbounds i32, i32* %arg, i64 %outer.iv -; CHECK-NEXT: store i32 0, i32* %ptr, align 4 -; CHECK-NEXT: %idx.1 = add i64 %outer.iv, 1 -; CHECK-NEXT: %ptr.1 = getelementptr inbounds i32, i32* %arg, i64 %idx.1 -; CHECK-NEXT: store i32 0, i32* %ptr.1, align 4 -; CHECK-NEXT: br label %outer.header - -; CHECK-LABEL: exit: ; preds = %outer.header -; CHECK-NEXT: ret void +; CHECK-LABEL: @test_with_nested_loop_unroll_inner( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] +; CHECK: outer.header: +; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[OUTER_IV_NEXT:%.*]], [[INNER_BODY:%.*]] ] +; CHECK-NEXT: [[OUTER_IV_NEXT]] = add nuw nsw i64 [[OUTER_IV]], 1 +; CHECK-NEXT: [[OUTER_COND:%.*]] = icmp eq i64 [[OUTER_IV]], 40000 +; CHECK-NEXT: br i1 [[OUTER_COND]], label [[EXIT:%.*]], label [[INNER_BODY_PREHEADER:%.*]] +; CHECK: inner.body.preheader: +; CHECK-NEXT: br label [[INNER_BODY]] +; CHECK: inner.body: +; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds i32, i32* [[ARG:%.*]], i64 [[OUTER_IV]] +; CHECK-NEXT: store i32 0, i32* [[PTR]], align 4 +; CHECK-NEXT: [[IDX_1:%.*]] = add i64 [[OUTER_IV]], 1 +; CHECK-NEXT: [[PTR_1:%.*]] = getelementptr inbounds i32, i32* [[ARG]], i64 [[IDX_1]] +; CHECK-NEXT: store i32 0, i32* [[PTR_1]], align 4 +; CHECK-NEXT: br label [[OUTER_HEADER]] +; CHECK: exit: +; CHECK-NEXT: ret void ; + + + + entry: br label %outer.header @@ -232,35 +235,35 @@ exit: ; preds = %outer.header ; Check that we do not crash for headers with non-branch instructions, e.g. ; switch. We do not unroll in those cases. define void @test_switchinst_in_header() { -; CHECK-LABEL: define void @test_switchinst_in_header() { -; CHECK-LABEL: entry: -; CHECK-NEXT: br label %while.header - -; CHECK-LABEL: while.header: ; preds = %while.latch, %entry -; CHECK-NEXT: switch i32 undef, label %exit [ -; CHECK-NEXT: i32 11, label %while.body1 -; CHECK-NEXT: i32 5, label %while.body2 +; CHECK-LABEL: @test_switchinst_in_header( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[WHILE_HEADER:%.*]] +; CHECK: while.header: +; CHECK-NEXT: switch i32 undef, label [[EXIT:%.*]] [ +; CHECK-NEXT: i32 11, label [[WHILE_BODY1:%.*]] +; CHECK-NEXT: i32 5, label [[WHILE_BODY2:%.*]] ; CHECK-NEXT: ] - -; CHECK-LABEL: while.body1: ; preds = %while.header +; CHECK: while.body1: ; CHECK-NEXT: unreachable - -; CHECK-LABEL: while.body2: ; preds = %while.header -; CHECK-NEXT: br label %while.latch - -; CHECK-LABEL: while.latch: ; preds = %while.body2 -; CHECK-NEXT: br label %while.header - -; CHECK-LABEL: exit: ; preds = %while.header +; CHECK: while.body2: +; CHECK-NEXT: br label [[WHILE_LATCH:%.*]] +; CHECK: while.latch: +; CHECK-NEXT: br label [[WHILE_HEADER]] +; CHECK: exit: ; CHECK-NEXT: ret void ; + + + + + entry: br label %while.header while.header: ; preds = %while.latch, %entry switch i32 undef, label %exit [ - i32 11, label %while.body1 - i32 5, label %while.body2 + i32 11, label %while.body1 + i32 5, label %while.body2 ] while.body1: ; preds = %while.header