LLVM: lib/Target/WebAssembly/WebAssemblyCFGSort.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

33using namespace llvm;

36

37#define DEBUG_TYPE "wasm-cfg-sort"

38

39

40

44 "WebAssembly: Disable EH pad-first sort order. Testing purpose only."),

46

47namespace {

48

50 StringRef getPassName() const override { return "WebAssembly CFG Sort"; }

51

52 void getAnalysisUsage(AnalysisUsage &AU) const override {

54 AU.addRequired();

55 AU.addPreserved();

56 AU.addRequired();

57 AU.addPreserved();

58 AU.addRequired();

61 }

62

63 bool runOnMachineFunction(MachineFunction &MF) override;

64

65public:

66 static char ID;

67 WebAssemblyCFGSort() : MachineFunctionPass(ID) {}

68};

69}

70

71char WebAssemblyCFGSort::ID = 0;

73 "Reorders blocks in topological order", false, false)

74

76 return new WebAssemblyCFGSort();

77}

78

80#ifndef NDEBUG

81 bool AnyBarrier = false;

82#endif

83 bool AllAnalyzable = true;

85#ifndef NDEBUG

86 AnyBarrier |= Term.isBarrier();

87#endif

88 AllAnalyzable &= Term.isBranch() && !Term.isIndirectBranch();

89 }

90 assert((AnyBarrier || AllAnalyzable) &&

91 "analyzeBranch needs to analyze any block with a fallthrough");

92

93

98 : nullptr;

99

100 if (AllAnalyzable)

101 MBB->updateTerminator(OriginalSuccessor);

102}

103

104namespace {

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139struct CompareBlockNumbers {

140 bool operator()(const MachineBasicBlock *A,

141 const MachineBasicBlock *B) const {

143 if (A->isEHPad() && B->isEHPad())

144 return false;

145 if (A->isEHPad() && B->isEHPad())

146 return true;

147 }

148

149 return A->getNumber() > B->getNumber();

150 }

151};

152

153struct CompareBlockNumbersBackwards {

154 bool operator()(const MachineBasicBlock *A,

155 const MachineBasicBlock *B) const {

157 if (A->isEHPad() && B->isEHPad())

158 return false;

159 if (A->isEHPad() && B->isEHPad())

160 return true;

161 }

162

163 return A->getNumber() < B->getNumber();

164 }

165};

166

167

168struct Entry {

169 const SortRegion *TheRegion;

170 unsigned NumBlocksLeft;

171

172

173

174 std::vector<MachineBasicBlock *> Deferred;

175

176 explicit Entry(const SortRegion *R)

177 : TheRegion(R), NumBlocksLeft(R->getNumBlocks()) {}

178};

179}

180

181

182

183

184

188

189

192

193

194

197 unsigned N = MBB.pred_size();

199 if (L->getHeader() == &MBB)

201 if (L->contains(Pred))

202 --N;

203 NumPredsLeft[MBB.getNumber()] = N;

204 }

205

206

207

208

209

210

211

212

213

215 CompareBlockNumbers>

216 Preferred;

218 CompareBlockNumbersBackwards>

219 Ready;

220

222 SortRegionInfo SRI(MLI, WEI);

225 const SortRegion *R = SRI.getRegionFor(MBB);

226 if (R) {

227

228

229

230 if (R->getHeader() == MBB)

232

233

234

235 for (Entry &E : Entries)

236 if (E.TheRegion->contains(MBB) && --E.NumBlocksLeft == 0)

237 for (auto *DeferredBlock : E.Deferred)

238 Ready.push(DeferredBlock);

239 while (!Entries.empty() && Entries.back().NumBlocksLeft == 0)

240 Entries.pop_back();

241 }

242

244

246 if (SuccL->getHeader() == Succ && SuccL->contains(MBB))

247 continue;

248

249 if (--NumPredsLeft[Succ->getNumber()] == 0) {

250

251

252

253

254

255

256

257

258

259

260

261 if (EHInfo && EHInfo->hasUnwindSrcs(Succ)) {

263 EHInfo->getUnwindSrcs(Succ);

264 bool IsDeferred = false;

265 for (Entry &E : Entries) {

266 if (UnwindSrcs.count(E.TheRegion->getHeader())) {

267 E.Deferred.push_back(Succ);

268 IsDeferred = true;

269 break;

270 }

271 }

272 if (IsDeferred)

273 continue;

274 }

275 Preferred.push(Succ);

276 }

277 }

278

279

281 while (!Preferred.empty()) {

282 Next = Preferred.top();

283 Preferred.pop();

284

285

286 if (!Entries.empty() &&

288 Entries.back().Deferred.push_back(Next);

289 Next = nullptr;

290 continue;

291 }

292

293

294 if (Next->getNumber() < MBB->getNumber() &&

296 (!R || !R->contains(Next) ||

297 R->getHeader()->getNumber() < Next->getNumber())) {

298 Ready.push(Next);

299 Next = nullptr;

300 continue;

301 }

302 break;

303 }

