llvm/test/Transforms/EarlyCSE/conditional.ll
Philip Reames e00c0df2c4 Extend EarlyCSE to handle basic cases from JumpThreading and CVP
This patch extends EarlyCSE to take advantage of the information that a controlling branch gives us about the value of a Value within this and dominated basic blocks. If the current block has a single predecessor with a controlling branch, we can infer what the branch condition must have been to execute this block. The actual change to support this is downright simple because EarlyCSE's existing scoped hash table logic deals with most of the complexity around merging.

The patch actually implements two optimizations.
1) The first is analogous to JumpThreading in that it enables EarlyCSE's CSE handling to fold branches which are exactly redundant due to a previous branch to branches on constants. (It doesn't actually replace the branch or change the CFG.) This is pretty clearly a win since it enables substantial CFG simplification before we start trying to inline.
2) The second is analogous to CVP in that it exploits the knowledge gained to replace dominated *uses* of the original value. EarlyCSE does not otherwise reason about specific uses, so this is the more arguable one. It does enable further simplication and constant folding within the rest of the visit by EarlyCSE.

In both cases, the added code only handles the easy dominance based case of each optimization. The general case is deferred to the existing passes.

Differential Revision: http://reviews.llvm.org/D9763



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238071 91177308-0d34-0410-b5e6-96231b3b80d8
2015-05-22 23:53:24 +00:00

108 lines
2.1 KiB
LLVM

; RUN: opt -early-cse -S < %s | FileCheck %s
; Can we CSE a known condition to a constant?
define i1 @test(i8* %p) {
; CHECK-LABEL: @test
entry:
%cnd1 = icmp eq i8* %p, null
br i1 %cnd1, label %taken, label %untaken
taken:
; CHECK-LABEL: taken:
; CHECK-NEXT: ret i1 true
%cnd2 = icmp eq i8* %p, null
ret i1 %cnd2
untaken:
; CHECK-LABEL: untaken:
; CHECK-NEXT: ret i1 false
%cnd3 = icmp eq i8* %p, null
ret i1 %cnd3
}
; We can CSE the condition, but we *don't* know it's value after the merge
define i1 @test_neg1(i8* %p) {
; CHECK-LABEL: @test_neg1
entry:
%cnd1 = icmp eq i8* %p, null
br i1 %cnd1, label %taken, label %untaken
taken:
br label %merge
untaken:
br label %merge
merge:
; CHECK-LABEL: merge:
; CHECK-NEXT: ret i1 %cnd1
%cnd3 = icmp eq i8* %p, null
ret i1 %cnd3
}
; Check specifically for a case where we have a unique predecessor, but
; not a single predecessor. We can not know the value of the condition here.
define i1 @test_neg2(i8* %p) {
; CHECK-LABEL: @test_neg2
entry:
%cnd1 = icmp eq i8* %p, null
br i1 %cnd1, label %merge, label %merge
merge:
; CHECK-LABEL: merge:
; CHECK-NEXT: ret i1 %cnd1
%cnd3 = icmp eq i8* %p, null
ret i1 %cnd3
}
; Replace a use rather than CSE
define i1 @test2(i8* %p) {
; CHECK-LABEL: @test2
entry:
%cnd = icmp eq i8* %p, null
br i1 %cnd, label %taken, label %untaken
taken:
; CHECK-LABEL: taken:
; CHECK-NEXT: ret i1 true
ret i1 %cnd
untaken:
; CHECK-LABEL: untaken:
; CHECK-NEXT: ret i1 false
ret i1 %cnd
}
; Not legal to replace use given it's not dominated by edge
define i1 @test2_neg1(i8* %p) {
; CHECK-LABEL: @test2_neg1
entry:
%cnd1 = icmp eq i8* %p, null
br i1 %cnd1, label %taken, label %untaken
taken:
br label %merge
untaken:
br label %merge
merge:
; CHECK-LABEL: merge:
; CHECK-NEXT: ret i1 %cnd1
ret i1 %cnd1
}
; Another single predecessor test, but for dominated use
define i1 @test2_neg2(i8* %p) {
; CHECK-LABEL: @test2_neg2
entry:
%cnd1 = icmp eq i8* %p, null
br i1 %cnd1, label %merge, label %merge
merge:
; CHECK-LABEL: merge:
; CHECK-NEXT: ret i1 %cnd1
ret i1 %cnd1
}