1; RUN: opt -S -passes=loop-rotate < %s | FileCheck --check-prefix=FULL %s 2; RUN: opt -S -passes=loop-rotate -rotation-prepare-for-lto < %s | FileCheck --check-prefix=PREPARE %s 3; RUN: opt -S -passes='require<target-ir>,require<assumptions>,loop(loop-rotate)' < %s | FileCheck --check-prefix=FULL %s 4; RUN: opt -S -passes='require<target-ir>,require<assumptions>,loop(loop-rotate)' -rotation-prepare-for-lto < %s | FileCheck --check-prefix=PREPARE %s 5 6; Test case to make sure loop-rotate avoids rotating during the prepare-for-lto 7; stage, when the header contains a call which may be inlined during the LTO stage. 8define void @test_prepare_for_lto() { 9; FULL-LABEL: @test_prepare_for_lto( 10; FULL-NEXT: entry: 11; FULL-NEXT: %array = alloca [20 x i32], align 16 12; FULL-NEXT: call void @may_be_inlined() 13; FULL-NEXT: br label %for.body 14; 15; PREPARE-LABEL: @test_prepare_for_lto( 16; PREPARE-NEXT: entry: 17; PREPARE-NEXT: %array = alloca [20 x i32], align 16 18; PREPARE-NEXT: br label %for.cond 19; 20entry: 21 %array = alloca [20 x i32], align 16 22 br label %for.cond 23 24for.cond: ; preds = %for.body, %entry 25 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ] 26 %cmp = icmp slt i32 %i.0, 100 27 call void @may_be_inlined() 28 br i1 %cmp, label %for.body, label %for.end 29 30for.body: ; preds = %for.cond 31 store i32 0, ptr %array, align 16 32 %inc = add nsw i32 %i.0, 1 33 br label %for.cond 34 35for.end: ; preds = %for.cond 36 ret void 37} 38 39define void @may_be_inlined() { 40 ret void 41} 42 43; Intrinsics, like @llvm.dbg.value are never inlined and should not block loop 44; rotation, even when preparing for LTO. 45define void @test_prepare_for_lto_intrinsic() !dbg !7 { 46; FULL-LABEL: @test_prepare_for_lto_intrinsic( 47; FULL-NEXT: entry: 48; FULL-NEXT: %array = alloca [20 x i32], align 16 49; FULL-NEXT: #dbg_value(i32 0, !12, !DIExpression(), !13 50; FULL-NEXT: br label %for.body 51; 52; PREPARE-LABEL: @test_prepare_for_lto_intrinsic( 53; PREPARE-NEXT: entry: 54; PREPARE-NEXT: %array = alloca [20 x i32], align 16 55; PREPARE-NEXT: #dbg_value(i32 0, !12, !DIExpression(), !13 56; PREPARE-NEXT: br label %for.body 57; 58entry: 59 %array = alloca [20 x i32], align 16 60 br label %for.cond 61 62for.cond: ; preds = %for.body, %entry 63 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ] 64 call void @llvm.dbg.value(metadata i32 %i.0, metadata !12, metadata !DIExpression()), !dbg !13 65 %cmp = icmp slt i32 %i.0, 100 66 br i1 %cmp, label %for.body, label %for.end 67 68for.body: ; preds = %for.cond 69 store i32 0, ptr %array, align 16 70 %inc = add nsw i32 %i.0, 1 71 br label %for.cond 72 73for.end: ; preds = %for.cond 74 ret void 75} 76 77declare void @llvm.dbg.value(metadata, metadata, metadata) #2 78 79 80!llvm.dbg.cu = !{!0} 81!llvm.module.flags = !{!3, !4, !5, !6} 82 83!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) 84!1 = !DIFile(filename: "test.c", directory: "/tmp") 85!2 = !{} 86!3 = !{i32 2, !"Dwarf Version", i32 4} 87!4 = !{i32 2, !"Debug Info Version", i32 3} 88!5 = !{i32 1, !"wchar_size", i32 4} 89!6 = !{i32 7, !"PIC Level", i32 2} 90!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) 91!8 = !DISubroutineType(types: !9) 92!9 = !{null, !10} 93!10 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed) 94!11 = !{!12} 95!12 = !DILocalVariable(name: "input", arg: 1, scope: !7, file: !1, line: 2, type: !10) 96!13 = !DILocation(line: 2, column: 15, scope: !7) 97