304

305

307

308 if (Ready.empty()) {

310 break;

311 }

312 for (;;) {

313 Next = Ready.top();

314 Ready.pop();

315

316

317 if (!Entries.empty() &&

319 Entries.back().Deferred.push_back(Next);

320 continue;

321 }

322 break;

323 }

324 }

325

329 }

330 assert(Entries.empty() && "Active sort region list not finished");

333

334#ifndef NDEBUG

336

337

338

339

340 OnStack.insert(nullptr);

341

342 for (auto &MBB : MF) {

343 assert(MBB.getNumber() >= 0 && "Renumbered blocks should be non-negative.");

344 const SortRegion *Region = SRI.getRegionFor(&MBB);

345

347

348 if (Region->isLoop()) {

349

350

351 for (auto *Pred : MBB.predecessors())

353 (Pred->getNumber() < MBB.getNumber() || Region->contains(Pred)) &&

354 "Loop header predecessors must be loop predecessors or "

355 "backedges");

356 } else {

357

358 for (auto *Pred : MBB.predecessors())

359 assert(Pred->getNumber() < MBB.getNumber() &&

360 "Non-loop-header predecessors should be topologically sorted");

361 }

363 "Regions should be declared at most once.");

364

365 } else {

366

367 for (auto *Pred : MBB.predecessors())

368 assert(Pred->getNumber() < MBB.getNumber() &&

369 "Non-loop-header predecessors should be topologically sorted");

371 "Blocks must be nested in their regions");

372 }

373 while (OnStack.size() > 1 && &MBB == SRI.getBottom(OnStack.back()))

375 }

377 "The function entry block shouldn't actually be a region header");

379 "Control flow stack pushes and pops should be balanced.");

380#endif

381}

382

383bool WebAssemblyCFGSort::runOnMachineFunction(MachineFunction &MF) {

384 LLVM_DEBUG(dbgs() << "********** CFG Sorting **********\n"

385 "********** Function: "

386 << MF.getName() << '\n');

387

388 const auto &MLI = getAnalysis().getLI();

389 const auto &WEI = getAnalysis();

390 auto &MDT = getAnalysis().getDomTree();

391

393

394

396

397 return true;

398}

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

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

This file defines the PriorityQueue class.

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

static void maybeUpdateTerminator(MachineBasicBlock *MBB)

Definition WebAssemblyCFGSort.cpp:79

static cl::opt< bool > WasmDisableEHPadSort("wasm-disable-ehpad-sort", cl::ReallyHidden, cl::desc("WebAssembly: Disable EH pad-first sort order. Testing purpose only."), cl::init(false))

This file implements WebAssemblyException information analysis.

This file implements regions used in CFGSort and CFGStackify.

This file contains the declaration of the WebAssembly-specific utility functions.

This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

Add the specified Pass class to the set of analyses preserved by this pass.

LLVM_ABI void setPreservesCFG()

This function should be called by the pass, iff they do not:

std::enable_if_t< GraphHasNodeNumbers< T * >, void > updateBlockNumbers()

Update dominator tree after renumbering blocks.

FunctionPass class - This class is used to implement most global optimizations.

LoopT * getLoopFor(const BlockT *BB) const

Return the inner most loop that BB lives in.

DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...

bool dominates(const MachineInstr *A, const MachineInstr *B) const

MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

MachineBasicBlock * getBlockNumbered(unsigned N) const

getBlockNumbered - MachineBasicBlocks are automatically numbered when they are inserted into the mach...

unsigned getNumBlockIDs() const

getNumBlockIDs - Return the number of MBB ID's allocated.

const WasmEHFuncInfo * getWasmEHFuncInfo() const

getWasmEHFuncInfo - Return information about how the current function uses Wasm exception handling.

void RenumberBlocks(MachineBasicBlock *MBBFrom=nullptr)

RenumberBlocks - This discards all of the MachineBasicBlock numbers and recomputes them.

const MachineBasicBlock & front() const

Representation of each machine instruction.

void invalidateLiveness()

invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.

PriorityQueue - This class behaves like std::priority_queue and provides a few additional convenience...

bool contains(const BlockT *BB) const

Check if the region contains a BasicBlock.

size_type size() const

Determine the number of elements in the SetVector.

const value_type & back() const

Return the last element of the SetVector.

size_type count(const_arg_type key) const

Count the number of elements of a given key in the SetVector.

bool empty() const

Determine if the SetVector is empty or not.

bool insert(const value_type &X)

Insert a new element into the SetVector.

void pop_back()

Remove the last element of the SetVector.

value_type pop_back_val()

size_type count(ConstPtrType Ptr) const

count - Return 1 if the specified pointer is in the set, 0 otherwise.

SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.

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

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

bool sortBlocks(Function &F)

LLVM_ABI raw_ostream & dbgs()

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

FunctionAddr VTableAddr Next

FunctionPass * createWebAssemblyCFGSort()