llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.59k stars 11.82k forks source link

Redundant computations should be optimized out #43002

Open zamazan4ik opened 5 years ago

zamazan4ik commented 5 years ago
Bugzilla Link 43657
Version trunk
OS Linux
CC @davidbolvansky,@dwblaikie,@LebedevRI,@RKSimon,@zygoloid,@rotateright

Extended Description

For the following code:

include

int foo(std::vector a, std::vector b) { int res = 0;

if(a.size() == b.size())
{
    res = a.size() - b.size();
}

return res;

}

clang(trunk) with -O3 generates:

foo(std::vector<int, std::allocator >, std::vector<int, std::allocator >): # @​foo(std::vector<int, std::allocator >, std::vector<int, std::allocator >) mov rcx, qword ptr [rdi + 8] sub rcx, qword ptr [rdi] sar rcx, 2 mov rdx, qword ptr [rsi + 8] sub rdx, qword ptr [rsi] sar rdx, 2 mov esi, ecx sub esi, edx xor eax, eax cmp rcx, rdx cmove eax, esi ret

gcc(trunk) with -O3 generates:

foo(std::vector<int, std::allocator >, std::vector<int, std::allocator >): xor eax, eax ret

Godbolt link: https://godbolt.org/z/s1cwUt

rotateright commented 5 years ago

I'm not sure what happens before we get here, but the IR at the end says that we are missing a select-equality fold that can look through a cast: https://rise4fun.com/Alive/7mdH

define i32 @​#43657 (i64 %x, i64 %y) { %t17 = icmp eq i64 %x, %y %t18 = sub nsw i64 %x, %y %t19 = trunc i64 %t18 to i32 %r = select i1 %t17, i32 %t19, i32 0 ret i32 %r }

davidbolvansky commented 5 years ago

Another missed opportunity caused by size_t -> int "shift tricks". Should InstCombine really do it? Is it really profitable?

If you use:

size_t foo(std::vector a, std::vector b) { size_t res = 0;

if(a.size() == b.size())
{
    res = a.size() - b.size();
}

return res;

}

foo(std::vector<int, std::allocator >, std::vector<int, std::allocator >): # @​foo(std::vector<int, std::allocator >, std::vector<int, std::allocator >) xor eax, eax ret