[llvm] aa5ec34 - [LoopDeletion] Emit a remark when a dead loop is deleted
Francis Visoiu Mistrih via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 3 15:41:44 PDT 2020
Author: Francis Visoiu Mistrih
Date: 2020-07-03T15:20:23-07:00
New Revision: aa5ec34e312699a2fe5263133129a1e103ac91ee
URL: https://github.com/llvm/llvm-project/commit/aa5ec34e312699a2fe5263133129a1e103ac91ee
DIFF: https://github.com/llvm/llvm-project/commit/aa5ec34e312699a2fe5263133129a1e103ac91ee.diff
LOG: [LoopDeletion] Emit a remark when a dead loop is deleted
This emits a remark when LoopDeletion deletes a dead loop, using the
source location of the loop's header. There are currently two reasons
for removing the loop: invariant loop or loop that never executes.
Differential Revision: https://reviews.llvm.org/D83113
Added:
llvm/test/Transforms/LoopDeletion/basic-remark.ll
Modified:
llvm/lib/Transforms/Scalar/LoopDeletion.cpp
llvm/test/Transforms/LoopDeletion/unreachable-loops.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
index 19493405c41c..be209d34be42 100644
--- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
@@ -19,6 +19,7 @@
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/MemorySSA.h"
+#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/InitializePasses.h"
@@ -136,7 +137,8 @@ static bool isLoopNeverExecuted(Loop *L) {
/// instructions out of the loop.
static LoopDeletionResult deleteLoopIfDead(Loop *L, DominatorTree &DT,
ScalarEvolution &SE, LoopInfo &LI,
- MemorySSA *MSSA) {
+ MemorySSA *MSSA,
+ OptimizationRemarkEmitter &ORE) {
assert(L->isLCSSAForm(DT) && "Expected LCSSA!");
// We can only remove the loop if there is a preheader that we can branch from
@@ -166,6 +168,11 @@ static LoopDeletionResult deleteLoopIfDead(Loop *L, DominatorTree &DT,
std::fill(P.incoming_values().begin(), P.incoming_values().end(),
UndefValue::get(P.getType()));
}
+ ORE.emit([&]() {
+ return OptimizationRemark(DEBUG_TYPE, "NeverExecutes", L->getStartLoc(),
+ L->getHeader())
+ << "Loop deleted because it never executes";
+ });
deleteDeadLoop(L, &DT, &SE, &LI, MSSA);
++NumDeleted;
return LoopDeletionResult::Deleted;
@@ -202,6 +209,11 @@ static LoopDeletionResult deleteLoopIfDead(Loop *L, DominatorTree &DT,
}
LLVM_DEBUG(dbgs() << "Loop is invariant, delete it!");
+ ORE.emit([&]() {
+ return OptimizationRemark(DEBUG_TYPE, "Invariant", L->getStartLoc(),
+ L->getHeader())
+ << "Loop deleted because it is invariant";
+ });
deleteDeadLoop(L, &DT, &SE, &LI, MSSA);
++NumDeleted;
@@ -215,7 +227,11 @@ PreservedAnalyses LoopDeletionPass::run(Loop &L, LoopAnalysisManager &AM,
LLVM_DEBUG(dbgs() << "Analyzing Loop for deletion: ");
LLVM_DEBUG(L.dump());
std::string LoopName = std::string(L.getName());
- auto Result = deleteLoopIfDead(&L, AR.DT, AR.SE, AR.LI, AR.MSSA);
+ // For the new PM, we can't use OptimizationRemarkEmitter as an analysis
+ // pass. Function analyses need to be preserved across loop transformations
+ // but ORE cannot be preserved (see comment before the pass definition).
+ OptimizationRemarkEmitter ORE(L.getHeader()->getParent());
+ auto Result = deleteLoopIfDead(&L, AR.DT, AR.SE, AR.LI, AR.MSSA, ORE);
if (Result == LoopDeletionResult::Unmodified)
return PreservedAnalyses::all();
@@ -265,11 +281,15 @@ bool LoopDeletionLegacyPass::runOnLoop(Loop *L, LPPassManager &LPM) {
MemorySSA *MSSA = nullptr;
if (MSSAAnalysis)
MSSA = &MSSAAnalysis->getMSSA();
+ // For the old PM, we can't use OptimizationRemarkEmitter as an analysis
+ // pass. Function analyses need to be preserved across loop transformations
+ // but ORE cannot be preserved (see comment before the pass definition).
+ OptimizationRemarkEmitter ORE(L->getHeader()->getParent());
LLVM_DEBUG(dbgs() << "Analyzing Loop for deletion: ");
LLVM_DEBUG(L->dump());
- LoopDeletionResult Result = deleteLoopIfDead(L, DT, SE, LI, MSSA);
+ LoopDeletionResult Result = deleteLoopIfDead(L, DT, SE, LI, MSSA, ORE);
if (Result == LoopDeletionResult::Deleted)
LPM.markLoopAsDeleted(*L);
diff --git a/llvm/test/Transforms/LoopDeletion/basic-remark.ll b/llvm/test/Transforms/LoopDeletion/basic-remark.ll
new file mode 100644
index 000000000000..c56ae9dcb03e
--- /dev/null
+++ b/llvm/test/Transforms/LoopDeletion/basic-remark.ll
@@ -0,0 +1,37 @@
+; RUN: opt -loop-deletion %s -o /dev/null --pass-remarks-output=%t --pass-remarks-filter=loop-delete
+; RUN: cat %t | FileCheck %s
+
+; Check that we use the right debug location: the loop header.
+; CHECK: --- !Passed
+; CHECK-NEXT: Pass: loop-delete
+; CHECK-NEXT: Name: Invariant
+; CHECK-NEXT: DebugLoc: { File: loop.c, Line: 2, Column: 3 }
+; CHECK-NEXT: Function: main
+; CHECK-NEXT: Args:
+; CHECK-NEXT: - String: Loop deleted because it is invariant
+; CHECK-NEXT: ...
+define i32 @main() local_unnamed_addr #0 {
+entry:
+ br label %for.cond, !dbg !9
+
+for.cond:
+ %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.cond ]
+ %cmp = icmp ult i32 %i.0, 1000
+ %inc = add nuw nsw i32 %i.0, 1
+ br i1 %cmp, label %for.cond, label %for.cond.cleanup
+
+for.cond.cleanup:
+ ret i32 0
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !2, nameTableKind: None, sysroot: "/")
+!1 = !DIFile(filename: "loop.c", directory: "")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!6 = distinct !DISubprogram(name: "main", scope: !7, file: !7, line: 1, type: !8, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
+!7 = !DIFile(filename: "loop.c", directory: "")
+!8 = !DISubroutineType(types: !2)
+!9 = !DILocation(line: 2, column: 3, scope: !6)
diff --git a/llvm/test/Transforms/LoopDeletion/unreachable-loops.ll b/llvm/test/Transforms/LoopDeletion/unreachable-loops.ll
index 5bdaeb11232a..a74ddf99285e 100644
--- a/llvm/test/Transforms/LoopDeletion/unreachable-loops.ll
+++ b/llvm/test/Transforms/LoopDeletion/unreachable-loops.ll
@@ -1,4 +1,5 @@
-; RUN: opt < %s -loop-deletion -verify-dom-info -S | FileCheck %s
+; RUN: opt < %s -loop-deletion -verify-dom-info --pass-remarks-output=%t --pass-remarks-filter=loop-delete -S | FileCheck %s
+; RUN: cat %t | FileCheck %s --check-prefix=REMARKS
; Checking that we can delete loops that are never executed.
; We do not change the constant conditional branch statement (where the not-taken target
@@ -10,6 +11,8 @@ define void @test1(i64 %n, i64 %m) nounwind {
; CHECK-LABEL: entry:
; CHECK-NEXT: br i1 true, label %return, label %bb.preheader
; CHECK-NOT: bb:
+; REMARKS-LABEL: Function: test1
+; REMARKS: Loop deleted because it never executes
entry:
br i1 true, label %return, label %bb
@@ -63,6 +66,8 @@ define i64 @test3(i64 %n, i64 %m, i64 %maybe_zero) nounwind {
; CHECK-LABEL: return:
; CHECK-NEXT: %x.lcssa = phi i64 [ 20, %entry ], [ %x.lcssa.ph, %return.loopexit ]
; CHECK-NEXT: ret i64 %x.lcssa
+; REMARKS-LABEL: Function: test3
+; REMARKS: Loop deleted because it never executes
entry:
br i1 false, label %bb, label %return
@@ -121,6 +126,8 @@ define void @test5(i64 %n, i64 %m, i1 %cond) nounwind {
; CHECK-LABEL: looppred2:
; CHECK-NEXT: br i1 true, label %return, label %bb.preheader
; CHECK-NOT: bb:
+; REMARKS-LABEL: Function: test5
+; REMARKS: Loop deleted because it never executes
entry:
br i1 %cond, label %looppred1, label %looppred2
@@ -179,6 +186,8 @@ define i64 @test7(i64 %n) {
; CHECK-LABEL: L1Latch:
; CHECK-NEXT: %y = phi i64 [ %y.next, %L1 ], [ %y.L2.lcssa, %L1Latch.loopexit ]
; CHECK: br i1 %cond2, label %exit, label %L1
+; REMARKS-LABEL: Function: test7
+; REMARKS: Loop deleted because it never executes
entry:
br label %L1
@@ -213,6 +222,8 @@ define void @test8(i64 %n) {
; CHECK-NEXT: br label %exit
; CHECK-LABEL: exit:
; CHECK-NEXT: ret void
+; REMARKS-LABEL: Function: test8
+; REMARKS: Loop deleted because it never executes
entry:
br label %L1
@@ -246,6 +257,8 @@ define void @test9(i64 %n) {
; CHECK-NEXT: br label %L3
; CHECK-LABEL: L3:
; CHECK: br i1 %cond2, label %L3, label %L1.loopexit
+; REMARKS-LABEL: Function: test9
+; REMARKS: Loop deleted because it never executes
entry:
br label %L1
@@ -311,6 +324,12 @@ define void @test11(i64 %n) {
; CHECK-NEXT: br label %exit
; CHECK-LABEL: exit:
; CHECK-NEXT: ret void
+; REMARKS-LABEL: Function: test11
+; REMARKS: Loop deleted because it is invariant
+; REMARKS-LABEL: Function: test11
+; REMARKS: Loop deleted because it never executes
+; REMARKS-LABEL: Function: test11
+; REMARKS: Loop deleted because it is invariant
entry:
br label %L1
@@ -345,6 +364,8 @@ define i64 @test12(i64 %n){
; CHECK-LABEL: exit:
; CHECK-NEXT: %y.phi = phi i64 [ undef, %L1.preheader ]
; CHECK-NEXT: ret i64 %y.phi
+; REMARKS-LABEL: Function: test12
+; REMARKS: Loop deleted because it never executes
entry:
br i1 true, label %exit1, label %L1
@@ -380,6 +401,8 @@ define i64 @test13(i64 %n) {
; CHECK-LABEL: exit:
; CHECK-NEXT: %y.phi = phi i64 [ undef, %L1.preheader ]
; CHECK-NEXT: ret i64 %y.phi
+; REMARKS-LABEL: Function: test13
+; REMARKS: Loop deleted because it never executes
entry:
br i1 true, label %exit1, label %L1
More information about the llvm-commits
mailing list