Closed
Description
Consider this code:
pub fn other(a: i32, b: i32) -> bool {
let c1 = (a >= 0) & (a <= 10);
let c2 = (b >= 0) & (b <= 20);
if c1 & c2 {
a + 100 != b
} else {
true
}
}
This compiles to just:
example::other:
mov al, 1
ret
(Godbolt)
However, changing any of the &
to &&
breaks this optimization and a bunch of cmps are generated as well as the addition, which seems unnecessary in this case, because &
/&&
shouldn't make any difference as short circuit can't be observed.
example::other:
mov al, 1
cmp edi, 10
ja .LBB0_3
cmp esi, 20
ja .LBB0_3
add edi, 100
cmp edi, esi
setne al
.LBB0_3:
ret
(Godbolt)
This works fine with Clang
Doesn't seem like an LLVM issue (to me?). The LLVM IR that Rust emits The resulting LLVM IR:
define zeroext i1 @test(i32 %a, i32 %b) unnamed_addr #0 {
start:
%0 = icmp ult i32 %a, 11
%1 = icmp ult i32 %b, 21
%_13.0 = select i1 %0, i1 %1, i1 false
br i1 %_13.0, label %bb4, label %bb6
bb4: ; preds = %start
%_16 = add nuw nsw i32 %a, 100
%2 = icmp ne i32 %_16, %b
br label %bb6
bb6: ; preds = %start, %bb4
%.0 = phi i1 [ %2, %bb4 ], [ true, %start ]
ret i1 %.0
}
correctly gets optimized to this with opt -O3 in -S -o out
define zeroext i1 @test(i32 %a, i32 %b) unnamed_addr #0 {
start:
ret i1 true
}
(Godbolt)
Metadata
Metadata
Assignees
Labels
Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generationCategory: This is a bug.Call for participation: An issue has been fixed and does not reproduce, but no test has been added.Issue: Problems and improvements with respect to performance of generated code.Relevant to the compiler team, which will review and decide on the PR/issue.