Skip to content

Commit 4750222

Browse files
committed
[MachineVerifier] Report errors from one thread at a time
1 parent 774893d commit 4750222

File tree

2 files changed

+85
-42
lines changed

2 files changed

+85
-42
lines changed

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 63 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,10 @@
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

9496
namespace {
9597

98+
static ManagedStatic<sys::SmartMutex<true>> ReportedErrorsLock;
99+
96100
struct 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

389420
bool 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

398425
bool 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

410433
void 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

550571
void 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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# RUN: not --crash llc -mtriple=aarch64 -o /dev/null -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s --implicit-check-not="Bad machine code"
2+
# REQUIRES: aarch64-registered-target
3+
4+
# Check that errors are reported from only one function.
5+
# CHECK: *** Bad machine code: Generic virtual register use cannot be undef ***
6+
# CHECK: Found 1 machine code errors.
7+
8+
---
9+
name: foo
10+
liveins:
11+
body: |
12+
bb.0:
13+
$x0 = COPY undef %0:_(s64)
14+
...
15+
16+
---
17+
name: bar
18+
liveins:
19+
body: |
20+
bb.0:
21+
$x0 = COPY undef %0:_(s64)
22+
...

0 commit comments

Comments
 (0)