PowerPC `altivec` intrinsics are unsound due to subnormal flushing
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
I tried this code, compiled on a PowerPC target with -O -Ctarget-feature=+altivec (-O -Ctarget-feature=-vsx is required instead if the chosen PowerPC target uses a default target CPU of pwr7 or later):
#![feature(stdarch_powerpc, powerpc_target_feature)]
#[cfg(target_arch = "powerpc64")]
use std::arch::powerpc64::{vector_float, vec_add};
#[cfg(target_arch = "powerpc")]
use std::arch::powerpc::{vector_float, vec_add};
use std::mem::transmute;
#[inline(never)]
fn print_vals(x: vector_float, i: usize, vals_i: u32) {
println!("x={x:?} i={i} vals[i]={vals_i}");
}
const ZERO: vector_float = unsafe { transmute([0, 0, 0, 0]) };
const INC: vector_float = unsafe { transmute([f32::MIN_POSITIVE / 128.0, f32::MIN_POSITIVE / 128.0, f32::MIN_POSITIVE / 128.0, f32::MIN_POSITIVE / 128.0]) };
const TARGET: u128 = unsafe { transmute([f32::MIN_POSITIVE, f32::MIN_POSITIVE, f32::MIN_POSITIVE, f32::MIN_POSITIVE]) };
#[inline(never)]
#[target_feature(enable = "altivec")]
pub unsafe fn evil(vals: &[u32; 300]) {
let mut x: vector_float = ZERO;
let mut i: usize = 0;
while unsafe { transmute::<vector_float, u128>(x) } != TARGET {
print_vals(x, i, vals[i]);
x = unsafe { vec_add(x, INC) };
x = unsafe { vec_add(x, INC) };
i += 2;
}
dbg!(unsafe { transmute::<vector_float, u128>(x) });
}
pub fn main() {
let mut vals: [u32; 300] = [0; 300];
for i in 0..300 { vals[i as usize] = i; }
unsafe { evil(&vals) };
}
#[cfg(not(target_feature = "altivec"))]
compile_error!("-Ctarget-feature=+altivec required");
#[cfg(target_feature = "vsx")]
compile_error!("-Ctarget-feature=-vsx required");
I expected to see this happen: The program does not segfault.
Instead, this happened: The program segfaults as LLVM optimisations presume that subnormals are not flushed to zero, whereas the altivec instructions flush subnormals to zero. This only occurs when the vsx feature is not enabled; the vsx instructions do not flush subnormals and therefore do not have this issue.
This is the PowerPC equivalent of #129880.
Meta
rustc --version --verbose:
rustc 1.82.0-nightly (a7399ba69 2024-08-31)
binary: rustc
commit-hash: a7399ba69d37b019677a9c47fe89ceb8dd82db2d
commit-date: 2024-08-31
host: x86_64-unknown-linux-gnu
release: 1.82.0-nightly
LLVM version: 19.1.0
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the supplied PowerPC program with +altivec and -vsx, then trace the vec_add intrinsic and PowerPC altivec target-feature handling. Compare the behavior with the referenced issue #129880; done means the reproducer no longer segfaults and coverage verifies correct handling of subnormal values.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100