LLVM: lib/Transforms/Coroutines/MaterializationUtils.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

20#include

21

22using namespace llvm;

23

24using namespace coro;

25

26

27

28#define DEBUG_TYPE "coro-suspend-crossing"

29

30namespace {

31

32

33

34

35

36

37

38struct RematGraph {

39

40

41 struct RematNode {

44 RematNode() = default;

46 };

47

48 RematNode *EntryNode;

49 using RematNodeMap =

51 RematNodeMap Remats;

52 const std::function<bool(Instruction &)> &MaterializableCallback;

54

55 RematGraph(const std::function<bool(Instruction &)> &MaterializableCallback,

57 : MaterializableCallback(MaterializableCallback), Checker(Checker) {

58 std::unique_ptr FirstNode = std::make_unique(I);

59 EntryNode = FirstNode.get();

60 std::deque<std::unique_ptr> WorkList;

61 addNode(std::move(FirstNode), WorkList, cast(I));

62 while (WorkList.size()) {

63 std::unique_ptr N = std::move(WorkList.front());

64 WorkList.pop_front();

65 addNode(std::move(N), WorkList, cast(I));

66 }

67 }

68

69 void addNode(std::unique_ptr NUPtr,

70 std::deque<std::unique_ptr> &WorkList,

71 User *FirstUse) {

72 RematNode *N = NUPtr.get();

73 auto [It, Inserted] = Remats.try_emplace(N->Node);

74 if (!Inserted)

75 return;

76

77

78 It->second = std::move(NUPtr);

79 for (auto &Def : N->Node->operands()) {

81 if (D || !MaterializableCallback(*D) ||

83 continue;

84

85 if (auto It = Remats.find(D); It != Remats.end()) {

86

87 N->Operands.push_back(It->second.get());

88 continue;

89 }

90

91 bool NoMatch = true;

92 for (auto &I : WorkList) {

93 if (I->Node == D) {

94 NoMatch = false;

95 N->Operands.push_back(I.get());

96 break;

97 }

98 }

99 if (NoMatch) {

100

101 std::unique_ptr ChildNode = std::make_unique(D);

102 N->Operands.push_back(ChildNode.get());

103 WorkList.push_back(std::move(ChildNode));

104 }

105 }

106 }

107

108#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

113 return;

114 }

115

117 }

118

119 void dump() const {

120 BasicBlock *BB = EntryNode->Node->getParent();

122

125

126 dbgs() << "Entry (";

128 dbgs() << ") : " << *EntryNode->Node << "\n";

129 for (auto &E : Remats) {

130 dbgs() << *(E.first) << "\n";

131 for (RematNode *U : E.second->Operands)

132 dbgs() << " " << *U->Node << "\n";

133 }

134 }

135#endif

136};

137

138}

139

141 using NodeRef = RematGraph::RematNode *;

143

146 return N->Operands.begin();

147 }

149};

150

151

152

153

156 &AllRemats) {

157

158

159

160

161

162 typedef struct {

166 } ProcessNode;

167

169

170 for (const auto &E : AllRemats) {

172 Instruction *CurrentMaterialization = nullptr;

173 RematGraph *RG = E.second.get();

176

177

178

179

180

183 BasicBlock *SuspendPredecessorBlock =

184 Use->getParent()->getSinglePredecessor();

185 assert(SuspendPredecessorBlock && "malformed coro suspend instruction");

187 }

188

189

190

191 auto I = RPOT.begin();

192 ++I;

193 for (; I != RPOT.end(); ++I) {

195 CurrentMaterialization = D->clone();

196 CurrentMaterialization->setName(D->getName());

197 CurrentMaterialization->insertBefore(InsertPoint);

198 InsertPoint = CurrentMaterialization->getIterator();

199

200

201

202 for (auto &I : InstructionsToProcess)

203 I->replaceUsesOfWith(D, CurrentMaterialization);

204

205

206

207

208 for (unsigned i = 0, E = Use->getNumOperands(); i != E; ++i)

209 if (Use->getOperand(i) == D)

210 FinalInstructionsToProcess.push_back(

211 {Use, D, CurrentMaterialization});

212

213 InstructionsToProcess.push_back(CurrentMaterialization);

214 }

215 }

