comparison unittests/IR/PassBuilderCallbacksTest.cpp @ 148:63bd29f05246

merged
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Wed, 14 Aug 2019 19:46:37 +0900
parents c2174574ed3a
children
comparison
equal deleted inserted replaced
146:3fc4d5c3e21e 148:63bd29f05246
1 //===- unittests/IR/PassBuilderCallbacksTest.cpp - PB Callback Tests --===// 1 //===- unittests/IR/PassBuilderCallbacksTest.cpp - PB Callback Tests --===//
2 // 2 //
3 // The LLVM Compiler Infrastructure 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // 4 // See https://llvm.org/LICENSE.txt for license information.
5 // This file is distributed under the University of Illinois Open Source 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 // License. See LICENSE.TXT for details.
7 // 6 //
8 //===----------------------------------------------------------------------===// 7 //===----------------------------------------------------------------------===//
9 8
9 #include "llvm/Testing/Support/Error.h"
10 #include <functional>
10 #include <gmock/gmock.h> 11 #include <gmock/gmock.h>
11 #include <gtest/gtest.h> 12 #include <gtest/gtest.h>
13 #include <llvm/ADT/Any.h>
12 #include <llvm/Analysis/CGSCCPassManager.h> 14 #include <llvm/Analysis/CGSCCPassManager.h>
13 #include <llvm/Analysis/LoopAnalysisManager.h> 15 #include <llvm/Analysis/LoopAnalysisManager.h>
14 #include <llvm/AsmParser/Parser.h> 16 #include <llvm/AsmParser/Parser.h>
15 #include <llvm/IR/LLVMContext.h> 17 #include <llvm/IR/LLVMContext.h>
18 #include <llvm/IR/PassInstrumentation.h>
16 #include <llvm/IR/PassManager.h> 19 #include <llvm/IR/PassManager.h>
17 #include <llvm/Passes/PassBuilder.h> 20 #include <llvm/Passes/PassBuilder.h>
21 #include <llvm/Support/Regex.h>
18 #include <llvm/Support/SourceMgr.h> 22 #include <llvm/Support/SourceMgr.h>
19 #include <llvm/Transforms/Scalar/LoopPassManager.h> 23 #include <llvm/Transforms/Scalar/LoopPassManager.h>
20 24
21 using namespace llvm; 25 using namespace llvm;
22 26
23 namespace llvm {
24 /// Provide an ostream operator for StringRef.
25 ///
26 /// For convenience we provide a custom matcher below for IRUnit's and analysis
27 /// result's getName functions, which most of the time returns a StringRef. The
28 /// matcher makes use of this operator.
29 static std::ostream &operator<<(std::ostream &O, StringRef S) {
30 return O << S.str();
31 }
32 }
33
34 namespace { 27 namespace {
28 using testing::AnyNumber;
29 using testing::AtLeast;
35 using testing::DoDefault; 30 using testing::DoDefault;
31 using testing::Not;
36 using testing::Return; 32 using testing::Return;
37 using testing::Expectation; 33 using testing::Expectation;
38 using testing::Invoke; 34 using testing::Invoke;
39 using testing::WithArgs; 35 using testing::WithArgs;
40 using testing::_; 36 using testing::_;
41 37
42 /// \brief A CRTP base for analysis mock handles 38 /// A CRTP base for analysis mock handles
43 /// 39 ///
44 /// This class reconciles mocking with the value semantics implementation of the 40 /// This class reconciles mocking with the value semantics implementation of the
45 /// AnalysisManager. Analysis mock handles should derive from this class and 41 /// AnalysisManager. Analysis mock handles should derive from this class and
46 /// call \c setDefault() in their constroctur for wiring up the defaults defined 42 /// call \c setDefault() in their constroctur for wiring up the defaults defined
47 /// by this base with their mock run() and invalidate() implementations. 43 /// by this base with their mock run() and invalidate() implementations.
85 81
86 Analysis getAnalysis() { return Analysis(static_cast<DerivedT &>(*this)); } 82 Analysis getAnalysis() { return Analysis(static_cast<DerivedT &>(*this)); }
87 typename Analysis::Result getResult() { 83 typename Analysis::Result getResult() {
88 return typename Analysis::Result(static_cast<DerivedT &>(*this)); 84 return typename Analysis::Result(static_cast<DerivedT &>(*this));
89 } 85 }
86 static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
90 87
91 protected: 88 protected:
92 // FIXME: MSVC seems unable to handle a lambda argument to Invoke from within 89 // FIXME: MSVC seems unable to handle a lambda argument to Invoke from within
93 // the template, so we use a boring static function. 90 // the template, so we use a boring static function.
94 static bool invalidateCallback(IRUnitT &IR, const PreservedAnalyses &PA, 91 static bool invalidateCallback(IRUnitT &IR, const PreservedAnalyses &PA,
108 ON_CALL(static_cast<DerivedT &>(*this), invalidate(_, _, _)) 105 ON_CALL(static_cast<DerivedT &>(*this), invalidate(_, _, _))
109 .WillByDefault(Invoke(&invalidateCallback)); 106 .WillByDefault(Invoke(&invalidateCallback));
110 } 107 }
111 }; 108 };
112 109
113 /// \brief A CRTP base for pass mock handles 110 /// A CRTP base for pass mock handles
114 /// 111 ///
115 /// This class reconciles mocking with the value semantics implementation of the 112 /// This class reconciles mocking with the value semantics implementation of the
116 /// PassManager. Pass mock handles should derive from this class and 113 /// PassManager. Pass mock handles should derive from this class and
117 /// call \c setDefault() in their constroctur for wiring up the defaults defined 114 /// call \c setDefault() in their constroctur for wiring up the defaults defined
118 /// by this base with their mock run() and invalidate() implementations. 115 /// by this base with their mock run() and invalidate() implementations.
140 PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, 137 PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
141 ExtraArgTs... ExtraArgs) { 138 ExtraArgTs... ExtraArgs) {
142 return Handle->run(IR, AM, ExtraArgs...); 139 return Handle->run(IR, AM, ExtraArgs...);
143 } 140 }
144 }; 141 };
142
143 static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
145 144
146 Pass getPass() { return Pass(static_cast<DerivedT &>(*this)); } 145 Pass getPass() { return Pass(static_cast<DerivedT &>(*this)); }
147 146
148 protected: 147 protected:
149 /// Derived classes should call this in their constructor to set up default 148 /// Derived classes should call this in their constructor to set up default
165 : MockPassHandleBase<MockPassHandle<Loop>, Loop, LoopAnalysisManager, 164 : MockPassHandleBase<MockPassHandle<Loop>, Loop, LoopAnalysisManager,
166 LoopStandardAnalysisResults &, LPMUpdater &> { 165 LoopStandardAnalysisResults &, LPMUpdater &> {
167 MOCK_METHOD4(run, 166 MOCK_METHOD4(run,
168 PreservedAnalyses(Loop &, LoopAnalysisManager &, 167 PreservedAnalyses(Loop &, LoopAnalysisManager &,
169 LoopStandardAnalysisResults &, LPMUpdater &)); 168 LoopStandardAnalysisResults &, LPMUpdater &));
169 static void invalidateLoop(Loop &L, LoopAnalysisManager &,
170 LoopStandardAnalysisResults &,
171 LPMUpdater &Updater) {
172 Updater.markLoopAsDeleted(L, L.getName());
173 }
170 MockPassHandle() { setDefaults(); } 174 MockPassHandle() { setDefaults(); }
171 }; 175 };
172 176
173 template <> 177 template <>
174 struct MockPassHandle<Function> 178 struct MockPassHandle<Function>
184 CGSCCAnalysisManager, LazyCallGraph &, 188 CGSCCAnalysisManager, LazyCallGraph &,
185 CGSCCUpdateResult &> { 189 CGSCCUpdateResult &> {
186 MOCK_METHOD4(run, 190 MOCK_METHOD4(run,
187 PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &, 191 PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
188 LazyCallGraph &G, CGSCCUpdateResult &UR)); 192 LazyCallGraph &G, CGSCCUpdateResult &UR));
193
194 static void invalidateSCC(LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
195 LazyCallGraph &, CGSCCUpdateResult &UR) {
196 UR.InvalidatedSCCs.insert(&C);
197 }
189 198
190 MockPassHandle() { setDefaults(); } 199 MockPassHandle() { setDefaults(); }
191 }; 200 };
192 201
193 template <> 202 template <>
255 264
256 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) { 265 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
257 SMDiagnostic Err; 266 SMDiagnostic Err;
258 return parseAssemblyString(IR, Err, C); 267 return parseAssemblyString(IR, Err, C);
259 } 268 }
269
270 /// Helper for HasName matcher that returns getName both for IRUnit and
271 /// for IRUnit pointer wrapper into llvm::Any (wrapped by PassInstrumentation).
272 template <typename IRUnitT> std::string getName(const IRUnitT &IR) {
273 return IR.getName();
274 }
275
276 template <> std::string getName(const StringRef &name) { return name; }
277
278 template <> std::string getName(const llvm::Any &WrappedIR) {
279 if (any_isa<const Module *>(WrappedIR))
280 return any_cast<const Module *>(WrappedIR)->getName().str();
281 if (any_isa<const Function *>(WrappedIR))
282 return any_cast<const Function *>(WrappedIR)->getName().str();
283 if (any_isa<const Loop *>(WrappedIR))
284 return any_cast<const Loop *>(WrappedIR)->getName().str();
285 if (any_isa<const LazyCallGraph::SCC *>(WrappedIR))
286 return any_cast<const LazyCallGraph::SCC *>(WrappedIR)->getName();
287 return "<UNKNOWN>";
288 }
289 /// Define a custom matcher for objects which support a 'getName' method.
290 ///
291 /// LLVM often has IR objects or analysis objects which expose a name
292 /// and in tests it is convenient to match these by name for readability.
293 /// Usually, this name is either a StringRef or a plain std::string. This
294 /// matcher supports any type exposing a getName() method of this form whose
295 /// return value is compatible with an std::ostream. For StringRef, this uses
296 /// the shift operator defined above.
297 ///
298 /// It should be used as:
299 ///
300 /// HasName("my_function")
301 ///
302 /// No namespace or other qualification is required.
303 MATCHER_P(HasName, Name, "") {
304 *result_listener << "has name '" << getName(arg) << "'";
305 return Name == getName(arg);
306 }
307
308 MATCHER_P(HasNameRegex, Name, "") {
309 *result_listener << "has name '" << getName(arg) << "'";
310 llvm::Regex r(Name);
311 return r.match(getName(arg));
312 }
313
314 struct MockPassInstrumentationCallbacks {
315 PassInstrumentationCallbacks Callbacks;
316
317 MockPassInstrumentationCallbacks() {
318 ON_CALL(*this, runBeforePass(_, _)).WillByDefault(Return(true));
319 }
320 MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any));
321 MOCK_METHOD2(runAfterPass, void(StringRef PassID, llvm::Any));
322 MOCK_METHOD1(runAfterPassInvalidated, void(StringRef PassID));
323 MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any));
324 MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any));
325
326 void registerPassInstrumentation() {
327 Callbacks.registerBeforePassCallback([this](StringRef P, llvm::Any IR) {
328 return this->runBeforePass(P, IR);
329 });
330 Callbacks.registerAfterPassCallback(
331 [this](StringRef P, llvm::Any IR) { this->runAfterPass(P, IR); });
332 Callbacks.registerAfterPassInvalidatedCallback(
333 [this](StringRef P) { this->runAfterPassInvalidated(P); });
334 Callbacks.registerBeforeAnalysisCallback([this](StringRef P, llvm::Any IR) {
335 return this->runBeforeAnalysis(P, IR);
336 });
337 Callbacks.registerAfterAnalysisCallback(
338 [this](StringRef P, llvm::Any IR) { this->runAfterAnalysis(P, IR); });
339 }
340
341 void ignoreNonMockPassInstrumentation(StringRef IRName) {
342 // Generic EXPECT_CALLs are needed to match instrumentation on unimportant
343 // parts of a pipeline that we do not care about (e.g. various passes added
344 // by default by PassBuilder - Verifier pass etc).
345 // Make sure to avoid ignoring Mock passes/analysis, we definitely want
346 // to check these explicitly.
347 EXPECT_CALL(*this,
348 runBeforePass(Not(HasNameRegex("Mock")), HasName(IRName)))
349 .Times(AnyNumber());
350 EXPECT_CALL(*this, runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName)))
351 .Times(AnyNumber());
352 EXPECT_CALL(*this,
353 runBeforeAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
354 .Times(AnyNumber());
355 EXPECT_CALL(*this,
356 runAfterAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
357 .Times(AnyNumber());
358 }
359 };
260 360
261 template <typename PassManagerT> class PassBuilderCallbacksTest; 361 template <typename PassManagerT> class PassBuilderCallbacksTest;
262 362
263 /// This test fixture is shared between all the actual tests below and 363 /// This test fixture is shared between all the actual tests below and
264 /// takes care of setting up appropriate defaults. 364 /// takes care of setting up appropriate defaults.
278 using AnalysisT = typename MockAnalysisHandle<IRUnitT>::Analysis; 378 using AnalysisT = typename MockAnalysisHandle<IRUnitT>::Analysis;
279 379
280 LLVMContext Context; 380 LLVMContext Context;
281 std::unique_ptr<Module> M; 381 std::unique_ptr<Module> M;
282 382
383 MockPassInstrumentationCallbacks CallbacksHandle;
384
283 PassBuilder PB; 385 PassBuilder PB;
284 ModulePassManager PM; 386 ModulePassManager PM;
285 LoopAnalysisManager LAM; 387 LoopAnalysisManager LAM;
286 FunctionAnalysisManager FAM; 388 FunctionAnalysisManager FAM;
287 CGSCCAnalysisManager CGAM; 389 CGSCCAnalysisManager CGAM;
310 " %cmp = icmp eq i32 %iv, %n\n" 412 " %cmp = icmp eq i32 %iv, %n\n"
311 " br i1 %cmp, label %exit, label %loop\n" 413 " br i1 %cmp, label %exit, label %loop\n"
312 "exit:\n" 414 "exit:\n"
313 " ret void\n" 415 " ret void\n"
314 "}\n")), 416 "}\n")),
417 CallbacksHandle(),
418 PB(nullptr, PipelineTuningOptions(), None, &CallbacksHandle.Callbacks),
315 PM(true), LAM(true), FAM(true), CGAM(true), AM(true) { 419 PM(true), LAM(true), FAM(true), CGAM(true), AM(true) {
316 420
317 /// Register a callback for analysis registration. 421 /// Register a callback for analysis registration.
318 /// 422 ///
319 /// The callback is a function taking a reference to an AnalyisManager 423 /// The callback is a function taking a reference to an AnalyisManager
354 PB.registerLoopAnalyses(LAM); 458 PB.registerLoopAnalyses(LAM);
355 PB.crossRegisterProxies(LAM, FAM, CGAM, AM); 459 PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
356 } 460 }
357 }; 461 };
358 462
359 /// Define a custom matcher for objects which support a 'getName' method.
360 ///
361 /// LLVM often has IR objects or analysis objects which expose a name
362 /// and in tests it is convenient to match these by name for readability.
363 /// Usually, this name is either a StringRef or a plain std::string. This
364 /// matcher supports any type exposing a getName() method of this form whose
365 /// return value is compatible with an std::ostream. For StringRef, this uses
366 /// the shift operator defined above.
367 ///
368 /// It should be used as:
369 ///
370 /// HasName("my_function")
371 ///
372 /// No namespace or other qualification is required.
373 MATCHER_P(HasName, Name, "") {
374 *result_listener << "has name '" << arg.getName() << "'";
375 return Name == arg.getName();
376 }
377
378 using ModuleCallbacksTest = PassBuilderCallbacksTest<ModulePassManager>; 463 using ModuleCallbacksTest = PassBuilderCallbacksTest<ModulePassManager>;
379 using CGSCCCallbacksTest = PassBuilderCallbacksTest<CGSCCPassManager>; 464 using CGSCCCallbacksTest = PassBuilderCallbacksTest<CGSCCPassManager>;
380 using FunctionCallbacksTest = PassBuilderCallbacksTest<FunctionPassManager>; 465 using FunctionCallbacksTest = PassBuilderCallbacksTest<FunctionPassManager>;
381 using LoopCallbacksTest = PassBuilderCallbacksTest<LoopPassManager>; 466 using LoopCallbacksTest = PassBuilderCallbacksTest<LoopPassManager>;
382 467
387 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)); 472 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
388 EXPECT_CALL(PassHandle, run(HasName("<string>"), _)) 473 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
389 .WillOnce(Invoke(getAnalysisResult)); 474 .WillOnce(Invoke(getAnalysisResult));
390 475
391 StringRef PipelineText = "test-transform"; 476 StringRef PipelineText = "test-transform";
392 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) 477 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
393 << "Pipeline was: " << PipelineText; 478 << "Pipeline was: " << PipelineText;
479
480 PM.run(*M, AM);
481 }
482
483 TEST_F(ModuleCallbacksTest, InstrumentedPasses) {
484 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
485 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
486 .WillOnce(Invoke(getAnalysisResult));
487
488 CallbacksHandle.registerPassInstrumentation();
489 // Non-mock instrumentation not specifically mentioned below can be ignored.
490 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
491
492 // PassInstrumentation calls should happen in-sequence, in the same order
493 // as passes/analyses are scheduled.
494 ::testing::Sequence PISequence;
495 EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
496 HasName("<string>")))
497 .InSequence(PISequence);
498 EXPECT_CALL(CallbacksHandle,
499 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"),
500 HasName("<string>")))
501 .InSequence(PISequence);
502 EXPECT_CALL(
503 CallbacksHandle,
504 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("<string>")))
505 .InSequence(PISequence);
506 EXPECT_CALL(CallbacksHandle,
507 runAfterPass(HasNameRegex("MockPassHandle"), HasName("<string>")))
508 .InSequence(PISequence);
509
510 StringRef PipelineText = "test-transform";
511 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
512 << "Pipeline was: " << PipelineText;
513
514 PM.run(*M, AM);
515 }
516
517 TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) {
518 CallbacksHandle.registerPassInstrumentation();
519 // Non-mock instrumentation run here can safely be ignored.
520 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
521
522 // Skip the pass by returning false.
523 EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
524 HasName("<string>")))
525 .WillOnce(Return(false));
526
527 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)).Times(0);
528 EXPECT_CALL(PassHandle, run(HasName("<string>"), _)).Times(0);
529
530 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
531 // as well.
532 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
533 .Times(0);
534 EXPECT_CALL(CallbacksHandle,
535 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
536 .Times(0);
537 EXPECT_CALL(CallbacksHandle,
538 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
539 .Times(0);
540
541 StringRef PipelineText = "test-transform";
542 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
543 << "Pipeline was: " << PipelineText;
544
394 PM.run(*M, AM); 545 PM.run(*M, AM);
395 } 546 }
396 547
397 TEST_F(FunctionCallbacksTest, Passes) { 548 TEST_F(FunctionCallbacksTest, Passes) {
398 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)); 549 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
399 EXPECT_CALL(PassHandle, run(HasName("foo"), _)) 550 EXPECT_CALL(PassHandle, run(HasName("foo"), _))
400 .WillOnce(Invoke(getAnalysisResult)); 551 .WillOnce(Invoke(getAnalysisResult));
401 552
402 StringRef PipelineText = "test-transform"; 553 StringRef PipelineText = "test-transform";
403 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) 554 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
555 << "Pipeline was: " << PipelineText;
556 PM.run(*M, AM);
557 }
558
559 TEST_F(FunctionCallbacksTest, InstrumentedPasses) {
560 CallbacksHandle.registerPassInstrumentation();
561 // Non-mock instrumentation not specifically mentioned below can be ignored.
562 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
563 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
564
565 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
566 EXPECT_CALL(PassHandle, run(HasName("foo"), _))
567 .WillOnce(Invoke(getAnalysisResult));
568
569 // PassInstrumentation calls should happen in-sequence, in the same order
570 // as passes/analyses are scheduled.
571 ::testing::Sequence PISequence;
572 EXPECT_CALL(CallbacksHandle,
573 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
574 .InSequence(PISequence);
575 EXPECT_CALL(
576 CallbacksHandle,
577 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
578 .InSequence(PISequence);
579 EXPECT_CALL(
580 CallbacksHandle,
581 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
582 .InSequence(PISequence);
583 EXPECT_CALL(CallbacksHandle,
584 runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo")))
585 .InSequence(PISequence);
586
587 // Our mock pass does not invalidate IR.
588 EXPECT_CALL(CallbacksHandle,
589 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
590 .Times(0);
591
592 StringRef PipelineText = "test-transform";
593 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
594 << "Pipeline was: " << PipelineText;
595 PM.run(*M, AM);
596 }
597
598 TEST_F(FunctionCallbacksTest, InstrumentedSkippedPasses) {
599 CallbacksHandle.registerPassInstrumentation();
600 // Non-mock instrumentation run here can safely be ignored.
601 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
602 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
603
604 // Skip the pass by returning false.
605 EXPECT_CALL(CallbacksHandle,
606 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
607 .WillOnce(Return(false));
608
609 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)).Times(0);
610 EXPECT_CALL(PassHandle, run(HasName("foo"), _)).Times(0);
611
612 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
613 // as well.
614 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
615 .Times(0);
616 EXPECT_CALL(CallbacksHandle,
617 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
618 .Times(0);
619 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
620 .Times(0);
621 EXPECT_CALL(CallbacksHandle,
622 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
623 .Times(0);
624 EXPECT_CALL(CallbacksHandle,
625 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
626 .Times(0);
627
628 StringRef PipelineText = "test-transform";
629 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
404 << "Pipeline was: " << PipelineText; 630 << "Pipeline was: " << PipelineText;
405 PM.run(*M, AM); 631 PM.run(*M, AM);
406 } 632 }
407 633
408 TEST_F(LoopCallbacksTest, Passes) { 634 TEST_F(LoopCallbacksTest, Passes) {
409 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)); 635 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
410 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)) 636 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
411 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult))); 637 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
412 638
413 StringRef PipelineText = "test-transform"; 639 StringRef PipelineText = "test-transform";
414 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) 640 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
641 << "Pipeline was: " << PipelineText;
642 PM.run(*M, AM);
643 }
644
645 TEST_F(LoopCallbacksTest, InstrumentedPasses) {
646 CallbacksHandle.registerPassInstrumentation();
647 // Non-mock instrumentation not specifically mentioned below can be ignored.
648 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
649 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
650 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
651
652 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
653 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
654 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
655
656 // PassInstrumentation calls should happen in-sequence, in the same order
657 // as passes/analyses are scheduled.
658 ::testing::Sequence PISequence;
659 EXPECT_CALL(CallbacksHandle,
660 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
661 .InSequence(PISequence);
662 EXPECT_CALL(
663 CallbacksHandle,
664 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
665 .InSequence(PISequence);
666 EXPECT_CALL(
667 CallbacksHandle,
668 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
669 .InSequence(PISequence);
670 EXPECT_CALL(CallbacksHandle,
671 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
672 .InSequence(PISequence);
673
674 // Our mock pass does not invalidate IR.
675 EXPECT_CALL(CallbacksHandle,
676 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
677 .Times(0);
678
679 StringRef PipelineText = "test-transform";
680 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
681 << "Pipeline was: " << PipelineText;
682 PM.run(*M, AM);
683 }
684
685 TEST_F(LoopCallbacksTest, InstrumentedInvalidatingPasses) {
686 CallbacksHandle.registerPassInstrumentation();
687 // Non-mock instrumentation not specifically mentioned below can be ignored.
688 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
689 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
690 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
691
692 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
693 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
694 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateLoop)),
695 WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
696
697 // PassInstrumentation calls should happen in-sequence, in the same order
698 // as passes/analyses are scheduled.
699 ::testing::Sequence PISequence;
700 EXPECT_CALL(CallbacksHandle,
701 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
702 .InSequence(PISequence);
703 EXPECT_CALL(
704 CallbacksHandle,
705 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
706 .InSequence(PISequence);
707 EXPECT_CALL(
708 CallbacksHandle,
709 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
710 .InSequence(PISequence);
711 EXPECT_CALL(CallbacksHandle,
712 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
713 .InSequence(PISequence);
714 EXPECT_CALL(CallbacksHandle,
715 runAfterPassInvalidated(HasNameRegex("^PassManager")))
716 .InSequence(PISequence);
717
718 // Our mock pass invalidates IR, thus normal runAfterPass is never called.
719 EXPECT_CALL(CallbacksHandle,
720 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
721 .Times(0);
722
723 StringRef PipelineText = "test-transform";
724 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
725 << "Pipeline was: " << PipelineText;
726 PM.run(*M, AM);
727 }
728
729 TEST_F(LoopCallbacksTest, InstrumentedSkippedPasses) {
730 CallbacksHandle.registerPassInstrumentation();
731 // Non-mock instrumentation run here can safely be ignored.
732 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
733 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
734 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
735
736 // Skip the pass by returning false.
737 EXPECT_CALL(CallbacksHandle,
738 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
739 .WillOnce(Return(false));
740
741 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)).Times(0);
742 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)).Times(0);
743
744 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
745 // as well.
746 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
747 .Times(0);
748 EXPECT_CALL(CallbacksHandle,
749 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
750 .Times(0);
751 EXPECT_CALL(CallbacksHandle,
752 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
753 .Times(0);
754 EXPECT_CALL(CallbacksHandle,
755 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
756 .Times(0);
757
758 StringRef PipelineText = "test-transform";
759 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
415 << "Pipeline was: " << PipelineText; 760 << "Pipeline was: " << PipelineText;
416 PM.run(*M, AM); 761 PM.run(*M, AM);
417 } 762 }
418 763
419 TEST_F(CGSCCCallbacksTest, Passes) { 764 TEST_F(CGSCCCallbacksTest, Passes) {
420 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)); 765 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
421 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)) 766 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
422 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult))); 767 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
423 768
424 StringRef PipelineText = "test-transform"; 769 StringRef PipelineText = "test-transform";
425 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) 770 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
771 << "Pipeline was: " << PipelineText;
772 PM.run(*M, AM);
773 }
774
775 TEST_F(CGSCCCallbacksTest, InstrumentedPasses) {
776 CallbacksHandle.registerPassInstrumentation();
777 // Non-mock instrumentation not specifically mentioned below can be ignored.
778 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
779 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
780
781 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
782 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
783 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
784
785 // PassInstrumentation calls should happen in-sequence, in the same order
786 // as passes/analyses are scheduled.
787 ::testing::Sequence PISequence;
788 EXPECT_CALL(CallbacksHandle,
789 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
790 .InSequence(PISequence);
791 EXPECT_CALL(
792 CallbacksHandle,
793 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
794 .InSequence(PISequence);
795 EXPECT_CALL(
796 CallbacksHandle,
797 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
798 .InSequence(PISequence);
799 EXPECT_CALL(CallbacksHandle,
800 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
801 .InSequence(PISequence);
802
803 // Our mock pass does not invalidate IR.
804 EXPECT_CALL(CallbacksHandle,
805 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
806 .Times(0);
807
808 StringRef PipelineText = "test-transform";
809 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
810 << "Pipeline was: " << PipelineText;
811 PM.run(*M, AM);
812 }
813
814 TEST_F(CGSCCCallbacksTest, InstrumentedInvalidatingPasses) {
815 CallbacksHandle.registerPassInstrumentation();
816 // Non-mock instrumentation not specifically mentioned below can be ignored.
817 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
818 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
819
820 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
821 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
822 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateSCC)),
823 WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
824
825 // PassInstrumentation calls should happen in-sequence, in the same order
826 // as passes/analyses are scheduled.
827 ::testing::Sequence PISequence;
828 EXPECT_CALL(CallbacksHandle,
829 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
830 .InSequence(PISequence);
831 EXPECT_CALL(
832 CallbacksHandle,
833 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
834 .InSequence(PISequence);
835 EXPECT_CALL(
836 CallbacksHandle,
837 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
838 .InSequence(PISequence);
839 EXPECT_CALL(CallbacksHandle,
840 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
841 .InSequence(PISequence);
842 EXPECT_CALL(CallbacksHandle,
843 runAfterPassInvalidated(HasNameRegex("^PassManager")))
844 .InSequence(PISequence);
845
846 // Our mock pass does invalidate IR, thus normal runAfterPass is never called.
847 EXPECT_CALL(CallbacksHandle,
848 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
849 .Times(0);
850
851 StringRef PipelineText = "test-transform";
852 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
853 << "Pipeline was: " << PipelineText;
854 PM.run(*M, AM);
855 }
856
857 TEST_F(CGSCCCallbacksTest, InstrumentedSkippedPasses) {
858 CallbacksHandle.registerPassInstrumentation();
859 // Non-mock instrumentation run here can safely be ignored.
860 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
861 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
862
863 // Skip the pass by returning false.
864 EXPECT_CALL(CallbacksHandle,
865 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
866 .WillOnce(Return(false));
867
868 // neither Analysis nor Pass are called.
869 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)).Times(0);
870 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)).Times(0);
871
872 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
873 // as well.
874 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
875 .Times(0);
876 EXPECT_CALL(CallbacksHandle,
877 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
878 .Times(0);
879 EXPECT_CALL(CallbacksHandle,
880 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
881 .Times(0);
882 EXPECT_CALL(CallbacksHandle,
883 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
884 .Times(0);
885
886 StringRef PipelineText = "test-transform";
887 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
426 << "Pipeline was: " << PipelineText; 888 << "Pipeline was: " << PipelineText;
427 PM.run(*M, AM); 889 PM.run(*M, AM);
428 } 890 }
429 891
430 /// Test parsing of the names of analysis utilities for our mock analysis 892 /// Test parsing of the names of analysis utilities for our mock analysis
435 TEST_F(ModuleCallbacksTest, AnalysisUtilities) { 897 TEST_F(ModuleCallbacksTest, AnalysisUtilities) {
436 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)); 898 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
437 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _)); 899 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
438 900
439 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>"; 901 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
440 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) 902 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
441 << "Pipeline was: " << PipelineText; 903 << "Pipeline was: " << PipelineText;
442 PM.run(*M, AM); 904 PM.run(*M, AM);
443 } 905 }
444 906
445 TEST_F(CGSCCCallbacksTest, PassUtilities) { 907 TEST_F(CGSCCCallbacksTest, PassUtilities) {
446 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)); 908 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
447 EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _)); 909 EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _));
448 910
449 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>"; 911 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
450 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) 912 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
451 << "Pipeline was: " << PipelineText; 913 << "Pipeline was: " << PipelineText;
452 PM.run(*M, AM); 914 PM.run(*M, AM);
453 } 915 }
454 916
455 TEST_F(FunctionCallbacksTest, AnalysisUtilities) { 917 TEST_F(FunctionCallbacksTest, AnalysisUtilities) {
456 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)); 918 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
457 EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _)); 919 EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _));
458 920
459 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>"; 921 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
460 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) 922 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
461 << "Pipeline was: " << PipelineText; 923 << "Pipeline was: " << PipelineText;
462 PM.run(*M, AM); 924 PM.run(*M, AM);
463 } 925 }
464 926
465 TEST_F(LoopCallbacksTest, PassUtilities) { 927 TEST_F(LoopCallbacksTest, PassUtilities) {
466 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)); 928 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
467 EXPECT_CALL(AnalysisHandle, invalidate(HasName("loop"), _, _)); 929 EXPECT_CALL(AnalysisHandle, invalidate(HasName("loop"), _, _));
468 930
469 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>"; 931 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
470 932
471 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) 933 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
472 << "Pipeline was: " << PipelineText; 934 << "Pipeline was: " << PipelineText;
473 PM.run(*M, AM); 935 PM.run(*M, AM);
474 } 936 }
475 937
476 /// Test parsing of the top-level pipeline. 938 /// Test parsing of the top-level pipeline.
506 .WillOnce(Invoke(getAnalysisResult)); 968 .WillOnce(Invoke(getAnalysisResult));
507 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _)); 969 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
508 970
509 StringRef PipelineText = 971 StringRef PipelineText =
510 "another-pipeline(test-transform,invalidate<test-analysis>)"; 972 "another-pipeline(test-transform,invalidate<test-analysis>)";
511 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) 973 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
512 << "Pipeline was: " << PipelineText; 974 << "Pipeline was: " << PipelineText;
513 PM.run(*M, AM); 975 PM.run(*M, AM);
514 976
515 /// Test the negative case 977 /// Test the negative case
516 PipelineText = "another-pipeline(instcombine)"; 978 PipelineText = "another-pipeline(instcombine)";
517 ASSERT_FALSE(PB.parsePassPipeline(PM, PipelineText, true)) 979 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Failed())
518 << "Pipeline was: " << PipelineText; 980 << "Pipeline was: " << PipelineText;
519 } 981 }
520 } // end anonymous namespace 982 } // end anonymous namespace