[NVPTX] Mixed denormal_fpenv input/output modes mishandled; no llvm.canonicalize lowering
- 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
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