diff --git a/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp b/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp --- a/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp @@ -831,6 +831,13 @@ if (SubLoopsSize != 1) return false; + // If the Loop does not have an exit block, cannot perform unroll and jam + if (!L->getExitBlock()) { + LLVM_DEBUG(dbgs() << "Won't unroll-and-jam; Loop does not have an exit " + "block\n"); + return false; + } + L = L->getSubLoops()[0]; } while (L); diff --git a/llvm/test/Transforms/LoopUnrollAndJam/no_exit_block.ll b/llvm/test/Transforms/LoopUnrollAndJam/no_exit_block.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/LoopUnrollAndJam/no_exit_block.ll @@ -0,0 +1,127 @@ +; RUN: opt -debug-only=loop-unroll-and-jam -passes="default" -disable-output -enable-unroll-and-jam -allow-unroll-and-jam -unroll-and-jam-count=8 %s 2>&1 | FileCheck %s + +; CHECK: Loop Unroll and Jam: F[h] Loop %bb24 +; CHECK: Won't unroll-and-jam; Ineligible loop form +; CHECK: Disabled due to not being safe. +; CHECK: Loop Unroll and Jam: F[h] Loop %bb46 +; CHECK: Won't unroll-and-jam; Ineligible loop form +; CHECK: Disabled due to not being safe. + +@a = external dso_local global i16, align 2 +@e = external dso_local global i32, align 4 +@f = external dso_local global i16, align 2 +@b = external dso_local global i16, align 2 +@c = external dso_local global i64, align 8 + +define dso_local i16 @g() #0 { +bb: + %i = load i16, i16* @a, align 2 + ret i16 %i +} + +define dso_local void @h() #1 { +bb: + %i = alloca i32, align 4 + %i1 = alloca i32, align 4 + %i2 = alloca [0 x i32], align 4 + %i3 = alloca i32*, align 8 + %i4 = alloca i32*, align 8 + store i32 4, i32* @e, align 4 + br label %bb5 + +bb5: ; preds = %bb47, %bb + %i6 = load i32, i32* @e, align 4 + %i7 = icmp ne i32 %i6, 0 + br i1 %i7, label %bb8, label %bb50 + +bb8: ; preds = %bb5 + %i9 = bitcast [0 x i32]* %i2 to i8* + call void @llvm.lifetime.start.p0i8(i64 0, i8* %i9) #4 + store i16 0, i16* @f, align 2 + br label %bb10 + +bb10: ; preds = %bb43, %bb8 + %i11 = load i16, i16* @f, align 2 + %i12 = sext i16 %i11 to i32 + %i13 = icmp sle i32 %i12, 7 + br i1 %i13, label %bb14, label %bb47 + +bb14: ; preds = %bb10 + store i32* %i, i32** %i3, align 8 + %i15 = load i16, i16* @b, align 2 + %i16 = sext i16 %i15 to i32 + %i17 = icmp sgt i32 %i16, 0 + %i18 = zext i1 %i17 to i32 + %i19 = load i32*, i32** %i3, align 8 + %i20 = load i32, i32* %i19, align 4 + %i21 = and i32 %i20, %i18 + store i32 %i21, i32* %i19, align 4 + %i22 = load i32, i32* %i1, align 4 + %i23 = icmp ne i32 %i22, 0 + br i1 %i23, label %bb24, label %bb32 + +bb24: ; preds = %bb14 + store i32* %i1, i32** %i4, align 8 + %i25 = load i32*, i32** %i3, align 8 + %i26 = load i32, i32* %i25, align 4 + %i27 = icmp ne i32 %i26, 0 + br i1 %i27, label %bb28, label %bb39 + +bb28: ; preds = %bb24 + %i29 = getelementptr inbounds [0 x i32], [0 x i32]* %i2, i64 0, i64 1 + %i30 = load i32, i32* %i29, align 4 + %i31 = load i32*, i32** %i4, align 8 + store i32 %i30, i32* %i31, align 4 + br label %bb39 + +bb32: ; preds = %bb35, %bb14 + %i33 = load i64, i64* @c, align 8 + %i34 = icmp ne i64 %i33, 0 + br i1 %i34, label %bb35, label %bb39 + +bb35: ; preds = %bb32 + %i36 = call signext i16 @g() + %i37 = sext i16 %i36 to i32 + %i38 = load i32*, i32** %i3, align 8 + store i32 %i37, i32* %i38, align 4 + store i64 0, i64* @c, align 8 + br label %bb32 + +bb39: ; preds = %bb32, %bb28, %bb24 + %i40 = load i32*, i32** %i3, align 8 + %i41 = load i32, i32* %i40, align 4 + %i42 = icmp ne i32 %i41, 0 + br i1 %i42, label %bb43, label %bb46 + +bb43: ; preds = %bb39 + %i44 = load i16, i16* @f, align 2 + %i45 = add i16 %i44, 1 + store i16 %i45, i16* @f, align 2 + br label %bb10 + +bb46: ; preds = %bb46, %bb39 + br label %bb46 + +bb47: ; preds = %bb10 + %i48 = load i32, i32* @e, align 4 + %i49 = add nsw i32 %i48, -1 + store i32 %i49, i32* @e, align 4 + br label %bb5 + +bb50: ; preds = %bb5 + ret void +} + +; Function Attrs: argmemonly nofree nosync nounwind willreturn +declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #2 + +define dso_local void @main() #3 { +bb: + ret void +} + +attributes #0 = { "no-jump-tables"="false" } +attributes #1 = { "target-features"="+transactional-execution,+vector,+vector-enhancements-1,+vector-enhancements-2" } +attributes #2 = { argmemonly nofree nosync nounwind willreturn } +attributes #3 = { "use-soft-float"="false" } +attributes #4 = { nounwind }