LLVM: lib/CodeGen/GlobalISel/Combiner.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

26

27#define DEBUG_TYPE "gi-combiner"

28

29using namespace llvm;

30

31STATISTIC(NumOneIteration, "Number of functions with one iteration");

32STATISTIC(NumTwoIterations, "Number of functions with two iterations");

34 "Number of functions with three or more iterations");

35

36namespace llvm {

38 "GlobalISel Combiner",

39 "Control the rules which are enabled. These options all take a comma "

40 "separated list of rules to disable and may be specified by number "

41 "or number range (e.g. 1-10)."

43 " They may also be specified by name."

44#endif

45);

46}

47

48

49

50

51

53protected:

54#ifndef NDEBUG

55

56

58#endif

60

61public:

62 static std::unique_ptr

64

66

70 dbgs() << "Created: " << *MI;

71 }

73 });

74 }

75

78};

79

80

81

82

83template <CombinerInfo::ObserverLevel Lvl>

85 WorkListTy &WorkList;

87

88

90

91

93

94public:

96 : WorkList(WorkList), MRI(MRI) {}

97

99

101 DeferList.clear();

102 LostUses.clear();

103 }

104

106

108 WorkList.remove(&MI);

109 if constexpr (Lvl != Level::Basic) {

110 DeferList.remove(&MI);

112 }

113 }

114

117 if constexpr (Lvl == Level::Basic)

118 WorkList.insert(&MI);

119 else

120

121

122

123 DeferList.insert(&MI);

124 }

125

128

129

130

131

132 if constexpr (Lvl != Level::Basic)

134 }

135

138 if constexpr (Lvl == Level::Basic)

139 WorkList.insert(&MI);

140 else

141

142 DeferList.insert(&MI);

143 }

144

145

146

147

148

150 if constexpr (Lvl == Level::Basic)

151 return;

152

153

154 while (!DeferList.empty()) {

156 if (tryDCE(MI, MRI))

157 continue;

158

159 if constexpr (Lvl >= Level::SinglePass)

161

162 WorkList.insert(&MI);

163 }

164

165

166 while (!LostUses.empty()) {

170 continue;

171

172

173

174 if (tryDCE(*UseMI, MRI))

175 continue;

176

177 if constexpr (Lvl >= Level::SinglePass) {

178

179

180 if (MRI.hasOneNonDBGUser(Use))

181 WorkList.insert(&*MRI.use_instr_nodbg_begin(Use));

182

183 WorkList.insert(UseMI);

184 }

185 }

186 }

187

189 for (auto &Use : MI.explicit_uses()) {

190 if (Use.isReg() || Use.getReg().isVirtual())

191 continue;

192 LostUses.insert(Use.getReg());

193 }

194 }

195

197 for (auto &Def : MI.defs()) {

198 Register DefReg = Def.getReg();

200 continue;

201 for (auto &UseMI : MRI.use_nodbg_instructions(DefReg)) {

202 WorkList.insert(&UseMI);

203 }

204 }

205 }

206};

207

208std::unique_ptrCombiner::WorkListMaintainer

211 switch (Lvl) {

212 case Level::Basic:

213 return std::make_unique<WorkListMaintainerImplLevel::Basic>(WorkList,

215 case Level::DCE:

216 return std::make_unique<WorkListMaintainerImplLevel::DCE>(WorkList, MRI);

217 case Level::SinglePass:

218 return std::make_unique<WorkListMaintainerImplLevel::SinglePass>(WorkList,

220 }

222}

223

230 MF.getRegInfo())),

232 Observer(*ObserverWrapper), B(*Builder), MF(MF), MRI(MF.getRegInfo()),

234 (void)this->TPC;

235

236

237 B.setMF(MF);

240

241 B.setChangeObserver(*ObserverWrapper);

242}

243

245

248 return false;

251 MI.eraseFromParent();

252 return true;

253}

254

256

257

258 if (MF.getProperties().hasFailedISel())

259 return false;

260

261

262

263 if (!HasSetupMF) {

264 HasSetupMF = true;

266 }

267

268 LLVM_DEBUG(dbgs() << "Generic MI Combiner for: " << MF.getName() << '\n');

269

271

272 bool MFChanged = false;

274

275 unsigned Iteration = 0;

276 while (true) {

277 ++Iteration;

278 LLVM_DEBUG(dbgs() << "\n\nCombiner iteration #" << Iteration << '\n');

279

281 WorkList.clear();

282 WLObserver->reset();

283 ObserverWrapper->clearObservers();

285 ObserverWrapper->addObserver(CSEInfo);

286

287

288

290 ? CInfo.EnableFullDCE && Iteration == 1

291 : CInfo.EnableFullDCE;

292

293

294

295

300

301 if (EnableDCE && tryDCE(CurMI, MRI))

302 continue;

303 WorkList.deferred_insert(&CurMI);

304 }

305 }

306 WorkList.finalize();

307

308

309 ObserverWrapper->addObserver(WLObserver.get());

310

311 while (!WorkList.empty()) {

312 MachineInstr &CurrInst = *WorkList.pop_back_val();

313 LLVM_DEBUG(dbgs() << "\nTry combining " << CurrInst);

315 LLVM_DEBUG(WLObserver->reportFullyCreatedInstrs());

316 Changed |= AppliedCombine;

317 if (AppliedCombine)

318 WLObserver->appliedCombine();

319 }

