mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2026-04-25 05:22:04 +00:00
improve switch formation to handle small range
comparisons formed by comparisons. For example,
this:
void foo(unsigned x) {
if (x == 0 || x == 1 || x == 3 || x == 4 || x == 6)
bar();
}
compiles into:
_foo: ## @foo
## BB#0: ## %entry
cmpl $6, %edi
ja LBB0_2
## BB#1: ## %entry
movl %edi, %eax
movl $91, %ecx
btq %rax, %rcx
jb LBB0_3
instead of:
_foo: ## @foo
## BB#0: ## %entry
cmpl $2, %edi
jb LBB0_4
## BB#1: ## %switch.early.test
cmpl $6, %edi
ja LBB0_3
## BB#2: ## %switch.early.test
movl %edi, %eax
movl $88, %ecx
btq %rax, %rcx
jb LBB0_4
This catches a bunch of cases in GCC, which look like this:
%804 = load i32* @which_alternative, align 4, !tbaa !0
%805 = icmp ult i32 %804, 2
%806 = icmp eq i32 %804, 3
%or.cond121 = or i1 %805, %806
%807 = icmp eq i32 %804, 4
%or.cond124 = or i1 %or.cond121, %807
br i1 %or.cond124, label %.thread, label %808
turning this into a range comparison.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122045 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -351,4 +351,73 @@ malformed:
|
||||
ret void
|
||||
; CHECK: @test12
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
; test13 - handle switch formation with ult.
|
||||
define void @test13(i32 %x) nounwind ssp noredzone {
|
||||
entry:
|
||||
%cmp = icmp ult i32 %x, 2
|
||||
br i1 %cmp, label %if.then, label %lor.lhs.false3
|
||||
|
||||
lor.lhs.false3: ; preds = %lor.lhs.false
|
||||
%cmp5 = icmp eq i32 %x, 3
|
||||
br i1 %cmp5, label %if.then, label %lor.lhs.false6
|
||||
|
||||
lor.lhs.false6: ; preds = %lor.lhs.false3
|
||||
%cmp8 = icmp eq i32 %x, 4
|
||||
br i1 %cmp8, label %if.then, label %lor.lhs.false9
|
||||
|
||||
lor.lhs.false9: ; preds = %lor.lhs.false6
|
||||
%cmp11 = icmp eq i32 %x, 6
|
||||
br i1 %cmp11, label %if.then, label %if.end
|
||||
|
||||
if.then: ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
|
||||
call void @foo1() noredzone
|
||||
br label %if.end
|
||||
|
||||
if.end: ; preds = %if.then, %lor.lhs.false9
|
||||
ret void
|
||||
; CHECK: @test13
|
||||
; CHECK: switch i32 %x, label %if.end [
|
||||
; CHECK: i32 6, label %if.then
|
||||
; CHECK: i32 4, label %if.then
|
||||
; CHECK: i32 3, label %if.then
|
||||
; CHECK: i32 1, label %if.then
|
||||
; CHECK: i32 0, label %if.then
|
||||
; CHECK: ]
|
||||
}
|
||||
|
||||
; test14 - handle switch formation with ult.
|
||||
define void @test14(i32 %x) nounwind ssp noredzone {
|
||||
entry:
|
||||
%cmp = icmp ugt i32 %x, 2
|
||||
br i1 %cmp, label %lor.lhs.false3, label %if.then
|
||||
|
||||
lor.lhs.false3: ; preds = %lor.lhs.false
|
||||
%cmp5 = icmp ne i32 %x, 3
|
||||
br i1 %cmp5, label %lor.lhs.false6, label %if.then
|
||||
|
||||
lor.lhs.false6: ; preds = %lor.lhs.false3
|
||||
%cmp8 = icmp ne i32 %x, 4
|
||||
br i1 %cmp8, label %lor.lhs.false9, label %if.then
|
||||
|
||||
lor.lhs.false9: ; preds = %lor.lhs.false6
|
||||
%cmp11 = icmp ne i32 %x, 6
|
||||
br i1 %cmp11, label %if.end, label %if.then
|
||||
|
||||
if.then: ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
|
||||
call void @foo1() noredzone
|
||||
br label %if.end
|
||||
|
||||
if.end: ; preds = %if.then, %lor.lhs.false9
|
||||
ret void
|
||||
; CHECK: @test14
|
||||
; CHECK: switch i32 %x, label %if.end [
|
||||
; CHECK: i32 6, label %if.then
|
||||
; CHECK: i32 4, label %if.then
|
||||
; CHECK: i32 3, label %if.then
|
||||
; CHECK: i32 1, label %if.then
|
||||
; CHECK: i32 0, label %if.then
|
||||
; CHECK: ]
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user