Summary: This patch extends the use of the OptimizationRemarkEmitter to provide information about loops that are not fused, and loops that are not eligible for fusion. In particular, it uses the OptimizationRemarkAnalysis to identify loops that are not eligible for fusion and the OptimizationRemarkMissed to identify loops that cannot be fused. It also reuses the statistics to provide the messages used in the OptimizationRemarks. This provides common message strings between the optimization remarks and the statistics. I would like feedback on this approach, in general. If people are OK with this, I will flesh out additional remarks in subsequent commits. Subscribers: hiraditya, jsji, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63844 llvm-svn: 367327
302 lines
14 KiB
LLVM
302 lines
14 KiB
LLVM
; RUN: opt -S -loop-fusion -pass-remarks-missed=loop-fusion -disable-output < %s 2>&1 | FileCheck %s
|
|
;
|
|
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
|
|
|
@B = common global [1024 x i32] zeroinitializer, align 16, !dbg !0
|
|
|
|
; CHECK: remark: diagnostics_missed.c:18:3: [non_adjacent]: entry and for.end: Loops are not adjacent
|
|
define void @non_adjacent(i32* noalias %A) !dbg !67 {
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.inc, %entry
|
|
%i.0 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
|
|
%exitcond1 = icmp ne i64 %i.0, 100
|
|
br i1 %exitcond1, label %for.body, label %for.cond.cleanup
|
|
|
|
for.cond.cleanup: ; preds = %for.cond
|
|
br label %for.end
|
|
|
|
for.body: ; preds = %for.cond
|
|
%sub = add nsw i64 %i.0, -3
|
|
%add = add nuw nsw i64 %i.0, 3
|
|
%mul = mul nsw i64 %sub, %add
|
|
%rem = srem i64 %mul, %i.0
|
|
%conv = trunc i64 %rem to i32
|
|
%arrayidx = getelementptr inbounds i32, i32* %A, i64 %i.0
|
|
store i32 %conv, i32* %arrayidx, align 4
|
|
br label %for.inc
|
|
|
|
for.inc: ; preds = %for.body
|
|
%inc = add nuw nsw i64 %i.0, 1, !dbg !86
|
|
br label %for.cond, !dbg !87, !llvm.loop !88
|
|
|
|
for.end: ; preds = %for.cond.cleanup
|
|
br label %for.cond2
|
|
|
|
for.cond2: ; preds = %for.inc13, %for.end
|
|
%i1.0 = phi i64 [ 0, %for.end ], [ %inc14, %for.inc13 ]
|
|
%exitcond = icmp ne i64 %i1.0, 100
|
|
br i1 %exitcond, label %for.body6, label %for.cond.cleanup5
|
|
|
|
for.cond.cleanup5: ; preds = %for.cond2
|
|
br label %for.end15
|
|
|
|
for.body6: ; preds = %for.cond2
|
|
%sub7 = add nsw i64 %i1.0, -3
|
|
%add8 = add nuw nsw i64 %i1.0, 3
|
|
%mul9 = mul nsw i64 %sub7, %add8
|
|
%rem10 = srem i64 %mul9, %i1.0
|
|
%conv11 = trunc i64 %rem10 to i32
|
|
%arrayidx12 = getelementptr inbounds [1024 x i32], [1024 x i32]* @B, i64 0, i64 %i1.0
|
|
store i32 %conv11, i32* %arrayidx12, align 4
|
|
br label %for.inc13
|
|
|
|
for.inc13: ; preds = %for.body6
|
|
%inc14 = add nuw nsw i64 %i1.0, 1, !dbg !100
|
|
br label %for.cond2, !dbg !101, !llvm.loop !102
|
|
|
|
for.end15: ; preds = %for.cond.cleanup5
|
|
ret void
|
|
}
|
|
|
|
|
|
; CHECK: remark: diagnostics_missed.c:28:3: [different_bounds]: entry and for.end: Loop trip counts are not the same
|
|
define void @different_bounds(i32* noalias %A) !dbg !105 {
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.inc, %entry
|
|
%i.0 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
|
|
%exitcond1 = icmp ne i64 %i.0, 100
|
|
br i1 %exitcond1, label %for.body, label %for.cond.cleanup
|
|
|
|
for.cond.cleanup: ; preds = %for.cond
|
|
br label %for.end
|
|
|
|
for.body: ; preds = %for.cond
|
|
%sub = add nsw i64 %i.0, -3
|
|
%add = add nuw nsw i64 %i.0, 3
|
|
%mul = mul nsw i64 %sub, %add
|
|
%rem = srem i64 %mul, %i.0
|
|
%conv = trunc i64 %rem to i32
|
|
%arrayidx = getelementptr inbounds i32, i32* %A, i64 %i.0
|
|
store i32 %conv, i32* %arrayidx, align 4
|
|
br label %for.inc
|
|
|
|
for.inc: ; preds = %for.body
|
|
%inc = add nuw nsw i64 %i.0, 1, !dbg !123
|
|
br label %for.cond, !dbg !124, !llvm.loop !125
|
|
|
|
for.end: ; preds = %for.cond.cleanup
|
|
br label %for.cond2
|
|
|
|
for.cond2: ; preds = %for.inc13, %for.end
|
|
%i1.0 = phi i64 [ 0, %for.end ], [ %inc14, %for.inc13 ]
|
|
%exitcond = icmp ne i64 %i1.0, 200
|
|
br i1 %exitcond, label %for.body6, label %for.cond.cleanup5
|
|
|
|
for.cond.cleanup5: ; preds = %for.cond2
|
|
br label %for.end15
|
|
|
|
for.body6: ; preds = %for.cond2
|
|
%sub7 = add nsw i64 %i1.0, -3
|
|
%add8 = add nuw nsw i64 %i1.0, 3
|
|
%mul9 = mul nsw i64 %sub7, %add8
|
|
%rem10 = srem i64 %mul9, %i1.0
|
|
%conv11 = trunc i64 %rem10 to i32
|
|
%arrayidx12 = getelementptr inbounds [1024 x i32], [1024 x i32]* @B, i64 0, i64 %i1.0
|
|
store i32 %conv11, i32* %arrayidx12, align 4
|
|
br label %for.inc13
|
|
|
|
for.inc13: ; preds = %for.body6
|
|
%inc14 = add nuw nsw i64 %i1.0, 1
|
|
br label %for.cond2, !dbg !138, !llvm.loop !139
|
|
|
|
for.end15: ; preds = %for.cond.cleanup5
|
|
ret void
|
|
}
|
|
|
|
; CHECK: remark: diagnostics_missed.c:38:3: [negative_dependence]: entry and for.end: Loop has a non-empty preheader
|
|
define void @negative_dependence(i32* noalias %A) !dbg !142 {
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.inc, %entry
|
|
%indvars.iv1 = phi i64 [ %indvars.iv.next2, %for.inc ], [ 0, %entry ]
|
|
%exitcond3 = icmp ne i64 %indvars.iv1, 100
|
|
br i1 %exitcond3, label %for.body, label %for.end
|
|
|
|
for.body: ; preds = %for.cond
|
|
%arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv1
|
|
%tmp = trunc i64 %indvars.iv1 to i32
|
|
store i32 %tmp, i32* %arrayidx, align 4
|
|
br label %for.inc
|
|
|
|
for.inc: ; preds = %for.body
|
|
%indvars.iv.next2 = add nuw nsw i64 %indvars.iv1, 1
|
|
br label %for.cond, !dbg !160, !llvm.loop !161
|
|
|
|
for.end: ; preds = %for.cond
|
|
call void @llvm.dbg.value(metadata i32 0, metadata !147, metadata !DIExpression()), !dbg !163
|
|
br label %for.cond2, !dbg !164
|
|
|
|
for.cond2: ; preds = %for.inc10, %for.end
|
|
%indvars.iv = phi i64 [ %indvars.iv.next, %for.inc10 ], [ 0, %for.end ]
|
|
%exitcond = icmp ne i64 %indvars.iv, 100
|
|
br i1 %exitcond, label %for.body5, label %for.end12
|
|
|
|
for.body5: ; preds = %for.cond2
|
|
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
|
|
%arrayidx7 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv.next
|
|
%tmp4 = load i32, i32* %arrayidx7, align 4
|
|
%mul = shl nsw i32 %tmp4, 1
|
|
%arrayidx9 = getelementptr inbounds [1024 x i32], [1024 x i32]* @B, i64 0, i64 %indvars.iv
|
|
store i32 %mul, i32* %arrayidx9, align 4
|
|
br label %for.inc10
|
|
|
|
for.inc10: ; preds = %for.body5
|
|
br label %for.cond2
|
|
|
|
for.end12: ; preds = %for.cond.
|
|
ret void, !dbg !178
|
|
}
|
|
|
|
; CHECK: remark: diagnostics_missed.c:51:3: [sumTest]: entry and for.cond2.preheader: Dependencies prevent fusion
|
|
define i32 @sumTest(i32* noalias %A) !dbg !179 {
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.inc, %entry
|
|
%indvars.iv1 = phi i64 [ %indvars.iv.next2, %for.inc ], [ 0, %entry ]
|
|
%sum.0 = phi i32 [ 0, %entry ], [ %add, %for.inc ]
|
|
%exitcond3 = icmp ne i64 %indvars.iv1, 100
|
|
br i1 %exitcond3, label %for.body, label %for.cond2
|
|
|
|
for.body: ; preds = %for.cond
|
|
br label %for.inc
|
|
|
|
for.inc: ; preds = %for.body
|
|
%arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv1
|
|
%tmp = load i32, i32* %arrayidx, align 4
|
|
%add = add nsw i32 %sum.0, %tmp
|
|
%indvars.iv.next2 = add nuw nsw i64 %indvars.iv1, 1
|
|
br label %for.cond, !dbg !199, !llvm.loop !200
|
|
|
|
for.cond2: ; preds = %for.inc10, %for.cond
|
|
%sum.0.lcssa = phi i32 [ %sum.0, %for.cond ], [ %sum.0.lcssa, %for.inc10 ]
|
|
%indvars.iv = phi i64 [ %indvars.iv.next, %for.inc10 ], [ 0, %for.cond ]
|
|
%exitcond = icmp ne i64 %indvars.iv, 100
|
|
br i1 %exitcond, label %for.body5, label %for.end12
|
|
|
|
for.body5: ; preds = %for.cond2
|
|
%arrayidx7 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
|
|
%tmp4 = load i32, i32* %arrayidx7, align 4
|
|
%div = sdiv i32 %tmp4, %sum.0.lcssa
|
|
%arrayidx9 = getelementptr inbounds [1024 x i32], [1024 x i32]* @B, i64 0, i64 %indvars.iv
|
|
store i32 %div, i32* %arrayidx9, align 4
|
|
br label %for.inc10
|
|
|
|
for.inc10: ; preds = %for.body5
|
|
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
|
|
br label %for.cond2
|
|
|
|
for.end12: ; preds = %for.cond2
|
|
ret i32 %sum.0.lcssa, !dbg !215
|
|
}
|
|
|
|
declare void @llvm.dbg.value(metadata, metadata, metadata)
|
|
|
|
|
|
!llvm.dbg.cu = !{!2}
|
|
!llvm.module.flags = !{!11, !12, !13, !14}
|
|
|
|
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
|
|
!1 = distinct !DIGlobalVariable(name: "B", scope: !2, file: !6, line: 46, type: !7, isLocal: false, isDefinition: true)
|
|
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 9.0.0 (git@github.ibm.com:compiler/llvm-project.git 23c4baaa9f5b33d2d52eda981d376c6b0a7a3180)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: GNU)
|
|
!3 = !DIFile(filename: "diagnostics_missed.c", directory: "/tmp")
|
|
!4 = !{}
|
|
!5 = !{!0}
|
|
!6 = !DIFile(filename: "diagnostics_missed.c", directory: "/tmp")
|
|
!7 = !DICompositeType(tag: DW_TAG_array_type, baseType: !8, size: 32768, elements: !9)
|
|
!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
!9 = !{!10}
|
|
!10 = !DISubrange(count: 1024)
|
|
!11 = !{i32 2, !"Dwarf Version", i32 4}
|
|
!12 = !{i32 2, !"Debug Info Version", i32 3}
|
|
!13 = !{i32 1, !"wchar_size", i32 4}
|
|
!14 = !{i32 7, !"PIC Level", i32 2}
|
|
!17 = !DISubroutineType(types: !18)
|
|
!18 = !{null, !19}
|
|
!19 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !20)
|
|
!20 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64)
|
|
!67 = distinct !DISubprogram(name: "non_adjacent", scope: !6, file: !6, line: 17, type: !17, scopeLine: 17, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !68)
|
|
!68 = !{!69, !70, !73}
|
|
!69 = !DILocalVariable(name: "A", arg: 1, scope: !67, file: !6, line: 17, type: !19)
|
|
!70 = !DILocalVariable(name: "i", scope: !71, file: !6, line: 18, type: !72)
|
|
!71 = distinct !DILexicalBlock(scope: !67, file: !6, line: 18, column: 3)
|
|
!72 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed)
|
|
!73 = !DILocalVariable(name: "i", scope: !74, file: !6, line: 22, type: !72)
|
|
!74 = distinct !DILexicalBlock(scope: !67, file: !6, line: 22, column: 3)
|
|
!79 = distinct !DILexicalBlock(scope: !71, file: !6, line: 18, column: 3)
|
|
!80 = !DILocation(line: 18, column: 3, scope: !71)
|
|
!86 = !DILocation(line: 18, column: 30, scope: !79)
|
|
!87 = !DILocation(line: 18, column: 3, scope: !79)
|
|
!88 = distinct !{!88, !80, !89}
|
|
!89 = !DILocation(line: 20, column: 3, scope: !71)
|
|
!93 = distinct !DILexicalBlock(scope: !74, file: !6, line: 22, column: 3)
|
|
!94 = !DILocation(line: 22, column: 3, scope: !74)
|
|
!100 = !DILocation(line: 22, column: 30, scope: !93)
|
|
!101 = !DILocation(line: 22, column: 3, scope: !93)
|
|
!102 = distinct !{!102, !94, !103}
|
|
!103 = !DILocation(line: 24, column: 3, scope: !74)
|
|
!105 = distinct !DISubprogram(name: "different_bounds", scope: !6, file: !6, line: 27, type: !17, scopeLine: 27, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !106)
|
|
!106 = !{!107, !108, !110}
|
|
!107 = !DILocalVariable(name: "A", arg: 1, scope: !105, file: !6, line: 27, type: !19)
|
|
!108 = !DILocalVariable(name: "i", scope: !109, file: !6, line: 28, type: !72)
|
|
!109 = distinct !DILexicalBlock(scope: !105, file: !6, line: 28, column: 3)
|
|
!110 = !DILocalVariable(name: "i", scope: !111, file: !6, line: 32, type: !72)
|
|
!111 = distinct !DILexicalBlock(scope: !105, file: !6, line: 32, column: 3)
|
|
!116 = distinct !DILexicalBlock(scope: !109, file: !6, line: 28, column: 3)
|
|
!117 = !DILocation(line: 28, column: 3, scope: !109)
|
|
!123 = !DILocation(line: 28, column: 30, scope: !116)
|
|
!124 = !DILocation(line: 28, column: 3, scope: !116)
|
|
!125 = distinct !{!125, !117, !126}
|
|
!126 = !DILocation(line: 30, column: 3, scope: !109)
|
|
!130 = distinct !DILexicalBlock(scope: !111, file: !6, line: 32, column: 3)
|
|
!131 = !DILocation(line: 32, column: 3, scope: !111)
|
|
!138 = !DILocation(line: 32, column: 3, scope: !130)
|
|
!139 = distinct !{!139, !131, !140}
|
|
!140 = !DILocation(line: 34, column: 3, scope: !111)
|
|
!142 = distinct !DISubprogram(name: "negative_dependence", scope: !6, file: !6, line: 37, type: !17, scopeLine: 37, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !143)
|
|
!143 = !{!144, !145, !147}
|
|
!144 = !DILocalVariable(name: "A", arg: 1, scope: !142, file: !6, line: 37, type: !19)
|
|
!145 = !DILocalVariable(name: "i", scope: !146, file: !6, line: 38, type: !8)
|
|
!146 = distinct !DILexicalBlock(scope: !142, file: !6, line: 38, column: 3)
|
|
!147 = !DILocalVariable(name: "i", scope: !148, file: !6, line: 42, type: !8)
|
|
!148 = distinct !DILexicalBlock(scope: !142, file: !6, line: 42, column: 3)
|
|
!153 = distinct !DILexicalBlock(scope: !146, file: !6, line: 38, column: 3)
|
|
!154 = !DILocation(line: 38, column: 3, scope: !146)
|
|
!160 = !DILocation(line: 38, column: 3, scope: !153)
|
|
!161 = distinct !{!161, !154, !162}
|
|
!162 = !DILocation(line: 40, column: 3, scope: !146)
|
|
!163 = !DILocation(line: 0, scope: !148)
|
|
!164 = !DILocation(line: 42, column: 8, scope: !148)
|
|
!178 = !DILocation(line: 45, column: 1, scope: !142)
|
|
!179 = distinct !DISubprogram(name: "sumTest", scope: !6, file: !6, line: 48, type: !180, scopeLine: 48, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !182)
|
|
!180 = !DISubroutineType(types: !181)
|
|
!181 = !{!8, !19}
|
|
!182 = !{!183, !184, !185, !187}
|
|
!183 = !DILocalVariable(name: "A", arg: 1, scope: !179, file: !6, line: 48, type: !19)
|
|
!184 = !DILocalVariable(name: "sum", scope: !179, file: !6, line: 49, type: !8)
|
|
!185 = !DILocalVariable(name: "i", scope: !186, file: !6, line: 51, type: !8)
|
|
!186 = distinct !DILexicalBlock(scope: !179, file: !6, line: 51, column: 3)
|
|
!187 = !DILocalVariable(name: "i", scope: !188, file: !6, line: 54, type: !8)
|
|
!188 = distinct !DILexicalBlock(scope: !179, file: !6, line: 54, column: 3)
|
|
!193 = distinct !DILexicalBlock(scope: !186, file: !6, line: 51, column: 3)
|
|
!194 = !DILocation(line: 51, column: 3, scope: !186)
|
|
!199 = !DILocation(line: 51, column: 3, scope: !193)
|
|
!200 = distinct !{!200, !194, !201}
|
|
!201 = !DILocation(line: 52, column: 15, scope: !186)
|
|
!215 = !DILocation(line: 57, column: 3, scope: !179)
|