[PATCH] D18762: Add Aggressive Control Dead Code Elimination
Mehdi Amini via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 25 15:42:16 PDT 2016
Sent from my iPhone
> On Apr 25, 2016, at 3:38 PM, Justin Bogner <mail at justinbogner.com> wrote:
>
> Mehdi AMINI via llvm-commits <llvm-commits at lists.llvm.org> writes:
>> (added llvm-commits as subscriber)
>
> Seems like phab didn't send a patch with the summary, so there isn't any
> rationale on the list as to what this is about.
>
I think I'll never understand this position...
http://reviews.llvm.org/file/data/g5nfdlo5z2lydyefkdsr/PHID-FILE-sfs3b7gzuupa35nv2jgg/D18762.diff
--
Mehdi
> David Callahan <dcallahan at fb.com> writes:
>> david2050 updated this revision to Diff 54871.
>> david2050 added a comment.
>>
>> Update to recent ADCE changes
>
> I haven't looked at this in detail or thought too much about the
> implications, but I have a few drive by comments inline below.
>
>>
>> http://reviews.llvm.org/D18762
>>
>> Files:
>> include/llvm/InitializePasses.h
>> include/llvm/LinkAllPasses.h
>> include/llvm/Transforms/Scalar.h
>> include/llvm/Transforms/Scalar/ACDCE.h
>> lib/Passes/PassBuilder.cpp
>> lib/Passes/PassRegistry.def
>> lib/Transforms/IPO/PassManagerBuilder.cpp
>> lib/Transforms/Scalar/ACDCE.cpp
>> lib/Transforms/Scalar/CMakeLists.txt
>> lib/Transforms/Scalar/Scalar.cpp
>> test/Transforms/ADCE/2002-01-31-UseStuckAround.ll
>> test/Transforms/ADCE/2002-05-22-PHITest.ll
>> test/Transforms/ADCE/2002-05-23-ZeroArgPHITest.ll
>> test/Transforms/ADCE/2002-05-28-Crash-distilled.ll
>> test/Transforms/ADCE/2002-05-28-Crash.ll
>> test/Transforms/ADCE/2002-07-17-AssertionFailure.ll
>> test/Transforms/ADCE/2002-07-17-PHIAssertion.ll
>> test/Transforms/ADCE/2002-07-29-Segfault.ll
>> test/Transforms/ADCE/2003-01-22-PredecessorProblem.ll
>> test/Transforms/ADCE/2003-04-25-PHIPostDominateProblem.ll
>> test/Transforms/ADCE/2003-06-11-InvalidCFG.ll
>> test/Transforms/ADCE/2003-06-24-BadSuccessor.ll
>> test/Transforms/ADCE/2003-06-24-BasicFunctionality.ll
>> test/Transforms/ADCE/2003-09-10-UnwindInstFail.ll
>> test/Transforms/ADCE/2003-09-15-InfLoopCrash.ll
>> test/Transforms/ADCE/2003-11-16-MissingPostDominanceInfo.ll
>> test/Transforms/ADCE/2004-05-04-UnreachableBlock.ll
>> test/Transforms/ADCE/2005-02-17-PHI-Invoke-Crash.ll
>> test/Transforms/ADCE/basictest.ll
>> test/Transforms/ADCE/basictest1.ll
>> test/Transforms/ADCE/basictest2.ll
>> test/Transforms/ADCE/unreachable-function.ll
>>
>> Index: test/Transforms/ADCE/unreachable-function.ll
>> ===================================================================
>> --- test/Transforms/ADCE/unreachable-function.ll
>> +++ test/Transforms/ADCE/unreachable-function.ll
>> @@ -1,4 +1,5 @@
>> ; RUN: opt < %s -adce -disable-output
>> +; RUN: opt < %s -acdce -disable-output
>
> Usually each transform gets its own test directory, rather than extra
> run lines in an existing one. Where are the tests that show this does
> anything differently than the existing ADCE pass?
>
>> define void @test() {
>> unreachable
>> Index: test/Transforms/ADCE/basictest2.ll
>> ===================================================================
>> --- test/Transforms/ADCE/basictest2.ll
>> +++ test/Transforms/ADCE/basictest2.ll
>> @@ -1,4 +1,7 @@
>> ; RUN: opt < %s -adce -simplifycfg | llvm-dis
>> +; RUN: opt < %s -acdce -disable-output
>> +; RUN: opt < %s -acdce -acdce-remove-loops -S | FileCheck %s
>> +
>> %FILE = type { i32, i8*, i8*, i8, i8, i32, i32, i32 }
>> %spec_fd_t = type { i32, i32, i32, i8* }
>> @__iob = external global [20 x %FILE] ; <[20 x %FILE]*> [#uses=1]
>> @@ -26,6 +29,7 @@
>> %cond266 = icmp sle i32 %reg109, 4 ; <i1> [#uses=1]
>> br i1 %cond266, label %bb3, label %bb2
>>
>> +; CHECK-NOT: bb2:
>> bb2: ; preds = %0
>> %cast273 = getelementptr [17 x i8], [17 x i8]* @.LC12, i64 0, i64 0 ; <i8*> [#uses=0]
>> br label %bb3
>> @@ -52,6 +56,9 @@
>> %cond270 = icmp slt i32 %reg1321, %reg1331 ; <i1> [#uses=1]
>> br i1 %cond270, label %bb9, label %bb6
>>
>> +; CHECK-NOT: bb6:
>> +; CHECK-NOT: bb7:
>> +; CHECK-NOT: bb:
>> bb6: ; preds = %bb5
>> %reg134 = load i32, i32* @dbglvl ; <i32> [#uses=1]
>> %cond271 = icmp sle i32 %reg134, 4 ; <i1> [#uses=1]
>> @@ -79,6 +86,7 @@
>> %cond272 = icmp sle i32 %reg163, 4 ; <i1> [#uses=1]
>> br i1 %cond272, label %bb11, label %bb10
>>
>> +; CHECK-NOT: bb10:
>> bb10: ; preds = %bb9
>> %cast279 = getelementptr [4 x i8], [4 x i8]* @.LC11, i64 0, i64 0 ; <i8*> [#uses=0]
>> br label %bb11
>> Index: test/Transforms/ADCE/basictest1.ll
>> ===================================================================
>> --- test/Transforms/ADCE/basictest1.ll
>> +++ test/Transforms/ADCE/basictest1.ll
>> @@ -1,4 +1,7 @@
>> ; RUN: opt < %s -adce -simplifycfg | llvm-dis
>> +; RUN: opt < %s -acdce -S | FileCheck %s
>> +; RUN: opt < %s -acdce -acdce-remove-loops -S | FileCheck %s
>> +
>> %FILE = type { i32, i8*, i8*, i8, i8, i32, i32, i32 }
>> %spec_fd_t = type { i32, i32, i32, i8* }
>> @__iob = external global [20 x %FILE] ; <[20 x %FILE]*> [#uses=1]
>> @@ -26,6 +29,8 @@
>> %cond266 = icmp sle i32 %reg109, 4 ; <i1> [#uses=1]
>> br i1 %cond266, label %bb3, label %bb2
>>
>> +; CHECK-NOT: bb2:
>> +
>> bb2: ; preds = %0
>> %cast273 = getelementptr [17 x i8], [17 x i8]* @.LC12, i64 0, i64 0 ; <i8*> [#uses=0]
>> br label %bb3
>> @@ -52,6 +57,10 @@
>> %cond270 = icmp slt i32 %reg1321, %reg1331 ; <i1> [#uses=1]
>> br i1 %cond270, label %bb9, label %bb6
>>
>> +; CHECK-NOT: bb6:
>> +; CHECK-NOT: bb7:
>> +; CHECK-NOT: bb8:
>> +
>> bb6: ; preds = %bb5
>> %reg134 = load i32, i32* @dbglvl ; <i32> [#uses=1]
>> %cond271 = icmp sle i32 %reg134, 4 ; <i1> [#uses=1]
>> @@ -79,6 +88,8 @@
>> %cond272 = icmp sle i32 %reg163, 4 ; <i1> [#uses=1]
>> br i1 %cond272, label %bb11, label %bb10
>>
>> +; CHECK-NOT: bb10:
>> +
>> bb10: ; preds = %bb9
>> %cast279 = getelementptr [4 x i8], [4 x i8]* @.LC11, i64 0, i64 0 ; <i8*> [#uses=0]
>> br label %bb11
>> Index: test/Transforms/ADCE/basictest.ll
>> ===================================================================
>> --- test/Transforms/ADCE/basictest.ll
>> +++ test/Transforms/ADCE/basictest.ll
>> @@ -1,5 +1,7 @@
>> ; RUN: opt < %s -adce -simplifycfg | llvm-dis
>> ; RUN: opt < %s -passes=adce | llvm-dis
>> +; RUN: opt < %s -acdce | llvm-dis
>> +; RUN: opt < %s -passes=acdce | llvm-dis
>>
>> define i32 @Test(i32 %A, i32 %B) {
>> BB1:
>> Index: test/Transforms/ADCE/2005-02-17-PHI-Invoke-Crash.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2005-02-17-PHI-Invoke-Crash.ll
>> +++ test/Transforms/ADCE/2005-02-17-PHI-Invoke-Crash.ll
>> @@ -1,4 +1,5 @@
>> ; RUN: opt < %s -adce -disable-output
>> +; RUN: opt < %s -acdce -disable-output
>>
>> declare void @strlen()
>>
>> Index: test/Transforms/ADCE/2004-05-04-UnreachableBlock.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2004-05-04-UnreachableBlock.ll
>> +++ test/Transforms/ADCE/2004-05-04-UnreachableBlock.ll
>> @@ -1,4 +1,6 @@
>> ; RUN: opt < %s -adce -disable-output
>> +; RUN: opt < %s -acdce -disable-output
>> +; RUN: opt < %s -acdce -acdce-remove-loops -disable-output
>>
>> define void @test() {
>> entry:
>> Index: test/Transforms/ADCE/2003-11-16-MissingPostDominanceInfo.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2003-11-16-MissingPostDominanceInfo.ll
>> +++ test/Transforms/ADCE/2003-11-16-MissingPostDominanceInfo.ll
>> @@ -1,4 +1,7 @@
>> ; RUN: opt < %s -adce -simplifycfg -S | grep call
>> +; RUN: opt < %s -acdce -simplifycfg -S | grep call
>> +; RUN: opt < %s -acdce -acdce-remove-loops -simplifycfg -S | grep call
>> +
>> declare void @exit(i32)
>>
>> define i32 @main(i32 %argc) {
>> Index: test/Transforms/ADCE/2003-09-15-InfLoopCrash.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2003-09-15-InfLoopCrash.ll
>> +++ test/Transforms/ADCE/2003-09-15-InfLoopCrash.ll
>> @@ -1,4 +1,6 @@
>> ; RUN: opt < %s -adce -disable-output
>> +; RUN: opt < %s -acdce -disable-output
>> +; RUN: opt < %s -acdce -acdce-remove-loops -disable-output
>>
>> define i32 @main() {
>> br label %loop
>> Index: test/Transforms/ADCE/2003-09-10-UnwindInstFail.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2003-09-10-UnwindInstFail.ll
>> +++ test/Transforms/ADCE/2003-09-10-UnwindInstFail.ll
>> @@ -1,4 +1,6 @@
>> ; RUN: opt < %s -adce -disable-output
>> +; RUN: opt < %s -acdce -disable-output
>> +; RUN: opt < %s -acdce -disable-output -acdce-remove-loops
>>
>> define void @test() personality i32 (...)* @__gxx_personality_v0 {
>> br i1 false, label %then, label %endif
>> Index: test/Transforms/ADCE/2003-06-24-BasicFunctionality.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2003-06-24-BasicFunctionality.ll
>> +++ test/Transforms/ADCE/2003-06-24-BasicFunctionality.ll
>> @@ -1,4 +1,6 @@
>> ; RUN: opt < %s -adce -simplifycfg -S | not grep then:
>> +; RUN: opt < %s -acdce -S | FileCheck %s
>> +; RUN: opt < %s -acdce -acdce-remove-loops -S | FileCheck %s
>>
>> define void @dead_test8(i32* %data.1, i32 %idx.1) {
>> entry:
>> @@ -20,6 +22,10 @@
>> %tmp.161 = icmp ne i32 %k.1, %tmp.14 ; <i1> [#uses=1]
>> br i1 %tmp.161, label %then, label %else
>>
>> +; CHECK-NOT: %tmp.161
>> +; CHECK-NOT: then:
>> +; CHECK-NOT: else
>> +
>> then: ; preds = %no_exit
>> %inc.0 = add i32 %k.1, 1 ; <i32> [#uses=1]
>> br label %endif
>> Index: test/Transforms/ADCE/2003-06-24-BadSuccessor.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2003-06-24-BadSuccessor.ll
>> +++ test/Transforms/ADCE/2003-06-24-BadSuccessor.ll
>> @@ -1,4 +1,7 @@
>> ; RUN: opt < %s -adce -disable-output
>> +; RUN: opt < %s -acdce -disable-output
>> +; RUN: opt < %s -acdce -acdce-remove-loops -S | FileCheck %s
>> +
>> target datalayout = "e-p:32:32"
>> %struct..CppObjTypeDesc = type { i32, i16, i16 }
>> %struct..TypeToken = type { i32, i16, i16 }
>> @@ -30,6 +33,7 @@
>> br i1 false, label %no_exit.1, label %loopentry.0
>>
>> no_exit.1: ; preds = %loopentry.1
>> +; CHECK: switch
>> switch i32 0, label %label.17 [
>> i32 2, label %label.11
>> i32 19, label %label.10
>> @@ -80,6 +84,7 @@
>> then.53: ; preds = %shortcirc_next.7, %label.17
>> %SubArrays.8 = phi i32* [ %SubArrays.10, %shortcirc_next.7 ], [ %SubArrays.10, %label.17 ] ; <i32*> [#uses=1]
>> %tmp.1023 = load i32, i32* null ; <i32> [#uses=1]
>> +; CHECK-NOT: switch
>> switch i32 %tmp.1023, label %loopentry.1 [
>> ]
>>
>> Index: test/Transforms/ADCE/2003-06-11-InvalidCFG.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2003-06-11-InvalidCFG.ll
>> +++ test/Transforms/ADCE/2003-06-11-InvalidCFG.ll
>> @@ -1,4 +1,6 @@
>> ; RUN: opt < %s -adce -disable-output
>> +; RUN: opt < %s -acdce -disable-output
>> +; RUN: opt < %s -acdce -acdce-remove-loops -disable-output
>>
>> @G = external global i32* ; <i32**> [#uses=1]
>>
>> Index: test/Transforms/ADCE/2003-04-25-PHIPostDominateProblem.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2003-04-25-PHIPostDominateProblem.ll
>> +++ test/Transforms/ADCE/2003-04-25-PHIPostDominateProblem.ll
>> @@ -3,6 +3,8 @@
>> ; PHI node is dead, so we just avoid patching up dead PHI nodes.
>>
>> ; RUN: opt < %s -adce
>> +; RUN: opt < %s -acdce -S | FileCheck %s
>> +; RUN: opt < %s -acdce -acdce-remove-loops -S | FileCheck %s
>>
>> target datalayout = "e-p:32:32"
>>
>> @@ -14,6 +16,9 @@
>> %k.1 = phi i32 [ %k.0, %endif ], [ 0, %entry ] ; <i32> [#uses=1]
>> br i1 false, label %no_exit, label %return
>>
>> +; CHECK-NOT: no_exit:
>> +; CHECK-NOT: then:
>> +; CHECK-NOT: else:
>> no_exit: ; preds = %loopentry
>> br i1 false, label %then, label %else
>>
>> Index: test/Transforms/ADCE/2003-01-22-PredecessorProblem.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2003-01-22-PredecessorProblem.ll
>> +++ test/Transforms/ADCE/2003-01-22-PredecessorProblem.ll
>> @@ -1,14 +1,18 @@
>> ; Testcase reduced from 197.parser by bugpoint
>> ; RUN: opt < %s -adce
>> +; RUN: opt < %s -acdce -S | FileCheck %s
>> +; RUN: opt < %s -acdce -acdce-remove-loops -S | FileCheck %s
>>
>> define void @conjunction_prune() {
>> ; <label>:0
>> br label %bb19
>>
>> +; CHECK-NOT: bb19:
>> bb19: ; preds = %bb23, %bb22, %0
>> %reg205 = phi i8* [ null, %bb22 ], [ null, %bb23 ], [ null, %0 ] ; <i8*> [#uses=1]
>> br i1 false, label %bb21, label %bb22
>>
>> +; CHECK-NOT: bb21:
>> bb21: ; preds = %bb19
>> %cast455 = bitcast i8* %reg205 to i8** ; <i8**> [#uses=0]
>> br label %bb22
>> Index: test/Transforms/ADCE/2002-07-29-Segfault.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2002-07-29-Segfault.ll
>> +++ test/Transforms/ADCE/2002-07-29-Segfault.ll
>> @@ -1,4 +1,6 @@
>> ; RUN: opt < %s -adce -disable-output
>> +; RUN: opt < %s -acdce -disable-output
>> +; RUN: opt < %s -acdce -acdce-remove-loops -disable-output
>>
>> define void @test() {
>> br label %BB3
>> Index: test/Transforms/ADCE/2002-07-17-PHIAssertion.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2002-07-17-PHIAssertion.ll
>> +++ test/Transforms/ADCE/2002-07-17-PHIAssertion.ll
>> @@ -1,6 +1,7 @@
>> ; This testcase was extracted from the gzip SPEC benchmark
>> ;
>> ; RUN: opt < %s -adce
>> +; RUN: opt < %s -acdce | FileCheck %s
>>
>> @bk = external global i32 ; <i32*> [#uses=2]
>> @hufts = external global i32 ; <i32*> [#uses=1]
>> @@ -16,6 +17,8 @@
>> bb3: ; preds = %bb2
>> br label %UnifiedExitNode
>>
>> +; CHECK-NOT: bb4:
>> +; CHECK-NOT: bb5:
>> bb4: ; preds = %bb2
>> %reg117 = load i32, i32* @hufts ; <i32> [#uses=2]
>> %cond241 = icmp ule i32 %reg117, %reg128 ; <i1> [#uses=1]
>> Index: test/Transforms/ADCE/2002-07-17-AssertionFailure.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2002-07-17-AssertionFailure.ll
>> +++ test/Transforms/ADCE/2002-07-17-AssertionFailure.ll
>> @@ -4,10 +4,12 @@
>> ; have to fix now, wouldn't it....
>> ;
>> ; RUN: opt < %s -adce
>> +; RUN: opt < %s -acdce -S | FileCheck %s
>>
>> define void @foo(i8* %reg5481) {
>> %cast611 = bitcast i8* %reg5481 to i8** ; <i8**> [#uses=1]
>> %reg162 = load i8*, i8** %cast611 ; <i8*> [#uses=1]
>> +; CHECK-NOT: ptrtoint
>> ptrtoint i8* %reg162 to i32 ; <i32>:1 [#uses=0]
>> ret void
>> }
>> Index: test/Transforms/ADCE/2002-05-28-Crash.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2002-05-28-Crash.ll
>> +++ test/Transforms/ADCE/2002-05-28-Crash.ll
>> @@ -12,6 +12,8 @@
>> ;}
>> ;
>> ; RUN: opt < %s -adce
>> +; RUN: opt < %s -acdce
>> +; RUN: opt < %s -acdce -acdce-remove-loops -S | FileCheck %s
>>
>> define i32 @rx_bitset_empty(i32 %size, i32* %set) {
>> bb1:
>> @@ -30,6 +32,7 @@
>> %cond232 = icmp ne i32 %reg125, 0 ; <i1> [#uses=1]
>> br i1 %cond232, label %bb3, label %bb2
>>
>> +; CHECK-NOT: bb2:
>> bb2: ; preds = %bb2, %bb1
>> %cann-indvar = phi i32 [ 0, %bb1 ], [ %add1-indvar, %bb2 ] ; <i32> [#uses=2]
>> %reg130-scale = mul i32 %cann-indvar, -1 ; <i32> [#uses=1]
>> Index: test/Transforms/ADCE/2002-05-28-Crash-distilled.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2002-05-28-Crash-distilled.ll
>> +++ test/Transforms/ADCE/2002-05-28-Crash-distilled.ll
>> @@ -1,12 +1,15 @@
>> ; This testcase is a distilled form of: 2002-05-28-Crash.ll
>>
>> ; RUN: opt < %s -adce
>> +; RUN: opt < %s -acdce
>> +; RUN: opt < %s -acdce -acdce-remove-loops -S | FileCheck %s
>>
>> define float @test(i32 %i) {
>> %F = sitofp i32 %i to float ; <float> [#uses=1]
>> %I = bitcast i32 %i to i32 ; <i32> [#uses=1]
>> br label %Loop
>>
>> +; CHECK-NOT: Loop:
>> Loop: ; preds = %Loop, %0
>> %B = icmp ne i32 %I, 0 ; <i1> [#uses=1]
>> br i1 %B, label %Out, label %Loop
>> Index: test/Transforms/ADCE/2002-05-23-ZeroArgPHITest.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2002-05-23-ZeroArgPHITest.ll
>> +++ test/Transforms/ADCE/2002-05-23-ZeroArgPHITest.ll
>> @@ -5,6 +5,8 @@
>> ; in with a dummy value before the PHI is deleted.
>> ;
>> ; RUN: opt < %s -adce
>> +; RUN: opt < %s -S -acdce | grep bb1
>> +; RUN: opt < %s -S -acdce -acdce-remove-loops | FileCheck %s
>>
>> %node_t = type { double*, %node_t*, %node_t**, double**, double*, i32, i32 }
>>
>> @@ -14,6 +16,8 @@
>> store %node_t* %nodelist, %node_t** %nodelist.upgrd.1
>> br label %bb1
>>
>> +; CHECK-NOT: bb1:
>> +; CHECK-NOT: bb2:
>> bb1: ; preds = %bb0
>> %reg107 = load %node_t*, %node_t** %nodelist.upgrd.1 ; <%node_t*> [#uses=2]
>> %cond211 = icmp eq %node_t* %reg107, null ; <i1> [#uses=1]
>> Index: test/Transforms/ADCE/2002-05-22-PHITest.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2002-05-22-PHITest.ll
>> +++ test/Transforms/ADCE/2002-05-22-PHITest.ll
>> @@ -1,6 +1,7 @@
>> ; It is illegal to remove BB1 because it will mess up the PHI node!
>> ;
>> ; RUN: opt < %s -adce -S | grep BB1
>> +; RUN: opt < %s -acdce -S | grep BB1
>>
>> define i32 @test(i1 %C, i32 %A, i32 %B) {
>> ; <label>:0
>> Index: test/Transforms/ADCE/2002-01-31-UseStuckAround.ll
>> ===================================================================
>> --- test/Transforms/ADCE/2002-01-31-UseStuckAround.ll
>> +++ test/Transforms/ADCE/2002-01-31-UseStuckAround.ll
>> @@ -1,4 +1,5 @@
>> ; RUN: opt < %s -adce
>> +; RUN: opt < %s -acdce
>>
>> define i32 @"main"(i32 %argc) {
>> br label %2
>> Index: lib/Transforms/Scalar/Scalar.cpp
>> ===================================================================
>> --- lib/Transforms/Scalar/Scalar.cpp
>> +++ lib/Transforms/Scalar/Scalar.cpp
>> @@ -31,6 +31,7 @@
>> /// initializeScalarOptsPasses - Initialize all passes linked into the
>> /// ScalarOpts library.
>> void llvm::initializeScalarOpts(PassRegistry &Registry) {
>> + initializeACDCELegacyPassPass(Registry);
>> initializeADCELegacyPassPass(Registry);
>> initializeBDCEPass(Registry);
>> initializeAlignmentFromAssumptionsPass(Registry);
>> @@ -96,6 +97,10 @@
>> initializeScalarOpts(*unwrap(R));
>> }
>>
>> +void LLVMAddAggressiveControlDCEPass(LLVMPassManagerRef PM) {
>> + unwrap(PM)->add(createAggressiveControlDCEPass());
>> +}
>> +
>> void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM) {
>> unwrap(PM)->add(createAggressiveDCEPass());
>> }
>> Index: lib/Transforms/Scalar/CMakeLists.txt
>> ===================================================================
>> --- lib/Transforms/Scalar/CMakeLists.txt
>> +++ lib/Transforms/Scalar/CMakeLists.txt
>> @@ -1,4 +1,5 @@
>> add_llvm_library(LLVMScalarOpts
>> + ACDCE.cpp
>> ADCE.cpp
>> AlignmentFromAssumptions.cpp
>> BDCE.cpp
>> Index: lib/Transforms/Scalar/ACDCE.cpp
>> ===================================================================
>> --- /dev/null
>> +++ lib/Transforms/Scalar/ACDCE.cpp
>> @@ -0,0 +1,1090 @@
>> +//===- ACDCE.cpp - Code to perform dead code elimination
>> +//-------------------===//
>> +//
>> +// The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// This file implements the Aggressive Dead Code Elimination pass. This pass
>> +// optimistically assumes that all instructions are dead until proven otherwise,
>> +// allowing it to eliminate dead computations that other DCE passes do not
>> +// catch, particularly involving loop computations.
>
> I'm guessing you forgot to update this comment after copying it from
> ADCE.cpp - it doesn't tell me what the 'C' stands for ;)
>
>> +//
>> +// https://groups.google.com/forum/#!topic/llvm-dev/j2vlIECKkdE -- dead loops
>> +// discussion
>
> Maybe this should mention what's relevant about this particular
> discussion? A link to a longish thread from 2010 isn't all that great on
> its own.
>
>> +//
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "llvm/Transforms/Scalar/ACDCE.h"
>> +
>> +#include "llvm/ADT/DenseMap.h"
>> +#include "llvm/ADT/PostOrderIterator.h"
>> +#include "llvm/ADT/SmallPtrSet.h"
>> +#include "llvm/ADT/SmallVector.h"
>> +#include "llvm/ADT/Statistic.h"
>> +#include "llvm/Analysis/CFGPrinter.h"
>> +#include "llvm/Analysis/GlobalsModRef.h"
>> +#include "llvm/Analysis/IteratedDominanceFrontier.h"
>> +#include "llvm/Analysis/PostDominators.h"
>> +#include "llvm/IR/BasicBlock.h"
>> +#include "llvm/IR/CFG.h"
>> +#include "llvm/IR/DebugInfoMetadata.h"
>> +#include "llvm/IR/IRBuilder.h"
>> +#include "llvm/IR/InstIterator.h"
>> +#include "llvm/IR/Instructions.h"
>> +#include "llvm/IR/IntrinsicInst.h"
>> +#include "llvm/Pass.h"
>> +#include "llvm/ProfileData/InstrProf.h"
>> +#include "llvm/Support/Debug.h"
>> +#include "llvm/Support/FileSystem.h"
>> +#include "llvm/Transforms/Scalar.h"
>> +
>> +using namespace llvm;
>> +
>> +#define DEBUG_TYPE "acdce"
>> +#define DEBUG_MSG(x) DEBUG(dbgs() << x << '\n';)
>
> This DEBUG_MSG define is pretty unusual - why not just use DEBUG()
> directly like everyone else?
>
>> +
>> +static cl::opt<bool> RemoveLoops("acdce-remove-loops", cl::init(false),
>> + cl::Hidden);
>> +
>> +STATISTIC(NumRemoved, "Number of non-branch instructions removed");
>> +STATISTIC(NumBranchesRemoved, "Number of branch instructions removed");
>> +
>> +namespace {
>> +
>> +// helper functions ...
>> +static bool isUnconditional(TerminatorInst *term) {
>
> static functions don't need to be in an anonymous namespace.
>
> Also, variable names should start with capital letters. There are a few
> places in the patch that should be updated.
>
>> + auto br = dyn_cast<BranchInst>(term);
>> + return br && br->isUnconditional();
>> +}
>> +
>> +// simplified erase pattern
>> +template <typename V, typename Pred> void erase(V *vec, Pred p) {
>> + vec->erase(std::remove_if(vec->begin(), vec->end(), p), vec->end());
>> +}
>> +// a composite transform and copy-if which test for non-null
>> +template <class InputIterator, class OutputIterator, class UnaryOperator>
>> +OutputIterator copy_non_null(InputIterator first1, InputIterator last1,
>> + OutputIterator result, UnaryOperator op) {
>> + while (first1 != last1) {
>> + auto value = op(*first1);
>> + if (value) {
>> + *result = value;
>> + ++result;
>> + }
>> + ++first1;
>> + }
>> + return result;
>> +}
>> +}
>> +
>> +namespace llvm {
>> +
>> +// Specialize po_iterator_storage to identify loop bottoms
>> +// which we define simply as back edges in a depth first
>> +// traversal of the CFG starting at the entry.
>> +class PO_WithLoops;
>> +
>> +template <> class po_iterator_storage<PO_WithLoops, true> {
>> + PO_WithLoops &Storage;
>> +
>> +public:
>> + po_iterator_storage(PO_WithLoops &Storage) : Storage(Storage) {}
>> + // These functions are defined below.
>> + bool insertEdge(BasicBlock *From, BasicBlock *To);
>> + void finishPostorder(BasicBlock *BB);
>> +};
>> +
>> +class PO_WithLoops {
>> + typedef SmallPtrSet<BasicBlock *, 32> LoopBottomsType;
>> + typedef po_iterator<BasicBlock *, PO_WithLoops, true> POTIterator;
>> +
>> + Function &F;
>> + // Visited[BB] is true while the basic block *BB is on
>> + // the stack of being visited nodes and false after
>> + // all children have been visited
>> + DenseMap<BasicBlock *, bool> Visited;
>> + LoopBottomsType LoopBottoms;
>> +
>> +public:
>> + PO_WithLoops(Function &F) : F(F) { Visited.grow(2 * F.size()); }
>> + POTIterator begin() { return po_ext_begin(&F.getEntryBlock(), *this); }
>> + POTIterator end() { return po_ext_end(&F.getEntryBlock(), *this); }
>> + bool insertEdge(BasicBlock *From, BasicBlock *To) {
>> + auto P = Visited.insert(std::make_pair(To, true));
>> + if (P.second) {
>> + return true;
>> + }
>> + if (P.first->second) {
>> + // back edge to an ancestor in DFS
>> + LoopBottoms.insert(From);
>> + }
>> + return false;
>> + }
>> +
>> + void finishPostorder(BasicBlock *BB) { Visited[BB] = false; }
>> + bool reachable(BasicBlock *BB) const {
>> + return (Visited.find(BB) != Visited.end());
>> + }
>> + const LoopBottomsType &getLoopBottoms() { return LoopBottoms; }
>> +};
>> +
>> +bool po_iterator_storage<PO_WithLoops, true>::insertEdge(BasicBlock *From,
>> + BasicBlock *To) {
>> + return Storage.insertEdge(From, To);
>> +}
>> +void po_iterator_storage<PO_WithLoops, true>::finishPostorder(BasicBlock *BB) {
>> + Storage.finishPostorder(BB);
>> +}
>> +}
>> +
>> +namespace {
>> +
>> +struct BlockInfoType;
>> +/// A Dead Region is a set of dead basic blocks with a common
>> +/// post-dominating live block
>> +struct DeadRegionInfo {
>> + /// true when all blocks have unconditional branches
>> + bool Trivial = true; // dead blocks are just unconditional branches
>> + /// the set of dead blocks in this region
>> + SmallVector<BlockInfoType *, 16> DeadBlocks;
>> + /// sources of edges from live nodes into dead ones of this region
>> + SmallPtrSet<BlockInfoType *, 16> LivePreds;
>> +};
>> +
>> +/// Information about basic blocks relevant to dead code elimination
>> +struct BlockInfoType {
>> + /// true when this block contains a live instructions
>> + bool Live = false;
>> + /// this block ends in an unconditional branch
>> + bool UnconditionalBranch = false;
>> + /// quick access to the Live flag for the terminator
>> + bool *TerminatorLive = nullptr; // == & InstInfo[Terminator].Live
>
> `bool *` is a pretty unusual type. Wouldn't it be easier to follow if
> we kept around a pointer to the InstInfo itself to modify?
>
>> +
>> + bool terminatorIsLive() const { return *TerminatorLive; }
>> +
>> + /// corresponding BasicBlock
>> + BasicBlock *BB = nullptr;
>> +
>> + /// points to this BB when this block is live, otherwise the most immediate
>> + /// live post-dominator of BB
>> + BasicBlock *LivePostDom = nullptr;
>> +
>> + TerminatorInst *Terminator = nullptr; ///< cache of BB->getTerminator()
>> +
>> + /// block found to not reach a function return point
>> + bool isUnreachable() const { return Terminator == nullptr; }
>> +
>> + /// the collection of dead blocks which have this block as
>> + /// the most-immediate live post-dominator
>> + DeadRegionInfo DeadRegion;
>> +
>> + /// used to control exploration of dead connected components
>> + unsigned RegionVisited = 0;
>> +};
>> +
>> +/// Information about Instruction's
>> +struct InstInfoType {
>> +
>> + bool Live = false; ///< true if this unstruction is live
>> +
>> + /// quick access to information for block containing associated Instruction
>> + BlockInfoType *Block = nullptr;
>> +};
>> +
>> +/// This class implements analysis to determine instructions including branching
>> +/// which does not effect the output. Such operations are removed as are
>> +/// unreachable operations for some scenarions. Dead loops are optionally
>> +/// removed
>> +/// or retained.
>> +class AggressiveCDCE {
>
> I think a longer name is in order - the C is easy to miss in
> AggressiveCDCE.
>
>> + Function &F;
>> +
>> + /// reverse partial order of blocks with a collection of sources of backward
>> + /// edges referred to as loop bottoms
>> + PO_WithLoops PO;
>> + PostDominatorTree &PDT;
>> + bool GraphWasModified = false;
>> +
>> + /// function-level statistics
>> + unsigned FuncNumBranchesRemoved = 0;
>> + unsigned FuncNumInstRemoved = 0;
>> +
>> + /// one per basic block in the function
>> + std::vector<BlockInfoType> BlockInfoVec;
>> +
>> + /// mapping of blocks to associated information, element in BlockInfoVec
>> + DenseMap<BasicBlock *, BlockInfoType *> BlockInfo;
>> + bool isLive(BasicBlock *BB) { return BlockInfo[BB]->Live; }
>> +
>> + /// mapping of instructions to associated information
>> + DenseMap<Instruction *, InstInfoType> InstInfo;
>> + bool isLive(Instruction *I) { return InstInfo[I].Live; }
>> +
>> + /// initialize maps and BlockInfoVec
>> + void initialize();
>> +
>> + /// live instructions to be processed or dead instructions to be deleted
>> + SmallVector<Instruction *, 128> Worklist;
>> + SmallPtrSet<const Metadata *, 32> AliveScopes;
>> +
>> + /// Propagate "live-ness" to definitions which reach "live" instructions
>> + void markLive();
>> + /// Mark I and its containing block as live.
>> + void markLive(Instruction *I);
>> + void collectLiveScopes(const DILocalScope &LS);
>> + void collectLiveScopes(const DILocation &DL);
>> +
>> + /// true for any instructions which is always treated as live
>> + bool alwaysLive(Instruction &I) const;
>> +
>> + /// vector of blocks with not known to be live terminators,
>> + SmallPtrSet<BasicBlock *, 16> BlocksWithDeadTerminators;
>> +
>> + /// The set of blocks which we have determined are live in the
>> + /// most recent pass
>> + SmallPtrSet<BasicBlock *, 16> NewLiveBlocks;
>> +
>> + /// Analyze basic blocks to find to loop bottoms to keep live and
>> + /// remove unreachable blocks
>> + void analyzeBlocks();
>> +
>> + /// blocks found to be unreachable when searching for back edges
>> + SmallVector<BasicBlock *, 16> UnreachableBlocks;
>> + void removeUnreachable(BasicBlock *);
>> +
>> + /// Analyze dead branches to find those whose branches are the sources
>> + /// of control dependences impacting a live block. Those branches are
>> + /// marked live.
>> + void checkControlDependences();
>> +
>> + /// look for phi nodes with complex value which force
>> + /// source blocks of reaching values to be treated as live.
>> + void checkPhiNodes();
>> +
>> + typedef SmallPtrSet<BasicBlock *, 8> RegionSetType;
>> +
>> + /// Traverse the connected component associated with BBInfo where
>> + /// nodes whose RegionVisited field is greater than FirstVisit are considered
>> + /// already 'visited' and we stop at tops of live blocks.
>> + /// Set RegionVisited for blocks newly visited to CurrentVisit.
>> + /// Record live blocks that are successors of DeadBlocks on this
>> + /// componente in LivePdoms
>> + void visitRegion(BlockInfoType *, unsigned FirstVisit, unsigned CurrentVisit,
>> + RegionSetType *LivePdoms);
>> +
>> + /// Incremented for each new traversal of connected components
>> + unsigned LastCurrentVisit = 0;
>> +
>> + /// Verify that all edges from "dead" predecessors into PN
>> + /// have the same associated value. To refine the precision, the
>> + /// dead blocks are partitioned into connnected components and
>> + /// all definitions associated with predecessor blocks in the same
>> + /// connected component must be the same
>> + void checkPhiNode(PHINode *PN, unsigned FirstVisit);
>> +
>> + /// find groups of dead blocks with common live post-dominator
>> + /// and rewrite the control flow graph
>> + void processDeadRegions();
>> +
>> + /// Rewrite non-trivial dead regions by redirection incoming live
>> + /// control flow to the post-dominator and updating phi-nnodes in the
>> + /// post-dominator
>> + void updateDeadRegion(BasicBlock *BB, DeadRegionInfo *Info);
>> +
>> + /// adjust BB so it has an unconditional branch to Target
>> + /// mark that branch live.
>> + void makeUnconditional(BasicBlock *BB, BasicBlock *Target);
>> +
>> + /// the collection of unconditional branch instructions created
>> + /// by makeUnconditional
>> + SmallVector<Instruction *, 32> NewBranches;
>> +
>> + /// for trivial regions, we just mark all the branches as live to be
>> + /// cleaned up by other phases
>> + void cleanTrivialRegion(const DeadRegionInfo &Info);
>> +
>> + void removeDeadCode();
>> +
>> +#ifndef NDEBUG
>> + /// the set of live blocks with dead predecessors
>> + SmallPtrSet<BasicBlock *, 31> BlocksForPhiValidation;
>> +
>> + /// verify one value for each predecessor after dead blocks are removed
>> + void validatePhiNodes(BasicBlock *);
>> +#endif
>> +
>> +public:
>> + AggressiveCDCE(Function &F, PostDominatorTree &PDT)
>> + : F(F), PO(F), PDT(PDT) {}
>> + bool doAggressiveCDCE();
>> +};
>> +}
>> +
>> +bool AggressiveCDCE::doAggressiveCDCE() {
>> +
>> + initialize();
>> + markLive();
>> + processDeadRegions();
>> + removeDeadCode();
>> +
>> + return GraphWasModified;
>> +}
>> +
>> +//===----------------------------------------------------------------------===//
>> +//
>> +//
>> +// Initialize of data structures and identification of
>> +// loops and unreachable code
>> +//
>> +//===----------------------------------------------------------------------===//
>> +void AggressiveCDCE::initialize() {
>> +
>> + DEBUG(PDT.print(dbgs()));
>> +
>> + auto NumBlocks = F.size();
>> + BlockInfoVec.resize(NumBlocks);
>> + BlockInfo.grow(2 * NumBlocks);
>> + auto InfoP = BlockInfoVec.begin();
>> + size_t NumInsts = 0;
>> + for (auto &BB : F) {
>> + NumInsts += BB.size();
>> + auto &Info = *InfoP;
>> + BlockInfo[&BB] = &Info;
>> + DEBUG_MSG("initializing block " << BB.getName());
>> + Info.BB = &BB;
>> + Info.Terminator = BB.getTerminator();
>> + Info.UnconditionalBranch = isUnconditional(Info.Terminator);
>> + ++InfoP;
>> + }
>> + if (!RemoveLoops) {
>> + // remove unreachable code, identify loop bottoms
>> + // to be forced live below.
>> + analyzeBlocks();
>> + }
>> + InstInfo.grow(2 * NumInsts);
>> + for (auto &BBInfo : BlockInfoVec) {
>> + if (BBInfo.isUnreachable()) { // removed unreachable node
>> + continue;
>> + }
>> + for (Instruction &I : *BBInfo.BB) {
>> + auto &IInfo = InstInfo[&I];
>> + IInfo.Block = &BBInfo;
>> + if (alwaysLive(I)) {
>> + markLive(&I);
>> + }
>> + }
>> + }
>> +
>> + // For blocks which do not reach a function return, mark
>> + // them live. Also branches where some reach the return
>> + // and some done as live.
>> + for (auto &BBInfo : BlockInfoVec) {
>> + if (!BBInfo.isUnreachable() && !PDT.getNode(BBInfo.BB)) {
>> + markLive(BBInfo.Terminator);
>> + for (auto Pred : predecessors(BBInfo.BB)) {
>> + DEBUG_MSG("no pdom pred live: " << Pred->getName());
>> + markLive(Pred->getTerminator());
>> + }
>> + }
>> + }
>> +
>> + // mark all loop bottom terminators as live so loops are not
>> + // deleted (in case they are infinite)
>> + for (auto BB : PO.getLoopBottoms()) {
>> + DEBUG_MSG("loop bottom " << BB->getName());
>> + markLive(BB->getTerminator());
>> + }
>> +
>> + for (auto &BBInfo : BlockInfoVec) {
>> + BBInfo.TerminatorLive = &InstInfo[BBInfo.Terminator].Live;
>> + if (! *BBInfo.TerminatorLive) {
>> + BlocksWithDeadTerminators.insert(BBInfo.BB);
>> + }
>> + }
>> +
>> + // Treat the entry block as always live
>> + auto BB = &F.getEntryBlock();
>> + auto &EntryInfo = *BlockInfo[BB];
>> + EntryInfo.Live = true;
>> + EntryInfo.LivePostDom = BB;
>> + if (EntryInfo.UnconditionalBranch) {
>> + *EntryInfo.TerminatorLive = true;
>> + BlocksWithDeadTerminators.erase(BB);
>> + }
>> +}
>> +
>> +// Find and remove unreachable code and compute the bottoms of loops
>> +// which will be forced live so loops are retained.
>> +void AggressiveCDCE::analyzeBlocks() {
>> +
>> + // This loop drives a Post Order traversal of the
>> + // control flow graph which will determine the set
>> + // of blocks reachable from the entry and also mark
>> + // those which are the sources of back edges (loop bottoms)
>> + for (auto BB : PO) {
>> + (void) BB;
>> + }
>> +
>> + for (auto &BB : F) {
>> + if (PO.reachable(&BB)) {
>> + continue;
>> + }
>> + DEBUG_MSG("unreachable " << BB.getName());
>> + removeUnreachable(&BB);
>> + UnreachableBlocks.push_back(&BB);
>> + }
>> + if (Worklist.empty()) {
>> + return;
>> + }
>> + GraphWasModified = true;
>> + for (auto I : Worklist) {
>> + I->eraseFromParent();
>> + }
>> + Worklist.clear();
>> +}
>> +
>> +// since we go to the trouble of finding unreachable blocks
>> +// might as well remove them.
>> +void AggressiveCDCE::removeUnreachable(BasicBlock *BB) {
>> + auto &Info = *BlockInfo[BB];
>> + Info.Live = true;
>> + Info.Terminator = nullptr;
>> +
>> + while (PHINode *PN = dyn_cast<PHINode>(BB->begin())) {
>> + PN->replaceAllUsesWith(Constant::getNullValue(PN->getType()));
>> + BB->getInstList().pop_front();
>> + }
>> + for (auto Succ : successors(BB)) {
>> + Succ->removePredecessor(BB);
>> + }
>> + BB->dropAllReferences();
>> + for (Instruction &I : *BB) {
>> + Worklist.push_back(&I);
>> + }
>> +}
>> +
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// Core algorithm to propagate liveness
>> +//
>> +//===----------------------------------------------------------------------===//
>> +void AggressiveCDCE::markLive() {
>> +
>> + DEBUG_MSG("propagate live\n");
>> +
>> + // Propagate liveness backwards to operands.
>> + do {
>> + while (!Worklist.empty()) {
>> + Instruction *Curr = Worklist.pop_back_val();
>> + DEBUG(dbgs() << "work live: "; Curr->dump(););
>> + for (Use &OI : Curr->operands()) {
>> + if (Instruction *Inst = dyn_cast<Instruction>(OI)) {
>> + markLive(Inst);
>> + }
>> + }
>> + }
>> + checkControlDependences();
>> + if (Worklist.empty()) {
>> + checkPhiNodes();
>> + }
>> + } while (!Worklist.empty());
>> +
>> + // Find blocks with dead terminators which are simply
>> + // unconditional branches and mark them live to avoid
>> + // trivial edits
>> + SmallVector<BasicBlock*, 32> NowLiveBlocks;
>> + for (auto BB : BlocksWithDeadTerminators) {
>> + auto Info = BlockInfo[BB];
>> + if (!Info->Live && Info->UnconditionalBranch &&
>> + &Info->BB->front() == Info->Terminator) {
>> + if (auto Pred = Info->BB->getSinglePredecessor()) {
>> + if (isLive(Pred->getTerminator())) {
>> + // this mostly avoids unnecessary work removing trival dead regions
>> + DEBUG_MSG("unconditional from live pred " << Info->BB->getName());
>> + Info->Live = true;
>> + *Info->TerminatorLive = true;
>> + Info->LivePostDom = BB;
>> + NowLiveBlocks.push_back(BB);
>> + }
>> + }
>> + }
>> + }
>> + for (auto BB : NowLiveBlocks) {
>> + BlocksWithDeadTerminators.erase(BB);
>> + }
>> +}
>> +
>> +// Check if this instruction is a runtime call for value profiling and
>> +// if it's instrumenting a constant.
>> +static bool isInstrumentsConstant(Instruction &I) {
>> + if (CallInst *CI = dyn_cast<CallInst>(&I))
>> + if (Function *Callee = CI->getCalledFunction())
>> + if (Callee->getName().equals(getInstrProfValueProfFuncName()))
>> + if (isa<Constant>(CI->getArgOperand(0)))
>> + return true;
>> + return false;
>> +}
>> +
>> +bool AggressiveCDCE::alwaysLive(Instruction &I) const {
>> + if (isa<DbgInfoIntrinsic>(I) || I.isEHPad() || I.mayHaveSideEffects()) {
>> + if (isInstrumentsConstant(I)) {
>> + return false;
>> + }
>> + return true;
>> + }
>> + if (!isa<TerminatorInst>(I)) {
>> + return false;
>> + }
>> + if (isa<BranchInst>(I) || isa<SwitchInst>(I)) {
>> + return false;
>> + }
>> + return true;
>> +}
>> +
>> +void AggressiveCDCE::markLive(Instruction *I) {
>> + auto &Info = InstInfo[I];
>> + if (Info.Live) {
>> + return;
>> + }
>> + DEBUG(dbgs() << "mark live: "; I->dump());
>> + Info.Live = true;
>> + Worklist.push_back(I);
>> +
>> + // Collect the live debug info scopes attached to this instruction.
>> + if (const DILocation *DL = I->getDebugLoc())
>> + collectLiveScopes(*DL);
>> +
>> + auto &BBInfo = *Info.Block;
>> + if (BBInfo.Live) {
>> + return;
>> + }
>> + DEBUG_MSG("mark block live: " << BBInfo.BB->getName());
>> + BBInfo.Live = true;
>> + NewLiveBlocks.insert(BBInfo.BB);
>> +
>> + // See comments below...
>
> Where? I don't see them...
>
>> + BBInfo.LivePostDom = BBInfo.BB;
>> + if (!BBInfo.UnconditionalBranch) {
>> + return;
>> + }
>> + BlocksWithDeadTerminators.erase(BBInfo.BB);
>> +
>> + if (!BBInfo.TerminatorLive) { // not set in first initialization pass
>> + InstInfo[BBInfo.Terminator].Live = true;
>> + } else {
>> + *BBInfo.TerminatorLive = true;
>> + }
>> +}
>> +
>> +void AggressiveCDCE::collectLiveScopes(const DILocalScope &LS) {
>> + if (!AliveScopes.insert(&LS).second)
>> + return;
>> +
>> + if (isa<DISubprogram>(LS))
>> + return;
>> +
>> + // Tail-recurse through the scope chain.
>> + collectLiveScopes(cast<DILocalScope>(*LS.getScope()));
>> +}
>> +
>> +void AggressiveCDCE::collectLiveScopes(const DILocation &DL) {
>> + // Even though DILocations are not scopes, shove them into AliveScopes so we
>> + // don't revisit them.
>> + if (!AliveScopes.insert(&DL).second)
>> + return;
>> +
>> + // Collect live scopes from the scope chain.
>> + collectLiveScopes(*DL.getScope());
>> +
>> + // Tail-recurse through the inlined-at chain.
>> + if (const DILocation *IA = DL.getInlinedAt())
>> + collectLiveScopes(*IA);
>> +}
>> +
>> +
>> +
>> +// Use the IDFCalculator to find control dependences
>> +// strting at newly discovered live blocks but stopping
>> +// at blocks with live terminators.
>> +void AggressiveCDCE::checkControlDependences() {
>> +
>> + if (BlocksWithDeadTerminators.empty()) {
>> + return ;
>> + }
>> +
>> + DEBUG({
>> + dbgs() << "new live blocks:\n";
>> + for (auto BB : NewLiveBlocks) {
>> + dbgs() << "\t" << BB->getName() << '\n';
>> + }
>> + dbgs() << "dead terminator blocks:\n";
>> + for (auto BB : BlocksWithDeadTerminators) {
>> + dbgs() << "\t" << BB->getName() << '\n';
>> + }
>> + });
>> +
>> + SmallVector<BasicBlock *, 32> IDFBlocks;
>> + ReverseIDFCalculator IDFs(PDT);
>> + IDFs.setDefiningBlocks(NewLiveBlocks);
>> + IDFs.setLiveInBlocks(BlocksWithDeadTerminators);
>> + IDFs.calculate(IDFBlocks);
>> + NewLiveBlocks.clear();
>> +
>> + /* dead terminators which control live blocks become live */
>> + for (auto BB : IDFBlocks) {
>> + DEBUG_MSG("live control in: " << BB->getName());
>> + markLive(BB->getTerminator());
>> + BlocksWithDeadTerminators.erase(BB);
>> + }
>> +}
>> +
>> +// there are scenarios in which a phi node is really short-hand
>> +// for a copy operations on the edge and the semantics of the program
>> +// rely on this. We look for situations where there are distinct values from
>> +// blocks with dead terminators (which we assume
>> +// are all replaced with
>> +// a single edge) and if we find this case we mark some of those terminators
>> +// as live.
>> +void AggressiveCDCE::checkPhiNodes() {
>> + RegionSetType LivePdoms;
>> + auto FirstVisit = LastCurrentVisit;
>> + for (auto DB : BlocksWithDeadTerminators) {
>> + auto DBInfo = BlockInfo[DB];
>> + if (DBInfo->RegionVisited > FirstVisit || DBInfo->terminatorIsLive()) {
>> + continue;
>> + }
>> + ++LastCurrentVisit;
>> + visitRegion(DBInfo, FirstVisit, LastCurrentVisit, &LivePdoms);
>> + }
>> + for (auto Succ : LivePdoms) {
>> + DEBUG_MSG("checking Phi Nodes " << Succ->getName());
>> + for (auto it = Succ->begin(); PHINode *PN = dyn_cast<PHINode>(it); ++it) {
>> + if (isLive(PN)) {
>> + checkPhiNode(PN, FirstVisit);
>> + }
>> + }
>> + }
>> +}
>> +
>> +// Traverse the connected component associated with BBInfo where
>> +// nodes whose RegionVisited field is > FirstVisit are considered 'visited'
>> +// and we stop at tops of live blocks.
>> +void AggressiveCDCE::visitRegion(BlockInfoType *BBInfo, unsigned FirstVisit,
>> + unsigned CurrentVisit,
>> + RegionSetType *LivePdoms) {
>> + BBInfo->RegionVisited = CurrentVisit;
>> + DEBUG_MSG("region visited " << CurrentVisit << " " << BBInfo->BB->getName());
>> + if (!BBInfo->Live) {
>> + for (auto Pred : predecessors(BBInfo->BB)) {
>> + auto PredInfo = BlockInfo[Pred];
>> + if (PredInfo->RegionVisited <= FirstVisit) {
>> + visitRegion(PredInfo, FirstVisit, CurrentVisit, LivePdoms);
>> + }
>> + }
>> + }
>> + for (auto Succ : successors(BBInfo->BB)) {
>> + auto SuccInfo = BlockInfo[Succ];
>> + if (SuccInfo->Live) {
>> + LivePdoms->insert(SuccInfo->BB);
>> + continue;
>> + }
>> + if (SuccInfo->RegionVisited <= FirstVisit) {
>> + visitRegion(SuccInfo, FirstVisit, CurrentVisit, LivePdoms);
>> + }
>> + }
>> +}
>> +
>> +// This code verifies that all edges from "dead" predecessors
>> +// have the same associated value. This might not be true
>> +// after certain optimizations of eliminated intermediate PHI
>> +// nodes
>> +void AggressiveCDCE::checkPhiNode(PHINode *PN, unsigned FirstVisit) {
>> + DenseMap<unsigned, Value *> DeadValues;
>> +
>> + auto NumIdx = PN->getNumIncomingValues();
>> + // A block P may be a direct predecessor of a block Q and have a live
>> + // terminator. It may also have a path from dead blocks leading to When that
>> + // path is removed, there will only be one edge from P to Q and so we can
>> + // only have one value in that case.
>> + for (unsigned Idx = 0; Idx < NumIdx; ++Idx) {
>> + auto PredBB = PN->getIncomingBlock(Idx);
>> + auto &Info = *BlockInfo[PredBB];
>> + if (Info.RegionVisited > FirstVisit && Info.Live &&
>> + Info.terminatorIsLive()) {
>> + DeadValues[Info.RegionVisited] = PN->getIncomingValue(Idx);
>> + DEBUG_MSG("live for region " << Info.RegionVisited << " from "
>> + << PredBB->getName());
>> + }
>> + }
>> + for (unsigned Idx = 0; Idx < NumIdx; ++Idx) {
>> + auto PredBB = PN->getIncomingBlock(Idx);
>> + auto PredInfo = BlockInfo[PredBB];
>> + if (PredInfo->terminatorIsLive()) {
>> + continue;
>> + }
>> + DEBUG_MSG("check pred " << PredInfo->RegionVisited << " "
>> + << PredBB->getName());
>> + auto Value = PN->getIncomingValue(Idx);
>> + auto &DeadValue = DeadValues[PredInfo->RegionVisited];
>> + if (DeadValue) {
>> + if (Value != DeadValue) {
>> + DEBUG(dbgs() << "hard phi, region = " << PredInfo->RegionVisited
>> + << " pred " << PredBB->getName() << '\n';
>> + PN->dump());
>> + markLive(PredInfo->Terminator);
>> + }
>> + } else {
>> + DeadValue = Value;
>> + }
>> + }
>> +}
>> +
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// Routines to update the CFG and SSA information before removing dead code
>> +//
>> +//===----------------------------------------------------------------------===//
>> +// A dead region is the set of dead blocks with a common live post-dominator
>> +// A trivial region is a region which consists of blocks with unconditional
>> +// branches. We don't bother removing such blocks and defer to other phases
>> +void AggressiveCDCE::processDeadRegions() {
>> +
>> +
>> + // Set LivePostDom fields for blocks which dead terminators
>> + SmallVector<DomTreeNodeBase<BasicBlock> *, 16> deadPdoms;
>> + for (auto & Info : BlockInfoVec) {
>> + if( Info.isUnreachable()) {
>> + continue;
>> + }
>> + if(Info.LivePostDom == nullptr) {
>> + assert(!Info.Live);
>> + auto Node = PDT.getNode(Info.BB)->getIDom();
>> + while(!isLive(Node->getBlock())) {
>> + deadPdoms.push_back(Node);
>> + Node = Node->getIDom();
>> + }
>> + Info.LivePostDom = Node->getBlock();
>> + for (auto DeadNode : deadPdoms) {
>> + BlockInfo[DeadNode->getBlock()]->LivePostDom = Info.LivePostDom;
>> + }
>> + deadPdoms.clear();
>> + }
>> + if (Info.LivePostDom != Info.BB) {
>> + DEBUG_MSG("live pdom " << Info.BB->getName() << " "
>> + << Info.LivePostDom->getName());
>> + }
>> + }
>> + SmallPtrSet<BlockInfoType *, 32> DeadRegions;
>> +
>> + // Examine dead blocks and collect them at their
>> + // live post-dominator to be processed as a region.
>> + for (auto DB : BlocksWithDeadTerminators) {
>> + auto Info = BlockInfo[DB];
>> + assert(! *Info->TerminatorLive);
>> + if (Info->Live) {
>> + // Look for live blocks with dead branches which
>> + // will need to be converted to unconditional branches
>> + for (auto Succ : successors(Info->BB)) {
>> + auto &SuccInfo = *BlockInfo[Succ];
>> + if (!SuccInfo.Live) {
>> + continue;
>> + }
>> + DEBUG_MSG("dead br in pred " << Info->BB->getName() << " reaches "
>> + << Succ->getName());
>> + SuccInfo.DeadRegion.LivePreds.insert(Info);
>> + SuccInfo.DeadRegion.Trivial = false;
>> + DeadRegions.insert(&SuccInfo);
>> + }
>> + continue;
>> + }
>> + auto LivePdom = Info->LivePostDom;
>> + DEBUG_MSG("Dead block: " << Info->BB->getName() << " pdom "
>> + << LivePdom->getName());
>> + auto &LivePdomInfo = *BlockInfo[LivePdom];
>> + DeadRegions.insert(&LivePdomInfo);
>> + auto &DeadRegion = LivePdomInfo.DeadRegion;
>> + for (auto PredBB : predecessors(Info->BB)) {
>> + auto &PredInfo = *BlockInfo[PredBB];
>> + if (PredInfo.Live) {
>> + DeadRegion.LivePreds.insert(&PredInfo);
>> + if (!PredInfo.terminatorIsLive()) {
>> + DeadRegion.Trivial = false;
>> + }
>> + }
>> + }
>> + if (!Info->UnconditionalBranch) {
>> + DeadRegion.Trivial = false;
>> + } else if (DeadRegion.Trivial) {
>> + DeadRegion.DeadBlocks.push_back(Info);
>> + }
>> + }
>> +
>> + for (auto Info : DeadRegions) {
>> + if (!Info->DeadRegion.Trivial) {
>> + updateDeadRegion(Info->BB, &Info->DeadRegion);
>> + } else {
>> + cleanTrivialRegion(Info->DeadRegion);
>> + }
>> + }
>> +}
>> +
>> +void AggressiveCDCE::updateDeadRegion(BasicBlock *BB, DeadRegionInfo *Info) {
>> +
>> + DEBUG({
>> + dbgs() << "live edges (unique predecessors) into " << BB->getName() << "\n";
>> + for (auto PredInfo : Info->LivePreds) {
>> + dbgs() << "\t" << PredInfo->BB->getName() << '\n';
>> + }
>> + });
>> +
>> + // update each phi based on the new incoming edges
>> + for (auto it = BB->begin(); PHINode *PN = dyn_cast<PHINode>(it); ++it) {
>> + if (!isLive(PN)) {
>> + continue;
>> + }
>> + DEBUG(dbgs() << "old phi: "; PN->dump());
>> + // Note that we have verified in checkPhiNodes that all are
>> + // the same from dead predecessors.
>> + DenseMap<unsigned, Value *> DeadValues;
>> +
>> + for (int64_t i = PN->getNumIncomingValues() - 1; i >= 0; --i) {
>> + auto PredBB = PN->getIncomingBlock(i);
>> + auto PredInfo = BlockInfo[PredBB];
>> + if (PredInfo->terminatorIsLive()) {
>> + continue;
>> + }
>> + DEBUG_MSG(" removing " << PredInfo->RegionVisited << " "
>> + << PredBB->getName());
>> + auto &DeadValue = DeadValues[PredInfo->RegionVisited];
>> + assert(!DeadValue || DeadValue == PN->getIncomingValue(i));
>> + DeadValue = PN->getIncomingValue(i);
>> + PN->removeIncomingValue(i, /*DeletePHIIfEmpty*/ false);
>> + }
>> + for (auto PredInfo : Info->LivePreds) {
>> + auto DeadValue = DeadValues[PredInfo->RegionVisited];
>> + assert(DeadValue && "Failed to find value for dead predecessor");
>> + PN->addIncoming(DeadValue, PredInfo->BB);
>> + }
>> + DEBUG(dbgs() << "new phi: "; PN->dump());
>> + }
>> +
>> + // update edges
>> + for (auto PredInfo : Info->LivePreds) {
>> + if (!PredInfo->terminatorIsLive()) {
>> + makeUnconditional(PredInfo->BB, BB);
>> + } else {
>> + auto PredTerm = PredInfo->Terminator;
>> + auto NumSucc = PredTerm->getNumSuccessors();
>> + for (unsigned Idx = 0; Idx != NumSucc; ++Idx) {
>> + auto Succ = PredTerm->getSuccessor(Idx);
>> + auto SuccInfo = BlockInfo[Succ];
>> + if (SuccInfo->LivePostDom == BB) {
>> + PredTerm->setSuccessor(Idx, BB);
>> + }
>> + }
>> + }
>> + }
>> +#ifndef NDEBUG
>> + BlocksForPhiValidation.insert(BB);
>> +#endif
>> +}
>> +void AggressiveCDCE::makeUnconditional(BasicBlock *BB, BasicBlock *Target) {
>> + auto PredTerm = BB->getTerminator();
>> + if (isUnconditional(PredTerm)) {
>> + InstInfo[PredTerm].Live = true;
>> + return;
>> + }
>> + DEBUG_MSG("making unconditional " << BB->getName());
>> + IRBuilder<> Builder(PredTerm);
>> + auto NewTerm = Builder.CreateBr(Target);
>> + // don't update InstInfo to protect pointers into it...
>> + NewBranches.push_back(NewTerm);
>> +}
>> +
>> +// mark trivial blocks live and their unconditional-branch terminators as well.
>> +void AggressiveCDCE::cleanTrivialRegion(const DeadRegionInfo &DRInfo) {
>> + for (auto DBInfo : DRInfo.DeadBlocks) {
>> + DEBUG_MSG("Trivial: " << DBInfo->BB->getName());
>> + DBInfo->Live = true;
>> + *DBInfo->TerminatorLive = true;
>> + }
>> +}
>> +
>> +// the actual work of removing dead instructions and blocks
>> +void AggressiveCDCE::removeDeadCode() {
>> +
>> + assert(Worklist.empty() &&
>> + "Expected empty work list when removing dead code");
>> + // The inverse of the live set is the dead set. These are those instructions
>> + // which have no side effects and do not influence the control flow or return
>> + // value of the function, and may therefore be deleted safely.
>> + // NOTE: We reuse the Worklist vector here for memory efficiency.
>> + unsigned LocalNumBranchesRemoved = std::count_if(
>> + BlocksWithDeadTerminators.begin(), BlocksWithDeadTerminators.end(),
>> + [this](BasicBlock *DB) { return !isLive(DB->getTerminator()); });
>> +
>> + // this update invalidates BlockInfoType::TerminatorLive fields
>> + for (Instruction *I : NewBranches) {
>> + InstInfo[I].Live = true;
>> + }
>> + for (Instruction &I : instructions(F)) {
>> + if (!isLive(&I)) {
>> + if (auto *DII = dyn_cast<DbgInfoIntrinsic>(&I)) {
>> + // Check if the scope of this variable location is alive.
>> + if (AliveScopes.count(DII->getDebugLoc()->getScope()))
>> + continue;
>> +
>> + // Fallthrough and drop the intrinsic.
>> + DEBUG({
>> + // If intrinsic is pointing at a live SSA value, there may be an
>> + // earlier optimization bug: if we know the location of the variable,
>> + // why isn't the scope of the location alive?
>> + if (Value *V = DII->getVariableLocation())
>> + if (Instruction *II = dyn_cast<Instruction>(V))
>> + if (isLive(II))
>> + dbgs() << "Dropping debug info for " << *DII << "\n";
>> + });
>> + }
>> +
>> + DEBUG(dbgs() << "dead: "; I.dump());
>> + Worklist.push_back(&I);
>> + I.dropAllReferences();
>> + }
>> + }
>> + for (auto UB : UnreachableBlocks) {
>> + DEBUG_MSG("removing unreachble " << UB->getName());
>> + UB->eraseFromParent();
>> + }
>> + if (Worklist.empty()) {
>> + return;
>> + }
>> + GraphWasModified = true;
>> + for (Instruction *I : Worklist) {
>> + I->eraseFromParent();
>> + }
>> + for (auto BB : BlocksWithDeadTerminators) {
>> + auto DB = BlockInfo[BB];
>> + if (!DB->Live) {
>> + DEBUG_MSG("deleting block " << DB->BB->getName());
>> + DB->BB->eraseFromParent();
>> + }
>> + }
>> + auto LocalNumRemoved = Worklist.size();
>> + DEBUG_MSG("Num removed " << LocalNumRemoved << "\n"
>> + << "Num branches removed "
>> + << LocalNumBranchesRemoved);
>> + FuncNumInstRemoved += LocalNumRemoved;
>> + FuncNumBranchesRemoved += LocalNumBranchesRemoved;
>> + NumBranchesRemoved += FuncNumBranchesRemoved;
>> + NumRemoved += FuncNumInstRemoved;
>> +}
>> +
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// Debugging and validation code
>> +//
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef NDEBUG
>> +void AggressiveCDCE::validatePhiNodes(BasicBlock *BB) {
>> +
>> + if (BB->empty())
>> + return;
>> + PHINode *APN = dyn_cast<PHINode>(&BB->front());
>> + if (!APN)
>> + return;
>> +
>> + SmallVector<std::pair<BasicBlock *, Value *>, 16> Preds;
>> + for (auto Pred : predecessors(BB)) {
>> + Preds.emplace_back(Pred, nullptr);
>> + }
>> + auto error = [this, BB](PHINode *PN, BasicBlock *Pred, const char *Message) {
>> + errs() << "Error in function: " << F.getName() << "\n\t" << Message << '\n';
>> + errs() << "\tblock " << BB->getName() << '\n';
>> + errs() << "\tpred " << Pred->getName() << "\n\t";
>> + PN->print(errs());
>> + errs() << '\n';
>> + };
>> +
>> + for (auto it = BB->begin(); PHINode *PN = dyn_cast<PHINode>(it); ++it) {
>> + if (!isLive(PN)) {
>> + continue;
>> + }
>> + auto NumIdx = PN->getNumIncomingValues();
>> + for (unsigned Idx = 0; Idx < NumIdx; ++Idx) {
>> + auto Value = PN->getIncomingValue(Idx);
>> + auto Pred = PN->getIncomingBlock(Idx);
>> + bool Found = false;
>> + for (auto &P : Preds) {
>> + if (P.first == Pred) {
>> + if (!P.second) {
>> + P.second = Value;
>> + Found = true;
>> + break;
>> + }
>> + if (P.second != Value) {
>> + error(PN, Pred, "multiple distinct values");
>> + }
>> + }
>> + }
>> + if (!Found) {
>> + error(PN, Pred, "no predecessor for value");
>> + }
>> + }
>> + for (auto &P : Preds) {
>> + if (!P.second) {
>> + error(PN, P.first, "no value for predecessor");
>> + }
>> + P.second = nullptr; // reset for next PHI
>> + }
>> + }
>> +}
>> +#endif
>> +
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// Pass Manager integration code
>> +//
>> +//===----------------------------------------------------------------------===//
>> +PreservedAnalyses ACDCEPass::run(Function &F, AnalysisManager<Function> &AM) {
>> + auto &PDT = AM.getResult<PostDominatorTreeAnalysis>(F);
>> + if (AggressiveCDCE(F, PDT).doAggressiveCDCE())
>> + return PreservedAnalyses::none();
>> + return PreservedAnalyses::all();
>> +}
>> +
>> +namespace {
>> +struct ACDCELegacyPass : public FunctionPass {
>> + static char ID; // Pass identification, replacement for typeid
>> + ACDCELegacyPass() : FunctionPass(ID) {
>> + initializeACDCELegacyPassPass(*PassRegistry::getPassRegistry());
>> + }
>> +
>> + bool runOnFunction(Function &F) override {
>> + if (skipFunction(F))
>> + return false;
>> + auto &PDT = getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
>> + return AggressiveCDCE(F, PDT).doAggressiveCDCE();
>> + }
>> +
>> + void getAnalysisUsage(AnalysisUsage &AU) const override {
>> + AU.addRequired<PostDominatorTreeWrapperPass>();
>> + AU.addPreserved<GlobalsAAWrapperPass>();
>> + }
>> +};
>> +}
>> +
>> +char ACDCELegacyPass::ID = 0;
>> +INITIALIZE_PASS_BEGIN(ACDCELegacyPass, "acdce",
>> + "Aggressive Control Dead Code Elimination", false, false)
>> +INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
>> +INITIALIZE_PASS_END(ACDCELegacyPass, "acdce",
>> + "Aggressive Control Dead Code Elimination", false, false)
>> +
>> +FunctionPass *llvm::createAggressiveControlDCEPass() {
>> + return new ACDCELegacyPass();
>> +}
>> Index: lib/Transforms/IPO/PassManagerBuilder.cpp
>> ===================================================================
>> --- lib/Transforms/IPO/PassManagerBuilder.cpp
>> +++ lib/Transforms/IPO/PassManagerBuilder.cpp
>> @@ -316,7 +316,12 @@
>> if (LoadCombine)
>> MPM.add(createLoadCombinePass());
>>
>> - MPM.add(createAggressiveDCEPass()); // Delete dead instructions
>> + if (OptLevel > 2) {
>> + MPM.add(createAggressiveControlDCEPass()); // Delete dead instructions
>> + }
>> + else {
>> + MPM.add(createAggressiveDCEPass()); // Delete dead instructions
>> + }
>> MPM.add(createCFGSimplificationPass()); // Merge & remove BBs
>> // Clean up after everything.
>> addInstructionCombiningPass(MPM);
>> Index: lib/Passes/PassRegistry.def
>> ===================================================================
>> --- lib/Passes/PassRegistry.def
>> +++ lib/Passes/PassRegistry.def
>> @@ -94,6 +94,7 @@
>> #ifndef FUNCTION_PASS
>> #define FUNCTION_PASS(NAME, CREATE_PASS)
>> #endif
>> +FUNCTION_PASS("acdce", ACDCEPass())
>> FUNCTION_PASS("aa-eval", AAEvaluator())
>> FUNCTION_PASS("adce", ADCEPass())
>> FUNCTION_PASS("dce", DCEPass())
>> Index: lib/Passes/PassBuilder.cpp
>> ===================================================================
>> --- lib/Passes/PassBuilder.cpp
>> +++ lib/Passes/PassBuilder.cpp
>> @@ -51,6 +51,7 @@
>> #include "llvm/Transforms/IPO/StripDeadPrototypes.h"
>> #include "llvm/Transforms/InstCombine/InstCombine.h"
>> #include "llvm/Transforms/InstrProfiling.h"
>> +#include "llvm/Transforms/Scalar/ACDCE.h"
>> #include "llvm/Transforms/Scalar/ADCE.h"
>> #include "llvm/Transforms/Scalar/DCE.h"
>> #include "llvm/Transforms/Scalar/EarlyCSE.h"
>> Index: include/llvm/Transforms/Scalar/ACDCE.h
>> ===================================================================
>> --- /dev/null
>> +++ include/llvm/Transforms/Scalar/ACDCE.h
>> @@ -0,0 +1,40 @@
>> +//===- ACDCE.h - Aggressive dead code elimination
>> +//--------------------------===//
>> +//
>> +// The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// This file provides the interface for the Aggressive Control Dead Code Elimination
>> +// pass. This pass optimistically assumes that all instructions are dead until
>> +// proven otherwise, allowing it to eliminate dead computations that other DCE
>> +// passes do not catch, particularly involving loop computations.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_TRANSFORMS_SCALAR_ACDCE_H
>> +#define LLVM_TRANSFORMS_SCALAR_ACDCE_H
>> +
>> +#include "llvm/IR/Function.h"
>> +#include "llvm/IR/PassManager.h"
>> +
>> +namespace llvm {
>> +
>> +/// A DCE pass that assumes instructions including branches are dead until
>> +/// proven otherwise.
>> +///
>> +/// This pass eliminates dead code by optimistically assuming that all
>> +/// instructions are dead until proven otherwise. This allows it to eliminate
>> +/// dead computations that other DCE passes do not catch, particularly involving
>> +/// loop computations. This pass augments the predecessor "Aggressive DCE" by
>> +/// not treating all branch operations as automatically live and by altering the
>> +/// control flow graph remove dead branching.
>> +struct ACDCEPass : PassInfoMixin<ACDCEPass> {
>> + PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
>> +};
>> +}
>> +
>> +#endif // LLVM_TRANSFORMS_SCALAR_ACDCE_H
>> Index: include/llvm/Transforms/Scalar.h
>> ===================================================================
>> --- include/llvm/Transforms/Scalar.h
>> +++ include/llvm/Transforms/Scalar.h
>> @@ -83,6 +83,15 @@
>>
>> //===----------------------------------------------------------------------===//
>> //
>> +// AggressiveControlDCE - This pass uses the SSA based Aggressive DCE algorithm. This
>> +// algorithm assumes instructions are dead until proven otherwise, which makes
>> +// it more successful at removing non-obviously dead instructions. This
>> +// variant does not treat branches as automatically live
>> +//
>> +FunctionPass *createAggressiveControlDCEPass();
>> +
>> +//===----------------------------------------------------------------------===//
>> +//
>> // BitTrackingDCE - This pass uses a bit-tracking DCE algorithm in order to
>> // remove computations of dead bits.
>> //
>> Index: include/llvm/LinkAllPasses.h
>> ===================================================================
>> --- include/llvm/LinkAllPasses.h
>> +++ include/llvm/LinkAllPasses.h
>> @@ -60,6 +60,7 @@
>> return;
>>
>> (void) llvm::createAAEvalPass();
>> + (void) llvm::createAggressiveControlDCEPass();
>> (void) llvm::createAggressiveDCEPass();
>> (void) llvm::createBitTrackingDCEPass();
>> (void) llvm::createArgumentPromotionPass();
>> Index: include/llvm/InitializePasses.h
>> ===================================================================
>> --- include/llvm/InitializePasses.h
>> +++ include/llvm/InitializePasses.h
>> @@ -63,6 +63,7 @@
>> void initializeTarget(PassRegistry&);
>>
>> void initializeAAEvalLegacyPassPass(PassRegistry&);
>> +void initializeACDCELegacyPassPass(PassRegistry&);
>> void initializeAddDiscriminatorsPass(PassRegistry&);
>> void initializeADCELegacyPassPass(PassRegistry&);
>> void initializeBDCEPass(PassRegistry&);
More information about the llvm-commits
mailing list