7777#include " llvm/Pass.h"
7878#include " llvm/Support/Casting.h"
7979#include " llvm/Support/ErrorHandling.h"
80+ #include " llvm/Support/ManagedStatic.h"
8081#include " llvm/Support/MathExtras.h"
8182#include " llvm/Support/ModRef.h"
83+ #include " llvm/Support/Mutex.h"
8284#include " llvm/Support/raw_ostream.h"
8385#include " llvm/Target/TargetMachine.h"
8486#include < algorithm>
@@ -93,21 +95,29 @@ using namespace llvm;
9395
9496namespace {
9597
98+ static ManagedStatic<sys::SmartMutex<true >> ReportedErrorsLock;
99+
96100struct MachineVerifier {
97101 MachineVerifier (MachineFunctionAnalysisManager &MFAM, const char *b,
98- raw_ostream *OS)
99- : MFAM(&MFAM), OS(OS ? *OS : nulls()), Banner(b) {}
102+ raw_ostream *OS, bool AbortOnError = true )
103+ : MFAM(&MFAM), OS(OS ? *OS : nulls()), Banner(b),
104+ ReportedErrs (AbortOnError) {}
100105
101- MachineVerifier (Pass *pass, const char *b, raw_ostream *OS)
102- : PASS(pass), OS(OS ? *OS : nulls()), Banner(b) {}
106+ MachineVerifier (Pass *pass, const char *b, raw_ostream *OS,
107+ bool AbortOnError = true )
108+ : PASS(pass), OS(OS ? *OS : nulls()), Banner(b),
109+ ReportedErrs(AbortOnError) {}
103110
104111 MachineVerifier (const char *b, LiveVariables *LiveVars,
105112 LiveIntervals *LiveInts, LiveStacks *LiveStks,
106- SlotIndexes *Indexes, raw_ostream *OS)
113+ SlotIndexes *Indexes, raw_ostream *OS,
114+ bool AbortOnError = true )
107115 : OS(OS ? *OS : nulls()), Banner(b), LiveVars(LiveVars),
108- LiveInts (LiveInts), LiveStks(LiveStks), Indexes(Indexes) {}
116+ LiveInts(LiveInts), LiveStks(LiveStks), Indexes(Indexes),
117+ ReportedErrs(AbortOnError) {}
109118
110- unsigned verify (const MachineFunction &MF);
119+ // / \returns true if no problems were found.
120+ bool verify (const MachineFunction &MF);
111121
112122 MachineFunctionAnalysisManager *MFAM = nullptr ;
113123 Pass *const PASS = nullptr ;
@@ -120,8 +130,6 @@ struct MachineVerifier {
120130 const MachineRegisterInfo *MRI = nullptr ;
121131 const RegisterBankInfo *RBI = nullptr ;
122132
123- unsigned foundErrors = 0 ;
124-
125133 // Avoid querying the MachineFunctionProperties for each operand.
126134 bool isFunctionRegBankSelected = false ;
127135 bool isFunctionSelected = false ;
@@ -231,6 +239,39 @@ struct MachineVerifier {
231239 LiveStacks *LiveStks = nullptr ;
232240 SlotIndexes *Indexes = nullptr ;
233241
242+ class ReportedErrors {
243+ unsigned NumReported = 0 ;
244+ bool AbortOnError;
245+
246+ public:
247+ ReportedErrors (bool AbortOnError) : AbortOnError(AbortOnError) {}
248+ ~ReportedErrors () {
249+ if (!hasError ())
250+ return ;
251+ if (AbortOnError)
252+ report_fatal_error (" Found " + Twine (NumReported) +
253+ " machine code errors." );
254+ // Since we haven't aborted, release the lock to allow other threads to
255+ // report errors.
256+ ReportedErrorsLock->unlock ();
257+ }
258+
259+ // / Increment the number of reported errors.
260+ // / \returns true if this is the first reported error.
261+ bool increment () {
262+ // If this is the first error this thread has encountered, grab the lock
263+ // to prevent other threads from reporting errors at the same time.
264+ // Otherwise we assume we already have the lock.
265+ if (!hasError ())
266+ ReportedErrorsLock->lock ();
267+ ++NumReported;
268+ return NumReported == 1 ;
269+ }
270+
271+ bool hasError () { return NumReported; }
272+ };
273+ ReportedErrors ReportedErrs;
274+
234275 // This is calculated only when trying to verify convergence control tokens.
235276 // Similar to the LLVM IR verifier, we calculate this locally instead of
236277 // relying on the pass manager.
@@ -337,11 +378,7 @@ struct MachineVerifierLegacyPass : public MachineFunctionPass {
337378 MachineFunctionProperties::Property::FailsVerification))
338379 return false ;
339380
340- unsigned FoundErrors =
341- MachineVerifier (this , Banner.c_str (), &errs ()).verify (MF);
342- if (FoundErrors)
343- report_fatal_error (" Found " + Twine (FoundErrors) +
344- " machine code errors." );
381+ MachineVerifier (this , Banner.c_str (), &errs ()).verify (MF);
345382 return false ;
346383 }
347384};
@@ -357,10 +394,7 @@ MachineVerifierPass::run(MachineFunction &MF,
357394 if (MF.getProperties ().hasProperty (
358395 MachineFunctionProperties::Property::FailsVerification))
359396 return PreservedAnalyses::all ();
360- unsigned FoundErrors =
361- MachineVerifier (MFAM, Banner.c_str (), &errs ()).verify (MF);
362- if (FoundErrors)
363- report_fatal_error (" Found " + Twine (FoundErrors) + " machine code errors." );
397+ MachineVerifier (MFAM, Banner.c_str (), &errs ()).verify (MF);
364398 return PreservedAnalyses::all ();
365399}
366400
@@ -380,31 +414,20 @@ void llvm::verifyMachineFunction(const std::string &Banner,
380414 // LiveIntervals *LiveInts;
381415 // LiveStacks *LiveStks;
382416 // SlotIndexes *Indexes;
383- unsigned FoundErrors =
384- MachineVerifier (nullptr , Banner.c_str (), &errs ()).verify (MF);
385- if (FoundErrors)
386- report_fatal_error (" Found " + Twine (FoundErrors) + " machine code errors." );
417+ MachineVerifier (nullptr , Banner.c_str (), &errs ()).verify (MF);
387418}
388419
389420bool MachineFunction::verify (Pass *p, const char *Banner, raw_ostream *OS,
390- bool AbortOnErrors) const {
391- MachineFunction &MF = const_cast <MachineFunction&>(*this );
392- unsigned FoundErrors = MachineVerifier (p, Banner, OS).verify (MF);
393- if (AbortOnErrors && FoundErrors)
394- report_fatal_error (" Found " +Twine (FoundErrors)+" machine code errors." );
395- return FoundErrors == 0 ;
421+ bool AbortOnError) const {
422+ return MachineVerifier (p, Banner, OS, AbortOnError).verify (*this );
396423}
397424
398425bool MachineFunction::verify (LiveIntervals *LiveInts, SlotIndexes *Indexes,
399426 const char *Banner, raw_ostream *OS,
400- bool AbortOnErrors) const {
401- MachineFunction &MF = const_cast <MachineFunction &>(*this );
402- unsigned FoundErrors =
403- MachineVerifier (Banner, nullptr , LiveInts, nullptr , Indexes, OS)
404- .verify (MF);
405- if (AbortOnErrors && FoundErrors)
406- report_fatal_error (" Found " + Twine (FoundErrors) + " machine code errors." );
407- return FoundErrors == 0 ;
427+ bool AbortOnError) const {
428+ return MachineVerifier (Banner, /* LiveVars=*/ nullptr , LiveInts,
429+ /* LiveStks=*/ nullptr , Indexes, OS, AbortOnError)
430+ .verify (*this );
408431}
409432
410433void MachineVerifier::verifySlotIndexes () const {
@@ -430,9 +453,7 @@ void MachineVerifier::verifyProperties(const MachineFunction &MF) {
430453 report (" Function has NoVRegs property but there are VReg operands" , &MF);
431454}
432455
433- unsigned MachineVerifier::verify (const MachineFunction &MF) {
434- foundErrors = 0 ;
435-
456+ bool MachineVerifier::verify (const MachineFunction &MF) {
436457 this ->MF = &MF;
437458 TM = &MF.getTarget ();
438459 TII = MF.getSubtarget ().getInstrInfo ();
@@ -447,7 +468,7 @@ unsigned MachineVerifier::verify(const MachineFunction &MF) {
447468 // it's expected that the MIR is somewhat broken but that's ok since we'll
448469 // reset it and clear the FailedISel attribute in ResetMachineFunctions.
449470 if (isFunctionFailedISel)
450- return foundErrors ;
471+ return true ;
451472
452473 isFunctionRegBankSelected = MF.getProperties ().hasProperty (
453474 MachineFunctionProperties::Property::RegBankSelected);
@@ -544,13 +565,13 @@ unsigned MachineVerifier::verify(const MachineFunction &MF) {
544565 regMasks.clear ();
545566 MBBInfoMap.clear ();
546567
547- return foundErrors ;
568+ return !ReportedErrs. hasError () ;
548569}
549570
550571void MachineVerifier::report (const char *msg, const MachineFunction *MF) {
551572 assert (MF);
552573 OS << ' \n ' ;
553- if (!foundErrors++ ) {
574+ if (ReportedErrs. increment () ) {
554575 if (Banner)
555576 OS << " # " << Banner << ' \n ' ;
556577
0 commit comments