forked from Floorp-Projects/Floorp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathr322401.patch
2215 lines (2109 loc) · 83.6 KB
/
r322401.patch
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
From 90f447e9556a9e094890a3da1affbb4f84fecb44 Mon Sep 17 00:00:00 2001
From: "Brian M. Rzycki" <brzycki@gmail.com>
Date: Fri, 12 Jan 2018 21:06:48 +0000
Subject: [PATCH 1/2] [JumpThreading] Preservation of DT and LVI across the
pass
Summary:
See D37528 for a previous (non-deferred) version of this
patch and its description.
Preserves dominance in a deferred manner using a new class
DeferredDominance. This reduces the performance impact of
updating the DominatorTree at every edge insertion and
deletion. A user may call DDT->flush() within JumpThreading
for an up-to-date DT. This patch currently has one flush()
at the end of runImpl() to ensure DT is preserved across
the pass.
LVI is also preserved to help subsequent passes such as
CorrelatedValuePropagation. LVI is simpler to maintain and
is done immediately (not deferred). The code to perform the
preversation was minimally altered and simply marked as
preserved for the PassManager to be informed.
This extends the analysis available to JumpThreading for
future enhancements such as threading across loop headers.
Reviewers: dberlin, kuhar, sebpop
Reviewed By: kuhar, sebpop
Subscribers: mgorny, dmgreen, kuba, rnk, rsmith, hiraditya, llvm-commits
Differential Revision: https://reviews.llvm.org/D40146
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@322401 91177308-0d34-0410-b5e6-96231b3b80d8
---
include/llvm/IR/Dominators.h | 84 +++++
.../llvm/Transforms/Scalar/JumpThreading.h | 6 +-
.../llvm/Transforms/Utils/BasicBlockUtils.h | 3 +-
include/llvm/Transforms/Utils/Local.h | 20 +-
lib/IR/Dominators.cpp | 188 ++++++++++
.../Scalar/CorrelatedValuePropagation.cpp | 2 +
lib/Transforms/Scalar/JumpThreading.cpp | 174 +++++++--
lib/Transforms/Utils/BasicBlockUtils.cpp | 18 +-
lib/Transforms/Utils/Local.cpp | 209 ++++++++---
.../lvi-after-jumpthreading.ll | 3 +
test/Transforms/JumpThreading/ddt-crash.ll | 265 ++++++++++++++
test/Transforms/JumpThreading/ddt-crash2.ll | 40 ++
test/Transforms/JumpThreading/lvi-tristate.ll | 50 +++
unittests/IR/CMakeLists.txt | 1 +
unittests/IR/DeferredDominanceTest.cpp | 344 ++++++++++++++++++
15 files changed, 1308 insertions(+), 99 deletions(-)
create mode 100644 test/Transforms/JumpThreading/ddt-crash.ll
create mode 100644 test/Transforms/JumpThreading/ddt-crash2.ll
create mode 100644 test/Transforms/JumpThreading/lvi-tristate.ll
create mode 100644 unittests/IR/DeferredDominanceTest.cpp
diff --git a/llvm/include/llvm/IR/Dominators.h b/llvm/include/llvm/IR/Dominators.h
index 6ad99e516fb..c5373376ade 100644
--- a/llvm/include/llvm/IR/Dominators.h
+++ b/llvm/include/llvm/IR/Dominators.h
@@ -290,6 +290,90 @@ public:
void print(raw_ostream &OS, const Module *M = nullptr) const override;
};
+//===-------------------------------------
+/// \brief Class to defer updates to a DominatorTree.
+///
+/// Definition: Applying updates to every edge insertion and deletion is
+/// expensive and not necessary. When one needs the DominatorTree for analysis
+/// they can request a flush() to perform a larger batch update. This has the
+/// advantage of the DominatorTree inspecting the set of updates to find
+/// duplicates or unnecessary subtree updates.
+///
+/// The scope of DeferredDominance operates at a Function level.
+///
+/// It is not necessary for the user to scrub the updates for duplicates or
+/// updates that point to the same block (Delete, BB_A, BB_A). Performance
+/// can be gained if the caller attempts to batch updates before submitting
+/// to applyUpdates(ArrayRef) in cases where duplicate edge requests will
+/// occur.
+///
+/// It is required for the state of the LLVM IR to be applied *before*
+/// submitting updates. The update routines must analyze the current state
+/// between a pair of (From, To) basic blocks to determine if the update
+/// needs to be queued.
+/// Example (good):
+/// TerminatorInstructionBB->removeFromParent();
+/// DDT->deleteEdge(BB, Successor);
+/// Example (bad):
+/// DDT->deleteEdge(BB, Successor);
+/// TerminatorInstructionBB->removeFromParent();
+class DeferredDominance {
+public:
+ DeferredDominance(DominatorTree &DT_) : DT(DT_) {}
+
+ /// \brief Queues multiple updates and discards duplicates.
+ void applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates);
+
+ /// \brief Helper method for a single edge insertion. It's almost always
+ /// better to batch updates and call applyUpdates to quickly remove duplicate
+ /// edges. This is best used when there is only a single insertion needed to
+ /// update Dominators.
+ void insertEdge(BasicBlock *From, BasicBlock *To);
+
+ /// \brief Helper method for a single edge deletion. It's almost always better
+ /// to batch updates and call applyUpdates to quickly remove duplicate edges.
+ /// This is best used when there is only a single deletion needed to update
+ /// Dominators.
+ void deleteEdge(BasicBlock *From, BasicBlock *To);
+
+ /// \brief Delays the deletion of a basic block until a flush() event.
+ void deleteBB(BasicBlock *DelBB);
+
+ /// \brief Returns true if DelBB is awaiting deletion at a flush() event.
+ bool pendingDeletedBB(BasicBlock *DelBB);
+
+ /// \brief Flushes all pending updates and block deletions. Returns a
+ /// correct DominatorTree reference to be used by the caller for analysis.
+ DominatorTree &flush();
+
+ /// \brief Drops all internal state and forces a (slow) recalculation of the
+ /// DominatorTree based on the current state of the LLVM IR in F. This should
+ /// only be used in corner cases such as the Entry block of F being deleted.
+ void recalculate(Function &F);
+
+ /// \brief Debug method to help view the state of pending updates.
+ LLVM_DUMP_METHOD void dump() const;
+
+private:
+ DominatorTree &DT;
+ SmallVector<DominatorTree::UpdateType, 16> PendUpdates;
+ SmallPtrSet<BasicBlock *, 8> DeletedBBs;
+
+ /// Apply an update (Kind, From, To) to the internal queued updates. The
+ /// update is only added when determined to be necessary. Checks for
+ /// self-domination, unnecessary updates, duplicate requests, and balanced
+ /// pairs of requests are all performed. Returns true if the update is
+ /// queued and false if it is discarded.
+ bool applyUpdate(DominatorTree::UpdateKind Kind, BasicBlock *From,
+ BasicBlock *To);
+
+ /// Performs all pending basic block deletions. We have to defer the deletion
+ /// of these blocks until after the DominatorTree updates are applied. The
+ /// internal workings of the DominatorTree code expect every update's From
+ /// and To blocks to exist and to be a member of the same Function.
+ bool flushDelBB();
+};
+
} // end namespace llvm
#endif // LLVM_IR_DOMINATORS_H
diff --git a/llvm/include/llvm/Transforms/Scalar/JumpThreading.h b/llvm/include/llvm/Transforms/Scalar/JumpThreading.h
index a9466713b8e..b3493a29249 100644
--- a/llvm/include/llvm/Transforms/Scalar/JumpThreading.h
+++ b/llvm/include/llvm/Transforms/Scalar/JumpThreading.h
@@ -34,6 +34,7 @@ class BinaryOperator;
class BranchInst;
class CmpInst;
class Constant;
+class DeferredDominance;
class Function;
class Instruction;
class IntrinsicInst;
@@ -77,6 +78,7 @@ class JumpThreadingPass : public PassInfoMixin<JumpThreadingPass> {
TargetLibraryInfo *TLI;
LazyValueInfo *LVI;
AliasAnalysis *AA;
+ DeferredDominance *DDT;
std::unique_ptr<BlockFrequencyInfo> BFI;
std::unique_ptr<BranchProbabilityInfo> BPI;
bool HasProfileData = false;
@@ -107,8 +109,8 @@ public:
// Glue for old PM.
bool runImpl(Function &F, TargetLibraryInfo *TLI_, LazyValueInfo *LVI_,
- AliasAnalysis *AA_, bool HasProfileData_,
- std::unique_ptr<BlockFrequencyInfo> BFI_,
+ AliasAnalysis *AA_, DeferredDominance *DDT_,
+ bool HasProfileData_, std::unique_ptr<BlockFrequencyInfo> BFI_,
std::unique_ptr<BranchProbabilityInfo> BPI_);
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
diff --git a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
index 74f75509f55..6f0d2deac0a 100644
--- a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -27,6 +27,7 @@ namespace llvm {
class BlockFrequencyInfo;
class BranchProbabilityInfo;
+class DeferredDominance;
class DominatorTree;
class Function;
class Instruction;
@@ -38,7 +39,7 @@ class TargetLibraryInfo;
class Value;
/// Delete the specified block, which must have no predecessors.
-void DeleteDeadBlock(BasicBlock *BB);
+void DeleteDeadBlock(BasicBlock *BB, DeferredDominance *DDT = nullptr);
/// We know that BB has one predecessor. If there are any single-entry PHI nodes
/// in it, fold them away. This handles the case when all entries to the PHI
diff --git a/llvm/include/llvm/Transforms/Utils/Local.h b/llvm/include/llvm/Transforms/Utils/Local.h
index 01db88bc15c..eb1f4c41b44 100644
--- a/llvm/include/llvm/Transforms/Utils/Local.h
+++ b/llvm/include/llvm/Transforms/Utils/Local.h
@@ -117,7 +117,8 @@ struct SimplifyCFGOptions {
/// conditions and indirectbr addresses this might make dead if
/// DeleteDeadConditions is true.
bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions = false,
- const TargetLibraryInfo *TLI = nullptr);
+ const TargetLibraryInfo *TLI = nullptr,
+ DeferredDominance *DDT = nullptr);
//===----------------------------------------------------------------------===//
// Local dead code elimination.
@@ -171,18 +172,21 @@ bool SimplifyInstructionsInBlock(BasicBlock *BB,
///
/// .. and delete the predecessor corresponding to the '1', this will attempt to
/// recursively fold the 'and' to 0.
-void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred);
+void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred,
+ DeferredDominance *DDT = nullptr);
/// BB is a block with one predecessor and its predecessor is known to have one
/// successor (BB!). Eliminate the edge between them, moving the instructions in
/// the predecessor into BB. This deletes the predecessor block.
-void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DominatorTree *DT = nullptr);
+void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DominatorTree *DT = nullptr,
+ DeferredDominance *DDT = nullptr);
/// BB is known to contain an unconditional branch, and contains no instructions
/// other than PHI nodes, potential debug intrinsics and the branch. If
/// possible, eliminate BB by rewriting all the predecessors to branch to the
/// successor block and return true. If we can't transform, return false.
-bool TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB);
+bool TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
+ DeferredDominance *DDT = nullptr);
/// Check for and eliminate duplicate PHI nodes in this block. This doesn't try
/// to be clever about PHI nodes which differ only in the order of the incoming
@@ -382,7 +386,8 @@ unsigned removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB);
/// Insert an unreachable instruction before the specified
/// instruction, making it and the rest of the code in the block dead.
unsigned changeToUnreachable(Instruction *I, bool UseLLVMTrap,
- bool PreserveLCSSA = false);
+ bool PreserveLCSSA = false,
+ DeferredDominance *DDT = nullptr);
/// Convert the CallInst to InvokeInst with the specified unwind edge basic
/// block. This also splits the basic block where CI is located, because
@@ -397,12 +402,13 @@ BasicBlock *changeToInvokeAndSplitBasicBlock(CallInst *CI,
///
/// \param BB Block whose terminator will be replaced. Its terminator must
/// have an unwind successor.
-void removeUnwindEdge(BasicBlock *BB);
+void removeUnwindEdge(BasicBlock *BB, DeferredDominance *DDT = nullptr);
/// Remove all blocks that can not be reached from the function's entry.
///
/// Returns true if any basic block was removed.
-bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI = nullptr);
+bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI = nullptr,
+ DeferredDominance *DDT = nullptr);
/// Combine the metadata of two instructions so that K can replace J
///
diff --git a/llvm/lib/IR/Dominators.cpp b/llvm/lib/IR/Dominators.cpp
index ad448a3f240..e44e845b324 100644
--- a/llvm/lib/IR/Dominators.cpp
+++ b/llvm/lib/IR/Dominators.cpp
@@ -18,6 +18,7 @@
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/CFG.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/CommandLine.h"
@@ -389,3 +390,190 @@ void DominatorTreeWrapperPass::print(raw_ostream &OS, const Module *) const {
DT.print(OS);
}
+//===----------------------------------------------------------------------===//
+// DeferredDominance Implementation
+//===----------------------------------------------------------------------===//
+//
+// The implementation details of the DeferredDominance class which allows
+// one to queue updates to a DominatorTree.
+//
+//===----------------------------------------------------------------------===//
+
+/// \brief Queues multiple updates and discards duplicates.
+void DeferredDominance::applyUpdates(
+ ArrayRef<DominatorTree::UpdateType> Updates) {
+ SmallVector<DominatorTree::UpdateType, 8> Seen;
+ for (auto U : Updates)
+ // Avoid duplicates to applyUpdate() to save on analysis.
+ if (std::none_of(Seen.begin(), Seen.end(),
+ [U](DominatorTree::UpdateType S) { return S == U; })) {
+ Seen.push_back(U);
+ applyUpdate(U.getKind(), U.getFrom(), U.getTo());
+ }
+}
+
+/// \brief Helper method for a single edge insertion. It's almost always better
+/// to batch updates and call applyUpdates to quickly remove duplicate edges.
+/// This is best used when there is only a single insertion needed to update
+/// Dominators.
+void DeferredDominance::insertEdge(BasicBlock *From, BasicBlock *To) {
+ applyUpdate(DominatorTree::Insert, From, To);
+}
+
+/// \brief Helper method for a single edge deletion. It's almost always better
+/// to batch updates and call applyUpdates to quickly remove duplicate edges.
+/// This is best used when there is only a single deletion needed to update
+/// Dominators.
+void DeferredDominance::deleteEdge(BasicBlock *From, BasicBlock *To) {
+ applyUpdate(DominatorTree::Delete, From, To);
+}
+
+/// \brief Delays the deletion of a basic block until a flush() event.
+void DeferredDominance::deleteBB(BasicBlock *DelBB) {
+ assert(DelBB && "Invalid push_back of nullptr DelBB.");
+ assert(pred_empty(DelBB) && "DelBB has one or more predecessors.");
+ // DelBB is unreachable and all its instructions are dead.
+ while (!DelBB->empty()) {
+ Instruction &I = DelBB->back();
+ // Replace used instructions with an arbitrary value (undef).
+ if (!I.use_empty())
+ I.replaceAllUsesWith(llvm::UndefValue::get(I.getType()));
+ DelBB->getInstList().pop_back();
+ }
+ // Make sure DelBB has a valid terminator instruction. As long as DelBB is a
+ // Child of Function F it must contain valid IR.
+ new UnreachableInst(DelBB->getContext(), DelBB);
+ DeletedBBs.insert(DelBB);
+}
+
+/// \brief Returns true if DelBB is awaiting deletion at a flush() event.
+bool DeferredDominance::pendingDeletedBB(BasicBlock *DelBB) {
+ if (DeletedBBs.empty())
+ return false;
+ return DeletedBBs.count(DelBB) != 0;
+}
+
+/// \brief Flushes all pending updates and block deletions. Returns a
+/// correct DominatorTree reference to be used by the caller for analysis.
+DominatorTree &DeferredDominance::flush() {
+ // Updates to DT must happen before blocks are deleted below. Otherwise the
+ // DT traversal will encounter badref blocks and assert.
+ if (!PendUpdates.empty()) {
+ DT.applyUpdates(PendUpdates);
+ PendUpdates.clear();
+ }
+ flushDelBB();
+ return DT;
+}
+
+/// \brief Drops all internal state and forces a (slow) recalculation of the
+/// DominatorTree based on the current state of the LLVM IR in F. This should
+/// only be used in corner cases such as the Entry block of F being deleted.
+void DeferredDominance::recalculate(Function &F) {
+ // flushDelBB must be flushed before the recalculation. The state of the IR
+ // must be consistent before the DT traversal algorithm determines the
+ // actual DT.
+ if (flushDelBB() || !PendUpdates.empty()) {
+ DT.recalculate(F);
+ PendUpdates.clear();
+ }
+}
+
+/// \brief Debug method to help view the state of pending updates.
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void DeferredDominance::dump() const {
+ raw_ostream &OS = llvm::dbgs();
+ OS << "PendUpdates:\n";
+ int I = 0;
+ for (auto U : PendUpdates) {
+ OS << " " << I << " : ";
+ ++I;
+ if (U.getKind() == DominatorTree::Insert)
+ OS << "Insert, ";
+ else
+ OS << "Delete, ";
+ BasicBlock *From = U.getFrom();
+ if (From) {
+ auto S = From->getName();
+ if (!From->hasName())
+ S = "(no name)";
+ OS << S << "(" << From << "), ";
+ } else {
+ OS << "(badref), ";
+ }
+ BasicBlock *To = U.getTo();
+ if (To) {
+ auto S = To->getName();
+ if (!To->hasName())
+ S = "(no_name)";
+ OS << S << "(" << To << ")\n";
+ } else {
+ OS << "(badref)\n";
+ }
+ }
+ OS << "DeletedBBs:\n";
+ I = 0;
+ for (auto BB : DeletedBBs) {
+ OS << " " << I << " : ";
+ ++I;
+ if (BB->hasName())
+ OS << BB->getName() << "(";
+ else
+ OS << "(no_name)(";
+ OS << BB << ")\n";
+ }
+}
+#endif
+
+/// Apply an update (Kind, From, To) to the internal queued updates. The
+/// update is only added when determined to be necessary. Checks for
+/// self-domination, unnecessary updates, duplicate requests, and balanced
+/// pairs of requests are all performed. Returns true if the update is
+/// queued and false if it is discarded.
+bool DeferredDominance::applyUpdate(DominatorTree::UpdateKind Kind,
+ BasicBlock *From, BasicBlock *To) {
+ if (From == To)
+ return false; // Cannot dominate self; discard update.
+
+ // Discard updates by inspecting the current state of successors of From.
+ // Since applyUpdate() must be called *after* the Terminator of From is
+ // altered we can determine if the update is unnecessary.
+ bool HasEdge = std::any_of(succ_begin(From), succ_end(From),
+ [To](BasicBlock *B) { return B == To; });
+ if (Kind == DominatorTree::Insert && !HasEdge)
+ return false; // Unnecessary Insert: edge does not exist in IR.
+ if (Kind == DominatorTree::Delete && HasEdge)
+ return false; // Unnecessary Delete: edge still exists in IR.
+
+ // Analyze pending updates to determine if the update is unnecessary.
+ DominatorTree::UpdateType Update = {Kind, From, To};
+ DominatorTree::UpdateType Invert = {Kind != DominatorTree::Insert
+ ? DominatorTree::Insert
+ : DominatorTree::Delete,
+ From, To};
+ for (auto I = PendUpdates.begin(), E = PendUpdates.end(); I != E; ++I) {
+ if (Update == *I)
+ return false; // Discard duplicate updates.
+ if (Invert == *I) {
+ // Update and Invert are both valid (equivalent to a no-op). Remove
+ // Invert from PendUpdates and discard the Update.
+ PendUpdates.erase(I);
+ return false;
+ }
+ }
+ PendUpdates.push_back(Update); // Save the valid update.
+ return true;
+}
+
+/// Performs all pending basic block deletions. We have to defer the deletion
+/// of these blocks until after the DominatorTree updates are applied. The
+/// internal workings of the DominatorTree code expect every update's From
+/// and To blocks to exist and to be a member of the same Function.
+bool DeferredDominance::flushDelBB() {
+ if (DeletedBBs.empty())
+ return false;
+ for (auto *BB : DeletedBBs)
+ BB->eraseFromParent();
+ DeletedBBs.clear();
+ return true;
+}
diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
index 8f468ebf894..535d43cdf9e 100644
--- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -77,6 +77,7 @@ namespace {
bool runOnFunction(Function &F) override;
void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<DominatorTreeWrapperPass>();
AU.addRequired<LazyValueInfoWrapperPass>();
AU.addPreserved<GlobalsAAWrapperPass>();
}
@@ -88,6 +89,7 @@ char CorrelatedValuePropagation::ID = 0;
INITIALIZE_PASS_BEGIN(CorrelatedValuePropagation, "correlated-propagation",
"Value Propagation", false, false)
+INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LazyValueInfoWrapperPass)
INITIALIZE_PASS_END(CorrelatedValuePropagation, "correlated-propagation",
"Value Propagation", false, false)
diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
index 141c9938bf8..4d366e8e392 100644
--- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
@@ -131,10 +131,11 @@ namespace {
bool runOnFunction(Function &F) override;
void getAnalysisUsage(AnalysisUsage &AU) const override {
- if (PrintLVIAfterJumpThreading)
- AU.addRequired<DominatorTreeWrapperPass>();
+ AU.addRequired<DominatorTreeWrapperPass>();
+ AU.addPreserved<DominatorTreeWrapperPass>();
AU.addRequired<AAResultsWrapperPass>();
AU.addRequired<LazyValueInfoWrapperPass>();
+ AU.addPreserved<LazyValueInfoWrapperPass>();
AU.addPreserved<GlobalsAAWrapperPass>();
AU.addRequired<TargetLibraryInfoWrapperPass>();
}
@@ -148,6 +149,7 @@ char JumpThreading::ID = 0;
INITIALIZE_PASS_BEGIN(JumpThreading, "jump-threading",
"Jump Threading", false, false)
+INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LazyValueInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
@@ -278,8 +280,12 @@ bool JumpThreading::runOnFunction(Function &F) {
if (skipFunction(F))
return false;
auto TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
+ // Get DT analysis before LVI. When LVI is initialized it conditionally adds
+ // DT if it's available.
+ auto DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
auto LVI = &getAnalysis<LazyValueInfoWrapperPass>().getLVI();
auto AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
+ DeferredDominance DDT(*DT);
std::unique_ptr<BlockFrequencyInfo> BFI;
std::unique_ptr<BranchProbabilityInfo> BPI;
bool HasProfileData = F.hasProfileData();
@@ -289,12 +295,11 @@ bool JumpThreading::runOnFunction(Function &F) {
BFI.reset(new BlockFrequencyInfo(F, *BPI, LI));
}
- bool Changed = Impl.runImpl(F, TLI, LVI, AA, HasProfileData, std::move(BFI),
- std::move(BPI));
+ bool Changed = Impl.runImpl(F, TLI, LVI, AA, &DDT, HasProfileData,
+ std::move(BFI), std::move(BPI));
if (PrintLVIAfterJumpThreading) {
dbgs() << "LVI for function '" << F.getName() << "':\n";
- LVI->printLVI(F, getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
- dbgs());
+ LVI->printLVI(F, *DT, dbgs());
}
return Changed;
}
@@ -302,8 +307,12 @@ bool JumpThreading::runOnFunction(Function &F) {
PreservedAnalyses JumpThreadingPass::run(Function &F,
FunctionAnalysisManager &AM) {
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
+ // Get DT analysis before LVI. When LVI is initialized it conditionally adds
+ // DT if it's available.
+ auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
auto &LVI = AM.getResult<LazyValueAnalysis>(F);
auto &AA = AM.getResult<AAManager>(F);
+ DeferredDominance DDT(DT);
std::unique_ptr<BlockFrequencyInfo> BFI;
std::unique_ptr<BranchProbabilityInfo> BPI;
@@ -313,25 +322,28 @@ PreservedAnalyses JumpThreadingPass::run(Function &F,
BFI.reset(new BlockFrequencyInfo(F, *BPI, LI));
}
- bool Changed = runImpl(F, &TLI, &LVI, &AA, HasProfileData, std::move(BFI),
- std::move(BPI));
+ bool Changed = runImpl(F, &TLI, &LVI, &AA, &DDT, HasProfileData,
+ std::move(BFI), std::move(BPI));
if (!Changed)
return PreservedAnalyses::all();
PreservedAnalyses PA;
PA.preserve<GlobalsAA>();
+ PA.preserve<DominatorTreeAnalysis>();
+ PA.preserve<LazyValueAnalysis>();
return PA;
}
bool JumpThreadingPass::runImpl(Function &F, TargetLibraryInfo *TLI_,
LazyValueInfo *LVI_, AliasAnalysis *AA_,
- bool HasProfileData_,
+ DeferredDominance *DDT_, bool HasProfileData_,
std::unique_ptr<BlockFrequencyInfo> BFI_,
std::unique_ptr<BranchProbabilityInfo> BPI_) {
DEBUG(dbgs() << "Jump threading on function '" << F.getName() << "'\n");
TLI = TLI_;
LVI = LVI_;
AA = AA_;
+ DDT = DDT_;
BFI.reset();
BPI.reset();
// When profile data is available, we need to update edge weights after
@@ -353,7 +365,7 @@ bool JumpThreadingPass::runImpl(Function &F, TargetLibraryInfo *TLI_,
// back edges. This works for normal cases but not for unreachable blocks as
// they may have cycle with no back edge.
bool EverChanged = false;
- EverChanged |= removeUnreachableBlocks(F, LVI);
+ EverChanged |= removeUnreachableBlocks(F, LVI, DDT);
FindLoopHeaders(F);
@@ -368,6 +380,10 @@ bool JumpThreadingPass::runImpl(Function &F, TargetLibraryInfo *TLI_,
++I;
+ // Don't thread branches over a block that's slated for deletion.
+ if (DDT->pendingDeletedBB(BB))
+ continue;
+
// If the block is trivially dead, zap it. This eliminates the successor
// edges which simplifies the CFG.
if (pred_empty(BB) &&
@@ -376,7 +392,7 @@ bool JumpThreadingPass::runImpl(Function &F, TargetLibraryInfo *TLI_,
<< "' with terminator: " << *BB->getTerminator() << '\n');
LoopHeaders.erase(BB);
LVI->eraseBlock(BB);
- DeleteDeadBlock(BB);
+ DeleteDeadBlock(BB, DDT);
Changed = true;
continue;
}
@@ -400,7 +416,7 @@ bool JumpThreadingPass::runImpl(Function &F, TargetLibraryInfo *TLI_,
// awesome, but it allows us to use AssertingVH to prevent nasty
// dangling pointer issues within LazyValueInfo.
LVI->eraseBlock(BB);
- if (TryToSimplifyUncondBranchFromEmptyBlock(BB))
+ if (TryToSimplifyUncondBranchFromEmptyBlock(BB, DDT))
Changed = true;
}
}
@@ -408,6 +424,7 @@ bool JumpThreadingPass::runImpl(Function &F, TargetLibraryInfo *TLI_,
} while (Changed);
LoopHeaders.clear();
+ DDT->flush();
return EverChanged;
}
@@ -931,8 +948,8 @@ static bool hasAddressTakenAndUsed(BasicBlock *BB) {
bool JumpThreadingPass::ProcessBlock(BasicBlock *BB) {
// If the block is trivially dead, just return and let the caller nuke it.
// This simplifies other transformations.
- if (pred_empty(BB) &&
- BB != &BB->getParent()->getEntryBlock())
+ if (DDT->pendingDeletedBB(BB) ||
+ (pred_empty(BB) && BB != &BB->getParent()->getEntryBlock()))
return false;
// If this block has a single predecessor, and if that pred has a single
@@ -948,7 +965,7 @@ bool JumpThreadingPass::ProcessBlock(BasicBlock *BB) {
LoopHeaders.insert(BB);
LVI->eraseBlock(SinglePred);
- MergeBasicBlockIntoOnlyPred(BB);
+ MergeBasicBlockIntoOnlyPred(BB, nullptr, DDT);
// Now that BB is merged into SinglePred (i.e. SinglePred Code followed by
// BB code within one basic block `BB`), we need to invalidate the LVI
@@ -1031,18 +1048,23 @@ bool JumpThreadingPass::ProcessBlock(BasicBlock *BB) {
// successors to branch to. Let GetBestDestForJumpOnUndef decide.
if (isa<UndefValue>(Condition)) {
unsigned BestSucc = GetBestDestForJumpOnUndef(BB);
+ std::vector<DominatorTree::UpdateType> Updates;
// Fold the branch/switch.
TerminatorInst *BBTerm = BB->getTerminator();
+ Updates.reserve(BBTerm->getNumSuccessors());
for (unsigned i = 0, e = BBTerm->getNumSuccessors(); i != e; ++i) {
if (i == BestSucc) continue;
- BBTerm->getSuccessor(i)->removePredecessor(BB, true);
+ BasicBlock *Succ = BBTerm->getSuccessor(i);
+ Succ->removePredecessor(BB, true);
+ Updates.push_back({DominatorTree::Delete, BB, Succ});
}
DEBUG(dbgs() << " In block '" << BB->getName()
<< "' folding undef terminator: " << *BBTerm << '\n');
BranchInst::Create(BBTerm->getSuccessor(BestSucc), BBTerm);
BBTerm->eraseFromParent();
+ DDT->applyUpdates(Updates);
return true;
}
@@ -1053,7 +1075,7 @@ bool JumpThreadingPass::ProcessBlock(BasicBlock *BB) {
DEBUG(dbgs() << " In block '" << BB->getName()
<< "' folding terminator: " << *BB->getTerminator() << '\n');
++NumFolds;
- ConstantFoldTerminator(BB, true);
+ ConstantFoldTerminator(BB, true, nullptr, DDT);
return true;
}
@@ -1086,7 +1108,8 @@ bool JumpThreadingPass::ProcessBlock(BasicBlock *BB) {
if (Ret != LazyValueInfo::Unknown) {
unsigned ToRemove = Ret == LazyValueInfo::True ? 1 : 0;
unsigned ToKeep = Ret == LazyValueInfo::True ? 0 : 1;
- CondBr->getSuccessor(ToRemove)->removePredecessor(BB, true);
+ BasicBlock *ToRemoveSucc = CondBr->getSuccessor(ToRemove);
+ ToRemoveSucc->removePredecessor(BB, true);
BranchInst::Create(CondBr->getSuccessor(ToKeep), CondBr);
CondBr->eraseFromParent();
if (CondCmp->use_empty())
@@ -1104,6 +1127,7 @@ bool JumpThreadingPass::ProcessBlock(BasicBlock *BB) {
ConstantInt::getFalse(CondCmp->getType());
ReplaceFoldableUses(CondCmp, CI);
}
+ DDT->deleteEdge(BB, ToRemoveSucc);
return true;
}
@@ -1182,9 +1206,12 @@ bool JumpThreadingPass::ProcessImpliedCondition(BasicBlock *BB) {
Optional<bool> Implication =
isImpliedCondition(PBI->getCondition(), Cond, DL, CondIsTrue);
if (Implication) {
- BI->getSuccessor(*Implication ? 1 : 0)->removePredecessor(BB);
- BranchInst::Create(BI->getSuccessor(*Implication ? 0 : 1), BI);
+ BasicBlock *KeepSucc = BI->getSuccessor(*Implication ? 0 : 1);
+ BasicBlock *RemoveSucc = BI->getSuccessor(*Implication ? 1 : 0);
+ RemoveSucc->removePredecessor(BB);
+ BranchInst::Create(KeepSucc, BI);
BI->eraseFromParent();
+ DDT->deleteEdge(BB, RemoveSucc);
return true;
}
CurrentBB = CurrentPred;
@@ -1591,17 +1618,22 @@ bool JumpThreadingPass::ProcessThreadableEdges(Value *Cond, BasicBlock *BB,
if (PredWithKnownDest ==
(size_t)std::distance(pred_begin(BB), pred_end(BB))) {
bool SeenFirstBranchToOnlyDest = false;
+ std::vector <DominatorTree::UpdateType> Updates;
+ Updates.reserve(BB->getTerminator()->getNumSuccessors() - 1);
for (BasicBlock *SuccBB : successors(BB)) {
- if (SuccBB == OnlyDest && !SeenFirstBranchToOnlyDest)
+ if (SuccBB == OnlyDest && !SeenFirstBranchToOnlyDest) {
SeenFirstBranchToOnlyDest = true; // Don't modify the first branch.
- else
+ } else {
SuccBB->removePredecessor(BB, true); // This is unreachable successor.
+ Updates.push_back({DominatorTree::Delete, BB, SuccBB});
+ }
}
// Finally update the terminator.
TerminatorInst *Term = BB->getTerminator();
BranchInst::Create(OnlyDest, Term);
Term->eraseFromParent();
+ DDT->applyUpdates(Updates);
// If the condition is now dead due to the removal of the old terminator,
// erase it.
@@ -1964,6 +1996,10 @@ bool JumpThreadingPass::ThreadEdge(BasicBlock *BB,
PredTerm->setSuccessor(i, NewBB);
}
+ DDT->applyUpdates({{DominatorTree::Insert, NewBB, SuccBB},
+ {DominatorTree::Insert, PredBB, NewBB},
+ {DominatorTree::Delete, PredBB, BB}});
+
// At this point, the IR is fully up to date and consistent. Do a quick scan
// over the new instructions and zap any that are constants or dead. This
// frequently happens because of phi translation.
@@ -1983,20 +2019,42 @@ bool JumpThreadingPass::ThreadEdge(BasicBlock *BB,
BasicBlock *JumpThreadingPass::SplitBlockPreds(BasicBlock *BB,
ArrayRef<BasicBlock *> Preds,
const char *Suffix) {
+ SmallVector<BasicBlock *, 2> NewBBs;
+
// Collect the frequencies of all predecessors of BB, which will be used to
- // update the edge weight on BB->SuccBB.
- BlockFrequency PredBBFreq(0);
+ // update the edge weight of the result of splitting predecessors.
+ DenseMap<BasicBlock *, BlockFrequency> FreqMap;
if (HasProfileData)
for (auto Pred : Preds)
- PredBBFreq += BFI->getBlockFreq(Pred) * BPI->getEdgeProbability(Pred, BB);
+ FreqMap.insert(std::make_pair(
+ Pred, BFI->getBlockFreq(Pred) * BPI->getEdgeProbability(Pred, BB)));
+
+ // In the case when BB is a LandingPad block we create 2 new predecessors
+ // instead of just one.
+ if (BB->isLandingPad()) {
+ std::string NewName = std::string(Suffix) + ".split-lp";
+ SplitLandingPadPredecessors(BB, Preds, Suffix, NewName.c_str(), NewBBs);
+ } else {
+ NewBBs.push_back(SplitBlockPredecessors(BB, Preds, Suffix));
+ }
- BasicBlock *PredBB = SplitBlockPredecessors(BB, Preds, Suffix);
+ std::vector<DominatorTree::UpdateType> Updates;
+ Updates.reserve((2 * Preds.size()) + NewBBs.size());
+ for (auto NewBB : NewBBs) {
+ BlockFrequency NewBBFreq(0);
+ Updates.push_back({DominatorTree::Insert, NewBB, BB});
+ for (auto Pred : predecessors(NewBB)) {
+ Updates.push_back({DominatorTree::Delete, Pred, BB});
+ Updates.push_back({DominatorTree::Insert, Pred, NewBB});
+ if (HasProfileData) // Update frequencies between Pred -> NewBB.
+ NewBBFreq += FreqMap.lookup(Pred);
+ }
+ if (HasProfileData) // Apply the summed frequency to NewBB.
+ BFI->setBlockFreq(NewBB, NewBBFreq.getFrequency());
+ }
- // Set the block frequency of the newly created PredBB, which is the sum of
- // frequencies of Preds.
- if (HasProfileData)
- BFI->setBlockFreq(PredBB, PredBBFreq.getFrequency());
- return PredBB;
+ DDT->applyUpdates(Updates);
+ return NewBBs[0];
}
bool JumpThreadingPass::doesBlockHaveProfileData(BasicBlock *BB) {
@@ -2140,6 +2198,7 @@ bool JumpThreadingPass::DuplicateCondBranchOnPHIIntoPred(
}
// And finally, do it! Start by factoring the predecessors if needed.
+ std::vector<DominatorTree::UpdateType> Updates;
BasicBlock *PredBB;
if (PredBBs.size() == 1)
PredBB = PredBBs[0];
@@ -2148,6 +2207,7 @@ bool JumpThreadingPass::DuplicateCondBranchOnPHIIntoPred(
<< " common predecessors.\n");
PredBB = SplitBlockPreds(BB, PredBBs, ".thr_comm");
}
+ Updates.push_back({DominatorTree::Delete, PredBB, BB});
// Okay, we decided to do this! Clone all the instructions in BB onto the end
// of PredBB.
@@ -2160,7 +2220,11 @@ bool JumpThreadingPass::DuplicateCondBranchOnPHIIntoPred(
BranchInst *OldPredBranch = dyn_cast<BranchInst>(PredBB->getTerminator());
if (!OldPredBranch || !OldPredBranch->isUnconditional()) {
- PredBB = SplitEdge(PredBB, BB);
+ BasicBlock *OldPredBB = PredBB;
+ PredBB = SplitEdge(OldPredBB, BB);
+ Updates.push_back({DominatorTree::Insert, OldPredBB, PredBB});
+ Updates.push_back({DominatorTree::Insert, PredBB, BB});
+ Updates.push_back({DominatorTree::Delete, OldPredBB, BB});
OldPredBranch = cast<BranchInst>(PredBB->getTerminator());
}
@@ -2202,6 +2266,10 @@ bool JumpThreadingPass::DuplicateCondBranchOnPHIIntoPred(
// Otherwise, insert the new instruction into the block.
New->setName(BI->getName());
PredBB->getInstList().insert(OldPredBranch->getIterator(), New);
+ // Update Dominance from simplified New instruction operands.
+ for (unsigned i = 0, e = New->getNumOperands(); i != e; ++i)
+ if (BasicBlock *SuccBB = dyn_cast<BasicBlock>(New->getOperand(i)))
+ Updates.push_back({DominatorTree::Insert, PredBB, SuccBB});
}
}
@@ -2257,6 +2325,7 @@ bool JumpThreadingPass::DuplicateCondBranchOnPHIIntoPred(
// Remove the unconditional branch at the end of the PredBB block.
OldPredBranch->eraseFromParent();
+ DDT->applyUpdates(Updates);
++NumDupes;
return true;
@@ -2329,6 +2398,8 @@ bool JumpThreadingPass::TryToUnfoldSelect(CmpInst *CondCmp, BasicBlock *BB) {
// The select is now dead.
SI->eraseFromParent();
+ DDT->applyUpdates({{DominatorTree::Insert, NewBB, BB},
+ {DominatorTree::Insert, Pred, NewBB}});
// Update any other PHI nodes in BB.
for (BasicBlock::iterator BI = BB->begin();
PHINode *Phi = dyn_cast<PHINode>(BI); ++BI)
@@ -2407,11 +2478,25 @@ bool JumpThreadingPass::TryToUnfoldSelectInCurrBB(BasicBlock *BB) {
// Expand the select.
TerminatorInst *Term =
SplitBlockAndInsertIfThen(SI->getCondition(), SI, false);
+ BasicBlock *SplitBB = SI->getParent();
+ BasicBlock *NewBB = Term->getParent();
PHINode *NewPN = PHINode::Create(SI->getType(), 2, "", SI);
NewPN->addIncoming(SI->getTrueValue(), Term->getParent());
NewPN->addIncoming(SI->getFalseValue(), BB);
SI->replaceAllUsesWith(NewPN);
SI->eraseFromParent();
+ // NewBB and SplitBB are newly created blocks which require insertion.
+ std::vector<DominatorTree::UpdateType> Updates;
+ Updates.reserve((2 * SplitBB->getTerminator()->getNumSuccessors()) + 3);
+ Updates.push_back({DominatorTree::Insert, BB, SplitBB});
+ Updates.push_back({DominatorTree::Insert, BB, NewBB});
+ Updates.push_back({DominatorTree::Insert, NewBB, SplitBB});
+ // BB's successors were moved to SplitBB, update DDT accordingly.
+ for (auto *Succ : successors(SplitBB)) {
+ Updates.push_back({DominatorTree::Delete, BB, Succ});
+ Updates.push_back({DominatorTree::Insert, SplitBB, Succ});
+ }
+ DDT->applyUpdates(Updates);
return true;
}
return false;
@@ -2498,8 +2583,8 @@ bool JumpThreadingPass::ThreadGuard(BasicBlock *BB, IntrinsicInst *Guard,
if (!TrueDestIsSafe && !FalseDestIsSafe)
return false;
- BasicBlock *UnguardedBlock = TrueDestIsSafe ? TrueDest : FalseDest;
- BasicBlock *GuardedBlock = FalseDestIsSafe ? TrueDest : FalseDest;
+ BasicBlock *PredUnguardedBlock = TrueDestIsSafe ? TrueDest : FalseDest;
+ BasicBlock *PredGuardedBlock = FalseDestIsSafe ? TrueDest : FalseDest;
ValueToValueMapTy UnguardedMapping, GuardedMapping;
Instruction *AfterGuard = Guard->getNextNode();
@@ -2508,18 +2593,29 @@ bool JumpThreadingPass::ThreadGuard(BasicBlock *BB, IntrinsicInst *Guard,
return false;
// Duplicate all instructions before the guard and the guard itself to the
// branch where implication is not proved.
- GuardedBlock = DuplicateInstructionsInSplitBetween(
- BB, GuardedBlock, AfterGuard, GuardedMapping);
+ BasicBlock *GuardedBlock = DuplicateInstructionsInSplitBetween(
+ BB, PredGuardedBlock, AfterGuard, GuardedMapping);
assert(GuardedBlock && "Could not create the guarded block?");
// Duplicate all instructions before the guard in the unguarded branch.
// Since we have successfully duplicated the guarded block and this block
// has fewer instructions, we expect it to succeed.
- UnguardedBlock = DuplicateInstructionsInSplitBetween(BB, UnguardedBlock,
- Guard, UnguardedMapping);
+ BasicBlock *UnguardedBlock = DuplicateInstructionsInSplitBetween(
+ BB, PredUnguardedBlock, Guard, UnguardedMapping);
assert(UnguardedBlock && "Could not create the unguarded block?");
DEBUG(dbgs() << "Moved guard " << *Guard << " to block "
<< GuardedBlock->getName() << "\n");
-
+ // DuplicateInstructionsInSplitBetween inserts a new block "BB.split" between
+ // PredBB and BB. We need to perform two inserts and one delete for each of
+ // the above calls to update Dominators.
+ DDT->applyUpdates(
+ {// Guarded block split.
+ {DominatorTree::Delete, PredGuardedBlock, BB},
+ {DominatorTree::Insert, PredGuardedBlock, GuardedBlock},
+ {DominatorTree::Insert, GuardedBlock, BB},
+ // Unguarded block split.
+ {DominatorTree::Delete, PredUnguardedBlock, BB},
+ {DominatorTree::Insert, PredUnguardedBlock, UnguardedBlock},
+ {DominatorTree::Insert, UnguardedBlock, BB}});
// Some instructions before the guard may still have uses. For them, we need
// to create Phi nodes merging their copies in both guarded and unguarded
// branches. Those instructions that have no uses can be just removed.
diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
index 8f59913e14b..f3a5f148def 100644
--- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
+++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
@@ -45,16 +45,22 @@
using namespace llvm;
-void llvm::DeleteDeadBlock(BasicBlock *BB) {
+void llvm::DeleteDeadBlock(BasicBlock *BB, DeferredDominance *DDT) {
assert((pred_begin(BB) == pred_end(BB) ||
// Can delete self loop.
BB->getSinglePredecessor() == BB) && "Block is not dead!");
TerminatorInst *BBTerm = BB->getTerminator();
+ std::vector<DominatorTree::UpdateType> Updates;
// Loop through all of our successors and make sure they know that one
// of their predecessors is going away.
- for (BasicBlock *Succ : BBTerm->successors())
+ if (DDT)
+ Updates.reserve(BBTerm->getNumSuccessors());
+ for (BasicBlock *Succ : BBTerm->successors()) {
Succ->removePredecessor(BB);
+ if (DDT)
+ Updates.push_back({DominatorTree::Delete, BB, Succ});
+ }
// Zap all the instructions in the block.
while (!BB->empty()) {
@@ -69,8 +75,12 @@ void llvm::DeleteDeadBlock(BasicBlock *BB) {
BB->getInstList().pop_back();
}
- // Zap the block!
- BB->eraseFromParent();
+ if (DDT) {
+ DDT->applyUpdates(Updates);
+ DDT->deleteBB(BB); // Deferred deletion of BB.
+ } else {
+ BB->eraseFromParent(); // Zap the block!
+ }
}
void llvm::FoldSingleEntryPHINodes(BasicBlock *BB,
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index acccf7abf80..6564e18856c 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -100,7 +100,8 @@ STATISTIC(NumRemoved, "Number of unreachable basic blocks removed");
/// conditions and indirectbr addresses this might make dead if
/// DeleteDeadConditions is true.
bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions,
- const TargetLibraryInfo *TLI) {
+ const TargetLibraryInfo *TLI,
+ DeferredDominance *DDT) {