LLVM: lib/Transforms/Utils/ControlFlowUtils.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

21

22#define DEBUG_TYPE "control-flow-hub"

23

24using namespace llvm;

25

28

29

30

31

32

33

34

38 "Only support branch terminator.");

39 auto *Branch = cast(BB->getTerminator());

40 auto *Condition = Branch->isConditional() ? Branch->getCondition() : nullptr;

41

42 assert(Succ0 || Succ1);

43

44 if (Branch->isUnconditional()) {

45 assert(Succ0 == Branch->getSuccessor(0));

47 Branch->setSuccessor(0, FirstGuardBlock);

48 } else {

49 assert(!Succ1 || Succ1 == Branch->getSuccessor(1));

50 if (Succ0 && !Succ1) {

51 Branch->setSuccessor(0, FirstGuardBlock);

52 } else if (Succ1 && !Succ0) {

53 Branch->setSuccessor(1, FirstGuardBlock);

54 } else {

55 Branch->eraseFromParent();

57 }

58 }

59

60 return Condition;

61}

62

63

64

65

66

67

73 int I = 0;

74 for (int E = GuardBlocks.size() - 1; I != E; ++I) {

77 GuardBlocks[I]);

78 }

81 GuardBlocks[I]);

82}

83

84

85

93

95 FirstGuardBlock);

96

97 for (auto [BB, Succ0, Succ1] : Branches) {

99 Value *IncomingId = nullptr;

100 if (Succ0 && Succ1) {

101 auto Succ0Iter = find(Outgoing, Succ0);

102 auto Succ1Iter = find(Outgoing, Succ1);

104 ConstantInt::get(Int32Ty, std::distance(Outgoing.begin(), Succ0Iter));

106 ConstantInt::get(Int32Ty, std::distance(Outgoing.begin(), Succ1Iter));

107 IncomingId = SelectInst::Create(Condition, Id0, Id1, "target.bb.idx",

108 BB->getTerminator()->getIterator());

109 } else {

110

111 auto SuccIter = Succ0 ? find(Outgoing, Succ0) : find(Outgoing, Succ1);

112 IncomingId =

113 ConstantInt::get(Int32Ty, std::distance(Outgoing.begin(), SuccIter));

114 }

115 Phi->addIncoming(IncomingId, BB);

116 }

117

118 for (int I = 0, E = Outgoing.size() - 1; I != E; ++I) {

121 << "\n");

122 auto *Cmp = ICmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_EQ, Phi,

123 ConstantInt::get(Int32Ty, I),

124 Out->getName() + ".predicate", GuardBlocks[I]);

125 GuardPredicates[Out] = Cmp;

126 }

127}

128

129

130

139

140

141

142 for (int I = 0, E = Outgoing.size() - 1; I != E; ++I) {

145 << "\n");

146

147 auto *Phi =

150 GuardPredicates[Out] = Phi;

151 }

152

153 for (auto [BB, Succ0, Succ1] : Branches) {

155

156

157

158

159

160

161

162

163 bool OneSuccessorDone = false;

164 for (int I = 0, E = Outgoing.size() - 1; I != E; ++I) {

166 PHINode *Phi = cast(GuardPredicates[Out]);

167 if (Out != Succ0 && Out != Succ1) {

168 Phi->addIncoming(BoolFalse, BB);

169 } else if (!Succ0 || !Succ1 || OneSuccessorDone) {

170

171

172 Phi->addIncoming(BoolTrue, BB);

173 } else {

174 assert(Succ0 && Succ1);

175 if (Out == Succ0) {

176 Phi->addIncoming(Condition, BB);

177 } else {

179 DeletionCandidates.push_back(Condition);

180 Phi->addIncoming(Inverted, BB);

181 }

182 OneSuccessorDone = true;

183 }

184 }

185 }

186}

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

206 std::optional MaxControlFlowBooleans) {

209

210 for (int I = 0, E = Outgoing.size() - 1; I != E; ++I)

213

214

215

216

217

218

219 if (!MaxControlFlowBooleans || Outgoing.size() <= *MaxControlFlowBooleans)

221 DeletionCandidates);

222 else

224

226}

227

228

229

230

231

232

233

234

235

236

240 auto I = Out->begin();

241 while (I != Out->end() && isa(I)) {

242 auto *Phi = cast(I);

243 auto *NewPhi =

245 Phi->getName() + ".moved", FirstGuardBlock->begin());

246 bool AllUndef = true;

247 for (auto [BB, Succ0, Succ1] : Incoming) {

249 if (BB == Out) {

250 V = NewPhi;

251 } else if (Phi->getBasicBlockIndex(BB) != -1) {

252 V = Phi->removeIncomingValue(BB, false);

253 AllUndef &= isa(V);

254 }

255 NewPhi->addIncoming(V, BB);

256 }

257 assert(NewPhi->getNumIncomingValues() == Incoming.size());

258 Value *NewV = NewPhi;

259 if (AllUndef) {

260 NewPhi->eraseFromParent();

262 }

263 if (Phi->getNumOperands() == 0) {

264 Phi->replaceAllUsesWith(NewV);

265 I = Phi->eraseFromParent();

266 continue;

267 }

