[PATCH] D18762: Add Aggressive Control Dead Code Elimination

Mehdi Amini via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 25 16:55:39 PDT 2016


> On Apr 25, 2016, at 4:30 PM, David Callahan <dcallahan at fb.com> wrote:
> 
> New to this process so forgive the learningsÅ 
> Are the comments below intended to be reflected in phabricator (because
> they are not at the moment) or is it a separate email discussion?

Phabricator does not cope with inlined comments in email. And unfortunately some people seems allergic to the web interface, so it makes the reviews harder.

-- 
Mehdi





> Comments inline...
> 
> On 4/25/16, 3:42 PM, "mehdi.amini at apple.com on behalf of Mehdi Amini"
> <mehdi.amini at apple.com> wrote:
> 
>> 
>> 
>> 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...
>> 
>> https://urldefense.proofpoint.com/v2/url?u=http-3A__reviews.llvm.org_file_
>> data_g5nfdlo5z2lydyefkdsr_PHID-2DFILE-2Dsfs3b7gzuupa35nv2jgg_D18762.diff&d
>> =CwIFAg&c=5VD0RTtNlTh3ycd41b3MUw&r=lFyiPUrFdOHdaobP7i4hoA&m=9JkXH0KSFTIbeS
>> L_jgglMtkxqfMt3c6zp--9Gg9ehIs&s=s9dqiatiE6Z2g28VKpZnFiLQDJRhce3OAL5RKzKZdY
>> k&e= 
>> 
>> 
>> -- 
>> Mehdi
> 
> 
> I did not follow this. Was a reference into the patch or a comment about
> phabricator?
> 
> 
>> 
>> 
>>> David Callahan <dcallahan at fb.com> writes:
>>>> david2050 updated this revision to Diff 54871.
>>>> david2050 added a comment.
>>>> 
>>>> Udate 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.
> 
> 
> Thank you.
> 
> 
>>> 
>>>> 
>>>> 
>>>> https://urldefense.proofpoint.com/v2/url?=http-3A__reviews.llvm.org_D18
>>>> 762&d=CwIFAg&c=5VD0RTtNlTh3ycd41b3MUw&r=lFyiPUrFdOHdaobP7i4oA&m=9JkXH0K
>>>> SFTIbeSL_jgglMtkxqfMt3c6zp--9Gg9ehIs&s=B84iHrdJiU7pRu4PJQDp5zAP-pfVk6pOc>>>-exRNXciWM&e= 
>>>> 
>>>> 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-UseStuckAroundll
>>>> 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-0-28-Crash.ll
>>>> test/Transforms/ADCE/2002-07-17-AssertionFailure.ll
>>>> tst/Transforms/ADCE/2002-07-17-PHIAssertion.ll
>>>> test/Transforms/ADCE/2002-07-29-Segfault.ll
>>>> tst/Transforms/ADCE/2003-01-22-PredecessorProblem.ll
>>>> test/Transforms/ADCE/2003-0-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
>>>> 
>>>> Inex: 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
>>> anythng differently than the existing ADCE pass?
> 
> Some of the tests just verify compilation without fault and where it
> matters, the FileCheck so where additional
> Work is done beyond the base. There were enough of these that it was not
> clear additional tests were needed.
> I would expect in the fullness of time to completely replace ADCE with
> ACDCE and would rename the tests at that point.
> 
>>> 
>>>> 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 ;)
> 
> Yes.
> 
>>> 
>>>> +//
>>>> +// 
>>>> https://urldefense.proofpoint.com/v2/url?u=https-3A__groups.google.com_f
>>>> orum_-23-21topic_llvm-2Ddev_j2vlIECKkdE&d=CwIFAg&c=5VD0RTtNlTh3ycd41b3MU
>>>> w&r=lFyiPUrFdOHdaobP7i4hoA&m=9JkXH0KSFTIbeSL_jgglMtkxqfMt3c6zp--9Gg9ehIs
>>>> &s=FA-XXrrUJMcYcp3Rzmy2c0rNlOoB1AkYYMNPioPSSMY&e=  -- 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.
> 
> Agreed, missed in cleanup
> 
>>> 
>>>> +//
>>>> 
>>>> +//===------------------------------------------------------------------
>>>> ----===//
>>>> +
>>>> +#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?
> 
> There was a fair amount of redundancy in the simple little debug lines I
> used commonly. Although I do notice it seems comment to remove debugging
> (or at least there is not much left).
> 
>>> 
>>>> +
>>>> +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.
> 
> Yes.
> 
>>> 
>>>> +  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?
> 
> Ok
> 
>>> 
>>>> +
>>>> +  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.
> 
> -> AggressiveControlDCE
> 
>>> 
>>>> +  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...
> 
> (left over from a previous version)
> 
>>> 
>>>> +  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