Skip to content

Commit f75d4f3

Browse files
author
Aditya Nandakumar
committed
[GISel]: Provide standard interface to observe changes in GISel passes
https://reviews.llvm.org/D54980 This provides a standard API across GISel passes to observe and notify passes about changes (insertions/deletions/mutations) to MachineInstrs. This patch also removes the recordInsertion method in MachineIRBuilder and instead provides method to setObserver. Reviewed by: vkeles. llvm-svn: 348406
1 parent 09415a8 commit f75d4f3

22 files changed

+213
-114
lines changed

llvm/include/llvm/CodeGen/GlobalISel/Combiner.h

-10
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,6 @@ class CombinerInfo;
2424
class TargetPassConfig;
2525
class MachineFunction;
2626

27-
class CombinerChangeObserver {
28-
public:
29-
virtual ~CombinerChangeObserver() {}
30-
31-
/// An instruction was erased.
32-
virtual void erasedInstr(MachineInstr &MI) = 0;
33-
/// An instruction was created and inseerted into the function.
34-
virtual void createdInstr(MachineInstr &MI) = 0;
35-
};
36-
3727
class Combiner {
3828
public:
3929
Combiner(CombinerInfo &CombinerInfo, const TargetPassConfig *TPC);

llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,21 @@
2020

2121
namespace llvm {
2222

23-
class CombinerChangeObserver;
23+
class GISelChangeObserver;
2424
class MachineIRBuilder;
2525
class MachineRegisterInfo;
2626
class MachineInstr;
2727

2828
class CombinerHelper {
2929
MachineIRBuilder &Builder;
3030
MachineRegisterInfo &MRI;
31-
CombinerChangeObserver &Observer;
31+
GISelChangeObserver &Observer;
3232

3333
void eraseInstr(MachineInstr &MI);
3434
void scheduleForVisit(MachineInstr &MI);
3535

3636
public:
37-
CombinerHelper(CombinerChangeObserver &Observer, MachineIRBuilder &B);
37+
CombinerHelper(GISelChangeObserver &Observer, MachineIRBuilder &B);
3838

3939
/// If \p MI is COPY, try to combine it.
4040
/// Returns true if MI changed.

llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include <cassert>
1818
namespace llvm {
1919

20-
class CombinerChangeObserver;
20+
class GISelChangeObserver;
2121
class LegalizerInfo;
2222
class MachineInstr;
2323
class MachineIRBuilder;
@@ -43,7 +43,7 @@ class CombinerInfo {
4343
/// illegal ops that are created.
4444
bool LegalizeIllegalOps; // TODO: Make use of this.
4545
const LegalizerInfo *LInfo;
46-
virtual bool combine(CombinerChangeObserver &Observer, MachineInstr &MI,
46+
virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI,
4747
MachineIRBuilder &B) const = 0;
4848
};
4949
} // namespace llvm
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//== ----- llvm/CodeGen/GlobalISel/GISelChangeObserver.h ---------------------
2+
//== //
3+
//
4+
// The LLVM Compiler Infrastructure
5+
//
6+
// This file is distributed under the University of Illinois Open Source
7+
// License. See LICENSE.TXT for details.
8+
//
9+
//===----------------------------------------------------------------------===//
10+
//
11+
/// This contains common code to allow clients to notify changes to machine
12+
/// instr.
13+
//
14+
//===----------------------------------------------------------------------===//
15+
#ifndef LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H
16+
#define LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H
17+
18+
namespace llvm {
19+
/// Abstract class that contains various methods for clients to notify about
20+
/// changes. This should be the preferred way for APIs to notify changes.
21+
/// Typically calling erasedInstr/createdInstr multiple times should not affect
22+
/// the result. The observer would likely need to check if it was already
23+
/// notified earlier (consider using GISelWorkList).
24+
class MachineInstr;
25+
class GISelChangeObserver {
26+
public:
27+
virtual ~GISelChangeObserver() {}
28+
29+
/// An instruction was erased.
30+
virtual void erasedInstr(MachineInstr &MI) = 0;
31+
/// An instruction was created and inserted into the function.
32+
virtual void createdInstr(MachineInstr &MI) = 0;
33+
/// This instruction was mutated in some way.
34+
virtual void changedInstr(MachineInstr &MI) = 0;
35+
};
36+
37+
} // namespace llvm
38+
#endif

llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ namespace llvm {
3232
class LegalizerInfo;
3333
class Legalizer;
3434
class MachineRegisterInfo;
35+
class GISelChangeObserver;
3536

3637
class LegalizerHelper {
3738
public:
@@ -48,8 +49,9 @@ class LegalizerHelper {
4849
UnableToLegalize,
4950
};
5051

51-
LegalizerHelper(MachineFunction &MF);
52-
LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI);
52+
LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer);
53+
LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
54+
GISelChangeObserver &Observer);
5355

5456
/// Replace \p MI by a sequence of legal instructions that can implement the
5557
/// same operation. Note that this means \p MI may be deleted, so any iterator
@@ -117,6 +119,8 @@ class LegalizerHelper {
117119

118120
MachineRegisterInfo &MRI;
119121
const LegalizerInfo &LI;
122+
/// To keep track of changes made by the LegalizerHelper.
123+
GISelChangeObserver &Observer;
120124
};
121125

122126
/// Helper function that creates the given libcall.

llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class MachineInstr;
3939
class MachineIRBuilder;
4040
class MachineRegisterInfo;
4141
class MCInstrInfo;
42+
class GISelChangeObserver;
4243

4344
namespace LegalizeActions {
4445
enum LegalizeAction : std::uint8_t {
@@ -949,9 +950,9 @@ class LegalizerInfo {
949950

950951
bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
951952

952-
virtual bool legalizeCustom(MachineInstr &MI,
953-
MachineRegisterInfo &MRI,
954-
MachineIRBuilder &MIRBuilder) const;
953+
virtual bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI,
954+
MachineIRBuilder &MIRBuilder,
955+
GISelChangeObserver &Observer) const;
955956

956957
private:
957958
/// Determine what action should be taken to legalize the given generic

llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h

+5-7
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ namespace llvm {
3030
class MachineFunction;
3131
class MachineInstr;
3232
class TargetInstrInfo;
33+
class GISelChangeObserver;
3334

3435
/// Class which stores all the state required in a MachineIRBuilder.
3536
/// Since MachineIRBuilders will only store state in this object, it allows
@@ -50,7 +51,7 @@ struct MachineIRBuilderState {
5051
MachineBasicBlock::iterator II;
5152
/// @}
5253

53-
std::function<void(MachineInstr *)> InsertedInstr;
54+
GISelChangeObserver *Observer;
5455
};
5556

5657
/// Helper class to build MachineInstr.
@@ -61,6 +62,7 @@ class MachineIRBuilderBase {
6162

6263
MachineIRBuilderState State;
6364
void validateTruncExt(unsigned Dst, unsigned Src, bool IsExtend);
65+
void recordInsertion(MachineInstr *MI) const;
6466

6567
protected:
6668
unsigned getDestFromArg(unsigned Reg) { return Reg; }
@@ -151,12 +153,8 @@ class MachineIRBuilderBase {
151153
void setInstr(MachineInstr &MI);
152154
/// @}
153155

154-
/// \name Control where instructions we create are recorded (typically for
155-
/// visiting again later during legalization).
156-
/// @{
157-
void recordInsertion(MachineInstr *InsertedInstr) const;
158-
void recordInsertions(std::function<void(MachineInstr *)> InsertedInstr);
159-
void stopRecordingInsertions();
156+
void setChangeObserver(GISelChangeObserver &Observer);
157+
void stopObservingChanges();
160158
/// @}
161159

162160
/// Set the debug location to \p DL for all the next build instructions.

llvm/lib/CodeGen/GlobalISel/Combiner.cpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "llvm/CodeGen/GlobalISel/Combiner.h"
15+
#include "llvm/ADT/PostOrderIterator.h"
1516
#include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
16-
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
17-
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
17+
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
1818
#include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
19-
#include "llvm/ADT/PostOrderIterator.h"
19+
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
2020
#include "llvm/CodeGen/GlobalISel/Utils.h"
21+
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
2122
#include "llvm/CodeGen/MachineRegisterInfo.h"
2223
#include "llvm/Support/Debug.h"
2324

@@ -34,7 +35,7 @@ namespace {
3435
/// instruction creation will schedule that instruction for a future visit.
3536
/// Other Combiner implementations may require more complex behaviour from
3637
/// their CombinerChangeObserver subclass.
37-
class WorkListMaintainer : public CombinerChangeObserver {
38+
class WorkListMaintainer : public GISelChangeObserver {
3839
using WorkListTy = GISelWorkList<512>;
3940
WorkListTy &WorkList;
4041

@@ -50,6 +51,11 @@ class WorkListMaintainer : public CombinerChangeObserver {
5051
LLVM_DEBUG(dbgs() << "Created: "; MI.print(dbgs()); dbgs() << "\n");
5152
WorkList.insert(&MI);
5253
}
54+
// Currently changed conservatively assumes erased.
55+
void changedInstr(MachineInstr &MI) override {
56+
LLVM_DEBUG(dbgs() << "Changed: "; MI.print(dbgs()); dbgs() << "\n");
57+
WorkList.remove(&MI);
58+
}
5359
};
5460
}
5561

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
// License. See LICENSE.TXT for details.
77
//
88
//===----------------------------------------------------------------------===//
9-
#include "llvm/CodeGen/GlobalISel/Combiner.h"
109
#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
10+
#include "llvm/CodeGen/GlobalISel/Combiner.h"
11+
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
1112
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
1213
#include "llvm/CodeGen/GlobalISel/Utils.h"
1314
#include "llvm/CodeGen/MachineInstr.h"
@@ -18,7 +19,7 @@
1819

1920
using namespace llvm;
2021

21-
CombinerHelper::CombinerHelper(CombinerChangeObserver &Observer,
22+
CombinerHelper::CombinerHelper(GISelChangeObserver &Observer,
2223
MachineIRBuilder &B)
2324
: Builder(B), MRI(Builder.getMF().getRegInfo()), Observer(Observer) {}
2425

llvm/lib/CodeGen/GlobalISel/Legalizer.cpp

+44-20
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "llvm/CodeGen/GlobalISel/Legalizer.h"
1717
#include "llvm/ADT/PostOrderIterator.h"
1818
#include "llvm/ADT/SetVector.h"
19+
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
1920
#include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
2021
#include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
2122
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
@@ -67,6 +68,42 @@ static bool isArtifact(const MachineInstr &MI) {
6768
return true;
6869
}
6970
}
71+
using InstListTy = GISelWorkList<256>;
72+
using ArtifactListTy = GISelWorkList<128>;
73+
74+
class LegalizerWorkListManager : public GISelChangeObserver {
75+
InstListTy &InstList;
76+
ArtifactListTy &ArtifactList;
77+
78+
public:
79+
LegalizerWorkListManager(InstListTy &Insts, ArtifactListTy &Arts)
80+
: InstList(Insts), ArtifactList(Arts) {}
81+
82+
void createdInstr(MachineInstr &MI) override {
83+
// Only legalize pre-isel generic instructions.
84+
// Legalization process could generate Target specific pseudo
85+
// instructions with generic types. Don't record them
86+
if (isPreISelGenericOpcode(MI.getOpcode())) {
87+
if (isArtifact(MI))
88+
ArtifactList.insert(&MI);
89+
else
90+
InstList.insert(&MI);
91+
}
92+
LLVM_DEBUG(dbgs() << ".. .. New MI: " << MI;);
93+
}
94+
95+
void erasedInstr(MachineInstr &MI) override {
96+
InstList.remove(&MI);
97+
ArtifactList.remove(&MI);
98+
}
99+
100+
void changedInstr(MachineInstr &MI) override {
101+
// When insts change, we want to revisit them to legalize them again.
102+
// We'll consider them the same as created.
103+
LLVM_DEBUG(dbgs() << ".. .. Changed MI: " << MI;);
104+
createdInstr(MI);
105+
}
106+
};
70107

71108
bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
72109
// If the ISel pipeline failed, do not bother running that pass.
@@ -77,14 +114,13 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
77114
init(MF);
78115
const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
79116
MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
80-
LegalizerHelper Helper(MF);
81117

82118
const size_t NumBlocks = MF.size();
83119
MachineRegisterInfo &MRI = MF.getRegInfo();
84120

85121
// Populate Insts
86-
GISelWorkList<256> InstList;
87-
GISelWorkList<128> ArtifactList;
122+
InstListTy InstList;
123+
ArtifactListTy ArtifactList;
88124
ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
89125
// Perform legalization bottom up so we can DCE as we legalize.
90126
// Traverse BB in RPOT and within each basic block, add insts top down,
@@ -103,24 +139,12 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
103139
InstList.insert(&MI);
104140
}
105141
}
106-
Helper.MIRBuilder.recordInsertions([&](MachineInstr *MI) {
107-
// Only legalize pre-isel generic instructions.
108-
// Legalization process could generate Target specific pseudo
109-
// instructions with generic types. Don't record them
110-
if (isPreISelGenericOpcode(MI->getOpcode())) {
111-
if (isArtifact(*MI))
112-
ArtifactList.insert(MI);
113-
else
114-
InstList.insert(MI);
115-
}
116-
LLVM_DEBUG(dbgs() << ".. .. New MI: " << *MI;);
117-
});
142+
LegalizerWorkListManager WorkListObserver(InstList, ArtifactList);
143+
LegalizerHelper Helper(MF, WorkListObserver);
118144
const LegalizerInfo &LInfo(Helper.getLegalizerInfo());
119145
LegalizationArtifactCombiner ArtCombiner(Helper.MIRBuilder, MF.getRegInfo(), LInfo);
120-
auto RemoveDeadInstFromLists = [&InstList,
121-
&ArtifactList](MachineInstr *DeadMI) {
122-
InstList.remove(DeadMI);
123-
ArtifactList.remove(DeadMI);
146+
auto RemoveDeadInstFromLists = [&WorkListObserver](MachineInstr *DeadMI) {
147+
WorkListObserver.erasedInstr(*DeadMI);
124148
};
125149
bool Changed = false;
126150
do {
@@ -138,7 +162,7 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
138162
// Error out if we couldn't legalize this instruction. We may want to
139163
// fall back to DAG ISel instead in the future.
140164
if (Res == LegalizerHelper::UnableToLegalize) {
141-
Helper.MIRBuilder.stopRecordingInsertions();
165+
Helper.MIRBuilder.stopObservingChanges();
142166
reportGISelFailure(MF, TPC, MORE, "gisel-legalize",
143167
"unable to legalize instruction", MI);
144168
return false;

0 commit comments

Comments
 (0)