[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