Skip to content

Commit 985d7c3

Browse files
committed
[MachineVerifier] Report errors from one thread at a time
1 parent af4a68e commit 985d7c3

File tree

2 files changed

+118
-42
lines changed

2 files changed

+118
-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: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# RUN: not --crash llc -march=x86-64 -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
2+
# This test ensures that the address is checked in machine verifier.
3+
4+
---
5+
name: baz
6+
tracksRegLiveness: true
7+
body: |
8+
bb.0:
9+
successors: %bb.1(0x80000000)
10+
liveins: $rdi, $xmm0
11+
12+
%1:vr128 = COPY $xmm0
13+
%0:gr64 = COPY $rdi
14+
%2:vr128 = COPY %1
15+
16+
bb.1:
17+
successors: %bb.1(0x80000000)
18+
19+
%3:vr256 = AVX_SET0
20+
%4:vr128 = VPSLLDri %2, 31
21+
%5:vr256 = VPMOVSXDQYrr killed %4
22+
%8:vr256 = IMPLICIT_DEF
23+
%6:vr256, %7:vr256 = VGATHERQPDYrm %3, %0, 16, killed %8, 0, $noreg, %5 :: (load unknown-size, align 8)
24+
%9:vr128 = COPY %6.sub_xmm
25+
VMOVLPDmr $noreg, 1, $noreg, 1111111111111, $noreg, killed %9 :: (store (s64) into `ptr undef`)
26+
JMP_1 %bb.1
27+
28+
...
29+
---
30+
name: bar
31+
tracksRegLiveness: true
32+
body: |
33+
bb.0:
34+
successors: %bb.1(0x80000000)
35+
liveins: $rdi, $xmm0
36+
37+
%1:vr128 = COPY $xmm0
38+
%0:gr64 = COPY $rdi
39+
%2:vr128 = COPY %1
40+
41+
bb.1:
42+
successors: %bb.1(0x80000000)
43+
44+
%3:vr256 = AVX_SET0
45+
%4:vr128 = VPSLLDri %2, 31
46+
%5:vr256 = VPMOVSXDQYrr killed %4
47+
%8:vr256 = IMPLICIT_DEF
48+
%6:vr256, %7:vr256 = VGATHERQPDYrm %3, %0, 16, killed %8, 0, $noreg, %5 :: (load unknown-size, align 8)
49+
%9:vr128 = COPY %6.sub_xmm
50+
VMOVLPDmr $noreg, 1, $noreg, 1111111111111, $noreg, killed %9 :: (store (s64) into `ptr undef`)
51+
JMP_1 %bb.1
52+
53+
...
54+
55+
; CHECK: LLVM ERROR: Found 2 machine code errors

0 commit comments

Comments
 (0)