[BDCE] Add a bit-tracking DCE pass
BDCE is a bit-tracking dead code elimination pass. It is based on ADCE (the
"aggressive DCE" pass), with the added capability to track dead bits of integer
valued instructions and remove those instructions when all of the bits are
dead.
Currently, it does not actually do this all-bits-dead removal, but rather
replaces the instruction's uses with a constant zero, and lets instcombine (and
the later run of ADCE) do the rest. Because we essentially get a run of ADCE
"for free" while tracking the dead bits, we also do what ADCE does and removes
actually-dead instructions as well (this includes instructions newly trivially
dead because all bits were dead, but not all such instructions can be removed).
The motivation for this is a case like:
int __attribute__((const)) foo(int i);
int bar(int x) {
x |= (4 & foo(5));
x |= (8 & foo(3));
x |= (16 & foo(2));
x |= (32 & foo(1));
x |= (64 & foo(0));
x |= (128& foo(4));
return x >> 4;
}
As it turns out, if you order the bit-field insertions so that all of the dead
ones come last, then instcombine will remove them. However, if you pick some
other order (such as the one above), the fact that some of the calls to foo()
are useless is not locally obvious, and we don't remove them (without this
pass).
I did a quick compile-time overhead check using sqlite from the test suite
(Release+Asserts). BDCE took ~0.4% of the compilation time (making it about
twice as expensive as ADCE).
I've not looked at why yet, but we eliminate instructions due to having
all-dead bits in:
External/SPEC/CFP2006/447.dealII/447.dealII
External/SPEC/CINT2006/400.perlbench/400.perlbench
External/SPEC/CINT2006/403.gcc/403.gcc
MultiSource/Applications/ClamAV/clamscan
MultiSource/Benchmarks/7zip/7zip-benchmark
llvm-svn: 229462
2015-02-17 02:36:59 +01:00
|
|
|
; RUN: opt -S -bdce -instsimplify < %s | FileCheck %s
|
|
|
|
; RUN: opt -S -instsimplify < %s | FileCheck %s -check-prefix=CHECK-IO
|
2018-02-21 02:55:33 +01:00
|
|
|
; RUN: opt -S -debugify -bdce < %s | FileCheck %s -check-prefix=DEBUGIFY
|
[BDCE] Add a bit-tracking DCE pass
BDCE is a bit-tracking dead code elimination pass. It is based on ADCE (the
"aggressive DCE" pass), with the added capability to track dead bits of integer
valued instructions and remove those instructions when all of the bits are
dead.
Currently, it does not actually do this all-bits-dead removal, but rather
replaces the instruction's uses with a constant zero, and lets instcombine (and
the later run of ADCE) do the rest. Because we essentially get a run of ADCE
"for free" while tracking the dead bits, we also do what ADCE does and removes
actually-dead instructions as well (this includes instructions newly trivially
dead because all bits were dead, but not all such instructions can be removed).
The motivation for this is a case like:
int __attribute__((const)) foo(int i);
int bar(int x) {
x |= (4 & foo(5));
x |= (8 & foo(3));
x |= (16 & foo(2));
x |= (32 & foo(1));
x |= (64 & foo(0));
x |= (128& foo(4));
return x >> 4;
}
As it turns out, if you order the bit-field insertions so that all of the dead
ones come last, then instcombine will remove them. However, if you pick some
other order (such as the one above), the fact that some of the calls to foo()
are useless is not locally obvious, and we don't remove them (without this
pass).
I did a quick compile-time overhead check using sqlite from the test suite
(Release+Asserts). BDCE took ~0.4% of the compilation time (making it about
twice as expensive as ADCE).
I've not looked at why yet, but we eliminate instructions due to having
all-dead bits in:
External/SPEC/CFP2006/447.dealII/447.dealII
External/SPEC/CINT2006/400.perlbench/400.perlbench
External/SPEC/CINT2006/403.gcc/403.gcc
MultiSource/Applications/ClamAV/clamscan
MultiSource/Benchmarks/7zip/7zip-benchmark
llvm-svn: 229462
2015-02-17 02:36:59 +01:00
|
|
|
target datalayout = "E-m:e-i64:64-n32:64"
|
|
|
|
target triple = "powerpc64-unknown-linux-gnu"
|
|
|
|
|
|
|
|
; Function Attrs: nounwind readnone
|
|
|
|
define signext i32 @bar(i32 signext %x) #0 {
|
|
|
|
entry:
|
|
|
|
%call = tail call signext i32 @foo(i32 signext 5) #0
|
|
|
|
%and = and i32 %call, 4
|
|
|
|
%or = or i32 %and, %x
|
|
|
|
%call1 = tail call signext i32 @foo(i32 signext 3) #0
|
|
|
|
%and2 = and i32 %call1, 8
|
|
|
|
%or3 = or i32 %or, %and2
|
|
|
|
%call4 = tail call signext i32 @foo(i32 signext 2) #0
|
|
|
|
%and5 = and i32 %call4, 16
|
|
|
|
%or6 = or i32 %or3, %and5
|
|
|
|
%call7 = tail call signext i32 @foo(i32 signext 1) #0
|
|
|
|
%and8 = and i32 %call7, 32
|
|
|
|
%or9 = or i32 %or6, %and8
|
|
|
|
%call10 = tail call signext i32 @foo(i32 signext 0) #0
|
|
|
|
%and11 = and i32 %call10, 64
|
|
|
|
%or12 = or i32 %or9, %and11
|
|
|
|
%call13 = tail call signext i32 @foo(i32 signext 4) #0
|
|
|
|
%and14 = and i32 %call13, 128
|
|
|
|
%or15 = or i32 %or12, %and14
|
|
|
|
%shr = ashr i32 %or15, 4
|
|
|
|
ret i32 %shr
|
|
|
|
|
|
|
|
; CHECK-LABEL: @bar
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 5)
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 3)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 2)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 1)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 0)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 4)
|
|
|
|
; CHECK: ret i32
|
|
|
|
|
|
|
|
; Check that instsimplify is not doing this all on its own.
|
|
|
|
; CHECK-IO-LABEL: @bar
|
|
|
|
; CHECK-IO: tail call signext i32 @foo(i32 signext 5)
|
|
|
|
; CHECK-IO: tail call signext i32 @foo(i32 signext 3)
|
|
|
|
; CHECK-IO: tail call signext i32 @foo(i32 signext 2)
|
|
|
|
; CHECK-IO: tail call signext i32 @foo(i32 signext 1)
|
|
|
|
; CHECK-IO: tail call signext i32 @foo(i32 signext 0)
|
|
|
|
; CHECK-IO: tail call signext i32 @foo(i32 signext 4)
|
|
|
|
; CHECK-IO: ret i32
|
|
|
|
}
|
|
|
|
|
|
|
|
; Function Attrs: nounwind readnone
|
|
|
|
declare signext i32 @foo(i32 signext) #0
|
|
|
|
|
|
|
|
; Function Attrs: nounwind readnone
|
|
|
|
define signext i32 @far(i32 signext %x) #1 {
|
|
|
|
entry:
|
|
|
|
%call = tail call signext i32 @goo(i32 signext 5) #1
|
|
|
|
%and = and i32 %call, 4
|
|
|
|
%or = or i32 %and, %x
|
|
|
|
%call1 = tail call signext i32 @goo(i32 signext 3) #1
|
|
|
|
%and2 = and i32 %call1, 8
|
|
|
|
%or3 = or i32 %or, %and2
|
|
|
|
%call4 = tail call signext i32 @goo(i32 signext 2) #1
|
|
|
|
%and5 = and i32 %call4, 16
|
|
|
|
%or6 = or i32 %or3, %and5
|
|
|
|
%call7 = tail call signext i32 @goo(i32 signext 1) #1
|
|
|
|
%and8 = and i32 %call7, 32
|
|
|
|
%or9 = or i32 %or6, %and8
|
|
|
|
%call10 = tail call signext i32 @goo(i32 signext 0) #1
|
|
|
|
%and11 = and i32 %call10, 64
|
|
|
|
%or12 = or i32 %or9, %and11
|
|
|
|
%call13 = tail call signext i32 @goo(i32 signext 4) #1
|
|
|
|
%and14 = and i32 %call13, 128
|
|
|
|
%or15 = or i32 %or12, %and14
|
|
|
|
%shr = ashr i32 %or15, 4
|
|
|
|
ret i32 %shr
|
|
|
|
|
|
|
|
; CHECK-LABEL: @far
|
|
|
|
; Calls to foo(5) and foo(3) are still there, but their results are not used.
|
|
|
|
; CHECK: tail call signext i32 @goo(i32 signext 5)
|
|
|
|
; CHECK-NEXT: tail call signext i32 @goo(i32 signext 3)
|
|
|
|
; CHECK-NEXT: tail call signext i32 @goo(i32 signext 2)
|
|
|
|
; CHECK: tail call signext i32 @goo(i32 signext 1)
|
|
|
|
; CHECK: tail call signext i32 @goo(i32 signext 0)
|
|
|
|
; CHECK: tail call signext i32 @goo(i32 signext 4)
|
|
|
|
; CHECK: ret i32
|
|
|
|
|
|
|
|
; Check that instsimplify is not doing this all on its own.
|
|
|
|
; CHECK-IO-LABEL: @far
|
|
|
|
; CHECK-IO: tail call signext i32 @goo(i32 signext 5)
|
|
|
|
; CHECK-IO: tail call signext i32 @goo(i32 signext 3)
|
|
|
|
; CHECK-IO: tail call signext i32 @goo(i32 signext 2)
|
|
|
|
; CHECK-IO: tail call signext i32 @goo(i32 signext 1)
|
|
|
|
; CHECK-IO: tail call signext i32 @goo(i32 signext 0)
|
|
|
|
; CHECK-IO: tail call signext i32 @goo(i32 signext 4)
|
|
|
|
; CHECK-IO: ret i32
|
|
|
|
}
|
|
|
|
|
|
|
|
declare signext i32 @goo(i32 signext) #1
|
|
|
|
|
|
|
|
; Function Attrs: nounwind readnone
|
|
|
|
define signext i32 @tar1(i32 signext %x) #0 {
|
|
|
|
entry:
|
|
|
|
%call = tail call signext i32 @foo(i32 signext 5) #0
|
|
|
|
%and = and i32 %call, 33554432
|
|
|
|
%or = or i32 %and, %x
|
|
|
|
%call1 = tail call signext i32 @foo(i32 signext 3) #0
|
|
|
|
%and2 = and i32 %call1, 67108864
|
|
|
|
%or3 = or i32 %or, %and2
|
|
|
|
%call4 = tail call signext i32 @foo(i32 signext 2) #0
|
|
|
|
%and5 = and i32 %call4, 16
|
|
|
|
%or6 = or i32 %or3, %and5
|
|
|
|
%call7 = tail call signext i32 @foo(i32 signext 1) #0
|
|
|
|
%and8 = and i32 %call7, 32
|
|
|
|
%or9 = or i32 %or6, %and8
|
|
|
|
%call10 = tail call signext i32 @foo(i32 signext 0) #0
|
|
|
|
%and11 = and i32 %call10, 64
|
|
|
|
%or12 = or i32 %or9, %and11
|
|
|
|
%call13 = tail call signext i32 @foo(i32 signext 4) #0
|
|
|
|
%and14 = and i32 %call13, 128
|
|
|
|
%or15 = or i32 %or12, %and14
|
|
|
|
%bs = tail call i32 @llvm.bswap.i32(i32 %or15) #0
|
|
|
|
%shr = ashr i32 %bs, 4
|
|
|
|
ret i32 %shr
|
|
|
|
|
|
|
|
; CHECK-LABEL: @tar1
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 5)
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 3)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 2)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 1)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 0)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 4)
|
|
|
|
; CHECK: ret i32
|
|
|
|
}
|
|
|
|
|
|
|
|
; Function Attrs: nounwind readnone
|
|
|
|
declare i32 @llvm.bswap.i32(i32) #0
|
|
|
|
|
2017-04-13 18:44:25 +02:00
|
|
|
; Function Attrs: nounwind readnone
|
|
|
|
define signext i32 @tim(i32 signext %x) #0 {
|
|
|
|
entry:
|
|
|
|
%call = tail call signext i32 @foo(i32 signext 5) #0
|
|
|
|
%and = and i32 %call, 536870912
|
|
|
|
%or = or i32 %and, %x
|
|
|
|
%call1 = tail call signext i32 @foo(i32 signext 3) #0
|
|
|
|
%and2 = and i32 %call1, 1073741824
|
|
|
|
%or3 = or i32 %or, %and2
|
|
|
|
%call4 = tail call signext i32 @foo(i32 signext 2) #0
|
|
|
|
%and5 = and i32 %call4, 16
|
|
|
|
%or6 = or i32 %or3, %and5
|
|
|
|
%call7 = tail call signext i32 @foo(i32 signext 1) #0
|
|
|
|
%and8 = and i32 %call7, 32
|
|
|
|
%or9 = or i32 %or6, %and8
|
|
|
|
%call10 = tail call signext i32 @foo(i32 signext 0) #0
|
|
|
|
%and11 = and i32 %call10, 64
|
|
|
|
%or12 = or i32 %or9, %and11
|
|
|
|
%call13 = tail call signext i32 @foo(i32 signext 4) #0
|
|
|
|
%and14 = and i32 %call13, 128
|
|
|
|
%or15 = or i32 %or12, %and14
|
|
|
|
%bs = tail call i32 @llvm.bitreverse.i32(i32 %or15) #0
|
|
|
|
%shr = ashr i32 %bs, 4
|
|
|
|
ret i32 %shr
|
|
|
|
|
|
|
|
; CHECK-LABEL: @tim
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 5)
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 3)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 2)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 1)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 0)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 4)
|
|
|
|
; CHECK: ret i32
|
|
|
|
}
|
|
|
|
|
|
|
|
; Function Attrs: nounwind readnone
|
|
|
|
declare i32 @llvm.bitreverse.i32(i32) #0
|
|
|
|
|
[BDCE] Add a bit-tracking DCE pass
BDCE is a bit-tracking dead code elimination pass. It is based on ADCE (the
"aggressive DCE" pass), with the added capability to track dead bits of integer
valued instructions and remove those instructions when all of the bits are
dead.
Currently, it does not actually do this all-bits-dead removal, but rather
replaces the instruction's uses with a constant zero, and lets instcombine (and
the later run of ADCE) do the rest. Because we essentially get a run of ADCE
"for free" while tracking the dead bits, we also do what ADCE does and removes
actually-dead instructions as well (this includes instructions newly trivially
dead because all bits were dead, but not all such instructions can be removed).
The motivation for this is a case like:
int __attribute__((const)) foo(int i);
int bar(int x) {
x |= (4 & foo(5));
x |= (8 & foo(3));
x |= (16 & foo(2));
x |= (32 & foo(1));
x |= (64 & foo(0));
x |= (128& foo(4));
return x >> 4;
}
As it turns out, if you order the bit-field insertions so that all of the dead
ones come last, then instcombine will remove them. However, if you pick some
other order (such as the one above), the fact that some of the calls to foo()
are useless is not locally obvious, and we don't remove them (without this
pass).
I did a quick compile-time overhead check using sqlite from the test suite
(Release+Asserts). BDCE took ~0.4% of the compilation time (making it about
twice as expensive as ADCE).
I've not looked at why yet, but we eliminate instructions due to having
all-dead bits in:
External/SPEC/CFP2006/447.dealII/447.dealII
External/SPEC/CINT2006/400.perlbench/400.perlbench
External/SPEC/CINT2006/403.gcc/403.gcc
MultiSource/Applications/ClamAV/clamscan
MultiSource/Benchmarks/7zip/7zip-benchmark
llvm-svn: 229462
2015-02-17 02:36:59 +01:00
|
|
|
; Function Attrs: nounwind readnone
|
|
|
|
define signext i32 @tar2(i32 signext %x) #0 {
|
|
|
|
entry:
|
|
|
|
%call = tail call signext i32 @foo(i32 signext 5) #0
|
|
|
|
%and = and i32 %call, 33554432
|
|
|
|
%or = or i32 %and, %x
|
|
|
|
%call1 = tail call signext i32 @foo(i32 signext 3) #0
|
|
|
|
%and2 = and i32 %call1, 67108864
|
|
|
|
%or3 = or i32 %or, %and2
|
|
|
|
%call4 = tail call signext i32 @foo(i32 signext 2) #0
|
|
|
|
%and5 = and i32 %call4, 16
|
|
|
|
%or6 = or i32 %or3, %and5
|
|
|
|
%call7 = tail call signext i32 @foo(i32 signext 1) #0
|
|
|
|
%and8 = and i32 %call7, 32
|
|
|
|
%or9 = or i32 %or6, %and8
|
|
|
|
%call10 = tail call signext i32 @foo(i32 signext 0) #0
|
|
|
|
%and11 = and i32 %call10, 64
|
|
|
|
%or12 = or i32 %or9, %and11
|
|
|
|
%call13 = tail call signext i32 @foo(i32 signext 4) #0
|
|
|
|
%and14 = and i32 %call13, 128
|
|
|
|
%or15 = or i32 %or12, %and14
|
|
|
|
%shl = shl i32 %or15, 10
|
|
|
|
ret i32 %shl
|
|
|
|
|
|
|
|
; CHECK-LABEL: @tar2
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 5)
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 3)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 2)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 1)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 0)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 4)
|
|
|
|
; CHECK: ret i32
|
|
|
|
}
|
|
|
|
|
|
|
|
; Function Attrs: nounwind readnone
|
|
|
|
define signext i32 @tar3(i32 signext %x) #0 {
|
|
|
|
entry:
|
|
|
|
%call = tail call signext i32 @foo(i32 signext 5) #0
|
|
|
|
%and = and i32 %call, 33554432
|
|
|
|
%or = or i32 %and, %x
|
|
|
|
%call1 = tail call signext i32 @foo(i32 signext 3) #0
|
|
|
|
%and2 = and i32 %call1, 67108864
|
|
|
|
%or3 = or i32 %or, %and2
|
|
|
|
%call4 = tail call signext i32 @foo(i32 signext 2) #0
|
|
|
|
%and5 = and i32 %call4, 16
|
|
|
|
%or6 = or i32 %or3, %and5
|
|
|
|
%call7 = tail call signext i32 @foo(i32 signext 1) #0
|
|
|
|
%and8 = and i32 %call7, 32
|
|
|
|
%or9 = or i32 %or6, %and8
|
|
|
|
%call10 = tail call signext i32 @foo(i32 signext 0) #0
|
|
|
|
%and11 = and i32 %call10, 64
|
|
|
|
%or12 = or i32 %or9, %and11
|
|
|
|
%call13 = tail call signext i32 @foo(i32 signext 4) #0
|
|
|
|
%and14 = and i32 %call13, 128
|
|
|
|
%or15 = or i32 %or12, %and14
|
|
|
|
%add = add i32 %or15, 5
|
|
|
|
%shl = shl i32 %add, 10
|
|
|
|
ret i32 %shl
|
|
|
|
|
|
|
|
; CHECK-LABEL: @tar3
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 5)
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 3)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 2)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 1)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 0)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 4)
|
|
|
|
; CHECK: ret i32
|
|
|
|
}
|
|
|
|
|
|
|
|
; Function Attrs: nounwind readnone
|
|
|
|
define signext i32 @tar4(i32 signext %x) #0 {
|
|
|
|
entry:
|
|
|
|
%call = tail call signext i32 @foo(i32 signext 5) #0
|
|
|
|
%and = and i32 %call, 33554432
|
|
|
|
%or = or i32 %and, %x
|
|
|
|
%call1 = tail call signext i32 @foo(i32 signext 3) #0
|
|
|
|
%and2 = and i32 %call1, 67108864
|
|
|
|
%or3 = or i32 %or, %and2
|
|
|
|
%call4 = tail call signext i32 @foo(i32 signext 2) #0
|
|
|
|
%and5 = and i32 %call4, 16
|
|
|
|
%or6 = or i32 %or3, %and5
|
|
|
|
%call7 = tail call signext i32 @foo(i32 signext 1) #0
|
|
|
|
%and8 = and i32 %call7, 32
|
|
|
|
%or9 = or i32 %or6, %and8
|
|
|
|
%call10 = tail call signext i32 @foo(i32 signext 0) #0
|
|
|
|
%and11 = and i32 %call10, 64
|
|
|
|
%or12 = or i32 %or9, %and11
|
|
|
|
%call13 = tail call signext i32 @foo(i32 signext 4) #0
|
|
|
|
%and14 = and i32 %call13, 128
|
|
|
|
%or15 = or i32 %or12, %and14
|
|
|
|
%sub = sub i32 %or15, 5
|
|
|
|
%shl = shl i32 %sub, 10
|
|
|
|
ret i32 %shl
|
|
|
|
|
|
|
|
; CHECK-LABEL: @tar4
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 5)
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 3)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 2)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 1)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 0)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 4)
|
|
|
|
; CHECK: ret i32
|
|
|
|
}
|
|
|
|
|
|
|
|
; Function Attrs: nounwind readnone
|
|
|
|
define signext i32 @tar5(i32 signext %x) #0 {
|
|
|
|
entry:
|
|
|
|
%call = tail call signext i32 @foo(i32 signext 5) #0
|
|
|
|
%and = and i32 %call, 33554432
|
|
|
|
%or = or i32 %and, %x
|
|
|
|
%call1 = tail call signext i32 @foo(i32 signext 3) #0
|
|
|
|
%and2 = and i32 %call1, 67108864
|
|
|
|
%or3 = or i32 %or, %and2
|
|
|
|
%call4 = tail call signext i32 @foo(i32 signext 2) #0
|
|
|
|
%and5 = and i32 %call4, 16
|
|
|
|
%or6 = or i32 %or3, %and5
|
|
|
|
%call7 = tail call signext i32 @foo(i32 signext 1) #0
|
|
|
|
%and8 = and i32 %call7, 32
|
|
|
|
%or9 = or i32 %or6, %and8
|
|
|
|
%call10 = tail call signext i32 @foo(i32 signext 0) #0
|
|
|
|
%and11 = and i32 %call10, 64
|
|
|
|
%or12 = or i32 %or9, %and11
|
|
|
|
%call13 = tail call signext i32 @foo(i32 signext 4) #0
|
|
|
|
%and14 = and i32 %call13, 128
|
|
|
|
%or15 = or i32 %or12, %and14
|
|
|
|
%xor = xor i32 %or15, 5
|
|
|
|
%shl = shl i32 %xor, 10
|
|
|
|
ret i32 %shl
|
|
|
|
|
|
|
|
; CHECK-LABEL: @tar5
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 5)
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 3)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 2)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 1)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 0)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 4)
|
|
|
|
; CHECK: ret i32
|
|
|
|
}
|
|
|
|
|
|
|
|
; Function Attrs: nounwind readnone
|
|
|
|
define signext i32 @tar7(i32 signext %x, i1 %b) #0 {
|
|
|
|
entry:
|
|
|
|
%call = tail call signext i32 @foo(i32 signext 5) #0
|
|
|
|
%and = and i32 %call, 33554432
|
|
|
|
%or = or i32 %and, %x
|
|
|
|
%call1 = tail call signext i32 @foo(i32 signext 3) #0
|
|
|
|
%and2 = and i32 %call1, 67108864
|
|
|
|
%or3 = or i32 %or, %and2
|
|
|
|
%call4 = tail call signext i32 @foo(i32 signext 2) #0
|
|
|
|
%and5 = and i32 %call4, 16
|
|
|
|
%or6 = or i32 %or3, %and5
|
|
|
|
%call7 = tail call signext i32 @foo(i32 signext 1) #0
|
|
|
|
%and8 = and i32 %call7, 32
|
|
|
|
%or9 = or i32 %or6, %and8
|
|
|
|
%call10 = tail call signext i32 @foo(i32 signext 0) #0
|
|
|
|
%and11 = and i32 %call10, 64
|
|
|
|
%or12 = or i32 %or9, %and11
|
|
|
|
%call13 = tail call signext i32 @foo(i32 signext 4) #0
|
|
|
|
%and14 = and i32 %call13, 128
|
|
|
|
%or15 = or i32 %or12, %and14
|
|
|
|
%v = select i1 %b, i32 %or15, i32 5
|
|
|
|
%shl = shl i32 %v, 10
|
|
|
|
ret i32 %shl
|
|
|
|
|
|
|
|
; CHECK-LABEL: @tar7
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 5)
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 3)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 2)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 1)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 0)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 4)
|
|
|
|
; CHECK: ret i32
|
|
|
|
}
|
|
|
|
|
|
|
|
; Function Attrs: nounwind readnone
|
|
|
|
define signext i16 @tar8(i32 signext %x) #0 {
|
|
|
|
entry:
|
|
|
|
%call = tail call signext i32 @foo(i32 signext 5) #0
|
|
|
|
%and = and i32 %call, 33554432
|
|
|
|
%or = or i32 %and, %x
|
|
|
|
%call1 = tail call signext i32 @foo(i32 signext 3) #0
|
|
|
|
%and2 = and i32 %call1, 67108864
|
|
|
|
%or3 = or i32 %or, %and2
|
|
|
|
%call4 = tail call signext i32 @foo(i32 signext 2) #0
|
|
|
|
%and5 = and i32 %call4, 16
|
|
|
|
%or6 = or i32 %or3, %and5
|
|
|
|
%call7 = tail call signext i32 @foo(i32 signext 1) #0
|
|
|
|
%and8 = and i32 %call7, 32
|
|
|
|
%or9 = or i32 %or6, %and8
|
|
|
|
%call10 = tail call signext i32 @foo(i32 signext 0) #0
|
|
|
|
%and11 = and i32 %call10, 64
|
|
|
|
%or12 = or i32 %or9, %and11
|
|
|
|
%call13 = tail call signext i32 @foo(i32 signext 4) #0
|
|
|
|
%and14 = and i32 %call13, 128
|
|
|
|
%or15 = or i32 %or12, %and14
|
|
|
|
%tr = trunc i32 %or15 to i16
|
|
|
|
ret i16 %tr
|
|
|
|
|
|
|
|
; CHECK-LABEL: @tar8
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 5)
|
|
|
|
; CHECK-NOT: tail call signext i32 @foo(i32 signext 3)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 2)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 1)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 0)
|
|
|
|
; CHECK: tail call signext i32 @foo(i32 signext 4)
|
|
|
|
; CHECK: ret i16
|
|
|
|
}
|
|
|
|
|
2018-02-21 02:55:33 +01:00
|
|
|
; DEBUGIFY-LABEL: @tar9
|
|
|
|
define signext i16 @tar9(i32 signext %x) #0 {
|
|
|
|
entry:
|
|
|
|
%call = tail call signext i32 @foo(i32 signext 5) #0
|
|
|
|
%and = and i32 %call, 33554432
|
|
|
|
; DEBUGIFY: call void @llvm.dbg.value(metadata i32 %call, metadata {{.*}}, metadata !DIExpression(DW_OP_constu, 33554432, DW_OP_and, DW_OP_stack_value))
|
|
|
|
%cast = trunc i32 %call to i16
|
|
|
|
ret i16 %cast
|
|
|
|
}
|
|
|
|
|
[BDCE] Add a bit-tracking DCE pass
BDCE is a bit-tracking dead code elimination pass. It is based on ADCE (the
"aggressive DCE" pass), with the added capability to track dead bits of integer
valued instructions and remove those instructions when all of the bits are
dead.
Currently, it does not actually do this all-bits-dead removal, but rather
replaces the instruction's uses with a constant zero, and lets instcombine (and
the later run of ADCE) do the rest. Because we essentially get a run of ADCE
"for free" while tracking the dead bits, we also do what ADCE does and removes
actually-dead instructions as well (this includes instructions newly trivially
dead because all bits were dead, but not all such instructions can be removed).
The motivation for this is a case like:
int __attribute__((const)) foo(int i);
int bar(int x) {
x |= (4 & foo(5));
x |= (8 & foo(3));
x |= (16 & foo(2));
x |= (32 & foo(1));
x |= (64 & foo(0));
x |= (128& foo(4));
return x >> 4;
}
As it turns out, if you order the bit-field insertions so that all of the dead
ones come last, then instcombine will remove them. However, if you pick some
other order (such as the one above), the fact that some of the calls to foo()
are useless is not locally obvious, and we don't remove them (without this
pass).
I did a quick compile-time overhead check using sqlite from the test suite
(Release+Asserts). BDCE took ~0.4% of the compilation time (making it about
twice as expensive as ADCE).
I've not looked at why yet, but we eliminate instructions due to having
all-dead bits in:
External/SPEC/CFP2006/447.dealII/447.dealII
External/SPEC/CINT2006/400.perlbench/400.perlbench
External/SPEC/CINT2006/403.gcc/403.gcc
MultiSource/Applications/ClamAV/clamscan
MultiSource/Benchmarks/7zip/7zip-benchmark
llvm-svn: 229462
2015-02-17 02:36:59 +01:00
|
|
|
attributes #0 = { nounwind readnone }
|
|
|
|
attributes #1 = { nounwind }
|
|
|
|
|