Skip to content

Commit 733d149

Browse files
authored
cmov: explicitly bind XOR output in portable CmovEq (#1337)
The `bitnz!` macro references its input value twice, so this more explicitly binds it to a local variable first. It's probably nothing LLVM's optimizer can't figure out, but this is more explicit.
1 parent 3008a4f commit 733d149

1 file changed

Lines changed: 13 additions & 9 deletions

File tree

cmov/src/portable.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
//! Portable "best effort" implementation of `Cmov`.
22
//!
3-
//! This implementation is based on portable bitwise arithmetic but cannot
4-
//! guarantee that the resulting generated assembly is free of branch
5-
//! instructions.
6-
7-
// TODO(tarcieri): more optimized implementation for small integers
3+
//! This implementation is based on portable bitwise arithmetic but cannot guarantee that the
4+
//! resulting generated assembly is free of branch instructions.
5+
//!
6+
//! For select platforms we use `asm!` for mask generation which should largely mitigate the
7+
//! optimizer potentially inserting branches.
88
99
use crate::{Cmov, CmovEq, Condition};
1010

@@ -60,13 +60,15 @@ impl Cmov for u32 {
6060
impl CmovEq for u32 {
6161
#[inline]
6262
fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) {
63-
let ne = bitnz!(self ^ rhs, u32::BITS) as u8;
63+
let xor = self ^ rhs;
64+
let ne = bitnz!(xor, u32::BITS) as u8;
6465
output.cmovnz(&input, ne);
6566
}
6667

6768
#[inline]
6869
fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) {
69-
let ne = bitnz!(self ^ rhs, u32::BITS) as u8;
70+
let xor = self ^ rhs;
71+
let ne = bitnz!(xor, u32::BITS) as u8;
7072
output.cmovnz(&input, ne ^ 1);
7173
}
7274
}
@@ -88,13 +90,15 @@ impl Cmov for u64 {
8890
impl CmovEq for u64 {
8991
#[inline]
9092
fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) {
91-
let ne = bitnz!(self ^ rhs, u64::BITS) as u8;
93+
let xor = self ^ rhs;
94+
let ne = bitnz!(xor, u64::BITS) as u8;
9295
output.cmovnz(&input, ne);
9396
}
9497

9598
#[inline]
9699
fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) {
97-
let ne = bitnz!(self ^ rhs, u64::BITS) as u8;
100+
let xor = self ^ rhs;
101+
let ne = bitnz!(xor, u64::BITS) as u8;
98102
output.cmovnz(&input, ne ^ 1);
99103
}
100104
}

0 commit comments

Comments
 (0)