This is an archive of the discontinued LLVM Phabricator instance.

[ConstantFolding] Disable constant folding for bitcasts to x86_fp80
Needs ReviewPublic

Authored by craig.topper on Dec 11 2019, 12:07 PM.

Details

Summary

80-bit floating point does not have an implicit hidden bit like single and double precision. If this bit is not set we can end up with various weird encodings like pseudo-denormals, pseudo-infinities, and unnormals. The APFloat conversion from APInt turns all of these things into a NAN and loses the original exponent from incoming bit representation. This means if the APFloat gets turned back into an APInt it might not be exactly the original value.

This patch disables the constant folding to avoid hitting this condition. We could maybe be smarter and look at the value we're going to convert and make sure its safe, but that would likely require a new APFloat interface to find that out.

Fixes PR44188. I can put together a test case based on that PR, but wanted to get an opinion on whether this patch was the right thing to do.

Diff Detail

Event Timeline

craig.topper created this revision.Dec 11 2019, 12:07 PM
Herald added a project: Restricted Project. · View Herald TranscriptDec 11 2019, 12:07 PM
Herald added a subscriber: hiraditya. · View Herald Transcript

Is this really the only place where we fold fp80 bitcasts? I guess it might be.

Would it make sense to allow encoding these non-canonical values into an APFloat? (Still treating it as a NaN, but keeping around enough information to reconstitute it if bitcastToAPInt is called.) If we don't think that's worthwhile, this seems like the right approach.

We could maybe be smarter and look at the value we're going to convert and make sure its safe

I'm a little concerned this might show up in more cases than you expect, where we end up with a bitcast in code that isn't explicitly reintepreting floats. For example, in code using C unions.

I was looking into trying to see if we could store this in APFloat. And I just noticed that we mark pseudonan, pseudoinfinity, and unnformals all as fcnan, and copy their original significand from the apint. I believe since the integer bit was 0, this makes apfloat encode them as a pseudonan. Then I think arithmetic operations with one of these as an operand will propagate the pseudonan. Should we have forced the integer bit of the significand when we created it to make it a true nan?

To match x87 semantics, arithmetic on a pseudonan should trigger an exception and produce a quiet NaN. This is similar to an SNaN. (Not sure if we currently handle SNaNs correctly, though.)