KhronosGroup / KhronosGroup/OpenCL-Docs

Floating point negation

Open
#1,266 1 comment 0 reactions 0 assignees View on GitHub
needs-cts-coverage
Dominant language
Python
Stars
420
Forks
131
Avg merge
5d 13h
Merged PRs (30d)
11

Description

Hi,

I have a question regarding the behavior of the unary negation operator -x for floating-point operands x.
Q: **May** the float unary operation be flushed to zero or not?

In the OpenCL30 spec, it’s specified: _“Denormalized single precision floating-point numbers passed as input or produced as the output of single precision floating-point operations such as add, sub, mul, divide, and the functions defined in math functions, common functions, and geometric functions may be flushed to zero”_.
The float unary negation operator isn't specified in any of the groups above.

Take for example the following two pieces of code:
Code 1:
```
float a = 1.4013e-44f; /* Denormal */
float b = 0.0f - a;
```

Code 2:
```
float a = 1.4013e-44f; /* Denormal */
float b = -a;
```
If I understand what’s written in the specification correctly, if ‘a’ is a denormal:
1. In Code 1, ‘b’ **may** be 0.0f as it’s a binary float subtract operation.
2. In Code 2, it's unclear if the result may be 0.0f or not.

I couldn’t find anywhere in the Spec an indication if the output of Code 2 **may** be zero or **must** be preserved.

If we compile the above 2 pieces of code to LLVM, we get that the operation in Code1 is mapped to an “fsub” operation, and the operation in Code2 is mapped to an “fneg” operation.
The following OpenCL code:
```
float Code1(float a) {
return 0.0f - a;
}
float Code2(float a) {
return -a;
}
```
is compiled to:
```
define dso_local noundef float @Code1(float noundef %0) local_unnamed_addr #0 {
%2 = fsub float 0.000000e+00, %0
ret float %2
}

define dso_local noundef float @Code2(float noundef %0) local_unnamed_addr #0 {
%2 = fneg float %0
ret float %2
}
```
According to the LLVM spec, fneg is considered a bit manipulation operation, therefore, it’s not allowed to flush inputs to zero. Quoting the LLVM spec:
_“For the purpose of this section, bitcast as well as the following operations are not “floating-point math operations”: fneg , llvm.fabs , and llvm.copysign . These operations act directly on the underlying bit representation and never change anything except possibly for the sign bit”_.

All the above make me believe that the value of ‘b’ in Code2 **must** be preserved.

Am I correct?

Contributor guide

Open the contributing guide

Research direction

Start with the OpenCL30 specification language quoted in the issue and compare it with the LLVM floating-point rules for fneg and fsub, using the Code1 and Code2 examples as cases. Done means resolving whether unary negation may flush denormals and recording that interpretation in the relevant OpenCL documentation section; no source file or test path is named.

Written by the indexing model from the issue text.

Assessment

Domain
documentation
Issue type
Documentation
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.