OSDN Git Service

[PM] Teach SCEV to invalidate itself when its dependencies become
authorChandler Carruth <chandlerc@gmail.com>
Mon, 9 Jan 2017 07:44:34 +0000 (07:44 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Mon, 9 Jan 2017 07:44:34 +0000 (07:44 +0000)
invalid.

This fixes use-after-free bugs that will arise with any interesting use
of SCEV.

I've added a dedicated test that works diligently to trigger these kinds
of bugs in the new pass manager and also checks for them explicitly as
well as triggering ASan failures when things go squirly.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@291426 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/ScalarEvolution.h
lib/Analysis/ScalarEvolution.cpp
test/Analysis/ScalarEvolution/invalidation.ll [new file with mode: 0644]

index 9dcffe1..1a93f9a 100644 (file)
@@ -1491,6 +1491,8 @@ public:
 
   void print(raw_ostream &OS) const;
   void verify() const;
+  bool invalidate(Function &F, const PreservedAnalyses &PA,
+                  FunctionAnalysisManager::Invalidator &Inv);
 
   /// Collect parametric terms occurring in step expressions (first step of
   /// delinearization).
index 5e566bc..44f1a6d 100644 (file)
@@ -10012,6 +10012,18 @@ void ScalarEvolution::verify() const {
   // TODO: Verify more things.
 }
 
+bool ScalarEvolution::invalidate(
+    Function &F, const PreservedAnalyses &PA,
+    FunctionAnalysisManager::Invalidator &Inv) {
+  // Invalidate the ScalarEvolution object whenever it isn't preserved or one
+  // of its dependencies is invalidated.
+  auto PAC = PA.getChecker<ScalarEvolutionAnalysis>();
+  return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>()) ||
+         Inv.invalidate<AssumptionAnalysis>(F, PA) ||
+         Inv.invalidate<DominatorTreeAnalysis>(F, PA) ||
+         Inv.invalidate<LoopAnalysis>(F, PA);
+}
+
 AnalysisKey ScalarEvolutionAnalysis::Key;
 
 ScalarEvolution ScalarEvolutionAnalysis::run(Function &F,
diff --git a/test/Analysis/ScalarEvolution/invalidation.ll b/test/Analysis/ScalarEvolution/invalidation.ll
new file mode 100644 (file)
index 0000000..1fcaddb
--- /dev/null
@@ -0,0 +1,70 @@
+; Test that SCEV gets invalidated when one of its dependencies is invalidated.
+;
+; Each of the RUNs checks that the pass manager runs SCEV, then invalidates it
+; due to a dependency being invalidated, and then re-urns it. This will
+; directly fail and indicates a failure that would occur later if we ddidn't
+; invalidate SCEV in this way.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; RUN: opt < %s -passes='require<scalar-evolution>,invalidate<assumptions>,print<scalar-evolution>' \
+; RUN:     -debug-pass-manager -disable-output 2>&1 \
+; RUN:     | FileCheck %s -check-prefixes=CHECK,CHECK-AC-INVALIDATE
+;
+; CHECK-AC-INVALIDATE: Running pass: RequireAnalysisPass
+; CHECK-AC-INVALIDATE: Running analysis: ScalarEvolutionAnalysis
+; CHECK-AC-INVALIDATE: Running analysis: AssumptionAnalysis
+; CHECK-AC-INVALIDATE: Running pass: InvalidateAnalysisPass
+; CHECK-AC-INVALIDATE: Invalidating analysis: AssumptionAnalysis
+; CHECK-AC-INVALIDATE: Running pass: ScalarEvolutionPrinterPass
+; CHECK-AC-INVALIDATE: Running analysis: ScalarEvolutionAnalysis
+; CHECK-AC-INVALIDATE: Running analysis: AssumptionAnalysis
+
+; RUN: opt < %s -passes='require<scalar-evolution>,invalidate<domtree>,print<scalar-evolution>' \
+; RUN:     -debug-pass-manager -disable-output 2>&1 \
+; RUN:     | FileCheck %s -check-prefixes=CHECK,CHECK-DT-INVALIDATE
+;
+; CHECK-DT-INVALIDATE: Running pass: RequireAnalysisPass
+; CHECK-DT-INVALIDATE: Running analysis: ScalarEvolutionAnalysis
+; CHECK-DT-INVALIDATE: Running analysis: DominatorTreeAnalysis
+; CHECK-DT-INVALIDATE: Running pass: InvalidateAnalysisPass
+; CHECK-DT-INVALIDATE: Invalidating analysis: DominatorTreeAnalysis
+; CHECK-DT-INVALIDATE: Running pass: ScalarEvolutionPrinterPass
+; CHECK-DT-INVALIDATE: Running analysis: ScalarEvolutionAnalysis
+; CHECK-DT-INVALIDATE: Running analysis: DominatorTreeAnalysis
+
+; RUN: opt < %s -passes='require<scalar-evolution>,invalidate<loops>,print<scalar-evolution>' \
+; RUN:     -debug-pass-manager -disable-output 2>&1 \
+; RUN:     | FileCheck %s -check-prefixes=CHECK,CHECK-LI-INVALIDATE
+;
+; CHECK-LI-INVALIDATE: Running pass: RequireAnalysisPass
+; CHECK-LI-INVALIDATE: Running analysis: ScalarEvolutionAnalysis
+; CHECK-LI-INVALIDATE: Running analysis: LoopAnalysis
+; CHECK-LI-INVALIDATE: Running pass: InvalidateAnalysisPass
+; CHECK-LI-INVALIDATE: Invalidating analysis: LoopAnalysis
+; CHECK-LI-INVALIDATE: Running pass: ScalarEvolutionPrinterPass
+; CHECK-LI-INVALIDATE: Running analysis: ScalarEvolutionAnalysis
+; CHECK-LI-INVALIDATE: Running analysis: LoopAnalysis
+
+; This test isn't particularly interesting, its just enough to make sure we
+; actually do some work inside of SCEV so that if we regress here despite the
+; debug pass printing continuing to match, ASan and other tools can catch it.
+define void @test(i32 %n) {
+; CHECK-LABEL: Classifying expressions for: @test
+; CHECK: Loop %loop: backedge-taken count is 14
+; CHECK: Loop %loop: max backedge-taken count is 14
+; CHECK: Loop %loop: Predicated backedge-taken count is 14
+
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
+  %iv.inc = add nsw i32 %iv, 3
+  %becond = icmp ne i32 %iv.inc, 46
+  br i1 %becond, label %loop, label %leave
+
+leave:
+  ret void
+}