From e5a65fe9ac50e8124d842fd8ed1564ef0dd57554 Mon Sep 17 00:00:00 2001 From: Gary Liu Date: Thu, 25 Aug 2016 15:47:10 -0400 Subject: [PATCH] [SystemZ] Disable shrinking of SNaN constants (#20) When expanding FP constants, we attempt to shrink doubles to floats and perform an extending load. However, on SystemZ, and possibly on other targets (I've only confirmed the problem on SystemZ), the FP extending load instruction may convert SNaN into QNaN, or may cause an exception. So in the general case, we would still like to shrink FP constants, but SNaNs should be left as doubles. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@277602 91177308-0d34-0410-b5e6-96231b3b80d8 LLLexer.cpp: Avoid using BitsToDouble() to preserve SNaN like "double 0x7FF4000000000000". We should not use double (or float) in the LLVM, unless it is really needed. x87 FP register doesn't preserve SNaN to move the value. FIXME: APFloat() may have the constructor by raw bit. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@277813 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AsmParser/LLLexer.cpp | 3 ++- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 27 ++++++++++++++---------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 68e9e34e372..9568f261dab 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -859,7 +859,8 @@ lltok::Kind LLLexer::Lex0x() { // HexFPConstant - Floating point constant represented in IEEE format as a // hexadecimal number for when exponential notation is not precise enough. // Half, Float, and double only. - APFloatVal = APFloat(BitsToDouble(HexIntToVal(TokStart+2, CurPtr))); + APFloatVal = APFloat(APFloat::IEEEdouble, + APInt(64, HexIntToVal(TokStart + 2, CurPtr))); return lltok::APFloat; } diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 4453e2b5533..d72b04e0bfc 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -263,19 +263,24 @@ SelectionDAGLegalize::ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP) { (VT == MVT::f64) ? MVT::i64 : MVT::i32); } + APFloat APF = CFP->getValueAPF(); EVT OrigVT = VT; EVT SVT = VT; - while (SVT != MVT::f32 && SVT != MVT::f16) { - SVT = (MVT::SimpleValueType)(SVT.getSimpleVT().SimpleTy - 1); - if (ConstantFPSDNode::isValueValidForType(SVT, CFP->getValueAPF()) && - // Only do this if the target has a native EXTLOAD instruction from - // smaller type. - TLI.isLoadExtLegal(ISD::EXTLOAD, OrigVT, SVT) && - TLI.ShouldShrinkFPConstant(OrigVT)) { - Type *SType = SVT.getTypeForEVT(*DAG.getContext()); - LLVMC = cast(ConstantExpr::getFPTrunc(LLVMC, SType)); - VT = SVT; - Extend = true; + // We don't want to shrink SNaNs. Converting the SNaN back to its real type + // can cause it to be changed into a QNaN on some platforms (e.g. on SystemZ). + if (!APF.isSignaling()) { + while (SVT != MVT::f32 && SVT != MVT::f16) { + SVT = (MVT::SimpleValueType)(SVT.getSimpleVT().SimpleTy - 1); + if (ConstantFPSDNode::isValueValidForType(SVT, APF) && + // Only do this if the target has a native EXTLOAD instruction from + // smaller type. + TLI.isLoadExtLegal(ISD::EXTLOAD, OrigVT, SVT) && + TLI.ShouldShrinkFPConstant(OrigVT)) { + Type *SType = SVT.getTypeForEVT(*DAG.getContext()); + LLVMC = cast(ConstantExpr::getFPTrunc(LLVMC, SType)); + VT = SVT; + Extend = true; + } } }