321

323 LLVM_DEBUG(dbgs() << "\nCombiner reached fixed-point after iteration #"

324 << Iteration << '\n');

325 break;

326 }

327

328

329 if (CInfo.MaxIterations && Iteration >= CInfo.MaxIterations) {

331 dbgs() << "\nCombiner reached iteration limit after iteration #"

332 << Iteration << '\n');

333 break;

334 }

335 }

336

337 if (Iteration == 1)

338 ++NumOneIteration;

339 else if (Iteration == 2)

340 ++NumTwoIterations;

341 else

342 ++NumThreeOrMoreIterations;

343

344#ifndef NDEBUG

346 if (auto E = CSEInfo->verify()) {

347 errs() << E << '\n';

348 assert(false && "CSEInfo is not consistent. Likely missing calls to "

349 "observer on mutations.");

350 }

351 }

352#endif

353 return MFChanged;

354}

unsigned const MachineRegisterInfo * MRI

MachineInstrBuilder & UseMI

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

Provides analysis for continuously CSEing during GISel passes.

This file implements a version of MachineIRBuilder which CSEs insts within a MachineBasicBlock.

Option class for Targets to specify which operations are combined how and when.

This contains the base class for all Combiners generated by TableGen.

This contains common code to allow clients to notify changes to machine instr.

This file declares the MachineIRBuilder class.

This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.

This file implements a set that has insertion order iteration characteristics.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

~WorkListMaintainerImpl() override=default

void appliedCombine() override

Definition Combiner.cpp:149

void erasingInstr(MachineInstr &MI) override

An instruction is about to be erased.

Definition Combiner.cpp:105

void reset() override

Definition Combiner.cpp:100

void noteLostUses(MachineInstr &MI)

Definition Combiner.cpp:188

void changedInstr(MachineInstr &MI) override

This instruction was mutated in some way.

Definition Combiner.cpp:136

void changingInstr(MachineInstr &MI) override

This instruction is about to be mutated in some way.

Definition Combiner.cpp:126

WorkListMaintainerImpl(WorkListTy &WorkList, MachineRegisterInfo &MRI)

Definition Combiner.cpp:95

void createdInstr(MachineInstr &MI) override

An instruction has been created and inserted into the function.

Definition Combiner.cpp:115

void addUsersToWorkList(MachineInstr &MI)

Definition Combiner.cpp:196

This class acts as the glue that joins the CombinerHelper to the overall Combine algorithm.

Definition Combiner.cpp:52

void reportFullyCreatedInstrs()

Definition Combiner.cpp:67

virtual void appliedCombine()=0

~WorkListMaintainer() override=default

SmallSetVector< const MachineInstr *, 32 > CreatedInstrs

The instructions that have been created but we want to report once they have their operands.

Definition Combiner.cpp:57

static std::unique_ptr< WorkListMaintainer > create(Level Lvl, WorkListTy &WorkList, MachineRegisterInfo &MRI)

Definition Combiner.cpp:209

CombinerInfo::ObserverLevel Level

Definition Combiner.cpp:59

Defines a builder that does CSE of MachineInstructions using GISelCSEInfo.

Combiner(MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, GISelValueTracking *VT, GISelCSEInfo *CSEInfo=nullptr)

If CSEInfo is not null, then the Combiner will use CSEInfo as the observer and also create a CSEMIRBu...

Definition Combiner.cpp:224

bool combineMachineInstrs()

Definition Combiner.cpp:255

MachineRegisterInfo & MRI

const TargetPassConfig * TPC

GISelChangeObserver & Observer

virtual bool tryCombineAll(MachineInstr &I) const =0

virtual void setupMF(MachineFunction &mf, GISelValueTracking *vt, CodeGenCoverage *covinfo=nullptr, ProfileSummaryInfo *psi=nullptr, BlockFrequencyInfo *bfi=nullptr)

Setup per-MF executor state.

Abstract class that contains various methods for clients to notify about changes.

Simple wrapper observer that takes several observers, and calls each one for each event.

Helper class to build MachineInstr.

Representation of each machine instruction.

MachineRegisterInfo - Keep track of information for virtual and physical registers,...

Class to install both of the above.

Wrapper class representing virtual and physical registers.

constexpr bool isVirtual() const

Return true if the specified register number is in the virtual register namespace.

A SetVector that performs no allocations if smaller than a certain size.

Target-Independent Code Generator Pass Configuration Options.

A Use represents the edge between a Value definition and its users.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI)

Assuming the instruction MI is going to be deleted, attempt to salvage debug users of MI by writing t...

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

iterator_range< po_iterator< T > > post_order(const T &G)

auto reverse(ContainerTy &&C)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

cl::OptionCategory GICombinerOptionCategory("GlobalISel Combiner", "Control the rules which are enabled. These options all take a comma " "separated list of rules to disable and may be specified by number " "or number range (e.g. 1-10)." " They may also be specified by name.")

LLVM_ABI bool isTriviallyDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)

Check whether an instruction MI is dead: it only defines dead virtual registers, and doesn't have oth...

Implement std::hash so that hash_code can be used in STL containers.

@ DCE

Enables Observer-based detection of dead instructions.