Skip to content

fmaxnm/fminnm convert SNAN to QNAN on aarch64 #176624

@youknowone

Description

@youknowone

I will try my best to describe what's this issue.

I only could reproduce this problem with Rust.
The original report to rust project: rust-lang/rust#151286

I tested it with llvm-project:main and found same issue remains.

I wrote a patch fix this problem #176625


This is what I am guessing.

On AArch64 in release builds, this code returns wrong result (only in complex code):

let snan: f64 = f64::from_bits(0x7FF0_0000_0000_0001);
let max = if snan > 0.0 { snan } else { 0.0 };
// Expected: 0.0 (because fcmp ogt returns false for SNAN)
// Got: QNAN 0x7FF8000000000001

Only happens at opt-level >= 1. Debug builds work fine.

LLVM generates this IR: https://godbolt.org/z/dnjYPrsKa

%cmp = fcmp ogt double %snan, 0.0
%max = select i1 %cmp, double %snan, double 0.0

DAGCombiner combines it to:

%max = fmaxnum double %snan, 0.0

AArch64 backend selects:

fmaxnm d0, d1, d2

The fmaxnm instruction converts SNAN to QNAN. But fcmp ogt returns false for SNAN, so the original code should return 0.0.

Metadata

Metadata

Assignees

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions