bool test1(unsigned long long x) { unsigned long long r = (x << 32) | (x >> 32); return r != 0; } bool test2(unsigned long long x) { unsigned long long r = (x << 32) | (x >> 32); return r == ~0ULL; } Trunk -O3: test1(unsigned long long): # @test1(unsigned long long) rol rdi, 32 test rdi, rdi setne al ret test2(unsigned long long): # @test2(unsigned long long) rol rdi, 32 cmp rdi, -1 sete al ret test3(unsigned long long): # @test3(unsigned long long) rol rdi, 32 test rdi, rdi setne al ret Current codegen: https://godbolt.org/z/q78xxhWe4 ---------------------------------------- define i1 @src(i64 %0) { %1: %2 = fshr i64 %0, i64 %0, i64 32 %3 = icmp ne i64 %2, 0 ret i1 %3 } => define i1 @tgt(i64 %0) { %1: %2 = icmp ne i64 %0, 0 ret i1 %2 } Transformation seems to be correct! ---------------------------------------- define i1 @src(i64 %0) { %1: %2 = fshr i64 %0, i64 %0, i64 32 %3 = icmp ne i64 %2, -1 ret i1 %3 } => define i1 @tgt(i64 %0) { %1: %2 = icmp ne i64 %0, -1 ret i1 %2 } Transformation seems to be correct! Alive: https://alive2.llvm.org/ce/z/kmrBvv
(In reply to David Bolvansky from comment #0) > https://alive2.llvm.org/ce/z/kmrBvv To generalize, the rotate amount can be anything if the result is checking if all bits are set/clear. So I think there are 8 cases to test: 1. Either fshl or fshr 2. Either eq or ne predicate 3. Either 0 or -1 icmp constant So something like this (and we can substitute fshr/fshl): https://alive2.llvm.org/ce/z/V-sEy9
Should be fixed with: https://reviews.llvm.org/rGfd807601a784