floating point to floating point casts have undefined behaviour #15536

Open
huonw opened this Issue Jul 8, 2014 · 14 comments

Comments

Projects
None yet
Owner

huonw commented Jul 8, 2014

If the value cannot fit within the destination type, ty2, then the results are undefined.

http://llvm.org/docs/LangRef.html#fptrunc-to-instruction

e.g. 1e300f64 as f32

cc #10184, #10185

Owner

huonw commented Jul 8, 2014

Nominating

Contributor

pcwalton commented Jul 8, 2014

I think this is not a 1.0 issue. There is no reasonable backwards incompatible language change we can make here to fix it. The only thing to do is to change the LLVM semantics here to not be UB, but rather be an undefined value.

zwarich commented Jul 10, 2014

@pcwalton the LLVM semantics here are that the result is an undefined value, not that the instruction exhibits undefined behavior. Otherwise you wouldn't be able to hoist an fptrunc out of a loop.

Contributor

pcwalton commented Jul 10, 2014

OK, then I believe this is not a bug, just something to remember to note in the spec.

Member

pnkfelix commented Jul 10, 2014

Assigning P-high, not 1.0 milestone, by the same reasoning as #10184 and #10185.

@pnkfelix pnkfelix added P-high and removed I-nominated labels Jul 10, 2014

Contributor

thestinger commented Jul 10, 2014

@zwarich: Rust allows undefined behaviour if you have an undefined value. An undefined value has no live range so it doesn't correspond to a reserved register with a preserved value and can vary between reads. That means something like xs[undef] can do an out-of-bounds index, because there's nothing forcing it to have the same value between the check and the read.

zwarich commented Jul 20, 2014

@thestinger That's a good point, but that just makes it like the other bugs that aren't in 1.0.

Contributor

thestinger commented Jul 20, 2014

Programs can be written depending on the value of undefined behaviour, and changing it to either fail or provide a specific result will break those programs. This isn't C where undefined behaviour is a problem in user code.

Contributor

bombless commented Apr 29, 2015

We may need a UB label for such issues IMO

@arielb1 arielb1 added A-LLVM A-codegen P-high and removed P-medium labels Jun 15, 2015

Contributor

ranma42 commented Jan 26, 2016

Can anybody reproduce this undefined behaviour? In

#![crate_type="rlib"]

const f:f64 = 1.0E+300;

pub static ffull:f64 = f;
pub static ftrunc:f32 = f as f32;
pub static f2i:u64 = f as u64;
pub static i2f:f32 = 0xFFFFFFFFFFFFFFFFu64 as f32;

ftrunc is rounded to +inf, while (based on this issue and LLVM documentation) I would have expected an undef. In the actual LLVM code fptrunc seems to be more well-behaved than what is stated in the docs (apparently it tries to respect the IEEE754 standard, with some minor quirks around NaNs).

I asked for additional information on llvm-dev

Contributor

nodakai commented Jan 31, 2016

@ranma42 From what I understood from the reference, the LLVM undef can turn into any value depending on each context. So we cannot complain if it happened to turn into 0x7FF0000000000000. I think the reasoning here is the same with select undef, %X, %Y can be optimized into either of %X or %Y (but not undef.)

@nrc nrc added P-medium and removed P-high labels Mar 31, 2016

Member

pnkfelix commented Mar 31, 2016

(moving this back to P-medium and letting the I-wrong reflect the severity; the conclusion of the lang team was that there are lots of open bugs that reflect wrong behavior, and we are not going to prioritize this one as P-high.)

Contributor

DemiMarie commented Jun 26, 2016

My thought is to define this as resulting as infinity.

Member

retep998 commented Jun 27, 2016

@drbo But doing that could be potentially more expensive than just making the result unspecified but without causing undefined behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment