LLVM: include/llvm/ADT/GenericUniformityImpl.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
44#ifndef LLVM_ADT_GENERICUNIFORMITYIMPL_H
45#define LLVM_ADT_GENERICUNIFORMITYIMPL_H
46
48
56#define DEBUG_TYPE "uniformity"
57
59
60
62
63
64
65
66
67
68
69
70
72
73
74
76
78
80
81
82
83
84
85
87public:
88 using BlockT = typename ContextT::BlockT;
89 using FunctionT = typename ContextT::FunctionT;
91
93 using CycleT = typename CycleInfoT::CycleT;
94 using const_iterator = typename std::vector<BlockT *>::const_iterator;
95
97
98 bool empty() const { return m_order.empty(); }
99 size_t size() const { return m_order.size(); }
100
103
106
108 POIndex[&BB] = m_order.size();
111 << "): " << Context.print(&BB) << "\n");
113 ReducibleCycleHeaders.insert(&BB);
114 }
115
118 return POIndex.lookup(BB);
119 }
120
122 return ReducibleCycleHeaders.contains(BB);
123 }
124
125private:
129 const ContextT &Context;
130
133
137};
138
139template <typename> class DivergencePropagator;
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
260public:
261 using BlockT = typename ContextT::BlockT;
263 using FunctionT = typename ContextT::FunctionT;
264 using ValueRefT = typename ContextT::ValueRefT;
266
268 using CycleT = typename CycleInfoT::CycleT;
269
272
273
274
275
276
277
278
279
281
282
283
285
287
289
291 };
292
294
297
298
299
300
301
302
303
304
305
306
308
309private:
311
313
316
318 CachedControlDivDescs;
319};
320
321
322
323
324
325
326
328public:
329 using BlockT = typename ContextT::BlockT;
330 using FunctionT = typename ContextT::FunctionT;
331 using ValueRefT = typename ContextT::ValueRefT;
333 using UseT = typename ContextT::UseT;
336
338 using CycleT = typename CycleInfoT::CycleT;
339
342 typename SyncDependenceAnalysisT::DivergenceDescriptor;
343 using BlockLabelMapT = typename SyncDependenceAnalysisT::BlockLabelMap;
344
349
351
353
354
356
357
359
360
361
363
364
365
367
368
369
371
372
374
375
376
378
380
382 if (I.isTerminator()) {
384 }
386 };
387
388
390
392
395 }
396
398
399protected:
400
404
407 };
408
413
414
417
418
419 std::vector<const InstructionT *> Worklist;
420
421
422
424
425private:
427
428
430
431
432
433
434
436
437
439
440
442
443
444
445 void taintAndPushAllDefs(const BlockT &JoinBlock);
446
447
448
449 void taintAndPushPhiNodes(const BlockT &JoinBlock);
450
451
452
453
454 void propagateCycleExitDivergence(const BlockT &DivExit,
455 const CycleT &DivCycle);
456
457
458 void analyzeCycleExitDivergence(const CycleT &DefCycle);
459
460
461 void propagateTemporalDivergence(const InstructionT &I,
462 const CycleT &DefCycle);
463
464
467
468 bool usesValueFromCycle(const InstructionT &I, const CycleT &DefCycle) const;
469
470
471 bool isTemporalDivergent(const BlockT &ObservingBlock,
473};
474
475template
477 delete Impl;
478}
479
480
482public:
483 using BlockT = typename ContextT::BlockT;
485 using FunctionT = typename ContextT::FunctionT;
486 using ValueRefT = typename ContextT::ValueRefT;
487
489 using CycleT = typename CycleInfoT::CycleT;
490
494 typename SyncDependenceAnalysisT::DivergenceDescriptor;
495 using BlockLabelMapT = typename SyncDependenceAnalysisT::BlockLabelMap;
496
502
503
504
505
506
508
509
512
518
520 Out << "Propagator::BlockLabels {\n";
521 for (int BlockIdx = (int)CyclePOT.size() - 1; BlockIdx >= 0; --BlockIdx) {
524 Out << Context.print(Block) << "(" << BlockIdx << ") : ";
525 if (!Label) {
526 Out << "\n";
527 } else {
528 Out << Context.print(Label) << "\n";
529 }
530 }
531 Out << "}\n";
532 }
533
534
535
537 const auto *OldLabel = BlockLabels[&SuccBlock];
538
540 << "\tpushed label: " << Context.print(&PushedLabel)
541 << "\n"
542 << "\told label: " << Context.print(OldLabel) << "\n");
543
544
545 if (OldLabel == &PushedLabel)
546 return false;
547
548 if (OldLabel != &SuccBlock) {
549 auto SuccIdx = CyclePOT.getIndex(&SuccBlock);
550
551 LLVM_DEBUG(dbgs() << "\tfresh label: " << SuccIdx << "\n");
553 }
554
555
556 if (!OldLabel) {
558 << "\n");
560 return false;
561 }
562
563
564
567
568 return true;
569 }
570
571
572
575 return false;
576
577
578 DivDesc->CycleDivBlocks.insert(&ExitBlock);
580 << "\n");
581 return true;
582 }
583
584
587 return false;
588
589
590 DivDesc->JoinDivBlocks.insert(&SuccBlock);
592 << "\n");
593 return true;
594 }
595
598
601
602
603 int FloorIdx = CyclePOT.size() - 1;
604 const BlockT *FloorLabel = nullptr;
606
607
608 auto const *DivTermCycle = CI.getCycle(&DivTermBlock);
610 if (DivTermCycle && !DivTermCycle->contains(SuccBlock)) {
611
612
613
614 DivDesc->CycleDivBlocks.insert(SuccBlock);
615 LLVM_DEBUG(dbgs() << "\tImmediate divergent cycle exit: "
616 << Context.print(SuccBlock) << "\n");
617 }
618 auto SuccIdx = CyclePOT.getIndex(SuccBlock);
619 visitEdge(*SuccBlock, *SuccBlock);
620 FloorIdx = std::min(FloorIdx, SuccIdx);
621 }
622
623 while (true) {
625 if (BlockIdx == -1 || BlockIdx < FloorIdx)
626 break;
627
629
631 if (BlockIdx == DivTermIdx) {
633 continue;
634 }
635
638 << BlockIdx << "\n");
639
642
643 bool CausedJoin = false;
644 int LoweredFloorIdx = FloorIdx;
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661 auto getReducibleParent = [&](const BlockT *Block) -> const CycleT * {
663 return nullptr;
664 const auto *BlockCycle = CI.getCycle(Block);
666 return BlockCycle;
667 return nullptr;
668 };
669
670 if (const auto *BlockCycle = getReducibleParent(Block)) {
672 BlockCycle->getExitBlocks(BlockCycleExits);
673 for (auto *BlockCycleExit : BlockCycleExits) {
675 LoweredFloorIdx =
676 std::min(LoweredFloorIdx, CyclePOT.getIndex(BlockCycleExit));
677 }
678 } else {
680 CausedJoin |= visitEdge(*SuccBlock, *Label);
681 LoweredFloorIdx =
682 std::min(LoweredFloorIdx, CyclePOT.getIndex(SuccBlock));
683 }
684 }
685
686
687 if (CausedJoin) {
688
689 FloorIdx = LoweredFloorIdx;
690 } else if (FloorLabel != Label) {
691
692
693 FloorIdx = LoweredFloorIdx;
694 FloorLabel = Label;
695 }
696 }
697
699
700
701
702
706
707
708 continue;
709 }
714 for (const auto *Exit : Exits) {
716
717 DivDesc->CycleDivBlocks.insert(Exit);
719 << "\n");
720 }
721 }
722 }
723
724 return std::move(DivDesc);
725 }
726};
727
728template
731
732template
735 : CyclePO(Context), DT(DT), CI(CI) {
736 CyclePO.compute(CI);
737}
738
739template
742
743 if (succ_size(DivTermBlock) <= 1) {
744 return EmptyDivergenceDesc;
745 }
746
747
748 auto ItCached = CachedControlDivDescs.find(DivTermBlock);
749 if (ItCached != CachedControlDivDescs.end())
750 return *ItCached->second;
751
752
755
758 Out << "[";
759 ListSeparator LS;
760 for (const auto *BB : Blocks) {
761 Out << LS << CI.getSSAContext().print(BB);
762 }
763 Out << "]\n";
764 });
765 };
766
768 dbgs() << "\nResult (" << CI.getSSAContext().print(DivTermBlock)
769 << "):\n JoinDivBlocks: " << printBlockSet(DivDesc->JoinDivBlocks)
770 << " CycleDivBlocks: " << printBlockSet(DivDesc->CycleDivBlocks)
771 << "\n");
772 (void)printBlockSet;
773
774 auto ItInserted =
775 CachedControlDivDescs.try_emplace(DivTermBlock, std::move(DivDesc));
776 assert(ItInserted.second);
777 return *ItInserted.first->second;
778}
779
780template
783 if (isAlwaysUniform(I))
784 return;
785 bool Marked = false;
786 if (I.isTerminator()) {
787 Marked = DivergentTermBlocks.insert(I.getParent()).second;
788 if (Marked) {
790 << Context.print(I.getParent()) << "\n");
791 }
792 } else {
793 Marked = markDefsDivergent(I);
794 }
795
796 if (Marked)
797 Worklist.push_back(&I);
798}
799
800template
803 if (DivergentValues.insert(Val).second) {
804 LLVM_DEBUG(dbgs() << "marked divergent: " << Context.print(Val) << "\n");
805 return true;
806 }
807 return false;
808}
809
810template
813 UniformOverrides.insert(&Instr);
814}
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829template
831 const CycleT &DefCycle) {
833 DefCycle.getExitBlocks(Exits);
834 for (auto *Exit : Exits) {
835 for (auto &Phi : Exit->phis()) {
836 if (usesValueFromCycle(Phi, DefCycle)) {
837 markDivergent(Phi);
838 }
839 }
840 }
841
842 for (auto *BB : DefCycle.blocks()) {
844 [&](BlockT *Exit) { return DT.dominates(BB, Exit); }))
845 continue;
846 for (auto &II : *BB) {
847 propagateTemporalDivergence(II, DefCycle);
848 }
849 }
850}
851
852template
853void GenericUniformityAnalysisImpl::propagateCycleExitDivergence(
854 const BlockT &DivExit, const CycleT &InnerDivCycle) {
855 LLVM_DEBUG(dbgs() << "\tpropCycleExitDiv " << Context.print(&DivExit)
856 << "\n");
857 auto *DivCycle = &InnerDivCycle;
858 auto *OuterDivCycle = DivCycle;
859 auto *ExitLevelCycle = CI.getCycle(&DivExit);
860 const unsigned CycleExitDepth =
861 ExitLevelCycle ? ExitLevelCycle->getDepth() : 0;
862
863
864 while (DivCycle && DivCycle->getDepth() > CycleExitDepth) {
866 << Context.print(DivCycle->getHeader()) << "\n");
867 OuterDivCycle = DivCycle;
868 DivCycle = DivCycle->getParentCycle();
869 }
871 << Context.print(OuterDivCycle->getHeader()) << "\n");
872
873 if (!DivergentExitCycles.insert(OuterDivCycle).second)
874 return;
875
876
877
878 for (const auto *C : AssumedDivergent) {
879 if (C->contains(OuterDivCycle))
880 return;
881 }
882
883 analyzeCycleExitDivergence(*OuterDivCycle);
884}
885
886template
887void GenericUniformityAnalysisImpl::taintAndPushAllDefs(
888 const BlockT &BB) {
889 LLVM_DEBUG(dbgs() << "taintAndPushAllDefs " << Context.print(&BB) << "\n");
890 for (const auto &I : instrs(BB)) {
891
892
893
894 if (I.isTerminator())
895 break;
896
897 markDivergent(I);
898 }
899}
900
901
902template
903void GenericUniformityAnalysisImpl::taintAndPushPhiNodes(
904 const BlockT &JoinBlock) {
905 LLVM_DEBUG(dbgs() << "taintAndPushPhiNodes in " << Context.print(&JoinBlock)
906 << "\n");
907 for (const auto &Phi : JoinBlock.phis()) {
908
909
910
911
912
913
914
915 if (ContextT::isConstantOrUndefValuePhi(Phi))
916 continue;
917 markDivergent(Phi);
918 }
919}
920
921
922
923
924template
926 CycleT *Candidate) {
928 [Candidate](CycleT *C) { return C->contains(Candidate); }))
929 return false;
931 return true;
932}
933
934
935
936
937
938
939template <typename CycleT, typename BlockT>
941 const BlockT *DivTermBlock,
942 const BlockT *JoinBlock) {
945
947 return nullptr;
948
949 const auto *OriginalCycle = Cycle;
951 while (Parent && !Parent->contains(DivTermBlock)) {
954 }
955
956
957
958
959 (void)OriginalCycle;
961
964 return nullptr;
965 }
966
967 LLVM_DEBUG(dbgs() << "cycle made divergent by external branch\n");
969}
970
971
972
973
974
975template <typename ContextT, typename CycleT, typename BlockT,
976 typename DominatorTreeT>
977static const CycleT *
979 const BlockT *JoinBlock, const DominatorTreeT &DT,
980 ContextT &Context) {
981 LLVM_DEBUG(dbgs() << "examine join " << Context.print(JoinBlock)
982 << " for internal branch " << Context.print(DivTermBlock)
983 << "\n");
985 return nullptr;
986
987
991 }
993 return nullptr;
994
996 return nullptr;
997
999 << " does not dominate join\n");
1000
1002 while (Parent && !DT.properlyDominates(Parent->getHeader(), JoinBlock)) {
1003 LLVM_DEBUG(dbgs() << " header " << Context.print(Parent->getHeader())
1004 << " does not dominate join\n");
1007 }
1008
1009 LLVM_DEBUG(dbgs() << " cycle made divergent by internal branch\n");
1011}
1012
1013template <typename ContextT, typename CycleT, typename BlockT,
1014 typename DominatorTreeT>
1015static const CycleT *
1017 const BlockT *JoinBlock, const DominatorTreeT &DT,
1018 ContextT &Context) {
1020 return nullptr;
1021
1022
1023
1025
1026
1028
1029 if (Int)
1030 return Int;
1031 return Ext;
1032}
1033
1034template
1035bool GenericUniformityAnalysisImpl::isTemporalDivergent(
1036 const BlockT &ObservingBlock, const InstructionT &Def) const {
1037 const BlockT *DefBlock = Def.getParent();
1038 for (const CycleT *Cycle = CI.getCycle(DefBlock);
1041 if (DivergentExitCycles.contains(Cycle)) {
1042 return true;
1043 }
1044 }
1045 return false;
1046}
1047
1048template
1051 const auto *DivTermBlock = Term.getParent();
1052 DivergentTermBlocks.insert(DivTermBlock);
1053 LLVM_DEBUG(dbgs() << "analyzeControlDiv " << Context.print(DivTermBlock)
1054 << "\n");
1055
1056
1058 return;
1059
1060 const auto &DivDesc = SDA.getJoinBlocks(DivTermBlock);
1062
1063
1064 for (const auto *JoinBlock : DivDesc.JoinDivBlocks) {
1065 const auto *Cycle = CI.getCycle(JoinBlock);
1066 LLVM_DEBUG(dbgs() << "visiting join block " << Context.print(JoinBlock)
1067 << "\n");
1069 Cycle, DivTermBlock, JoinBlock, DT, Context)) {
1072 continue;
1073 }
1074 taintAndPushPhiNodes(*JoinBlock);
1075 }
1076
1077
1078
1080 return A->getDepth() > B->getDepth();
1081 });
1082
1083
1084
1085
1086
1087
1088 for (auto *C : DivCycles) {
1090 continue;
1092 for (const BlockT *BB : C->blocks()) {
1093 taintAndPushAllDefs(*BB);
1094 }
1095 }
1096
1097 const auto *BranchCycle = CI.getCycle(DivTermBlock);
1098 assert(DivDesc.CycleDivBlocks.empty() || BranchCycle);
1099 for (const auto *DivExitBlock : DivDesc.CycleDivBlocks) {
1100 propagateCycleExitDivergence(*DivExitBlock, *BranchCycle);
1101 }
1102}
1103
1104template
1106
1107 auto DivValuesCopy = DivergentValues;
1108 for (const auto DivVal : DivValuesCopy) {
1109 assert(isDivergent(DivVal) && "Worklist invariant violated!");
1110 pushUsers(DivVal);
1111 }
1112
1113
1114
1115 while (!Worklist.empty()) {
1117 Worklist.pop_back();
1118
1119 LLVM_DEBUG(dbgs() << "worklist pop: " << Context.print(I) << "\n");
1120
1121 if (I->isTerminator()) {
1122 analyzeControlDivergence(*I);
1123 continue;
1124 }
1125
1126
1127 assert(isDivergent(*I) && "Worklist invariant violated!");
1128 pushUsers(*I);
1129 }
1130}
1131
1132template
1135 return UniformOverrides.contains(&Instr);
1136}
1137
1138template
1142 DA.reset(new ImplT{DT, CI, TTI});
1143}
1144
1145template
1147 bool haveDivergentArgs = false;
1148
1149
1150
1151
1152 if (DivergentValues.empty() && DivergentTermBlocks.empty() &&
1153 DivergentExitCycles.empty()) {
1154 OS << "ALL VALUES UNIFORM\n";
1155 return;
1156 }
1157
1158 for (const auto &entry : DivergentValues) {
1159 const BlockT *parent = Context.getDefBlock(entry);
1160 if (!parent) {
1161 if (!haveDivergentArgs) {
1162 OS << "DIVERGENT ARGUMENTS:\n";
1163 haveDivergentArgs = true;
1164 }
1165 OS << " DIVERGENT: " << Context.print(entry) << '\n';
1166 }
1167 }
1168
1169 if (!AssumedDivergent.empty()) {
1170 OS << "CYCLES ASSSUMED DIVERGENT:\n";
1171 for (const CycleT *cycle : AssumedDivergent) {
1172 OS << " " << cycle->print(Context) << '\n';
1173 }
1174 }
1175
1176 if (!DivergentExitCycles.empty()) {
1177 OS << "CYCLES WITH DIVERGENT EXIT:\n";
1178 for (const CycleT *cycle : DivergentExitCycles) {
1179 OS << " " << cycle->print(Context) << '\n';
1180 }
1181 }
1182
1184 OS << "\nBLOCK " << Context.print(&block) << '\n';
1185
1186 OS << "DEFINITIONS\n";
1188 Context.appendBlockDefs(defs, block);
1189 for (auto value : defs) {
1190 if (isDivergent(value))
1191 OS << " DIVERGENT: ";
1192 else
1193 OS << " ";
1194 OS << Context.print(value) << '\n';
1195 }
1196
1197 OS << "TERMINATORS\n";
1199 Context.appendBlockTerms(terms, block);
1200 bool divergentTerminators = hasDivergentTerminator(block);
1201 for (auto *T : terms) {
1202 if (divergentTerminators)
1203 OS << " DIVERGENT: ";
1204 else
1205 OS << " ";
1206 OS << Context.print(T) << '\n';
1207 }
1208
1209 OS << "END BLOCK\n";
1210 }
1211}
1212
1213template
1215 return DA->hasDivergence();
1216}
1217
1218template
1219const typename ContextT::FunctionT &
1221 return DA->getFunction();
1222}
1223
1224
1225template
1227 return DA->isDivergent(V);
1228}
1229
1230template
1232 return DA->isDivergent(*I);
1233}
1234
1235template
1237 return DA->isDivergentUse(U);
1238}
1239
1240template
1242 return DA->hasDivergentTerminator(B);
1243}
1244
1245
1246template
1248 DA->print(out);
1249}
1250
1251template
1256 while (!Stack.empty()) {
1257 auto *NextBB = Stack.back();
1258 if (Finalized.count(NextBB)) {
1259 Stack.pop_back();
1260 continue;
1261 }
1262 LLVM_DEBUG(dbgs() << " visiting " << CI.getSSAContext().print(NextBB)
1263 << "\n");
1264 auto *NestedCycle = CI.getCycle(NextBB);
1267 while (NestedCycle->getParentCycle() != Cycle)
1268 NestedCycle = NestedCycle->getParentCycle();
1269
1270 SmallVector<BlockT *, 3> NestedExits;
1271 NestedCycle->getExitBlocks(NestedExits);
1272 bool PushedNodes = false;
1273 for (auto *NestedExitBB : NestedExits) {
1275 << CI.getSSAContext().print(NestedExitBB) << "\n");
1277 continue;
1278 if (Finalized.count(NestedExitBB))
1279 continue;
1280 PushedNodes = true;
1281 Stack.push_back(NestedExitBB);
1283 << CI.getSSAContext().print(NestedExitBB) << "\n");
1284 }
1285 if (!PushedNodes) {
1286
1287 Stack.pop_back();
1288 computeCyclePO(CI, NestedCycle, Finalized);
1289 }
1290 continue;
1291 }
1292
1293 LLVM_DEBUG(dbgs() << " no nested cycle, going into DAG\n");
1294
1295 bool PushedNodes = false;
1296 for (auto *SuccBB : successors(NextBB)) {
1298 << CI.getSSAContext().print(SuccBB) << "\n");
1300 continue;
1301 if (Finalized.count(SuccBB))
1302 continue;
1303 PushedNodes = true;
1304 Stack.push_back(SuccBB);
1305 LLVM_DEBUG(dbgs() << " pushed succ: " << CI.getSSAContext().print(SuccBB)
1306 << "\n");
1307 }
1308 if (!PushedNodes) {
1309
1311 << CI.getSSAContext().print(NextBB) << "\n");
1312 Stack.pop_back();
1313 Finalized.insert(NextBB);
1314 appendBlock(*NextBB);
1315 }
1316 }
1318}
1319
1320template
1321void ModifiedPostOrder::computeCyclePO(
1322 const CycleInfoT &CI, const CycleT *Cycle,
1323 SmallPtrSetImpl<const BlockT *> &Finalized) {
1325 SmallVector<const BlockT *> Stack;
1327
1329 << CI.getSSAContext().print(CycleHeader) << "\n");
1330 assert(!Finalized.count(CycleHeader));
1331 Finalized.insert(CycleHeader);
1332
1333
1335 << CI.getSSAContext().print(CycleHeader) << "\n");
1337
1338
1339 for (auto *BB : successors(CycleHeader)) {
1340 LLVM_DEBUG(dbgs() << " examine succ: " << CI.getSSAContext().print(BB)
1341 << "\n");
1343 continue;
1344 if (BB == CycleHeader)
1345 continue;
1346 if (!Finalized.count(BB)) {
1347 LLVM_DEBUG(dbgs() << " pushed succ: " << CI.getSSAContext().print(BB)
1348 << "\n");
1349 Stack.push_back(BB);
1350 }
1351 }
1352
1353
1354 computeStackPO(Stack, CI, Cycle, Finalized);
1355
1357}
1358
1359
1360template
1364 auto *F = CI.getFunction();
1365 Stack.reserve(24);
1366 Stack.push_back(&F->front());
1367 computeStackPO(Stack, CI, nullptr, Finalized);
1368}
1369
1370}
1371
1372#undef DEBUG_TYPE
1373
1374#endif
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Given that RA is a live value
This file defines the DenseSet and SmallDenseSet classes.
DenseMap< Block *, BlockRelaxAux > Blocks
uint64_t IntrinsicInst * II
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SparseBitVector class.
unify loop Fixup each natural loop to have a single exit block
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Implements a dense probed hash-table based set.
Compute divergence starting with a divergent branch.
typename SyncDependenceAnalysisT::BlockLabelMap BlockLabelMapT
const ModifiedPO & CyclePOT
GenericSyncDependenceAnalysis< ContextT > SyncDependenceAnalysisT
typename ContextT::DominatorTreeT DominatorTreeT
bool computeJoin(const BlockT &SuccBlock, const BlockT &PushedLabel)
const BlockT & DivTermBlock
std::unique_ptr< DivergenceDescriptorT > DivDesc
void printDefs(raw_ostream &Out)
typename ContextT::FunctionT FunctionT
GenericCycleInfo< ContextT > CycleInfoT
const DominatorTreeT & DT
ModifiedPostOrder< ContextT > ModifiedPO
std::unique_ptr< DivergenceDescriptorT > computeJoinPoints()
BlockLabelMapT & BlockLabels
SparseBitVector FreshLabels
bool visitCycleExitEdge(const BlockT &ExitBlock, const BlockT &Label)
typename ContextT::ValueRefT ValueRefT
typename ContextT::BlockT BlockT
typename SyncDependenceAnalysisT::DivergenceDescriptor DivergenceDescriptorT
typename CycleInfoT::CycleT CycleT
DivergencePropagator(const ModifiedPO &CyclePOT, const DominatorTreeT &DT, const CycleInfoT &CI, const BlockT &DivTermBlock)
bool visitEdge(const BlockT &SuccBlock, const BlockT &Label)
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Cycle information for a function.
A possibly irreducible generalization of a Loop.
BlockT * getHeader() const
bool isReducible() const
Whether the cycle is a natural loop.
void getExitBlocks(SmallVectorImpl< BlockT * > &TmpStorage) const
Return all of the successor blocks of this cycle.
bool contains(const BlockT *Block) const
Return whether Block is contained in the cycle.
const GenericCycle * getParentCycle() const
Locate join blocks for disjoint paths starting at a divergent branch.
GenericSyncDependenceAnalysis(const ContextT &Context, const DominatorTreeT &DT, const CycleInfoT &CI)
ModifiedPostOrder< ContextT > ModifiedPO
typename ContextT::DominatorTreeT DominatorTreeT
GenericCycleInfo< ContextT > CycleInfoT
typename ContextT::FunctionT FunctionT
typename ContextT::InstructionT InstructionT
typename ContextT::BlockT BlockT
typename ContextT::ValueRefT ValueRefT
typename CycleInfoT::CycleT CycleT
const DivergenceDescriptor & getJoinBlocks(const BlockT *DivTermBlock)
Computes divergent join points and cycle exits caused by branch divergence in Term.
Analysis that identifies uniform values in a data-parallel execution.
bool isAlwaysUniform(const InstructionT &Instr) const
Whether Val will always return a uniform value regardless of its operands.
typename ContextT::BlockT BlockT
typename ContextT::ValueRefT ValueRefT
void analyzeControlDivergence(const InstructionT &Term)
Mark Term as divergent and push all Instructions that become divergent as a result on the worklist.
const FunctionT & getFunction() const
bool isDivergent(ConstValueRefT V) const
Whether Val is divergent at its definition.
bool isDivergentUse(const UseT &U) const
bool hasDivergentDefs(const InstructionT &I) const
typename ContextT::InstructionT InstructionT
DenseSet< ConstValueRefT > DivergentValues
typename ContextT::UseT UseT
typename ContextT::ConstValueRefT ConstValueRefT
typename SyncDependenceAnalysisT::BlockLabelMap BlockLabelMapT
bool hasDivergence() const
Whether any value was marked or analyzed to be divergent.
typename ContextT::DominatorTreeT DominatorTreeT
void compute()
Propagate divergence to all instructions in the region.
bool hasDivergentTerminator(const BlockT &B) const
GenericUniformityAnalysisImpl(const DominatorTreeT &DT, const CycleInfoT &CI, const TargetTransformInfo *TTI)
bool markDefsDivergent(const InstructionT &Instr)
Mark outputs of Instr as divergent.
typename ContextT::FunctionT FunctionT
bool isDivergent(const InstructionT &I) const
std::vector< const InstructionT * > Worklist
void markDivergent(const InstructionT &I)
Examine I for divergent outputs and add to the worklist.
void print(raw_ostream &out) const
SmallPtrSet< const BlockT *, 32 > DivergentTermBlocks
GenericCycleInfo< ContextT > CycleInfoT
void addUniformOverride(const InstructionT &Instr)
Mark UniVal as a value that is always uniform.
typename SyncDependenceAnalysisT::DivergenceDescriptor DivergenceDescriptorT
typename CycleInfoT::CycleT CycleT
GenericSyncDependenceAnalysis< ContextT > SyncDependenceAnalysisT
bool hasDivergentTerminator(const BlockT &B)
bool isDivergentUse(const UseT &U) const
Whether U is divergent.
bool isDivergent(ConstValueRefT V) const
Whether V is divergent at its definition.
void print(raw_ostream &Out) const
T helper function for printing.
typename ContextT::ConstValueRefT ConstValueRefT
typename ContextT::BlockT BlockT
typename ContextT::InstructionT InstructionT
typename ContextT::UseT UseT
bool hasDivergence() const
Whether any divergence was detected.
const FunctionT & getFunction() const
The GPU kernel this analysis result is for.
GenericUniformityInfo()=default
GenericCycleInfo< ContextT > CycleInfoT
typename ContextT::DominatorTreeT DominatorTreeT
Construct a specially modified post-order traversal of cycles.
typename ContextT::FunctionT FunctionT
const BlockT * operator[](size_t idx) const
typename CycleInfoT::CycleT CycleT
bool isReducibleCycleHeader(const BlockT *BB) const
ModifiedPostOrder(const ContextT &C)
unsigned count(BlockT *BB) const
void compute(const CycleInfoT &CI)
Generically compute the modified post order.
GenericCycleInfo< ContextT > CycleInfoT
void appendBlock(const BlockT &BB, bool isReducibleCycleHeader=false)
unsigned getIndex(const BlockT *BB) const
typename std::vector< BlockT * >::const_iterator const_iterator
typename ContextT::DominatorTreeT DominatorTreeT
typename ContextT::BlockT BlockT
Simple wrapper around std::function<void(raw_ostream&)>.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
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.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
This class implements an extremely fast bulk output stream that can only output to a stream.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
static const CycleT * getIntDivCycle(const CycleT *Cycle, const BlockT *DivTermBlock, const BlockT *JoinBlock, const DominatorTreeT &DT, ContextT &Context)
Return the outermost cycle made divergent by branch inside it.
static const CycleT * getExtDivCycle(const CycleT *Cycle, const BlockT *DivTermBlock, const BlockT *JoinBlock)
Return the outermost cycle made divergent by branch outside it.
auto successors(const MachineBasicBlock *BB)
static bool insertIfNotContained(SmallVector< CycleT * > &Cycles, CycleT *Candidate)
Add Candidate to Cycles if it is not already contained in Cycles.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
auto succ_size(const MachineBasicBlock *BB)
auto instrs(const MachineBasicBlock &BB)
static const CycleT * getOutermostDivergentCycle(const CycleT *Cycle, const BlockT *DivTermBlock, const BlockT *JoinBlock, const DominatorTreeT &DT, ContextT &Context)
Information discovered by the sync dependence analysis for each divergent branch.
ConstBlockSet CycleDivBlocks
ConstBlockSet JoinDivBlocks
BlockLabelMap BlockLabels
void operator()(ImplT *Impl)
Value/block pair representing a single phi input.
PhiInput(ConstValueRefT value, BlockT *predBlock)