Skip to content

Add SIMD algebraic intrinsics - #164952

Open
calebzulawski wants to merge 10 commits into
rust-lang:mainfrom
calebzulawski:feature/algebraic-simd
Open

calebzulawski wants to merge 10 commits into
rust-lang:mainfrom
calebzulawski:feature/algebraic-simd

Conversation

@calebzulawski

@calebzulawski calebzulawski commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

View all comments

Added algebraic intrinsics for SIMD. First half of rust-lang/portable-simd#539

@rustbot

rustbot commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

Some changes occurred to the platform-builtins intrinsics. Make sure the
LLVM backend as well as portable-simd gets adapted for the changes.

cc @antoyo, @GuillaumeGomez, @bjorn3, @programmerjake

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

@rustbot rustbot added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Oct 26, 2026
@rustbot

rustbot commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator

r? @davidtwco

rustbot has assigned @davidtwco.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 77 candidates
  • Random selection from 21 candidates

@calebzulawski
calebzulawski force-pushed the feature/algebraic-simd branch from e92596e to 9d8b178 Compare October 26, 2026 03:30
sym::simd_reduce_add_algebraic | sym::simd_reduce_mul_algebraic
);
let mut res = init;
for i in 0..op_len {

@programmerjake programmerjake Oct 26, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the unordered ops should probably also pick a random order to reduce in, but imo that doesn't need to be part of this PR.

View changes since the review

@RalfJung RalfJung Oct 26, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In const-eval the order must be deterministic so we can't randomize.

However, Miri needs to randomize them. With this PR Miri will start running them, without proper randomization. That's a bug introduced by this PR. So I disagree, if we have Miri support here then it must be correct.

Comment on lines +231 to +235
sym::simd_add_algebraic => Op::MirOp(BinOp::Add),
sym::simd_sub_algebraic => Op::MirOp(BinOp::Sub),
sym::simd_mul_algebraic => Op::MirOp(BinOp::Mul),
sym::simd_div_algebraic => Op::MirOp(BinOp::Div),
sym::simd_rem_algebraic => Op::MirOp(BinOp::Rem),

@RalfJung RalfJung Oct 26, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems cleaner to represent this as a MirOpFloatAlgebraic or so to avoid having to match twice.

View changes since the review

Comment on lines +269 to +271
if val.layout.ty.is_floating_point() && nondet {
val = M::apply_float_nondet(self, val)?;
}

@RalfJung RalfJung Oct 26, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To ensure that this really makes things non-deterministic, please add a test like this in the tests/pass/intrinsics/portable-simd.rs file.

View changes since the review

Comment thread library/core/src/intrinsics/simd/mod.rs Resolved
@rustbot

rustbot commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator

miri is developed in its own repository. If the Miri part of this change can be broken out, consider making this change to rust-lang/miri instead. However, if Miri needs adjusting for rustc changes, just ignore this message.

cc @rust-lang/miri

@rustbot

rustbot commented Oct 27, 2026

Copy link
Copy Markdown
Collaborator

rustc_codegen_gcc is developed in its own repository. If possible, consider making this change to rust-lang/rustc_codegen_gcc instead.

cc @antoyo, @GuillaumeGomez

rustc_codegen_cranelift is developed in its own repository. If possible, consider making this change to rust-lang/rustc_codegen_cranelift instead.

cc @bjorn3

@calebzulawski
calebzulawski force-pushed the feature/algebraic-simd branch from 3125bca to 6796d73 Compare October 27, 2026 00:36
};

let mut res = init;
for i in M::nondet_index_iterator(self, op_len) {

@programmerjake programmerjake Oct 27, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add a comment noting that this doesn't fully randomize the reduce order, since it only randomizes the order of the inputs then does an ordered reduce -- that will never give you an evaluation order like (a + b) + (c + d).

View changes since the review

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

an example implementation that does cover all possible evaluation orders: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=c2f778ccd6b16d881b5afac8200ffaf7

pub fn random_reduce<T>(mut inputs: Vec<T>, mut reduce: impl FnMut(T, T) -> T) -> Option<T> {
    while inputs.len() >= 2 {
        let lhs_index = rand::random_range(0..inputs.len());
        let lhs = inputs.swap_remove(lhs_index);
        let rhs_index = rand::random_range(0..inputs.len());
        let rhs = inputs.swap_remove(rhs_index);
        inputs.push(reduce(lhs, rhs));
    }
    inputs.pop()
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious if this is actually necessary, miri's float nondeterminism doesn't generate every possible distribution of nondeterminism

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe not, but in the case of catastrophic cancellation, you can get wildly different results for the different evaluation orders so imo it would be useful for miri to be able to give you those.

@rust-log-analyzer

This comment has been minimized.

@calebzulawski
calebzulawski force-pushed the feature/algebraic-simd branch from 4db7858 to 3067057 Compare October 31, 2026 02:23
@rust-log-analyzer

This comment has been minimized.

@calebzulawski
calebzulawski force-pushed the feature/algebraic-simd branch from 3067057 to 95f5629 Compare October 31, 2026 03:54
@rustbot

rustbot commented Oct 31, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@calebzulawski

Copy link
Copy Markdown
Member Author

I think #164924 introduced a minor break to cg_gcc vector frem, I repaired that here

#[inline(always)]
fn nondet_index_iterator(ecx: &mut InterpCx<'tcx, Self>, len: u64) -> impl Iterator<Item = u64> + use<'tcx> {
let mut indices = (0..len).collect::<Vec<u64>>();
if ecx.machine.float_nondet {

@RalfJung RalfJung Oct 31, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the implementation is float-specific, let's call this unordered_float_reduction_iter or something like that.

View changes since the review


let (op, op_len) = self.project_to_simd(&args[0])?;

let scalar = |f: Double| {

@RalfJung RalfJung Oct 31, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are creating the initial value via casts anyway, might as well use int_to_int_or_float and cast from an integer, that should be a bit simpler.

View changes since the review

for i in M::nondet_index_iterator(self, op_len) {
let op = self.read_immediate(&self.project_index(&op, i)?)?;
res = self.binary_op(mir_op, &res, &op)?;
if dest.layout.ty.is_floating_point() {

@RalfJung RalfJung Oct 31, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should only be called on float types anyway, right?

View changes since the review


let (op, op_len) = self.project_to_simd(&args[0])?;

let scalar = |f: Double| {

@RalfJung RalfJung Oct 31, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let scalar = |f: Double| {
// Compute starting value and reduction MIR op.
let from_int = |i: i32| {

View changes since the review

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants