Skip to content

PowerPC altivec intrinsics are unsound due to subnormal flushing #129886

Open
@beetrees

Description

@beetrees

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-floating-pointArea: Floating point numbers and arithmeticC-bugCategory: This is a bug.I-miscompileIssue: Correct Rust code lowers to incorrect machine codeI-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessO-PowerPCTarget: PowerPC processorsP-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions