llvm / llvm/llvm-project

[CIR] f80 long double parsing corruption when beyond f64 range in cir-opt

Open
#216,422 0 comments 0 reactions 0 assignees View on GitHub
ClangIR
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

On target cir.triple = "x86_64-unknown-linux-gnu":

Take this program:

```c
long double f(void) { return 1e309L; }
```

Compile this through CIR without cir-opt:

```sh
~/llvm-project/build-cir/bin/clang -fclangir -emit-cir -std=gnu23 -Xclang -disable-llvm-passes -o - repro.c
```

You get the right answer:

```mlir
%1 = cir.const #cir.fp<9.99999999999999999986E+308> : !cir.long_double loc(#loc3)
```

However, this gets corrupted to +inf through cir-opt:

```sh
~/llvm-project/build-cir/bin/clang -fclangir -emit-cir -std=gnu23 -Xclang -disable-llvm-passes -S -o - repro.c | ~/llvm-project/build-cir/bin/cir-opt --verify-each=false
```

```mlir
%1 = cir.const #cir.fp<0x7FFF8000000000000000> : !cir.long_double
```

I assume there's some casting to f64 in APFloat that's done and then when turning back to f80, it's being turned into infinity cause this value fits in f80 but not in f64.

Contributor guide

Open the contributing guide

Research direction

Reproduce the issue with the provided clang and cir-opt commands using the long double repro, then compare the finite f80 value before and after cir-opt. Start at the CIR floating-point constant handling and the suspected APFloat conversion path mentioned in the report. Done means cir-opt preserves the finite 1e309L value as an f80 constant rather than converting it to +inf.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.