[FunctionAttrs] addNoUndefAttrs infers noundef on return without accounting for nofpclass poison
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
**Fuzzer Generated Test**
**Reproducer**
https://alive2.llvm.org/ce/z/LsEUem
**Description**
FunctionAttrs' `addNoUndefAttrs` adds `noundef` to a function's return value by proving all return paths produce non-poison values (all inputs are `noundef`, all operations propagate non-poison). However, it does not account for the fact that a `nofpclass(...)` attribute on the return can introduce poison.
**Steps to reproduce**
- Minimized test case, `input.ll`
```llvm
declare nofpclass(nan inf zero psub norm) half @returns_nsub()
define nofpclass(nsub) half @ret_nonsub__fadd_self__nonsub(i1 noundef %cond, half noundef %unknown) {
%nsub = call noundef half @returns_nsub()
%select = select i1 %cond, half %nsub, half %unknown
%add = fadd half %select, %select
ret half %add
}
```
**Output**
```llvm
----------------------------------------
declare half @returns_nsub() nofpclass(1007)
define half @ret_nonsub__fadd_self__nonsub(i1 noundef %cond, half noundef %unknown) nofpclass(16) {
#0:
%nsub = call half @returns_nsub() noundef nofpclass(1007)
%select = select i1 noundef %cond, half %nsub, half noundef %unknown
%add = fadd half %select, %select
ret half %add
}
=>
declare half @returns_nsub() nofpclass(1007)
define half @ret_nonsub__fadd_self__nonsub(i1 noundef %cond, half noundef %unknown) noundef nofpclass(16) {
#0:
%nsub = call half @returns_nsub() noundef nofpclass(1007)
%select = select i1 noundef %cond, half %nsub, half noundef %unknown
%add = fadd half %select, %select
ret half %add
}
Transformation doesn't verify!
ERROR: Source is more defined than target
Example:
i1 noundef %cond = #x0 (0)
half noundef %unknown = #x8040 (-0.000003814697?)
Source:
half %nsub = #x8004 (-0.000000238418?)
half %select = #x8040 (-0.000003814697?)
half %add = #x8080 (-0.000007629394?)
SOURCE MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 > size: 0 align: 1 alloc type: 0 alive: false address: #x0
Block 1 > size: 0 align: 1 alloc type: 0 alive: true address: #x4
Target:
half %nsub = #x8004 (-0.000000238418?)
half %select = #x8040 (-0.000003814697?)
half %add = #x8080 (-0.000007629394?)
half return = UB triggered!
TARGET MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 > size: 0 align: 1 alloc type: 0 alive: false address: #x0
Block 1 > size: 0 align: 1 alloc type: 0 alive: true address: #x4
Summary:
0 correct transformations
1 incorrect transformations
0 failed-to-prove transformations
0 Alive2 errors
```
Contributor guide
Assessment
This issue has not been assessed yet.