268 Phi->addIncoming(NewV, GuardBlock);

269 ++I;

270 }

271}

272

275 const StringRef Prefix, std::optional MaxControlFlowBooleans) {

276#ifndef NDEBUG

278#endif

280

281 for (auto [BB, Succ0, Succ1] : Branches) {

282#ifndef NDEBUG

283 assert(Incoming.insert(BB).second && "Duplicate entry for incoming block.");

284#endif

285 if (Succ0)

286 Outgoing.insert(Succ0);

287 if (Succ1)

288 Outgoing.insert(Succ1);

289 }

290

291 if (Outgoing.size() < 2)

292 return Outgoing.front();

293

295 if (DTU) {

296 for (auto [BB, Succ0, Succ1] : Branches) {

297 if (Succ0)

299 if (Succ1)

301 }

302 }

303

306 DeletionCandidates, Prefix, MaxControlFlowBooleans);

308

309

310 for (int I = 0, E = GuardBlocks.size(); I != E; ++I)

312

314

315 if (DTU) {

316 int NumGuards = GuardBlocks.size();

317

318 for (auto [BB, Succ0, Succ1] : Branches)

320

321 for (int I = 0; I != NumGuards - 1; ++I) {

325 }

326

327

329 Outgoing[NumGuards - 1]});

331 Outgoing[NumGuards]});

333 }

334

335 for (auto I : DeletionCandidates) {

336 if (I->use_empty())

337 if (auto *Inst = dyn_cast_or_null(I))

338 Inst->eraseFromParent();

339 }

340

341 return FirstGuardBlock;

342}

This file contains the declarations for the subclasses of Constant, which represent the different fla...

static void calcPredicateUsingBooleans(ArrayRef< EdgeDescriptor > Branches, ArrayRef< BasicBlock * > Outgoing, SmallVectorImpl< BasicBlock * > &GuardBlocks, BBPredicates &GuardPredicates, SmallVectorImpl< WeakVH > &DeletionCandidates)

static void setupBranchForGuard(ArrayRef< BasicBlock * > GuardBlocks, ArrayRef< BasicBlock * > Outgoing, BBPredicates &GuardPredicates)

static void reconnectPhis(BasicBlock *Out, BasicBlock *GuardBlock, ArrayRef< EdgeDescriptor > Incoming, BasicBlock *FirstGuardBlock)

static void calcPredicateUsingInteger(ArrayRef< EdgeDescriptor > Branches, ArrayRef< BasicBlock * > Outgoing, ArrayRef< BasicBlock * > GuardBlocks, BBPredicates &GuardPredicates)

static Value * redirectToHub(BasicBlock *BB, BasicBlock *Succ0, BasicBlock *Succ1, BasicBlock *FirstGuardBlock)

static void convertToGuardPredicates(ArrayRef< EdgeDescriptor > Branches, ArrayRef< BasicBlock * > Outgoing, SmallVectorImpl< BasicBlock * > &GuardBlocks, SmallVectorImpl< WeakVH > &DeletionCandidates, const StringRef Prefix, std::optional< unsigned > MaxControlFlowBooleans)

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

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

This file defines the SmallSet class.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

const T & front() const

front - Get the first element.

size_t size() const

size - Get the array size.

LLVM Basic Block Representation.

iterator begin()

Instruction iterator methods.

static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)

Creates a new BasicBlock.

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...

static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)

static ConstantInt * getTrue(LLVMContext &Context)

static ConstantInt * getFalse(LLVMContext &Context)

static constexpr UpdateKind Delete

static constexpr UpdateKind Insert

void applyUpdates(ArrayRef< UpdateT > Updates)

Submit updates to all available trees.

This is an important class for using LLVM in a threaded context.

static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)

Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...

static PoisonValue * get(Type *T)

Static factory methods - Return an 'poison' object of the specified type.

static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, Instruction *MDFrom=nullptr)

A vector that has set insertion semantics.

ArrayRef< value_type > getArrayRef() const

size_type size() const

Determine the number of elements in the SetVector.

const value_type & front() const

Return the first element of the SetVector.

const value_type & back() const

Return the last element of the SetVector.

bool insert(const value_type &X)

Insert a new element into the SetVector.

SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

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.

The instances of the Type class are immutable: once they are created, they are never changed.

static IntegerType * getInt1Ty(LLVMContext &C)

static IntegerType * getInt32Ty(LLVMContext &C)

LLVM Value Representation.

StringRef getName() const

Return a constant reference to the value's name.

This is an optimization pass for GlobalISel generic memory operations.

auto find(R &&Range, const T &Val)

Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.

raw_ostream & dbgs()

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

Value * invertCondition(Value *Condition)

Invert the given true/false value, possibly reusing an existing copy.

BasicBlock * finalize(DomTreeUpdater *DTU, SmallVectorImpl< BasicBlock * > &GuardBlocks, const StringRef Prefix, std::optional< unsigned > MaxControlFlowBooleans=std::nullopt)

SmallVector< BranchDescriptor > Branches

Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...