forked from llvm-mirror/llvm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMachineBlockPlacement.cpp
2771 lines (2509 loc) · 113 KB
/
MachineBlockPlacement.cpp
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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
139
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
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//===-- MachineBlockPlacement.cpp - Basic Block Code Layout optimization --===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements basic block placement transformations using the CFG
// structure and branch probability estimates.
//
// The pass strives to preserve the structure of the CFG (that is, retain
// a topological ordering of basic blocks) in the absence of a *strong* signal
// to the contrary from probabilities. However, within the CFG structure, it
// attempts to choose an ordering which favors placing more likely sequences of
// blocks adjacent to each other.
//
// The algorithm works from the inner-most loop within a function outward, and
// at each stage walks through the basic blocks, trying to coalesce them into
// sequential chains where allowed by the CFG (or demanded by heavy
// probabilities). Finally, it walks the blocks in topological order, and the
// first time it reaches a chain of basic blocks, it schedules them in the
// function in-order.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "BranchFolding.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/BlockFrequencyInfoImpl.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachinePostDominators.h"
#include "llvm/CodeGen/TailDuplicator.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include <algorithm>
#include <forward_list>
#include <functional>
#include <utility>
using namespace llvm;
#define DEBUG_TYPE "block-placement"
STATISTIC(NumCondBranches, "Number of conditional branches");
STATISTIC(NumUncondBranches, "Number of unconditional branches");
STATISTIC(CondBranchTakenFreq,
"Potential frequency of taking conditional branches");
STATISTIC(UncondBranchTakenFreq,
"Potential frequency of taking unconditional branches");
static cl::opt<unsigned> AlignAllBlock("align-all-blocks",
cl::desc("Force the alignment of all "
"blocks in the function."),
cl::init(0), cl::Hidden);
static cl::opt<unsigned> AlignAllNonFallThruBlocks(
"align-all-nofallthru-blocks",
cl::desc("Force the alignment of all "
"blocks that have no fall-through predecessors (i.e. don't add "
"nops that are executed)."),
cl::init(0), cl::Hidden);
// FIXME: Find a good default for this flag and remove the flag.
static cl::opt<unsigned> ExitBlockBias(
"block-placement-exit-block-bias",
cl::desc("Block frequency percentage a loop exit block needs "
"over the original exit to be considered the new exit."),
cl::init(0), cl::Hidden);
// Definition:
// - Outlining: placement of a basic block outside the chain or hot path.
static cl::opt<unsigned> LoopToColdBlockRatio(
"loop-to-cold-block-ratio",
cl::desc("Outline loop blocks from loop chain if (frequency of loop) / "
"(frequency of block) is greater than this ratio"),
cl::init(5), cl::Hidden);
static cl::opt<bool>
PreciseRotationCost("precise-rotation-cost",
cl::desc("Model the cost of loop rotation more "
"precisely by using profile data."),
cl::init(false), cl::Hidden);
static cl::opt<bool>
ForcePreciseRotationCost("force-precise-rotation-cost",
cl::desc("Force the use of precise cost "
"loop rotation strategy."),
cl::init(false), cl::Hidden);
static cl::opt<unsigned> MisfetchCost(
"misfetch-cost",
cl::desc("Cost that models the probabilistic risk of an instruction "
"misfetch due to a jump comparing to falling through, whose cost "
"is zero."),
cl::init(1), cl::Hidden);
static cl::opt<unsigned> JumpInstCost("jump-inst-cost",
cl::desc("Cost of jump instructions."),
cl::init(1), cl::Hidden);
static cl::opt<bool>
TailDupPlacement("tail-dup-placement",
cl::desc("Perform tail duplication during placement. "
"Creates more fallthrough opportunites in "
"outline branches."),
cl::init(true), cl::Hidden);
static cl::opt<bool>
BranchFoldPlacement("branch-fold-placement",
cl::desc("Perform branch folding during placement. "
"Reduces code size."),
cl::init(true), cl::Hidden);
// Heuristic for tail duplication.
static cl::opt<unsigned> TailDupPlacementThreshold(
"tail-dup-placement-threshold",
cl::desc("Instruction cutoff for tail duplication during layout. "
"Tail merging during layout is forced to have a threshold "
"that won't conflict."), cl::init(2),
cl::Hidden);
// Heuristic for tail duplication.
static cl::opt<unsigned> TailDupPlacementPenalty(
"tail-dup-placement-penalty",
cl::desc("Cost penalty for blocks that can avoid breaking CFG by copying. "
"Copying can increase fallthrough, but it also increases icache "
"pressure. This parameter controls the penalty to account for that. "
"Percent as integer."),
cl::init(2),
cl::Hidden);
// Heuristic for triangle chains.
static cl::opt<unsigned> TriangleChainCount(
"triangle-chain-count",
cl::desc("Number of triangle-shaped-CFG's that need to be in a row for the "
"triangle tail duplication heuristic to kick in. 0 to disable."),
cl::init(3),
cl::Hidden);
extern cl::opt<unsigned> StaticLikelyProb;
extern cl::opt<unsigned> ProfileLikelyProb;
// Internal option used to control BFI display only after MBP pass.
// Defined in CodeGen/MachineBlockFrequencyInfo.cpp:
// -view-block-layout-with-bfi=
extern cl::opt<GVDAGType> ViewBlockLayoutWithBFI;
// Command line option to specify the name of the function for CFG dump
// Defined in Analysis/BlockFrequencyInfo.cpp: -view-bfi-func-name=
extern cl::opt<std::string> ViewBlockFreqFuncName;
namespace {
class BlockChain;
/// \brief Type for our function-wide basic block -> block chain mapping.
typedef DenseMap<const MachineBasicBlock *, BlockChain *> BlockToChainMapType;
}
namespace {
/// \brief A chain of blocks which will be laid out contiguously.
///
/// This is the datastructure representing a chain of consecutive blocks that
/// are profitable to layout together in order to maximize fallthrough
/// probabilities and code locality. We also can use a block chain to represent
/// a sequence of basic blocks which have some external (correctness)
/// requirement for sequential layout.
///
/// Chains can be built around a single basic block and can be merged to grow
/// them. They participate in a block-to-chain mapping, which is updated
/// automatically as chains are merged together.
class BlockChain {
/// \brief The sequence of blocks belonging to this chain.
///
/// This is the sequence of blocks for a particular chain. These will be laid
/// out in-order within the function.
SmallVector<MachineBasicBlock *, 4> Blocks;
/// \brief A handle to the function-wide basic block to block chain mapping.
///
/// This is retained in each block chain to simplify the computation of child
/// block chains for SCC-formation and iteration. We store the edges to child
/// basic blocks, and map them back to their associated chains using this
/// structure.
BlockToChainMapType &BlockToChain;
public:
/// \brief Construct a new BlockChain.
///
/// This builds a new block chain representing a single basic block in the
/// function. It also registers itself as the chain that block participates
/// in with the BlockToChain mapping.
BlockChain(BlockToChainMapType &BlockToChain, MachineBasicBlock *BB)
: Blocks(1, BB), BlockToChain(BlockToChain), UnscheduledPredecessors(0) {
assert(BB && "Cannot create a chain with a null basic block");
BlockToChain[BB] = this;
}
/// \brief Iterator over blocks within the chain.
typedef SmallVectorImpl<MachineBasicBlock *>::iterator iterator;
typedef SmallVectorImpl<MachineBasicBlock *>::const_iterator const_iterator;
/// \brief Beginning of blocks within the chain.
iterator begin() { return Blocks.begin(); }
const_iterator begin() const { return Blocks.begin(); }
/// \brief End of blocks within the chain.
iterator end() { return Blocks.end(); }
const_iterator end() const { return Blocks.end(); }
bool remove(MachineBasicBlock* BB) {
for(iterator i = begin(); i != end(); ++i) {
if (*i == BB) {
Blocks.erase(i);
return true;
}
}
return false;
}
/// \brief Merge a block chain into this one.
///
/// This routine merges a block chain into this one. It takes care of forming
/// a contiguous sequence of basic blocks, updating the edge list, and
/// updating the block -> chain mapping. It does not free or tear down the
/// old chain, but the old chain's block list is no longer valid.
void merge(MachineBasicBlock *BB, BlockChain *Chain) {
assert(BB);
assert(!Blocks.empty());
// Fast path in case we don't have a chain already.
if (!Chain) {
assert(!BlockToChain[BB]);
Blocks.push_back(BB);
BlockToChain[BB] = this;
return;
}
assert(BB == *Chain->begin());
assert(Chain->begin() != Chain->end());
// Update the incoming blocks to point to this chain, and add them to the
// chain structure.
for (MachineBasicBlock *ChainBB : *Chain) {
Blocks.push_back(ChainBB);
assert(BlockToChain[ChainBB] == Chain && "Incoming blocks not in chain");
BlockToChain[ChainBB] = this;
}
}
#ifndef NDEBUG
/// \brief Dump the blocks in this chain.
LLVM_DUMP_METHOD void dump() {
for (MachineBasicBlock *MBB : *this)
MBB->dump();
}
#endif // NDEBUG
/// \brief Count of predecessors of any block within the chain which have not
/// yet been scheduled. In general, we will delay scheduling this chain
/// until those predecessors are scheduled (or we find a sufficiently good
/// reason to override this heuristic.) Note that when forming loop chains,
/// blocks outside the loop are ignored and treated as if they were already
/// scheduled.
///
/// Note: This field is reinitialized multiple times - once for each loop,
/// and then once for the function as a whole.
unsigned UnscheduledPredecessors;
};
}
namespace {
class MachineBlockPlacement : public MachineFunctionPass {
/// \brief A typedef for a block filter set.
typedef SmallSetVector<const MachineBasicBlock *, 16> BlockFilterSet;
/// Pair struct containing basic block and taildup profitiability
struct BlockAndTailDupResult {
MachineBasicBlock *BB;
bool ShouldTailDup;
};
/// Triple struct containing edge weight and the edge.
struct WeightedEdge {
BlockFrequency Weight;
MachineBasicBlock *Src;
MachineBasicBlock *Dest;
};
/// \brief work lists of blocks that are ready to be laid out
SmallVector<MachineBasicBlock *, 16> BlockWorkList;
SmallVector<MachineBasicBlock *, 16> EHPadWorkList;
/// Edges that have already been computed as optimal.
DenseMap<const MachineBasicBlock *, BlockAndTailDupResult> ComputedEdges;
/// \brief Machine Function
MachineFunction *F;
/// \brief A handle to the branch probability pass.
const MachineBranchProbabilityInfo *MBPI;
/// \brief A handle to the function-wide block frequency pass.
std::unique_ptr<BranchFolder::MBFIWrapper> MBFI;
/// \brief A handle to the loop info.
MachineLoopInfo *MLI;
/// \brief Preferred loop exit.
/// Member variable for convenience. It may be removed by duplication deep
/// in the call stack.
MachineBasicBlock *PreferredLoopExit;
/// \brief A handle to the target's instruction info.
const TargetInstrInfo *TII;
/// \brief A handle to the target's lowering info.
const TargetLoweringBase *TLI;
/// \brief A handle to the post dominator tree.
MachinePostDominatorTree *MPDT;
/// \brief Duplicator used to duplicate tails during placement.
///
/// Placement decisions can open up new tail duplication opportunities, but
/// since tail duplication affects placement decisions of later blocks, it
/// must be done inline.
TailDuplicator TailDup;
/// \brief Allocator and owner of BlockChain structures.
///
/// We build BlockChains lazily while processing the loop structure of
/// a function. To reduce malloc traffic, we allocate them using this
/// slab-like allocator, and destroy them after the pass completes. An
/// important guarantee is that this allocator produces stable pointers to
/// the chains.
SpecificBumpPtrAllocator<BlockChain> ChainAllocator;
/// \brief Function wide BasicBlock to BlockChain mapping.
///
/// This mapping allows efficiently moving from any given basic block to the
/// BlockChain it participates in, if any. We use it to, among other things,
/// allow implicitly defining edges between chains as the existing edges
/// between basic blocks.
DenseMap<const MachineBasicBlock *, BlockChain *> BlockToChain;
#ifndef NDEBUG
/// The set of basic blocks that have terminators that cannot be fully
/// analyzed. These basic blocks cannot be re-ordered safely by
/// MachineBlockPlacement, and we must preserve physical layout of these
/// blocks and their successors through the pass.
SmallPtrSet<MachineBasicBlock *, 4> BlocksWithUnanalyzableExits;
#endif
/// Decrease the UnscheduledPredecessors count for all blocks in chain, and
/// if the count goes to 0, add them to the appropriate work list.
void markChainSuccessors(
const BlockChain &Chain, const MachineBasicBlock *LoopHeaderBB,
const BlockFilterSet *BlockFilter = nullptr);
/// Decrease the UnscheduledPredecessors count for a single block, and
/// if the count goes to 0, add them to the appropriate work list.
void markBlockSuccessors(
const BlockChain &Chain, const MachineBasicBlock *BB,
const MachineBasicBlock *LoopHeaderBB,
const BlockFilterSet *BlockFilter = nullptr);
BranchProbability
collectViableSuccessors(
const MachineBasicBlock *BB, const BlockChain &Chain,
const BlockFilterSet *BlockFilter,
SmallVector<MachineBasicBlock *, 4> &Successors);
bool shouldPredBlockBeOutlined(
const MachineBasicBlock *BB, const MachineBasicBlock *Succ,
const BlockChain &Chain, const BlockFilterSet *BlockFilter,
BranchProbability SuccProb, BranchProbability HotProb);
bool repeatedlyTailDuplicateBlock(
MachineBasicBlock *BB, MachineBasicBlock *&LPred,
const MachineBasicBlock *LoopHeaderBB,
BlockChain &Chain, BlockFilterSet *BlockFilter,
MachineFunction::iterator &PrevUnplacedBlockIt);
bool maybeTailDuplicateBlock(
MachineBasicBlock *BB, MachineBasicBlock *LPred,
BlockChain &Chain, BlockFilterSet *BlockFilter,
MachineFunction::iterator &PrevUnplacedBlockIt,
bool &DuplicatedToPred);
bool hasBetterLayoutPredecessor(
const MachineBasicBlock *BB, const MachineBasicBlock *Succ,
const BlockChain &SuccChain, BranchProbability SuccProb,
BranchProbability RealSuccProb, const BlockChain &Chain,
const BlockFilterSet *BlockFilter);
BlockAndTailDupResult selectBestSuccessor(
const MachineBasicBlock *BB, const BlockChain &Chain,
const BlockFilterSet *BlockFilter);
MachineBasicBlock *selectBestCandidateBlock(
const BlockChain &Chain, SmallVectorImpl<MachineBasicBlock *> &WorkList);
MachineBasicBlock *getFirstUnplacedBlock(
const BlockChain &PlacedChain,
MachineFunction::iterator &PrevUnplacedBlockIt,
const BlockFilterSet *BlockFilter);
/// \brief Add a basic block to the work list if it is appropriate.
///
/// If the optional parameter BlockFilter is provided, only MBB
/// present in the set will be added to the worklist. If nullptr
/// is provided, no filtering occurs.
void fillWorkLists(const MachineBasicBlock *MBB,
SmallPtrSetImpl<BlockChain *> &UpdatedPreds,
const BlockFilterSet *BlockFilter);
void buildChain(const MachineBasicBlock *BB, BlockChain &Chain,
BlockFilterSet *BlockFilter = nullptr);
MachineBasicBlock *findBestLoopTop(
const MachineLoop &L, const BlockFilterSet &LoopBlockSet);
MachineBasicBlock *findBestLoopExit(
const MachineLoop &L, const BlockFilterSet &LoopBlockSet);
BlockFilterSet collectLoopBlockSet(const MachineLoop &L);
void buildLoopChains(const MachineLoop &L);
void rotateLoop(
BlockChain &LoopChain, const MachineBasicBlock *ExitingBB,
const BlockFilterSet &LoopBlockSet);
void rotateLoopWithProfile(
BlockChain &LoopChain, const MachineLoop &L,
const BlockFilterSet &LoopBlockSet);
void buildCFGChains();
void optimizeBranches();
void alignBlocks();
/// Returns true if a block should be tail-duplicated to increase fallthrough
/// opportunities.
bool shouldTailDuplicate(MachineBasicBlock *BB);
/// Check the edge frequencies to see if tail duplication will increase
/// fallthroughs.
bool isProfitableToTailDup(
const MachineBasicBlock *BB, const MachineBasicBlock *Succ,
BranchProbability AdjustedSumProb,
const BlockChain &Chain, const BlockFilterSet *BlockFilter);
/// Check for a trellis layout.
bool isTrellis(const MachineBasicBlock *BB,
const SmallVectorImpl<MachineBasicBlock *> &ViableSuccs,
const BlockChain &Chain, const BlockFilterSet *BlockFilter);
/// Get the best successor given a trellis layout.
BlockAndTailDupResult getBestTrellisSuccessor(
const MachineBasicBlock *BB,
const SmallVectorImpl<MachineBasicBlock *> &ViableSuccs,
BranchProbability AdjustedSumProb, const BlockChain &Chain,
const BlockFilterSet *BlockFilter);
/// Get the best pair of non-conflicting edges.
static std::pair<WeightedEdge, WeightedEdge> getBestNonConflictingEdges(
const MachineBasicBlock *BB,
SmallVector<SmallVector<WeightedEdge, 8>, 2> &Edges);
/// Returns true if a block can tail duplicate into all unplaced
/// predecessors. Filters based on loop.
bool canTailDuplicateUnplacedPreds(
const MachineBasicBlock *BB, MachineBasicBlock *Succ,
const BlockChain &Chain, const BlockFilterSet *BlockFilter);
/// Find chains of triangles to tail-duplicate where a global analysis works,
/// but a local analysis would not find them.
void precomputeTriangleChains();
public:
static char ID; // Pass identification, replacement for typeid
MachineBlockPlacement() : MachineFunctionPass(ID) {
initializeMachineBlockPlacementPass(*PassRegistry::getPassRegistry());
}
bool runOnMachineFunction(MachineFunction &F) override;
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<MachineBranchProbabilityInfo>();
AU.addRequired<MachineBlockFrequencyInfo>();
if (TailDupPlacement)
AU.addRequired<MachinePostDominatorTree>();
AU.addRequired<MachineLoopInfo>();
AU.addRequired<TargetPassConfig>();
MachineFunctionPass::getAnalysisUsage(AU);
}
};
}
char MachineBlockPlacement::ID = 0;
char &llvm::MachineBlockPlacementID = MachineBlockPlacement::ID;
INITIALIZE_PASS_BEGIN(MachineBlockPlacement, "block-placement",
"Branch Probability Basic Block Placement", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfo)
INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
INITIALIZE_PASS_END(MachineBlockPlacement, "block-placement",
"Branch Probability Basic Block Placement", false, false)
#ifndef NDEBUG
/// \brief Helper to print the name of a MBB.
///
/// Only used by debug logging.
static std::string getBlockName(const MachineBasicBlock *BB) {
std::string Result;
raw_string_ostream OS(Result);
OS << "BB#" << BB->getNumber();
OS << " ('" << BB->getName() << "')";
OS.flush();
return Result;
}
#endif
/// \brief Mark a chain's successors as having one fewer preds.
///
/// When a chain is being merged into the "placed" chain, this routine will
/// quickly walk the successors of each block in the chain and mark them as
/// having one fewer active predecessor. It also adds any successors of this
/// chain which reach the zero-predecessor state to the appropriate worklist.
void MachineBlockPlacement::markChainSuccessors(
const BlockChain &Chain, const MachineBasicBlock *LoopHeaderBB,
const BlockFilterSet *BlockFilter) {
// Walk all the blocks in this chain, marking their successors as having
// a predecessor placed.
for (MachineBasicBlock *MBB : Chain) {
markBlockSuccessors(Chain, MBB, LoopHeaderBB, BlockFilter);
}
}
/// \brief Mark a single block's successors as having one fewer preds.
///
/// Under normal circumstances, this is only called by markChainSuccessors,
/// but if a block that was to be placed is completely tail-duplicated away,
/// and was duplicated into the chain end, we need to redo markBlockSuccessors
/// for just that block.
void MachineBlockPlacement::markBlockSuccessors(
const BlockChain &Chain, const MachineBasicBlock *MBB,
const MachineBasicBlock *LoopHeaderBB, const BlockFilterSet *BlockFilter) {
// Add any successors for which this is the only un-placed in-loop
// predecessor to the worklist as a viable candidate for CFG-neutral
// placement. No subsequent placement of this block will violate the CFG
// shape, so we get to use heuristics to choose a favorable placement.
for (MachineBasicBlock *Succ : MBB->successors()) {
if (BlockFilter && !BlockFilter->count(Succ))
continue;
BlockChain &SuccChain = *BlockToChain[Succ];
// Disregard edges within a fixed chain, or edges to the loop header.
if (&Chain == &SuccChain || Succ == LoopHeaderBB)
continue;
// This is a cross-chain edge that is within the loop, so decrement the
// loop predecessor count of the destination chain.
if (SuccChain.UnscheduledPredecessors == 0 ||
--SuccChain.UnscheduledPredecessors > 0)
continue;
auto *NewBB = *SuccChain.begin();
if (NewBB->isEHPad())
EHPadWorkList.push_back(NewBB);
else
BlockWorkList.push_back(NewBB);
}
}
/// This helper function collects the set of successors of block
/// \p BB that are allowed to be its layout successors, and return
/// the total branch probability of edges from \p BB to those
/// blocks.
BranchProbability MachineBlockPlacement::collectViableSuccessors(
const MachineBasicBlock *BB, const BlockChain &Chain,
const BlockFilterSet *BlockFilter,
SmallVector<MachineBasicBlock *, 4> &Successors) {
// Adjust edge probabilities by excluding edges pointing to blocks that is
// either not in BlockFilter or is already in the current chain. Consider the
// following CFG:
//
// --->A
// | / \
// | B C
// | \ / \
// ----D E
//
// Assume A->C is very hot (>90%), and C->D has a 50% probability, then after
// A->C is chosen as a fall-through, D won't be selected as a successor of C
// due to CFG constraint (the probability of C->D is not greater than
// HotProb to break top-order). If we exclude E that is not in BlockFilter
// when calculating the probability of C->D, D will be selected and we
// will get A C D B as the layout of this loop.
auto AdjustedSumProb = BranchProbability::getOne();
for (MachineBasicBlock *Succ : BB->successors()) {
bool SkipSucc = false;
if (Succ->isEHPad() || (BlockFilter && !BlockFilter->count(Succ))) {
SkipSucc = true;
} else {
BlockChain *SuccChain = BlockToChain[Succ];
if (SuccChain == &Chain) {
SkipSucc = true;
} else if (Succ != *SuccChain->begin()) {
DEBUG(dbgs() << " " << getBlockName(Succ) << " -> Mid chain!\n");
continue;
}
}
if (SkipSucc)
AdjustedSumProb -= MBPI->getEdgeProbability(BB, Succ);
else
Successors.push_back(Succ);
}
return AdjustedSumProb;
}
/// The helper function returns the branch probability that is adjusted
/// or normalized over the new total \p AdjustedSumProb.
static BranchProbability
getAdjustedProbability(BranchProbability OrigProb,
BranchProbability AdjustedSumProb) {
BranchProbability SuccProb;
uint32_t SuccProbN = OrigProb.getNumerator();
uint32_t SuccProbD = AdjustedSumProb.getNumerator();
if (SuccProbN >= SuccProbD)
SuccProb = BranchProbability::getOne();
else
SuccProb = BranchProbability(SuccProbN, SuccProbD);
return SuccProb;
}
/// Check if \p BB has exactly the successors in \p Successors.
static bool
hasSameSuccessors(MachineBasicBlock &BB,
SmallPtrSetImpl<const MachineBasicBlock *> &Successors) {
if (BB.succ_size() != Successors.size())
return false;
// We don't want to count self-loops
if (Successors.count(&BB))
return false;
for (MachineBasicBlock *Succ : BB.successors())
if (!Successors.count(Succ))
return false;
return true;
}
/// Check if a block should be tail duplicated to increase fallthrough
/// opportunities.
/// \p BB Block to check.
bool MachineBlockPlacement::shouldTailDuplicate(MachineBasicBlock *BB) {
// Blocks with single successors don't create additional fallthrough
// opportunities. Don't duplicate them. TODO: When conditional exits are
// analyzable, allow them to be duplicated.
bool IsSimple = TailDup.isSimpleBB(BB);
if (BB->succ_size() == 1)
return false;
return TailDup.shouldTailDuplicate(IsSimple, *BB);
}
/// Compare 2 BlockFrequency's with a small penalty for \p A.
/// In order to be conservative, we apply a X% penalty to account for
/// increased icache pressure and static heuristics. For small frequencies
/// we use only the numerators to improve accuracy. For simplicity, we assume the
/// penalty is less than 100%
/// TODO(iteratee): Use 64-bit fixed point edge frequencies everywhere.
static bool greaterWithBias(BlockFrequency A, BlockFrequency B,
uint64_t EntryFreq) {
BranchProbability ThresholdProb(TailDupPlacementPenalty, 100);
BlockFrequency Gain = A - B;
return (Gain / ThresholdProb).getFrequency() >= EntryFreq;
}
/// Check the edge frequencies to see if tail duplication will increase
/// fallthroughs. It only makes sense to call this function when
/// \p Succ would not be chosen otherwise. Tail duplication of \p Succ is
/// always locally profitable if we would have picked \p Succ without
/// considering duplication.
bool MachineBlockPlacement::isProfitableToTailDup(
const MachineBasicBlock *BB, const MachineBasicBlock *Succ,
BranchProbability QProb,
const BlockChain &Chain, const BlockFilterSet *BlockFilter) {
// We need to do a probability calculation to make sure this is profitable.
// First: does succ have a successor that post-dominates? This affects the
// calculation. The 2 relevant cases are:
// BB BB
// | \Qout | \Qout
// P| C |P C
// = C' = C'
// | /Qin | /Qin
// | / | /
// Succ Succ
// / \ | \ V
// U/ =V |U \
// / \ = D
// D E | /
// | /
// |/
// PDom
// '=' : Branch taken for that CFG edge
// In the second case, Placing Succ while duplicating it into C prevents the
// fallthrough of Succ into either D or PDom, because they now have C as an
// unplaced predecessor
// Start by figuring out which case we fall into
MachineBasicBlock *PDom = nullptr;
SmallVector<MachineBasicBlock *, 4> SuccSuccs;
// Only scan the relevant successors
auto AdjustedSuccSumProb =
collectViableSuccessors(Succ, Chain, BlockFilter, SuccSuccs);
BranchProbability PProb = MBPI->getEdgeProbability(BB, Succ);
auto BBFreq = MBFI->getBlockFreq(BB);
auto SuccFreq = MBFI->getBlockFreq(Succ);
BlockFrequency P = BBFreq * PProb;
BlockFrequency Qout = BBFreq * QProb;
uint64_t EntryFreq = MBFI->getEntryFreq();
// If there are no more successors, it is profitable to copy, as it strictly
// increases fallthrough.
if (SuccSuccs.size() == 0)
return greaterWithBias(P, Qout, EntryFreq);
auto BestSuccSucc = BranchProbability::getZero();
// Find the PDom or the best Succ if no PDom exists.
for (MachineBasicBlock *SuccSucc : SuccSuccs) {
auto Prob = MBPI->getEdgeProbability(Succ, SuccSucc);
if (Prob > BestSuccSucc)
BestSuccSucc = Prob;
if (PDom == nullptr)
if (MPDT->dominates(SuccSucc, Succ)) {
PDom = SuccSucc;
break;
}
}
// For the comparisons, we need to know Succ's best incoming edge that isn't
// from BB.
auto SuccBestPred = BlockFrequency(0);
for (MachineBasicBlock *SuccPred : Succ->predecessors()) {
if (SuccPred == Succ || SuccPred == BB
|| BlockToChain[SuccPred] == &Chain
|| (BlockFilter && !BlockFilter->count(SuccPred)))
continue;
auto Freq = MBFI->getBlockFreq(SuccPred)
* MBPI->getEdgeProbability(SuccPred, Succ);
if (Freq > SuccBestPred)
SuccBestPred = Freq;
}
// Qin is Succ's best unplaced incoming edge that isn't BB
BlockFrequency Qin = SuccBestPred;
// If it doesn't have a post-dominating successor, here is the calculation:
// BB BB
// | \Qout | \
// P| C | =
// = C' | C
// | /Qin | |
// | / | C' (+Succ)
// Succ Succ /|
// / \ | \/ |
// U/ =V | == |
// / \ | / \|
// D E D E
// '=' : Branch taken for that CFG edge
// Cost in the first case is: P + V
// For this calculation, we always assume P > Qout. If Qout > P
// The result of this function will be ignored at the caller.
// Cost in the second case is: Qout + Qin * U + P * V
if (PDom == nullptr || !Succ->isSuccessor(PDom)) {
BranchProbability UProb = BestSuccSucc;
BranchProbability VProb = AdjustedSuccSumProb - UProb;
BlockFrequency V = SuccFreq * VProb;
BlockFrequency QinU = Qin * UProb;
BlockFrequency BaseCost = P + V;
BlockFrequency DupCost = Qout + QinU + P * VProb;
return greaterWithBias(BaseCost, DupCost, EntryFreq);
}
BranchProbability UProb = MBPI->getEdgeProbability(Succ, PDom);
BranchProbability VProb = AdjustedSuccSumProb - UProb;
BlockFrequency U = SuccFreq * UProb;
BlockFrequency V = SuccFreq * VProb;
// If there is a post-dominating successor, here is the calculation:
// BB BB BB BB
// | \Qout | \ | \Qout | \
// |P C | = |P C | =
// = C' |P C = C' |P C
// | /Qin | | | /Qin | |
// | / | C' (+Succ) | / | C' (+Succ)
// Succ Succ /| Succ Succ /|
// | \ V | \/ | | \ V | \/ |
// |U \ |U /\ | |U = |U /\ |
// = D = = \= | D | = =|
// | / |/ D | / |/ D
// | / | / | = | /
// |/ | / |/ | =
// Dom Dom Dom Dom
// '=' : Branch taken for that CFG edge
// The cost for taken branches in the first case is P + U
// The cost in the second case (assuming independence), given the layout:
// BB, Succ, (C+Succ), D, Dom
// is Qout + P * V + Qin * U
// compare P + U vs Qout + P * U + Qin.
//
// The 3rd and 4th cases cover when Dom would be chosen to follow Succ.
//
// For the 3rd case, the cost is P + 2 * V
// For the 4th case, the cost is Qout + Qin * U + P * V + V
// We choose 4 over 3 when (P + V) > Qout + Qin * U + P * V
if (UProb > AdjustedSuccSumProb / 2 &&
!hasBetterLayoutPredecessor(Succ, PDom, *BlockToChain[PDom], UProb, UProb,
Chain, BlockFilter))
// Cases 3 & 4
return greaterWithBias((P + V), (Qout + Qin * UProb + P * VProb),
EntryFreq);
// Cases 1 & 2
return greaterWithBias(
(P + U), (Qout + Qin * AdjustedSuccSumProb + P * UProb), EntryFreq);
}
/// Check for a trellis layout. \p BB is the upper part of a trellis if its
/// successors form the lower part of a trellis. A successor set S forms the
/// lower part of a trellis if all of the predecessors of S are either in S or
/// have all of S as successors. We ignore trellises where BB doesn't have 2
/// successors because for fewer than 2, it's trivial, and for 3 or greater they
/// are very uncommon and complex to compute optimally. Allowing edges within S
/// is not strictly a trellis, but the same algorithm works, so we allow it.
bool MachineBlockPlacement::isTrellis(
const MachineBasicBlock *BB,
const SmallVectorImpl<MachineBasicBlock *> &ViableSuccs,
const BlockChain &Chain, const BlockFilterSet *BlockFilter) {
// Technically BB could form a trellis with branching factor higher than 2.
// But that's extremely uncommon.
if (BB->succ_size() != 2 || ViableSuccs.size() != 2)
return false;
SmallPtrSet<const MachineBasicBlock *, 2> Successors(BB->succ_begin(),
BB->succ_end());
// To avoid reviewing the same predecessors twice.
SmallPtrSet<const MachineBasicBlock *, 8> SeenPreds;
for (MachineBasicBlock *Succ : ViableSuccs) {
int PredCount = 0;
for (auto SuccPred : Succ->predecessors()) {
// Allow triangle successors, but don't count them.
if (Successors.count(SuccPred))
continue;
const BlockChain *PredChain = BlockToChain[SuccPred];
if (SuccPred == BB || (BlockFilter && !BlockFilter->count(SuccPred)) ||
PredChain == &Chain || PredChain == BlockToChain[Succ])
continue;
++PredCount;
// Perform the successor check only once.
if (!SeenPreds.insert(SuccPred).second)
continue;
if (!hasSameSuccessors(*SuccPred, Successors))
return false;
}
// If one of the successors has only BB as a predecessor, it is not a
// trellis.
if (PredCount < 1)
return false;
}
return true;
}
/// Pick the highest total weight pair of edges that can both be laid out.
/// The edges in \p Edges[0] are assumed to have a different destination than
/// the edges in \p Edges[1]. Simple counting shows that the best pair is either
/// the individual highest weight edges to the 2 different destinations, or in
/// case of a conflict, one of them should be replaced with a 2nd best edge.
std::pair<MachineBlockPlacement::WeightedEdge,
MachineBlockPlacement::WeightedEdge>
MachineBlockPlacement::getBestNonConflictingEdges(
const MachineBasicBlock *BB,
SmallVector<SmallVector<MachineBlockPlacement::WeightedEdge, 8>, 2>
&Edges) {
// Sort the edges, and then for each successor, find the best incoming
// predecessor. If the best incoming predecessors aren't the same,
// then that is clearly the best layout. If there is a conflict, one of the
// successors will have to fallthrough from the second best predecessor. We
// compare which combination is better overall.
// Sort for highest frequency.
auto Cmp = [](WeightedEdge A, WeightedEdge B) { return A.Weight > B.Weight; };
std::stable_sort(Edges[0].begin(), Edges[0].end(), Cmp);
std::stable_sort(Edges[1].begin(), Edges[1].end(), Cmp);
auto BestA = Edges[0].begin();
auto BestB = Edges[1].begin();
// Arrange for the correct answer to be in BestA and BestB
// If the 2 best edges don't conflict, the answer is already there.
if (BestA->Src == BestB->Src) {
// Compare the total fallthrough of (Best + Second Best) for both pairs
auto SecondBestA = std::next(BestA);
auto SecondBestB = std::next(BestB);
BlockFrequency BestAScore = BestA->Weight + SecondBestB->Weight;
BlockFrequency BestBScore = BestB->Weight + SecondBestA->Weight;
if (BestAScore < BestBScore)
BestA = SecondBestA;
else
BestB = SecondBestB;
}
// Arrange for the BB edge to be in BestA if it exists.
if (BestB->Src == BB)
std::swap(BestA, BestB);
return std::make_pair(*BestA, *BestB);
}
/// Get the best successor from \p BB based on \p BB being part of a trellis.
/// We only handle trellises with 2 successors, so the algorithm is
/// straightforward: Find the best pair of edges that don't conflict. We find
/// the best incoming edge for each successor in the trellis. If those conflict,
/// we consider which of them should be replaced with the second best.
/// Upon return the two best edges will be in \p BestEdges. If one of the edges
/// comes from \p BB, it will be in \p BestEdges[0]
MachineBlockPlacement::BlockAndTailDupResult
MachineBlockPlacement::getBestTrellisSuccessor(
const MachineBasicBlock *BB,
const SmallVectorImpl<MachineBasicBlock *> &ViableSuccs,
BranchProbability AdjustedSumProb, const BlockChain &Chain,
const BlockFilterSet *BlockFilter) {
BlockAndTailDupResult Result = {nullptr, false};
SmallPtrSet<const MachineBasicBlock *, 4> Successors(BB->succ_begin(),
BB->succ_end());
// We assume size 2 because it's common. For general n, we would have to do
// the Hungarian algorithm, but it's not worth the complexity because more
// than 2 successors is fairly uncommon, and a trellis even more so.
if (Successors.size() != 2 || ViableSuccs.size() != 2)
return Result;
// Collect the edge frequencies of all edges that form the trellis.
SmallVector<SmallVector<WeightedEdge, 8>, 2> Edges(2);
int SuccIndex = 0;
for (auto Succ : ViableSuccs) {
for (MachineBasicBlock *SuccPred : Succ->predecessors()) {
// Skip any placed predecessors that are not BB
if (SuccPred != BB)
if ((BlockFilter && !BlockFilter->count(SuccPred)) ||
BlockToChain[SuccPred] == &Chain ||
BlockToChain[SuccPred] == BlockToChain[Succ])
continue;
BlockFrequency EdgeFreq = MBFI->getBlockFreq(SuccPred) *
MBPI->getEdgeProbability(SuccPred, Succ);
Edges[SuccIndex].push_back({EdgeFreq, SuccPred, Succ});
}
++SuccIndex;
}
// Pick the best combination of 2 edges from all the edges in the trellis.
WeightedEdge BestA, BestB;
std::tie(BestA, BestB) = getBestNonConflictingEdges(BB, Edges);
if (BestA.Src != BB) {
// If we have a trellis, and BB doesn't have the best fallthrough edges,
// we shouldn't choose any successor. We've already looked and there's a
// better fallthrough edge for all the successors.
DEBUG(dbgs() << "Trellis, but not one of the chosen edges.\n");
return Result;
}
// Did we pick the triangle edge? If tail-duplication is profitable, do
// that instead. Otherwise merge the triangle edge now while we know it is
// optimal.
if (BestA.Dest == BestB.Src) {
// The edges are BB->Succ1->Succ2, and we're looking to see if BB->Succ2
// would be better.
MachineBasicBlock *Succ1 = BestA.Dest;
MachineBasicBlock *Succ2 = BestB.Dest;
// Check to see if tail-duplication would be profitable.
if (TailDupPlacement && shouldTailDuplicate(Succ2) &&
canTailDuplicateUnplacedPreds(BB, Succ2, Chain, BlockFilter) &&
isProfitableToTailDup(BB, Succ2, MBPI->getEdgeProbability(BB, Succ1),
Chain, BlockFilter)) {
DEBUG(BranchProbability Succ2Prob = getAdjustedProbability(
MBPI->getEdgeProbability(BB, Succ2), AdjustedSumProb);
dbgs() << " Selected: " << getBlockName(Succ2)
<< ", probability: " << Succ2Prob << " (Tail Duplicate)\n");
Result.BB = Succ2;
Result.ShouldTailDup = true;
return Result;
}
}
// We have already computed the optimal edge for the other side of the
// trellis.
ComputedEdges[BestB.Src] = { BestB.Dest, false };
auto TrellisSucc = BestA.Dest;
DEBUG(BranchProbability SuccProb = getAdjustedProbability(
MBPI->getEdgeProbability(BB, TrellisSucc), AdjustedSumProb);
dbgs() << " Selected: " << getBlockName(TrellisSucc)
<< ", probability: " << SuccProb << " (Trellis)\n");
Result.BB = TrellisSucc;
return Result;
}
/// When the option TailDupPlacement is on, this method checks if the
/// fallthrough candidate block \p Succ (of block \p BB) can be tail-duplicated
/// into all of its unplaced, unfiltered predecessors, that are not BB.
bool MachineBlockPlacement::canTailDuplicateUnplacedPreds(
const MachineBasicBlock *BB, MachineBasicBlock *Succ,
const BlockChain &Chain, const BlockFilterSet *BlockFilter) {