216

217

218 for (auto &R : FinalInstructionsToProcess) {

220 assert(PN->getNumIncomingValues() == 1 && "unexpected number of incoming "

221 "values in the PHINode");

222 PN->replaceAllUsesWith(R.Remat);

223 PN->eraseFromParent();

224 continue;

225 }

226 R.Use->replaceUsesOfWith(R.Def, R.Remat);

227 }

228}

229

230

231

232

237

241

242#ifndef NDEBUG

246 dbgs() << "------------- " << Title << "--------------\n";

247 for (const auto &E : RM) {

248 E.second->dump();

249 dbgs() << "--\n";

250 }

251}

252#endif

253

256 std::function<bool(Instruction &)> IsMaterializable) {

257 if (F.hasOptNone())

258 return;

259

261

262

263

264

266 if (!IsMaterializable(I))

267 continue;

268 for (User *U : I.users())

271 }

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

289 for (auto &E : Spills) {

291

292

293 auto [It, Inserted] = AllRemats.try_emplace(U);

294 if (!Inserted)

295 continue;

296

297

298 auto RematUPtr =

299 std::make_unique(IsMaterializable, U, Checker);

300

301 LLVM_DEBUG(dbgs() << "***** Next remat group *****\n";

303 for (auto I = RPOT.begin(); I != RPOT.end();

304 ++I) { (*I)->Node->dump(); } dbgs()

305 << "\n";);

306

307 It->second = std::move(RematUPtr);

308 }

309 }

310

311

312

315}

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

Expand Atomic instructions

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

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

static void rewriteMaterializableInstructions(const SmallMapVector< Instruction *, std::unique_ptr< RematGraph >, 8 > &AllRemats)

Definition MaterializationUtils.cpp:154

static void dumpRemats(StringRef Title, const SmallMapVector< Instruction *, std::unique_ptr< RematGraph >, 8 > &RM)

Definition MaterializationUtils.cpp:243

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

LLVM Basic Block Representation.

const Function * getParent() const

Return the enclosing method, or null if none.

InstListType::iterator iterator

Instruction iterators...

const Instruction * getTerminator() const LLVM_READONLY

Returns the terminator instruction if the block is well formed or null if the block is not well forme...

LLVM_ABI void insertBefore(InstListType::iterator InsertPos)

Insert an unlinked instruction into a basic block immediately before the specified position.

std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)

Manage lifetime of a slot tracker for printing IR.

int getLocalSlot(const Value *V)

Return the slot number of the specified local value.

void incorporateFunction(const Function &F)

Incorporate the given function.

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.

bool isDefinitionAcrossSuspend(BasicBlock *DefBB, User *U) const

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

LLVM_ABI void setName(const Twine &Name)

Change the name of the value.

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

self_iterator getIterator()

SmallMapVector< Value *, SmallVector< Instruction *, 2 >, 8 > SpillInfo

bool defaultMaterializable(Instruction &V)

Default materializable callback.

Definition MaterializationUtils.cpp:233

LLVM_ABI bool isTriviallyMaterializable(Instruction &I)

Definition MaterializationUtils.cpp:238

LLVM_ABI void doRematerializations(Function &F, SuspendCrossingInfo &Checker, std::function< bool(Instruction &)> IsMaterializable)

Definition MaterializationUtils.cpp:254

This is an optimization pass for GlobalISel generic memory operations.

void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

static void dumpBasicBlockLabel(const BasicBlock *BB, ModuleSlotTracker &MST)

LLVM_ABI raw_ostream & dbgs()

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

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

RematGraph::RematNode * NodeRef

Definition MaterializationUtils.cpp:141

static ChildIteratorType child_end(NodeRef N)

Definition MaterializationUtils.cpp:148

RematGraph::RematNode ** ChildIteratorType

Definition MaterializationUtils.cpp:142

static NodeRef getEntryNode(RematGraph *G)

Definition MaterializationUtils.cpp:144

static ChildIteratorType child_begin(NodeRef N)

Definition MaterializationUtils.cpp:145

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