llvm / llvm/llvm-project

[NVPTX] Mixed denormal_fpenv input/output modes mishandled; no llvm.canonicalize lowering

Open
#222,484 1 comment 0 reactions 0 assignees View on GitHub
backend:NVPTX floating-point
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

AI-assisted report, but only for the examples, I found the issue.

https://godbolt.org/z/dTdq1dddd

`NVPTXTargetLowering::useF32FTZ()` picks `.ftz` from the **output** denormal mode alone, and treats
output-`preservesign` as an obligation. But `.ftz` flushes inputs *and* result, and LangRef says
output flushing is *permitted, never mandated*, while **input** flushing *is* mandated. So both
mixed modes are wrong. Reachable only via the IR attribute — `-denormal-fp-math[-f32]=` is a single
`DenormalModeKind`, so a command line always sets `Input == Output`.

```llvm
declare float @llvm.canonicalize.f32(float)
define float @a(float %x, float %y) #0 { %r = fadd float %x, %y ret float %r }
define float @b(float %x, float %y) #1 { %r = fadd float %x, %y ret float %r }
define float @c(float %x) #1 { %r = call float @llvm.canonicalize.f32(float %x) ret float %r }
attributes #0 = { denormal_fpenv(float: preservesign|ieee) }
attributes #1 = { denormal_fpenv(float: ieee|preservesign) }
```
`llc -march=nvptx64 -mcpu=sm_90 -mattr=+ptx78`

| fn | mode (Out\|In) | got | want |
|---|---|---|---|
| `a` | `preservesign\|ieee` | `add.rn.ftz.f32` | `add.rn.f32` — IEEE inputs must not be flushed; the output permission need not be taken |
| `b` | `ieee\|preservesign` | `add.rn.f32` | canonicalize `%x`,`%y` then `add.rn.f32` — the input flush is mandated |
| `c` | `ieee\|preservesign` | `mul.rn.f32 %r2, %r1, 0f3F800000` | `mul.rn.ftz.f32` — NVPTX has **no `ISD::FCANONICALIZE` lowering**, so LangRef's own remedy falls to the generic mul-by-1.0, which also picks `.ftz` via `useF32FTZ()` and is a no-op |

`.ftz` legally implements only `preservesign|preservesign`; a non-flushing op is legal whenever the
input mode is `ieee`. Fix is to compare the whole `DenormalMode` (as AMDGPU's
`atomicIgnoresDenormalModeOrFPModeIsFTZ` does) and add NVPTX `FCANONICALIZE` lowering keyed on the
*input* mode. `useF32FTZ()` also feeds `doF32FTZ`/`FTZFlag`, so this reaches `mul`/`div`/`setp`/`cvt`
and f16; and `atomicrmw fadd`, whose CAS fallback is an ordinary `fadd`. LLVM 24.0.0git.

Contributor guide

Open the contributing guide

Research direction

Start at NVPTXTargetLowering::useF32FTZ() and trace its doF32FTZ/FTZFlag callers, including mul, div, setp, cvt, f16, and atomicrmw fadd. Add the missing NVPTX FCANONICALIZE lowering based on the input denormal mode, then run the issue's llc command and verify the a, b, and c examples produce the expected instructions.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.