106f32e7eSjoerg //===-------- LegalizeFloatTypes.cpp - Legalization of float types --------===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // This file implements float type expansion and softening for LegalizeTypes.
1006f32e7eSjoerg // Softening is the act of turning a computation in an illegal floating point
1106f32e7eSjoerg // type into a computation in an integer type of the same size; also known as
1206f32e7eSjoerg // "soft float".  For example, turning f32 arithmetic into operations using i32.
1306f32e7eSjoerg // The resulting integer value is the same as what you would get by performing
1406f32e7eSjoerg // the floating point operation and bitcasting the result to the integer type.
1506f32e7eSjoerg // Expansion is the act of changing a computation in an illegal type to be a
1606f32e7eSjoerg // computation in two identical registers of a smaller type.  For example,
1706f32e7eSjoerg // implementing ppcf128 arithmetic in two f64 registers.
1806f32e7eSjoerg //
1906f32e7eSjoerg //===----------------------------------------------------------------------===//
2006f32e7eSjoerg 
2106f32e7eSjoerg #include "LegalizeTypes.h"
2206f32e7eSjoerg #include "llvm/Support/ErrorHandling.h"
2306f32e7eSjoerg #include "llvm/Support/raw_ostream.h"
2406f32e7eSjoerg using namespace llvm;
2506f32e7eSjoerg 
2606f32e7eSjoerg #define DEBUG_TYPE "legalize-types"
2706f32e7eSjoerg 
2806f32e7eSjoerg /// GetFPLibCall - Return the right libcall for the given floating point type.
GetFPLibCall(EVT VT,RTLIB::Libcall Call_F32,RTLIB::Libcall Call_F64,RTLIB::Libcall Call_F80,RTLIB::Libcall Call_F128,RTLIB::Libcall Call_PPCF128)2906f32e7eSjoerg static RTLIB::Libcall GetFPLibCall(EVT VT,
3006f32e7eSjoerg                                    RTLIB::Libcall Call_F32,
3106f32e7eSjoerg                                    RTLIB::Libcall Call_F64,
3206f32e7eSjoerg                                    RTLIB::Libcall Call_F80,
3306f32e7eSjoerg                                    RTLIB::Libcall Call_F128,
3406f32e7eSjoerg                                    RTLIB::Libcall Call_PPCF128) {
3506f32e7eSjoerg   return
3606f32e7eSjoerg     VT == MVT::f32 ? Call_F32 :
3706f32e7eSjoerg     VT == MVT::f64 ? Call_F64 :
3806f32e7eSjoerg     VT == MVT::f80 ? Call_F80 :
3906f32e7eSjoerg     VT == MVT::f128 ? Call_F128 :
4006f32e7eSjoerg     VT == MVT::ppcf128 ? Call_PPCF128 :
4106f32e7eSjoerg     RTLIB::UNKNOWN_LIBCALL;
4206f32e7eSjoerg }
4306f32e7eSjoerg 
4406f32e7eSjoerg //===----------------------------------------------------------------------===//
4506f32e7eSjoerg //  Convert Float Results to Integer
4606f32e7eSjoerg //===----------------------------------------------------------------------===//
4706f32e7eSjoerg 
SoftenFloatResult(SDNode * N,unsigned ResNo)4806f32e7eSjoerg void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) {
4906f32e7eSjoerg   LLVM_DEBUG(dbgs() << "Soften float result " << ResNo << ": "; N->dump(&DAG);
5006f32e7eSjoerg              dbgs() << "\n");
5106f32e7eSjoerg   SDValue R = SDValue();
5206f32e7eSjoerg 
5306f32e7eSjoerg   switch (N->getOpcode()) {
5406f32e7eSjoerg   default:
5506f32e7eSjoerg #ifndef NDEBUG
5606f32e7eSjoerg     dbgs() << "SoftenFloatResult #" << ResNo << ": ";
5706f32e7eSjoerg     N->dump(&DAG); dbgs() << "\n";
5806f32e7eSjoerg #endif
5906f32e7eSjoerg     llvm_unreachable("Do not know how to soften the result of this operator!");
6006f32e7eSjoerg 
6106f32e7eSjoerg     case ISD::MERGE_VALUES:R = SoftenFloatRes_MERGE_VALUES(N, ResNo); break;
6206f32e7eSjoerg     case ISD::BITCAST:     R = SoftenFloatRes_BITCAST(N); break;
6306f32e7eSjoerg     case ISD::BUILD_PAIR:  R = SoftenFloatRes_BUILD_PAIR(N); break;
6406f32e7eSjoerg     case ISD::ConstantFP:  R = SoftenFloatRes_ConstantFP(N); break;
6506f32e7eSjoerg     case ISD::EXTRACT_VECTOR_ELT:
6606f32e7eSjoerg       R = SoftenFloatRes_EXTRACT_VECTOR_ELT(N, ResNo); break;
6706f32e7eSjoerg     case ISD::FABS:        R = SoftenFloatRes_FABS(N); break;
68*da58b97aSjoerg     case ISD::STRICT_FMINNUM:
6906f32e7eSjoerg     case ISD::FMINNUM:     R = SoftenFloatRes_FMINNUM(N); break;
70*da58b97aSjoerg     case ISD::STRICT_FMAXNUM:
7106f32e7eSjoerg     case ISD::FMAXNUM:     R = SoftenFloatRes_FMAXNUM(N); break;
72*da58b97aSjoerg     case ISD::STRICT_FADD:
7306f32e7eSjoerg     case ISD::FADD:        R = SoftenFloatRes_FADD(N); break;
7406f32e7eSjoerg     case ISD::FCBRT:       R = SoftenFloatRes_FCBRT(N); break;
75*da58b97aSjoerg     case ISD::STRICT_FCEIL:
7606f32e7eSjoerg     case ISD::FCEIL:       R = SoftenFloatRes_FCEIL(N); break;
7706f32e7eSjoerg     case ISD::FCOPYSIGN:   R = SoftenFloatRes_FCOPYSIGN(N); break;
78*da58b97aSjoerg     case ISD::STRICT_FCOS:
7906f32e7eSjoerg     case ISD::FCOS:        R = SoftenFloatRes_FCOS(N); break;
80*da58b97aSjoerg     case ISD::STRICT_FDIV:
8106f32e7eSjoerg     case ISD::FDIV:        R = SoftenFloatRes_FDIV(N); break;
82*da58b97aSjoerg     case ISD::STRICT_FEXP:
8306f32e7eSjoerg     case ISD::FEXP:        R = SoftenFloatRes_FEXP(N); break;
84*da58b97aSjoerg     case ISD::STRICT_FEXP2:
8506f32e7eSjoerg     case ISD::FEXP2:       R = SoftenFloatRes_FEXP2(N); break;
86*da58b97aSjoerg     case ISD::STRICT_FFLOOR:
8706f32e7eSjoerg     case ISD::FFLOOR:      R = SoftenFloatRes_FFLOOR(N); break;
88*da58b97aSjoerg     case ISD::STRICT_FLOG:
8906f32e7eSjoerg     case ISD::FLOG:        R = SoftenFloatRes_FLOG(N); break;
90*da58b97aSjoerg     case ISD::STRICT_FLOG2:
9106f32e7eSjoerg     case ISD::FLOG2:       R = SoftenFloatRes_FLOG2(N); break;
92*da58b97aSjoerg     case ISD::STRICT_FLOG10:
9306f32e7eSjoerg     case ISD::FLOG10:      R = SoftenFloatRes_FLOG10(N); break;
94*da58b97aSjoerg     case ISD::STRICT_FMA:
9506f32e7eSjoerg     case ISD::FMA:         R = SoftenFloatRes_FMA(N); break;
96*da58b97aSjoerg     case ISD::STRICT_FMUL:
9706f32e7eSjoerg     case ISD::FMUL:        R = SoftenFloatRes_FMUL(N); break;
98*da58b97aSjoerg     case ISD::STRICT_FNEARBYINT:
9906f32e7eSjoerg     case ISD::FNEARBYINT:  R = SoftenFloatRes_FNEARBYINT(N); break;
10006f32e7eSjoerg     case ISD::FNEG:        R = SoftenFloatRes_FNEG(N); break;
101*da58b97aSjoerg     case ISD::STRICT_FP_EXTEND:
10206f32e7eSjoerg     case ISD::FP_EXTEND:   R = SoftenFloatRes_FP_EXTEND(N); break;
103*da58b97aSjoerg     case ISD::STRICT_FP_ROUND:
10406f32e7eSjoerg     case ISD::FP_ROUND:    R = SoftenFloatRes_FP_ROUND(N); break;
10506f32e7eSjoerg     case ISD::FP16_TO_FP:  R = SoftenFloatRes_FP16_TO_FP(N); break;
106*da58b97aSjoerg     case ISD::STRICT_FPOW:
10706f32e7eSjoerg     case ISD::FPOW:        R = SoftenFloatRes_FPOW(N); break;
108*da58b97aSjoerg     case ISD::STRICT_FPOWI:
10906f32e7eSjoerg     case ISD::FPOWI:       R = SoftenFloatRes_FPOWI(N); break;
110*da58b97aSjoerg     case ISD::STRICT_FREM:
11106f32e7eSjoerg     case ISD::FREM:        R = SoftenFloatRes_FREM(N); break;
112*da58b97aSjoerg     case ISD::STRICT_FRINT:
11306f32e7eSjoerg     case ISD::FRINT:       R = SoftenFloatRes_FRINT(N); break;
114*da58b97aSjoerg     case ISD::STRICT_FROUND:
11506f32e7eSjoerg     case ISD::FROUND:      R = SoftenFloatRes_FROUND(N); break;
116*da58b97aSjoerg     case ISD::STRICT_FROUNDEVEN:
117*da58b97aSjoerg     case ISD::FROUNDEVEN:  R = SoftenFloatRes_FROUNDEVEN(N); break;
118*da58b97aSjoerg     case ISD::STRICT_FSIN:
11906f32e7eSjoerg     case ISD::FSIN:        R = SoftenFloatRes_FSIN(N); break;
120*da58b97aSjoerg     case ISD::STRICT_FSQRT:
12106f32e7eSjoerg     case ISD::FSQRT:       R = SoftenFloatRes_FSQRT(N); break;
122*da58b97aSjoerg     case ISD::STRICT_FSUB:
12306f32e7eSjoerg     case ISD::FSUB:        R = SoftenFloatRes_FSUB(N); break;
124*da58b97aSjoerg     case ISD::STRICT_FTRUNC:
12506f32e7eSjoerg     case ISD::FTRUNC:      R = SoftenFloatRes_FTRUNC(N); break;
12606f32e7eSjoerg     case ISD::LOAD:        R = SoftenFloatRes_LOAD(N); break;
12706f32e7eSjoerg     case ISD::ATOMIC_SWAP: R = BitcastToInt_ATOMIC_SWAP(N); break;
12806f32e7eSjoerg     case ISD::SELECT:      R = SoftenFloatRes_SELECT(N); break;
12906f32e7eSjoerg     case ISD::SELECT_CC:   R = SoftenFloatRes_SELECT_CC(N); break;
130*da58b97aSjoerg     case ISD::FREEZE:      R = SoftenFloatRes_FREEZE(N); break;
131*da58b97aSjoerg     case ISD::STRICT_SINT_TO_FP:
132*da58b97aSjoerg     case ISD::STRICT_UINT_TO_FP:
13306f32e7eSjoerg     case ISD::SINT_TO_FP:
13406f32e7eSjoerg     case ISD::UINT_TO_FP:  R = SoftenFloatRes_XINT_TO_FP(N); break;
13506f32e7eSjoerg     case ISD::UNDEF:       R = SoftenFloatRes_UNDEF(N); break;
13606f32e7eSjoerg     case ISD::VAARG:       R = SoftenFloatRes_VAARG(N); break;
137*da58b97aSjoerg     case ISD::VECREDUCE_FADD:
138*da58b97aSjoerg     case ISD::VECREDUCE_FMUL:
139*da58b97aSjoerg     case ISD::VECREDUCE_FMIN:
140*da58b97aSjoerg     case ISD::VECREDUCE_FMAX:
141*da58b97aSjoerg       R = SoftenFloatRes_VECREDUCE(N);
142*da58b97aSjoerg       break;
143*da58b97aSjoerg     case ISD::VECREDUCE_SEQ_FADD:
144*da58b97aSjoerg     case ISD::VECREDUCE_SEQ_FMUL:
145*da58b97aSjoerg       R = SoftenFloatRes_VECREDUCE_SEQ(N);
146*da58b97aSjoerg       break;
14706f32e7eSjoerg   }
14806f32e7eSjoerg 
14906f32e7eSjoerg   // If R is null, the sub-method took care of registering the result.
15006f32e7eSjoerg   if (R.getNode()) {
15106f32e7eSjoerg     assert(R.getNode() != N);
15206f32e7eSjoerg     SetSoftenedFloat(SDValue(N, ResNo), R);
15306f32e7eSjoerg   }
15406f32e7eSjoerg }
15506f32e7eSjoerg 
SoftenFloatRes_Unary(SDNode * N,RTLIB::Libcall LC)156*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_Unary(SDNode *N, RTLIB::Libcall LC) {
157*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
158*da58b97aSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
159*da58b97aSjoerg   unsigned Offset = IsStrict ? 1 : 0;
160*da58b97aSjoerg   assert(N->getNumOperands() == (1 + Offset) &&
161*da58b97aSjoerg          "Unexpected number of operands!");
162*da58b97aSjoerg   SDValue Op = GetSoftenedFloat(N->getOperand(0 + Offset));
163*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
164*da58b97aSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
165*da58b97aSjoerg   EVT OpVT = N->getOperand(0 + Offset).getValueType();
166*da58b97aSjoerg   CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0), true);
167*da58b97aSjoerg   std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, NVT, Op,
168*da58b97aSjoerg                                                     CallOptions, SDLoc(N),
169*da58b97aSjoerg                                                     Chain);
170*da58b97aSjoerg   if (IsStrict)
171*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Tmp.second);
172*da58b97aSjoerg   return Tmp.first;
173*da58b97aSjoerg }
174*da58b97aSjoerg 
SoftenFloatRes_Binary(SDNode * N,RTLIB::Libcall LC)175*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_Binary(SDNode *N, RTLIB::Libcall LC) {
176*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
177*da58b97aSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
178*da58b97aSjoerg   unsigned Offset = IsStrict ? 1 : 0;
179*da58b97aSjoerg   assert(N->getNumOperands() == (2 + Offset) &&
180*da58b97aSjoerg          "Unexpected number of operands!");
181*da58b97aSjoerg   SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0 + Offset)),
182*da58b97aSjoerg                      GetSoftenedFloat(N->getOperand(1 + Offset)) };
183*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
184*da58b97aSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
185*da58b97aSjoerg   EVT OpsVT[2] = { N->getOperand(0 + Offset).getValueType(),
186*da58b97aSjoerg                    N->getOperand(1 + Offset).getValueType() };
187*da58b97aSjoerg   CallOptions.setTypeListBeforeSoften(OpsVT, N->getValueType(0), true);
188*da58b97aSjoerg   std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, NVT, Ops,
189*da58b97aSjoerg                                                     CallOptions, SDLoc(N),
190*da58b97aSjoerg                                                     Chain);
191*da58b97aSjoerg   if (IsStrict)
192*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Tmp.second);
193*da58b97aSjoerg   return Tmp.first;
194*da58b97aSjoerg }
195*da58b97aSjoerg 
SoftenFloatRes_BITCAST(SDNode * N)19606f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_BITCAST(SDNode *N) {
19706f32e7eSjoerg   return BitConvertToInteger(N->getOperand(0));
19806f32e7eSjoerg }
19906f32e7eSjoerg 
SoftenFloatRes_FREEZE(SDNode * N)200*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FREEZE(SDNode *N) {
201*da58b97aSjoerg   EVT Ty = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
202*da58b97aSjoerg   return DAG.getNode(ISD::FREEZE, SDLoc(N), Ty,
203*da58b97aSjoerg                      GetSoftenedFloat(N->getOperand(0)));
204*da58b97aSjoerg }
205*da58b97aSjoerg 
SoftenFloatRes_MERGE_VALUES(SDNode * N,unsigned ResNo)20606f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_MERGE_VALUES(SDNode *N,
20706f32e7eSjoerg                                                       unsigned ResNo) {
20806f32e7eSjoerg   SDValue Op = DisintegrateMERGE_VALUES(N, ResNo);
20906f32e7eSjoerg   return BitConvertToInteger(Op);
21006f32e7eSjoerg }
21106f32e7eSjoerg 
SoftenFloatRes_BUILD_PAIR(SDNode * N)21206f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_BUILD_PAIR(SDNode *N) {
21306f32e7eSjoerg   // Convert the inputs to integers, and build a new pair out of them.
21406f32e7eSjoerg   return DAG.getNode(ISD::BUILD_PAIR, SDLoc(N),
21506f32e7eSjoerg                      TLI.getTypeToTransformTo(*DAG.getContext(),
21606f32e7eSjoerg                                               N->getValueType(0)),
21706f32e7eSjoerg                      BitConvertToInteger(N->getOperand(0)),
21806f32e7eSjoerg                      BitConvertToInteger(N->getOperand(1)));
21906f32e7eSjoerg }
22006f32e7eSjoerg 
SoftenFloatRes_ConstantFP(SDNode * N)22106f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_ConstantFP(SDNode *N) {
22206f32e7eSjoerg   ConstantFPSDNode *CN = cast<ConstantFPSDNode>(N);
22306f32e7eSjoerg   // In ppcf128, the high 64 bits are always first in memory regardless
22406f32e7eSjoerg   // of Endianness. LLVM's APFloat representation is not Endian sensitive,
22506f32e7eSjoerg   // and so always converts into a 128-bit APInt in a non-Endian-sensitive
22606f32e7eSjoerg   // way. However, APInt's are serialized in an Endian-sensitive fashion,
22706f32e7eSjoerg   // so on big-Endian targets, the two doubles are output in the wrong
22806f32e7eSjoerg   // order. Fix this by manually flipping the order of the high 64 bits
22906f32e7eSjoerg   // and the low 64 bits here.
23006f32e7eSjoerg   if (DAG.getDataLayout().isBigEndian() &&
23106f32e7eSjoerg       CN->getValueType(0).getSimpleVT() == llvm::MVT::ppcf128) {
23206f32e7eSjoerg     uint64_t words[2] = { CN->getValueAPF().bitcastToAPInt().getRawData()[1],
23306f32e7eSjoerg                           CN->getValueAPF().bitcastToAPInt().getRawData()[0] };
23406f32e7eSjoerg     APInt Val(128, words);
23506f32e7eSjoerg     return DAG.getConstant(Val, SDLoc(CN),
23606f32e7eSjoerg                            TLI.getTypeToTransformTo(*DAG.getContext(),
23706f32e7eSjoerg                                                     CN->getValueType(0)));
23806f32e7eSjoerg   } else {
23906f32e7eSjoerg     return DAG.getConstant(CN->getValueAPF().bitcastToAPInt(), SDLoc(CN),
24006f32e7eSjoerg                            TLI.getTypeToTransformTo(*DAG.getContext(),
24106f32e7eSjoerg                                                     CN->getValueType(0)));
24206f32e7eSjoerg   }
24306f32e7eSjoerg }
24406f32e7eSjoerg 
SoftenFloatRes_EXTRACT_VECTOR_ELT(SDNode * N,unsigned ResNo)24506f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_EXTRACT_VECTOR_ELT(SDNode *N, unsigned ResNo) {
24606f32e7eSjoerg   SDValue NewOp = BitConvertVectorToIntegerVector(N->getOperand(0));
24706f32e7eSjoerg   return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
24806f32e7eSjoerg                      NewOp.getValueType().getVectorElementType(),
24906f32e7eSjoerg                      NewOp, N->getOperand(1));
25006f32e7eSjoerg }
25106f32e7eSjoerg 
SoftenFloatRes_FABS(SDNode * N)25206f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FABS(SDNode *N) {
25306f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
25406f32e7eSjoerg   unsigned Size = NVT.getSizeInBits();
25506f32e7eSjoerg 
25606f32e7eSjoerg   // Mask = ~(1 << (Size-1))
25706f32e7eSjoerg   APInt API = APInt::getAllOnesValue(Size);
25806f32e7eSjoerg   API.clearBit(Size - 1);
25906f32e7eSjoerg   SDValue Mask = DAG.getConstant(API, SDLoc(N), NVT);
26006f32e7eSjoerg   SDValue Op = GetSoftenedFloat(N->getOperand(0));
26106f32e7eSjoerg   return DAG.getNode(ISD::AND, SDLoc(N), NVT, Op, Mask);
26206f32e7eSjoerg }
26306f32e7eSjoerg 
SoftenFloatRes_FMINNUM(SDNode * N)26406f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FMINNUM(SDNode *N) {
265*da58b97aSjoerg   return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
26606f32e7eSjoerg                                                RTLIB::FMIN_F32,
26706f32e7eSjoerg                                                RTLIB::FMIN_F64,
26806f32e7eSjoerg                                                RTLIB::FMIN_F80,
26906f32e7eSjoerg                                                RTLIB::FMIN_F128,
270*da58b97aSjoerg                                                RTLIB::FMIN_PPCF128));
27106f32e7eSjoerg }
27206f32e7eSjoerg 
SoftenFloatRes_FMAXNUM(SDNode * N)27306f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FMAXNUM(SDNode *N) {
274*da58b97aSjoerg   return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
27506f32e7eSjoerg                                                RTLIB::FMAX_F32,
27606f32e7eSjoerg                                                RTLIB::FMAX_F64,
27706f32e7eSjoerg                                                RTLIB::FMAX_F80,
27806f32e7eSjoerg                                                RTLIB::FMAX_F128,
279*da58b97aSjoerg                                                RTLIB::FMAX_PPCF128));
28006f32e7eSjoerg }
28106f32e7eSjoerg 
SoftenFloatRes_FADD(SDNode * N)28206f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FADD(SDNode *N) {
283*da58b97aSjoerg   return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
28406f32e7eSjoerg                                                RTLIB::ADD_F32,
28506f32e7eSjoerg                                                RTLIB::ADD_F64,
28606f32e7eSjoerg                                                RTLIB::ADD_F80,
28706f32e7eSjoerg                                                RTLIB::ADD_F128,
288*da58b97aSjoerg                                                RTLIB::ADD_PPCF128));
28906f32e7eSjoerg }
29006f32e7eSjoerg 
SoftenFloatRes_FCBRT(SDNode * N)29106f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FCBRT(SDNode *N) {
292*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
29306f32e7eSjoerg                                            RTLIB::CBRT_F32,
29406f32e7eSjoerg                                            RTLIB::CBRT_F64,
29506f32e7eSjoerg                                            RTLIB::CBRT_F80,
29606f32e7eSjoerg                                            RTLIB::CBRT_F128,
297*da58b97aSjoerg                                            RTLIB::CBRT_PPCF128));
29806f32e7eSjoerg }
29906f32e7eSjoerg 
SoftenFloatRes_FCEIL(SDNode * N)30006f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FCEIL(SDNode *N) {
301*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
30206f32e7eSjoerg                                               RTLIB::CEIL_F32,
30306f32e7eSjoerg                                               RTLIB::CEIL_F64,
30406f32e7eSjoerg                                               RTLIB::CEIL_F80,
30506f32e7eSjoerg                                               RTLIB::CEIL_F128,
306*da58b97aSjoerg                                               RTLIB::CEIL_PPCF128));
30706f32e7eSjoerg }
30806f32e7eSjoerg 
SoftenFloatRes_FCOPYSIGN(SDNode * N)30906f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN(SDNode *N) {
31006f32e7eSjoerg   SDValue LHS = GetSoftenedFloat(N->getOperand(0));
31106f32e7eSjoerg   SDValue RHS = BitConvertToInteger(N->getOperand(1));
31206f32e7eSjoerg   SDLoc dl(N);
31306f32e7eSjoerg 
31406f32e7eSjoerg   EVT LVT = LHS.getValueType();
31506f32e7eSjoerg   EVT RVT = RHS.getValueType();
31606f32e7eSjoerg 
31706f32e7eSjoerg   unsigned LSize = LVT.getSizeInBits();
31806f32e7eSjoerg   unsigned RSize = RVT.getSizeInBits();
31906f32e7eSjoerg 
32006f32e7eSjoerg   // First get the sign bit of second operand.
32106f32e7eSjoerg   SDValue SignBit = DAG.getNode(
32206f32e7eSjoerg       ISD::SHL, dl, RVT, DAG.getConstant(1, dl, RVT),
32306f32e7eSjoerg       DAG.getConstant(RSize - 1, dl,
32406f32e7eSjoerg                       TLI.getShiftAmountTy(RVT, DAG.getDataLayout())));
32506f32e7eSjoerg   SignBit = DAG.getNode(ISD::AND, dl, RVT, RHS, SignBit);
32606f32e7eSjoerg 
32706f32e7eSjoerg   // Shift right or sign-extend it if the two operands have different types.
32806f32e7eSjoerg   int SizeDiff = RVT.getSizeInBits() - LVT.getSizeInBits();
32906f32e7eSjoerg   if (SizeDiff > 0) {
33006f32e7eSjoerg     SignBit =
33106f32e7eSjoerg         DAG.getNode(ISD::SRL, dl, RVT, SignBit,
33206f32e7eSjoerg                     DAG.getConstant(SizeDiff, dl,
33306f32e7eSjoerg                                     TLI.getShiftAmountTy(SignBit.getValueType(),
33406f32e7eSjoerg                                                          DAG.getDataLayout())));
33506f32e7eSjoerg     SignBit = DAG.getNode(ISD::TRUNCATE, dl, LVT, SignBit);
33606f32e7eSjoerg   } else if (SizeDiff < 0) {
33706f32e7eSjoerg     SignBit = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, SignBit);
33806f32e7eSjoerg     SignBit =
33906f32e7eSjoerg         DAG.getNode(ISD::SHL, dl, LVT, SignBit,
34006f32e7eSjoerg                     DAG.getConstant(-SizeDiff, dl,
34106f32e7eSjoerg                                     TLI.getShiftAmountTy(SignBit.getValueType(),
34206f32e7eSjoerg                                                          DAG.getDataLayout())));
34306f32e7eSjoerg   }
34406f32e7eSjoerg 
34506f32e7eSjoerg   // Clear the sign bit of the first operand.
34606f32e7eSjoerg   SDValue Mask = DAG.getNode(
34706f32e7eSjoerg       ISD::SHL, dl, LVT, DAG.getConstant(1, dl, LVT),
34806f32e7eSjoerg       DAG.getConstant(LSize - 1, dl,
34906f32e7eSjoerg                       TLI.getShiftAmountTy(LVT, DAG.getDataLayout())));
35006f32e7eSjoerg   Mask = DAG.getNode(ISD::SUB, dl, LVT, Mask, DAG.getConstant(1, dl, LVT));
35106f32e7eSjoerg   LHS = DAG.getNode(ISD::AND, dl, LVT, LHS, Mask);
35206f32e7eSjoerg 
35306f32e7eSjoerg   // Or the value with the sign bit.
35406f32e7eSjoerg   return DAG.getNode(ISD::OR, dl, LVT, LHS, SignBit);
35506f32e7eSjoerg }
35606f32e7eSjoerg 
SoftenFloatRes_FCOS(SDNode * N)35706f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FCOS(SDNode *N) {
358*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
35906f32e7eSjoerg                                               RTLIB::COS_F32,
36006f32e7eSjoerg                                               RTLIB::COS_F64,
36106f32e7eSjoerg                                               RTLIB::COS_F80,
36206f32e7eSjoerg                                               RTLIB::COS_F128,
363*da58b97aSjoerg                                               RTLIB::COS_PPCF128));
36406f32e7eSjoerg }
36506f32e7eSjoerg 
SoftenFloatRes_FDIV(SDNode * N)36606f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FDIV(SDNode *N) {
367*da58b97aSjoerg   return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
36806f32e7eSjoerg                                                RTLIB::DIV_F32,
36906f32e7eSjoerg                                                RTLIB::DIV_F64,
37006f32e7eSjoerg                                                RTLIB::DIV_F80,
37106f32e7eSjoerg                                                RTLIB::DIV_F128,
372*da58b97aSjoerg                                                RTLIB::DIV_PPCF128));
37306f32e7eSjoerg }
37406f32e7eSjoerg 
SoftenFloatRes_FEXP(SDNode * N)37506f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FEXP(SDNode *N) {
376*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
37706f32e7eSjoerg                                               RTLIB::EXP_F32,
37806f32e7eSjoerg                                               RTLIB::EXP_F64,
37906f32e7eSjoerg                                               RTLIB::EXP_F80,
38006f32e7eSjoerg                                               RTLIB::EXP_F128,
381*da58b97aSjoerg                                               RTLIB::EXP_PPCF128));
38206f32e7eSjoerg }
38306f32e7eSjoerg 
SoftenFloatRes_FEXP2(SDNode * N)38406f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FEXP2(SDNode *N) {
385*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
38606f32e7eSjoerg                                               RTLIB::EXP2_F32,
38706f32e7eSjoerg                                               RTLIB::EXP2_F64,
38806f32e7eSjoerg                                               RTLIB::EXP2_F80,
38906f32e7eSjoerg                                               RTLIB::EXP2_F128,
390*da58b97aSjoerg                                               RTLIB::EXP2_PPCF128));
39106f32e7eSjoerg }
39206f32e7eSjoerg 
SoftenFloatRes_FFLOOR(SDNode * N)39306f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FFLOOR(SDNode *N) {
394*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
39506f32e7eSjoerg                                               RTLIB::FLOOR_F32,
39606f32e7eSjoerg                                               RTLIB::FLOOR_F64,
39706f32e7eSjoerg                                               RTLIB::FLOOR_F80,
39806f32e7eSjoerg                                               RTLIB::FLOOR_F128,
399*da58b97aSjoerg                                               RTLIB::FLOOR_PPCF128));
40006f32e7eSjoerg }
40106f32e7eSjoerg 
SoftenFloatRes_FLOG(SDNode * N)40206f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FLOG(SDNode *N) {
403*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
40406f32e7eSjoerg                                               RTLIB::LOG_F32,
40506f32e7eSjoerg                                               RTLIB::LOG_F64,
40606f32e7eSjoerg                                               RTLIB::LOG_F80,
40706f32e7eSjoerg                                               RTLIB::LOG_F128,
408*da58b97aSjoerg                                               RTLIB::LOG_PPCF128));
40906f32e7eSjoerg }
41006f32e7eSjoerg 
SoftenFloatRes_FLOG2(SDNode * N)41106f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FLOG2(SDNode *N) {
412*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
41306f32e7eSjoerg                                               RTLIB::LOG2_F32,
41406f32e7eSjoerg                                               RTLIB::LOG2_F64,
41506f32e7eSjoerg                                               RTLIB::LOG2_F80,
41606f32e7eSjoerg                                               RTLIB::LOG2_F128,
417*da58b97aSjoerg                                               RTLIB::LOG2_PPCF128));
41806f32e7eSjoerg }
41906f32e7eSjoerg 
SoftenFloatRes_FLOG10(SDNode * N)42006f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FLOG10(SDNode *N) {
421*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
42206f32e7eSjoerg                                               RTLIB::LOG10_F32,
42306f32e7eSjoerg                                               RTLIB::LOG10_F64,
42406f32e7eSjoerg                                               RTLIB::LOG10_F80,
42506f32e7eSjoerg                                               RTLIB::LOG10_F128,
426*da58b97aSjoerg                                               RTLIB::LOG10_PPCF128));
42706f32e7eSjoerg }
42806f32e7eSjoerg 
SoftenFloatRes_FMA(SDNode * N)42906f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FMA(SDNode *N) {
430*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
43106f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
432*da58b97aSjoerg   unsigned Offset = IsStrict ? 1 : 0;
433*da58b97aSjoerg   SDValue Ops[3] = { GetSoftenedFloat(N->getOperand(0 + Offset)),
434*da58b97aSjoerg                      GetSoftenedFloat(N->getOperand(1 + Offset)),
435*da58b97aSjoerg                      GetSoftenedFloat(N->getOperand(2 + Offset)) };
436*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
43706f32e7eSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
438*da58b97aSjoerg   EVT OpsVT[3] = { N->getOperand(0 + Offset).getValueType(),
439*da58b97aSjoerg                    N->getOperand(1 + Offset).getValueType(),
440*da58b97aSjoerg                    N->getOperand(2 + Offset).getValueType() };
44106f32e7eSjoerg   CallOptions.setTypeListBeforeSoften(OpsVT, N->getValueType(0), true);
442*da58b97aSjoerg   std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG,
443*da58b97aSjoerg                                                     GetFPLibCall(N->getValueType(0),
44406f32e7eSjoerg                                                                  RTLIB::FMA_F32,
44506f32e7eSjoerg                                                                  RTLIB::FMA_F64,
44606f32e7eSjoerg                                                                  RTLIB::FMA_F80,
44706f32e7eSjoerg                                                                  RTLIB::FMA_F128,
44806f32e7eSjoerg                                                                  RTLIB::FMA_PPCF128),
449*da58b97aSjoerg                          NVT, Ops, CallOptions, SDLoc(N), Chain);
450*da58b97aSjoerg   if (IsStrict)
451*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Tmp.second);
452*da58b97aSjoerg   return Tmp.first;
45306f32e7eSjoerg }
45406f32e7eSjoerg 
SoftenFloatRes_FMUL(SDNode * N)45506f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FMUL(SDNode *N) {
456*da58b97aSjoerg   return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
45706f32e7eSjoerg                                                RTLIB::MUL_F32,
45806f32e7eSjoerg                                                RTLIB::MUL_F64,
45906f32e7eSjoerg                                                RTLIB::MUL_F80,
46006f32e7eSjoerg                                                RTLIB::MUL_F128,
461*da58b97aSjoerg                                                RTLIB::MUL_PPCF128));
46206f32e7eSjoerg }
46306f32e7eSjoerg 
SoftenFloatRes_FNEARBYINT(SDNode * N)46406f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FNEARBYINT(SDNode *N) {
465*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
46606f32e7eSjoerg                                               RTLIB::NEARBYINT_F32,
46706f32e7eSjoerg                                               RTLIB::NEARBYINT_F64,
46806f32e7eSjoerg                                               RTLIB::NEARBYINT_F80,
46906f32e7eSjoerg                                               RTLIB::NEARBYINT_F128,
470*da58b97aSjoerg                                               RTLIB::NEARBYINT_PPCF128));
47106f32e7eSjoerg }
47206f32e7eSjoerg 
SoftenFloatRes_FNEG(SDNode * N)47306f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FNEG(SDNode *N) {
47406f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
47506f32e7eSjoerg   SDLoc dl(N);
47606f32e7eSjoerg 
47706f32e7eSjoerg   // Expand Y = FNEG(X) -> Y = X ^ sign mask
47806f32e7eSjoerg   APInt SignMask = APInt::getSignMask(NVT.getSizeInBits());
47906f32e7eSjoerg   return DAG.getNode(ISD::XOR, dl, NVT, GetSoftenedFloat(N->getOperand(0)),
48006f32e7eSjoerg                      DAG.getConstant(SignMask, dl, NVT));
48106f32e7eSjoerg }
48206f32e7eSjoerg 
SoftenFloatRes_FP_EXTEND(SDNode * N)48306f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FP_EXTEND(SDNode *N) {
484*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
48506f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
486*da58b97aSjoerg   SDValue Op = N->getOperand(IsStrict ? 1 : 0);
48706f32e7eSjoerg 
488*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
48906f32e7eSjoerg 
49006f32e7eSjoerg   if (getTypeAction(Op.getValueType()) == TargetLowering::TypePromoteFloat) {
49106f32e7eSjoerg     Op = GetPromotedFloat(Op);
49206f32e7eSjoerg     // If the promotion did the FP_EXTEND to the destination type for us,
49306f32e7eSjoerg     // there's nothing left to do here.
494*da58b97aSjoerg     if (Op.getValueType() == N->getValueType(0))
49506f32e7eSjoerg       return BitConvertToInteger(Op);
49606f32e7eSjoerg   }
497*da58b97aSjoerg 
498*da58b97aSjoerg   // There's only a libcall for f16 -> f32, so proceed in two stages. Also, it's
499*da58b97aSjoerg   // entirely possible for both f16 and f32 to be legal, so use the fully
500*da58b97aSjoerg   // hard-float FP_EXTEND rather than FP16_TO_FP.
501*da58b97aSjoerg   if (Op.getValueType() == MVT::f16 && N->getValueType(0) != MVT::f32) {
502*da58b97aSjoerg     if (IsStrict) {
503*da58b97aSjoerg       Op = DAG.getNode(ISD::STRICT_FP_EXTEND, SDLoc(N),
504*da58b97aSjoerg                        { MVT::f32, MVT::Other }, { Chain, Op });
505*da58b97aSjoerg       Chain = Op.getValue(1);
506*da58b97aSjoerg     } else {
507*da58b97aSjoerg       Op = DAG.getNode(ISD::FP_EXTEND, SDLoc(N), MVT::f32, Op);
508*da58b97aSjoerg     }
50906f32e7eSjoerg   }
51006f32e7eSjoerg 
51106f32e7eSjoerg   RTLIB::Libcall LC = RTLIB::getFPEXT(Op.getValueType(), N->getValueType(0));
51206f32e7eSjoerg   assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_EXTEND!");
51306f32e7eSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
514*da58b97aSjoerg   EVT OpVT = N->getOperand(IsStrict ? 1 : 0).getValueType();
515*da58b97aSjoerg   CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0), true);
516*da58b97aSjoerg   std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, NVT, Op,
517*da58b97aSjoerg                                                     CallOptions, SDLoc(N),
518*da58b97aSjoerg                                                     Chain);
519*da58b97aSjoerg   if (IsStrict)
520*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Tmp.second);
521*da58b97aSjoerg   return Tmp.first;
52206f32e7eSjoerg }
52306f32e7eSjoerg 
52406f32e7eSjoerg // FIXME: Should we just use 'normal' FP_EXTEND / FP_TRUNC instead of special
52506f32e7eSjoerg // nodes?
SoftenFloatRes_FP16_TO_FP(SDNode * N)52606f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FP16_TO_FP(SDNode *N) {
52706f32e7eSjoerg   EVT MidVT = TLI.getTypeToTransformTo(*DAG.getContext(), MVT::f32);
52806f32e7eSjoerg   SDValue Op = N->getOperand(0);
52906f32e7eSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
53006f32e7eSjoerg   EVT OpsVT[1] = { N->getOperand(0).getValueType() };
53106f32e7eSjoerg   CallOptions.setTypeListBeforeSoften(OpsVT, N->getValueType(0), true);
53206f32e7eSjoerg   SDValue Res32 = TLI.makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MidVT, Op,
53306f32e7eSjoerg                                   CallOptions, SDLoc(N)).first;
53406f32e7eSjoerg   if (N->getValueType(0) == MVT::f32)
53506f32e7eSjoerg     return Res32;
53606f32e7eSjoerg 
53706f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
53806f32e7eSjoerg   RTLIB::Libcall LC = RTLIB::getFPEXT(MVT::f32, N->getValueType(0));
53906f32e7eSjoerg   assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_EXTEND!");
54006f32e7eSjoerg   return TLI.makeLibCall(DAG, LC, NVT, Res32, CallOptions, SDLoc(N)).first;
54106f32e7eSjoerg }
54206f32e7eSjoerg 
SoftenFloatRes_FP_ROUND(SDNode * N)54306f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FP_ROUND(SDNode *N) {
544*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
54506f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
546*da58b97aSjoerg   SDValue Op = N->getOperand(IsStrict ? 1 : 0);
547*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
54806f32e7eSjoerg   RTLIB::Libcall LC = RTLIB::getFPROUND(Op.getValueType(), N->getValueType(0));
54906f32e7eSjoerg   assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_ROUND!");
55006f32e7eSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
551*da58b97aSjoerg   EVT OpVT = N->getOperand(IsStrict ? 1 : 0).getValueType();
552*da58b97aSjoerg   CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0), true);
553*da58b97aSjoerg   std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, NVT, Op,
554*da58b97aSjoerg                                                     CallOptions, SDLoc(N),
555*da58b97aSjoerg                                                     Chain);
556*da58b97aSjoerg   if (IsStrict)
557*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Tmp.second);
558*da58b97aSjoerg   return Tmp.first;
55906f32e7eSjoerg }
56006f32e7eSjoerg 
SoftenFloatRes_FPOW(SDNode * N)56106f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FPOW(SDNode *N) {
562*da58b97aSjoerg   return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
56306f32e7eSjoerg                                                RTLIB::POW_F32,
56406f32e7eSjoerg                                                RTLIB::POW_F64,
56506f32e7eSjoerg                                                RTLIB::POW_F80,
56606f32e7eSjoerg                                                RTLIB::POW_F128,
567*da58b97aSjoerg                                                RTLIB::POW_PPCF128));
56806f32e7eSjoerg }
56906f32e7eSjoerg 
SoftenFloatRes_FPOWI(SDNode * N)57006f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FPOWI(SDNode *N) {
571*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
572*da58b97aSjoerg   unsigned Offset = IsStrict ? 1 : 0;
573*da58b97aSjoerg   assert(N->getOperand(1 + Offset).getValueType() == MVT::i32 &&
57406f32e7eSjoerg          "Unsupported power type!");
575*da58b97aSjoerg   RTLIB::Libcall LC = GetFPLibCall(N->getValueType(0),
57606f32e7eSjoerg                                    RTLIB::POWI_F32,
57706f32e7eSjoerg                                    RTLIB::POWI_F64,
57806f32e7eSjoerg                                    RTLIB::POWI_F80,
57906f32e7eSjoerg                                    RTLIB::POWI_F128,
580*da58b97aSjoerg                                    RTLIB::POWI_PPCF128);
581*da58b97aSjoerg   if (!TLI.getLibcallName(LC)) {
582*da58b97aSjoerg     // Some targets don't have a powi libcall; use pow instead.
583*da58b97aSjoerg     // FIXME: Implement this if some target needs it.
584*da58b97aSjoerg     DAG.getContext()->emitError("Don't know how to soften fpowi to fpow");
585*da58b97aSjoerg     return DAG.getUNDEF(N->getValueType(0));
586*da58b97aSjoerg   }
587*da58b97aSjoerg 
588*da58b97aSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
589*da58b97aSjoerg   SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0 + Offset)),
590*da58b97aSjoerg                      N->getOperand(1 + Offset) };
591*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
592*da58b97aSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
593*da58b97aSjoerg   EVT OpsVT[2] = { N->getOperand(0 + Offset).getValueType(),
594*da58b97aSjoerg                    N->getOperand(1 + Offset).getValueType() };
595*da58b97aSjoerg   CallOptions.setTypeListBeforeSoften(OpsVT, N->getValueType(0), true);
596*da58b97aSjoerg   std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, NVT, Ops,
597*da58b97aSjoerg                                                     CallOptions, SDLoc(N),
598*da58b97aSjoerg                                                     Chain);
599*da58b97aSjoerg   if (IsStrict)
600*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Tmp.second);
601*da58b97aSjoerg   return Tmp.first;
60206f32e7eSjoerg }
60306f32e7eSjoerg 
SoftenFloatRes_FREM(SDNode * N)60406f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FREM(SDNode *N) {
605*da58b97aSjoerg   return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
60606f32e7eSjoerg                                                RTLIB::REM_F32,
60706f32e7eSjoerg                                                RTLIB::REM_F64,
60806f32e7eSjoerg                                                RTLIB::REM_F80,
60906f32e7eSjoerg                                                RTLIB::REM_F128,
610*da58b97aSjoerg                                                RTLIB::REM_PPCF128));
61106f32e7eSjoerg }
61206f32e7eSjoerg 
SoftenFloatRes_FRINT(SDNode * N)61306f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FRINT(SDNode *N) {
614*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
61506f32e7eSjoerg                                               RTLIB::RINT_F32,
61606f32e7eSjoerg                                               RTLIB::RINT_F64,
61706f32e7eSjoerg                                               RTLIB::RINT_F80,
61806f32e7eSjoerg                                               RTLIB::RINT_F128,
619*da58b97aSjoerg                                               RTLIB::RINT_PPCF128));
62006f32e7eSjoerg }
62106f32e7eSjoerg 
SoftenFloatRes_FROUND(SDNode * N)62206f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FROUND(SDNode *N) {
623*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
62406f32e7eSjoerg                                               RTLIB::ROUND_F32,
62506f32e7eSjoerg                                               RTLIB::ROUND_F64,
62606f32e7eSjoerg                                               RTLIB::ROUND_F80,
62706f32e7eSjoerg                                               RTLIB::ROUND_F128,
628*da58b97aSjoerg                                               RTLIB::ROUND_PPCF128));
629*da58b97aSjoerg }
630*da58b97aSjoerg 
SoftenFloatRes_FROUNDEVEN(SDNode * N)631*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FROUNDEVEN(SDNode *N) {
632*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
633*da58b97aSjoerg                                               RTLIB::ROUNDEVEN_F32,
634*da58b97aSjoerg                                               RTLIB::ROUNDEVEN_F64,
635*da58b97aSjoerg                                               RTLIB::ROUNDEVEN_F80,
636*da58b97aSjoerg                                               RTLIB::ROUNDEVEN_F128,
637*da58b97aSjoerg                                               RTLIB::ROUNDEVEN_PPCF128));
63806f32e7eSjoerg }
63906f32e7eSjoerg 
SoftenFloatRes_FSIN(SDNode * N)64006f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FSIN(SDNode *N) {
641*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
64206f32e7eSjoerg                                               RTLIB::SIN_F32,
64306f32e7eSjoerg                                               RTLIB::SIN_F64,
64406f32e7eSjoerg                                               RTLIB::SIN_F80,
64506f32e7eSjoerg                                               RTLIB::SIN_F128,
646*da58b97aSjoerg                                               RTLIB::SIN_PPCF128));
64706f32e7eSjoerg }
64806f32e7eSjoerg 
SoftenFloatRes_FSQRT(SDNode * N)64906f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FSQRT(SDNode *N) {
650*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
65106f32e7eSjoerg                                               RTLIB::SQRT_F32,
65206f32e7eSjoerg                                               RTLIB::SQRT_F64,
65306f32e7eSjoerg                                               RTLIB::SQRT_F80,
65406f32e7eSjoerg                                               RTLIB::SQRT_F128,
655*da58b97aSjoerg                                               RTLIB::SQRT_PPCF128));
65606f32e7eSjoerg }
65706f32e7eSjoerg 
SoftenFloatRes_FSUB(SDNode * N)65806f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FSUB(SDNode *N) {
659*da58b97aSjoerg   return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
66006f32e7eSjoerg                                                RTLIB::SUB_F32,
66106f32e7eSjoerg                                                RTLIB::SUB_F64,
66206f32e7eSjoerg                                                RTLIB::SUB_F80,
66306f32e7eSjoerg                                                RTLIB::SUB_F128,
664*da58b97aSjoerg                                                RTLIB::SUB_PPCF128));
66506f32e7eSjoerg }
66606f32e7eSjoerg 
SoftenFloatRes_FTRUNC(SDNode * N)66706f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_FTRUNC(SDNode *N) {
668*da58b97aSjoerg   return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
66906f32e7eSjoerg                                               RTLIB::TRUNC_F32,
67006f32e7eSjoerg                                               RTLIB::TRUNC_F64,
67106f32e7eSjoerg                                               RTLIB::TRUNC_F80,
67206f32e7eSjoerg                                               RTLIB::TRUNC_F128,
673*da58b97aSjoerg                                               RTLIB::TRUNC_PPCF128));
67406f32e7eSjoerg }
67506f32e7eSjoerg 
SoftenFloatRes_LOAD(SDNode * N)67606f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_LOAD(SDNode *N) {
67706f32e7eSjoerg   LoadSDNode *L = cast<LoadSDNode>(N);
67806f32e7eSjoerg   EVT VT = N->getValueType(0);
67906f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
68006f32e7eSjoerg   SDLoc dl(N);
68106f32e7eSjoerg 
68206f32e7eSjoerg   auto MMOFlags =
68306f32e7eSjoerg       L->getMemOperand()->getFlags() &
68406f32e7eSjoerg       ~(MachineMemOperand::MOInvariant | MachineMemOperand::MODereferenceable);
68506f32e7eSjoerg   SDValue NewL;
68606f32e7eSjoerg   if (L->getExtensionType() == ISD::NON_EXTLOAD) {
68706f32e7eSjoerg     NewL = DAG.getLoad(L->getAddressingMode(), L->getExtensionType(), NVT, dl,
68806f32e7eSjoerg                        L->getChain(), L->getBasePtr(), L->getOffset(),
689*da58b97aSjoerg                        L->getPointerInfo(), NVT, L->getOriginalAlign(),
690*da58b97aSjoerg                        MMOFlags, L->getAAInfo());
69106f32e7eSjoerg     // Legalized the chain result - switch anything that used the old chain to
69206f32e7eSjoerg     // use the new one.
69306f32e7eSjoerg     ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
69406f32e7eSjoerg     return NewL;
69506f32e7eSjoerg   }
69606f32e7eSjoerg 
69706f32e7eSjoerg   // Do a non-extending load followed by FP_EXTEND.
69806f32e7eSjoerg   NewL = DAG.getLoad(L->getAddressingMode(), ISD::NON_EXTLOAD, L->getMemoryVT(),
69906f32e7eSjoerg                      dl, L->getChain(), L->getBasePtr(), L->getOffset(),
700*da58b97aSjoerg                      L->getPointerInfo(), L->getMemoryVT(),
701*da58b97aSjoerg                      L->getOriginalAlign(), MMOFlags, L->getAAInfo());
70206f32e7eSjoerg   // Legalized the chain result - switch anything that used the old chain to
70306f32e7eSjoerg   // use the new one.
70406f32e7eSjoerg   ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
70506f32e7eSjoerg   auto ExtendNode = DAG.getNode(ISD::FP_EXTEND, dl, VT, NewL);
70606f32e7eSjoerg   return BitConvertToInteger(ExtendNode);
70706f32e7eSjoerg }
70806f32e7eSjoerg 
SoftenFloatRes_SELECT(SDNode * N)70906f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_SELECT(SDNode *N) {
71006f32e7eSjoerg   SDValue LHS = GetSoftenedFloat(N->getOperand(1));
71106f32e7eSjoerg   SDValue RHS = GetSoftenedFloat(N->getOperand(2));
71206f32e7eSjoerg   return DAG.getSelect(SDLoc(N),
71306f32e7eSjoerg                        LHS.getValueType(), N->getOperand(0), LHS, RHS);
71406f32e7eSjoerg }
71506f32e7eSjoerg 
SoftenFloatRes_SELECT_CC(SDNode * N)71606f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_SELECT_CC(SDNode *N) {
71706f32e7eSjoerg   SDValue LHS = GetSoftenedFloat(N->getOperand(2));
71806f32e7eSjoerg   SDValue RHS = GetSoftenedFloat(N->getOperand(3));
71906f32e7eSjoerg   return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
72006f32e7eSjoerg                      LHS.getValueType(), N->getOperand(0),
72106f32e7eSjoerg                      N->getOperand(1), LHS, RHS, N->getOperand(4));
72206f32e7eSjoerg }
72306f32e7eSjoerg 
SoftenFloatRes_UNDEF(SDNode * N)72406f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_UNDEF(SDNode *N) {
72506f32e7eSjoerg   return DAG.getUNDEF(TLI.getTypeToTransformTo(*DAG.getContext(),
72606f32e7eSjoerg                                                N->getValueType(0)));
72706f32e7eSjoerg }
72806f32e7eSjoerg 
SoftenFloatRes_VAARG(SDNode * N)72906f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_VAARG(SDNode *N) {
73006f32e7eSjoerg   SDValue Chain = N->getOperand(0); // Get the chain.
73106f32e7eSjoerg   SDValue Ptr = N->getOperand(1); // Get the pointer.
73206f32e7eSjoerg   EVT VT = N->getValueType(0);
73306f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
73406f32e7eSjoerg   SDLoc dl(N);
73506f32e7eSjoerg 
73606f32e7eSjoerg   SDValue NewVAARG;
73706f32e7eSjoerg   NewVAARG = DAG.getVAArg(NVT, dl, Chain, Ptr, N->getOperand(2),
73806f32e7eSjoerg                           N->getConstantOperandVal(3));
73906f32e7eSjoerg 
74006f32e7eSjoerg   // Legalized the chain result - switch anything that used the old chain to
74106f32e7eSjoerg   // use the new one.
74206f32e7eSjoerg   if (N != NewVAARG.getValue(1).getNode())
74306f32e7eSjoerg     ReplaceValueWith(SDValue(N, 1), NewVAARG.getValue(1));
74406f32e7eSjoerg   return NewVAARG;
74506f32e7eSjoerg }
74606f32e7eSjoerg 
SoftenFloatRes_XINT_TO_FP(SDNode * N)74706f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_XINT_TO_FP(SDNode *N) {
748*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
749*da58b97aSjoerg   bool Signed = N->getOpcode() == ISD::SINT_TO_FP ||
750*da58b97aSjoerg                 N->getOpcode() == ISD::STRICT_SINT_TO_FP;
751*da58b97aSjoerg   EVT SVT = N->getOperand(IsStrict ? 1 : 0).getValueType();
75206f32e7eSjoerg   EVT RVT = N->getValueType(0);
75306f32e7eSjoerg   EVT NVT = EVT();
75406f32e7eSjoerg   SDLoc dl(N);
75506f32e7eSjoerg 
75606f32e7eSjoerg   // If the input is not legal, eg: i1 -> fp, then it needs to be promoted to
75706f32e7eSjoerg   // a larger type, eg: i8 -> fp.  Even if it is legal, no libcall may exactly
75806f32e7eSjoerg   // match.  Look for an appropriate libcall.
75906f32e7eSjoerg   RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
76006f32e7eSjoerg   for (unsigned t = MVT::FIRST_INTEGER_VALUETYPE;
76106f32e7eSjoerg        t <= MVT::LAST_INTEGER_VALUETYPE && LC == RTLIB::UNKNOWN_LIBCALL; ++t) {
76206f32e7eSjoerg     NVT = (MVT::SimpleValueType)t;
76306f32e7eSjoerg     // The source needs to big enough to hold the operand.
76406f32e7eSjoerg     if (NVT.bitsGE(SVT))
76506f32e7eSjoerg       LC = Signed ? RTLIB::getSINTTOFP(NVT, RVT):RTLIB::getUINTTOFP (NVT, RVT);
76606f32e7eSjoerg   }
76706f32e7eSjoerg   assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!");
76806f32e7eSjoerg 
769*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
77006f32e7eSjoerg   // Sign/zero extend the argument if the libcall takes a larger type.
77106f32e7eSjoerg   SDValue Op = DAG.getNode(Signed ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, dl,
772*da58b97aSjoerg                            NVT, N->getOperand(IsStrict ? 1 : 0));
77306f32e7eSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
77406f32e7eSjoerg   CallOptions.setSExt(Signed);
775*da58b97aSjoerg   CallOptions.setTypeListBeforeSoften(SVT, RVT, true);
776*da58b97aSjoerg   std::pair<SDValue, SDValue> Tmp =
777*da58b97aSjoerg       TLI.makeLibCall(DAG, LC, TLI.getTypeToTransformTo(*DAG.getContext(), RVT),
778*da58b97aSjoerg                       Op, CallOptions, dl, Chain);
779*da58b97aSjoerg 
780*da58b97aSjoerg   if (IsStrict)
781*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Tmp.second);
782*da58b97aSjoerg   return Tmp.first;
78306f32e7eSjoerg }
78406f32e7eSjoerg 
SoftenFloatRes_VECREDUCE(SDNode * N)785*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_VECREDUCE(SDNode *N) {
786*da58b97aSjoerg   // Expand and soften recursively.
787*da58b97aSjoerg   ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduce(N, DAG));
788*da58b97aSjoerg   return SDValue();
789*da58b97aSjoerg }
790*da58b97aSjoerg 
SoftenFloatRes_VECREDUCE_SEQ(SDNode * N)791*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftenFloatRes_VECREDUCE_SEQ(SDNode *N) {
792*da58b97aSjoerg   ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduceSeq(N, DAG));
793*da58b97aSjoerg   return SDValue();
794*da58b97aSjoerg }
79506f32e7eSjoerg 
79606f32e7eSjoerg //===----------------------------------------------------------------------===//
79706f32e7eSjoerg //  Convert Float Operand to Integer
79806f32e7eSjoerg //===----------------------------------------------------------------------===//
79906f32e7eSjoerg 
SoftenFloatOperand(SDNode * N,unsigned OpNo)80006f32e7eSjoerg bool DAGTypeLegalizer::SoftenFloatOperand(SDNode *N, unsigned OpNo) {
80106f32e7eSjoerg   LLVM_DEBUG(dbgs() << "Soften float operand " << OpNo << ": "; N->dump(&DAG);
80206f32e7eSjoerg              dbgs() << "\n");
80306f32e7eSjoerg   SDValue Res = SDValue();
80406f32e7eSjoerg 
80506f32e7eSjoerg   switch (N->getOpcode()) {
80606f32e7eSjoerg   default:
80706f32e7eSjoerg #ifndef NDEBUG
80806f32e7eSjoerg     dbgs() << "SoftenFloatOperand Op #" << OpNo << ": ";
80906f32e7eSjoerg     N->dump(&DAG); dbgs() << "\n";
81006f32e7eSjoerg #endif
81106f32e7eSjoerg     llvm_unreachable("Do not know how to soften this operator's operand!");
81206f32e7eSjoerg 
81306f32e7eSjoerg   case ISD::BITCAST:     Res = SoftenFloatOp_BITCAST(N); break;
81406f32e7eSjoerg   case ISD::BR_CC:       Res = SoftenFloatOp_BR_CC(N); break;
81506f32e7eSjoerg   case ISD::FP_TO_FP16:  // Same as FP_ROUND for softening purposes
816*da58b97aSjoerg   case ISD::STRICT_FP_ROUND:
81706f32e7eSjoerg   case ISD::FP_ROUND:    Res = SoftenFloatOp_FP_ROUND(N); break;
818*da58b97aSjoerg   case ISD::STRICT_FP_TO_SINT:
819*da58b97aSjoerg   case ISD::STRICT_FP_TO_UINT:
82006f32e7eSjoerg   case ISD::FP_TO_SINT:
82106f32e7eSjoerg   case ISD::FP_TO_UINT:  Res = SoftenFloatOp_FP_TO_XINT(N); break;
822*da58b97aSjoerg   case ISD::FP_TO_SINT_SAT:
823*da58b97aSjoerg   case ISD::FP_TO_UINT_SAT:
824*da58b97aSjoerg                          Res = SoftenFloatOp_FP_TO_XINT_SAT(N); break;
825*da58b97aSjoerg   case ISD::STRICT_LROUND:
82606f32e7eSjoerg   case ISD::LROUND:      Res = SoftenFloatOp_LROUND(N); break;
827*da58b97aSjoerg   case ISD::STRICT_LLROUND:
82806f32e7eSjoerg   case ISD::LLROUND:     Res = SoftenFloatOp_LLROUND(N); break;
829*da58b97aSjoerg   case ISD::STRICT_LRINT:
83006f32e7eSjoerg   case ISD::LRINT:       Res = SoftenFloatOp_LRINT(N); break;
831*da58b97aSjoerg   case ISD::STRICT_LLRINT:
83206f32e7eSjoerg   case ISD::LLRINT:      Res = SoftenFloatOp_LLRINT(N); break;
83306f32e7eSjoerg   case ISD::SELECT_CC:   Res = SoftenFloatOp_SELECT_CC(N); break;
834*da58b97aSjoerg   case ISD::STRICT_FSETCC:
835*da58b97aSjoerg   case ISD::STRICT_FSETCCS:
83606f32e7eSjoerg   case ISD::SETCC:       Res = SoftenFloatOp_SETCC(N); break;
83706f32e7eSjoerg   case ISD::STORE:       Res = SoftenFloatOp_STORE(N, OpNo); break;
838*da58b97aSjoerg   case ISD::FCOPYSIGN:   Res = SoftenFloatOp_FCOPYSIGN(N); break;
83906f32e7eSjoerg   }
84006f32e7eSjoerg 
84106f32e7eSjoerg   // If the result is null, the sub-method took care of registering results etc.
84206f32e7eSjoerg   if (!Res.getNode()) return false;
84306f32e7eSjoerg 
84406f32e7eSjoerg   // If the result is N, the sub-method updated N in place.  Tell the legalizer
84506f32e7eSjoerg   // core about this to re-analyze.
84606f32e7eSjoerg   if (Res.getNode() == N)
84706f32e7eSjoerg     return true;
84806f32e7eSjoerg 
84906f32e7eSjoerg   assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
850*da58b97aSjoerg          "Invalid operand softening");
85106f32e7eSjoerg 
85206f32e7eSjoerg   ReplaceValueWith(SDValue(N, 0), Res);
85306f32e7eSjoerg   return false;
85406f32e7eSjoerg }
85506f32e7eSjoerg 
SoftenFloatOp_BITCAST(SDNode * N)85606f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatOp_BITCAST(SDNode *N) {
85706f32e7eSjoerg   SDValue Op0 = GetSoftenedFloat(N->getOperand(0));
85806f32e7eSjoerg 
85906f32e7eSjoerg   return DAG.getNode(ISD::BITCAST, SDLoc(N), N->getValueType(0), Op0);
86006f32e7eSjoerg }
86106f32e7eSjoerg 
SoftenFloatOp_FP_ROUND(SDNode * N)86206f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatOp_FP_ROUND(SDNode *N) {
86306f32e7eSjoerg   // We actually deal with the partially-softened FP_TO_FP16 node too, which
86406f32e7eSjoerg   // returns an i16 so doesn't meet the constraints necessary for FP_ROUND.
865*da58b97aSjoerg   assert(N->getOpcode() == ISD::FP_ROUND || N->getOpcode() == ISD::FP_TO_FP16 ||
866*da58b97aSjoerg          N->getOpcode() == ISD::STRICT_FP_ROUND);
86706f32e7eSjoerg 
868*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
869*da58b97aSjoerg   SDValue Op = N->getOperand(IsStrict ? 1 : 0);
870*da58b97aSjoerg   EVT SVT = Op.getValueType();
87106f32e7eSjoerg   EVT RVT = N->getValueType(0);
87206f32e7eSjoerg   EVT FloatRVT = N->getOpcode() == ISD::FP_TO_FP16 ? MVT::f16 : RVT;
87306f32e7eSjoerg 
87406f32e7eSjoerg   RTLIB::Libcall LC = RTLIB::getFPROUND(SVT, FloatRVT);
87506f32e7eSjoerg   assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_ROUND libcall");
87606f32e7eSjoerg 
877*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
878*da58b97aSjoerg   Op = GetSoftenedFloat(Op);
87906f32e7eSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
880*da58b97aSjoerg   CallOptions.setTypeListBeforeSoften(SVT, RVT, true);
881*da58b97aSjoerg   std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, RVT, Op,
882*da58b97aSjoerg                                                     CallOptions, SDLoc(N),
883*da58b97aSjoerg                                                     Chain);
884*da58b97aSjoerg   if (IsStrict) {
885*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Tmp.second);
886*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 0), Tmp.first);
887*da58b97aSjoerg     return SDValue();
888*da58b97aSjoerg   }
889*da58b97aSjoerg   return Tmp.first;
89006f32e7eSjoerg }
89106f32e7eSjoerg 
SoftenFloatOp_BR_CC(SDNode * N)89206f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatOp_BR_CC(SDNode *N) {
89306f32e7eSjoerg   SDValue NewLHS = N->getOperand(2), NewRHS = N->getOperand(3);
89406f32e7eSjoerg   ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(1))->get();
89506f32e7eSjoerg 
89606f32e7eSjoerg   EVT VT = NewLHS.getValueType();
89706f32e7eSjoerg   NewLHS = GetSoftenedFloat(NewLHS);
89806f32e7eSjoerg   NewRHS = GetSoftenedFloat(NewRHS);
89906f32e7eSjoerg   TLI.softenSetCCOperands(DAG, VT, NewLHS, NewRHS, CCCode, SDLoc(N),
90006f32e7eSjoerg                           N->getOperand(2), N->getOperand(3));
90106f32e7eSjoerg 
90206f32e7eSjoerg   // If softenSetCCOperands returned a scalar, we need to compare the result
90306f32e7eSjoerg   // against zero to select between true and false values.
90406f32e7eSjoerg   if (!NewRHS.getNode()) {
90506f32e7eSjoerg     NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
90606f32e7eSjoerg     CCCode = ISD::SETNE;
90706f32e7eSjoerg   }
90806f32e7eSjoerg 
90906f32e7eSjoerg   // Update N to have the operands specified.
91006f32e7eSjoerg   return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0),
91106f32e7eSjoerg                                 DAG.getCondCode(CCCode), NewLHS, NewRHS,
91206f32e7eSjoerg                                 N->getOperand(4)),
91306f32e7eSjoerg                  0);
91406f32e7eSjoerg }
91506f32e7eSjoerg 
916*da58b97aSjoerg // Even if the result type is legal, no libcall may exactly match. (e.g. We
917*da58b97aSjoerg // don't have FP-i8 conversions) This helper method looks for an appropriate
918*da58b97aSjoerg // promoted libcall.
findFPToIntLibcall(EVT SrcVT,EVT RetVT,EVT & Promoted,bool Signed)919*da58b97aSjoerg static RTLIB::Libcall findFPToIntLibcall(EVT SrcVT, EVT RetVT, EVT &Promoted,
920*da58b97aSjoerg                                          bool Signed) {
921*da58b97aSjoerg   RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
922*da58b97aSjoerg   for (unsigned IntVT = MVT::FIRST_INTEGER_VALUETYPE;
923*da58b97aSjoerg        IntVT <= MVT::LAST_INTEGER_VALUETYPE && LC == RTLIB::UNKNOWN_LIBCALL;
924*da58b97aSjoerg        ++IntVT) {
925*da58b97aSjoerg     Promoted = (MVT::SimpleValueType)IntVT;
926*da58b97aSjoerg     // The type needs to big enough to hold the result.
927*da58b97aSjoerg     if (Promoted.bitsGE(RetVT))
928*da58b97aSjoerg       LC = Signed ? RTLIB::getFPTOSINT(SrcVT, Promoted)
929*da58b97aSjoerg                   : RTLIB::getFPTOUINT(SrcVT, Promoted);
930*da58b97aSjoerg   }
931*da58b97aSjoerg   return LC;
932*da58b97aSjoerg }
933*da58b97aSjoerg 
SoftenFloatOp_FP_TO_XINT(SDNode * N)93406f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_XINT(SDNode *N) {
935*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
936*da58b97aSjoerg   bool Signed = N->getOpcode() == ISD::FP_TO_SINT ||
937*da58b97aSjoerg                 N->getOpcode() == ISD::STRICT_FP_TO_SINT;
938*da58b97aSjoerg 
939*da58b97aSjoerg   SDValue Op = N->getOperand(IsStrict ? 1 : 0);
940*da58b97aSjoerg   EVT SVT = Op.getValueType();
94106f32e7eSjoerg   EVT RVT = N->getValueType(0);
94206f32e7eSjoerg   EVT NVT = EVT();
94306f32e7eSjoerg   SDLoc dl(N);
94406f32e7eSjoerg 
94506f32e7eSjoerg   // If the result is not legal, eg: fp -> i1, then it needs to be promoted to
94606f32e7eSjoerg   // a larger type, eg: fp -> i32. Even if it is legal, no libcall may exactly
94706f32e7eSjoerg   // match, eg. we don't have fp -> i8 conversions.
94806f32e7eSjoerg   // Look for an appropriate libcall.
949*da58b97aSjoerg   RTLIB::Libcall LC = findFPToIntLibcall(SVT, RVT, NVT, Signed);
950*da58b97aSjoerg   assert(LC != RTLIB::UNKNOWN_LIBCALL && NVT.isSimple() &&
951*da58b97aSjoerg          "Unsupported FP_TO_XINT!");
95206f32e7eSjoerg 
953*da58b97aSjoerg   Op = GetSoftenedFloat(Op);
954*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
95506f32e7eSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
956*da58b97aSjoerg   CallOptions.setTypeListBeforeSoften(SVT, RVT, true);
957*da58b97aSjoerg   std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, NVT, Op,
958*da58b97aSjoerg                                                     CallOptions, dl, Chain);
95906f32e7eSjoerg 
96006f32e7eSjoerg   // Truncate the result if the libcall returns a larger type.
961*da58b97aSjoerg   SDValue Res = DAG.getNode(ISD::TRUNCATE, dl, RVT, Tmp.first);
962*da58b97aSjoerg 
963*da58b97aSjoerg   if (!IsStrict)
964*da58b97aSjoerg     return Res;
965*da58b97aSjoerg 
966*da58b97aSjoerg   ReplaceValueWith(SDValue(N, 1), Tmp.second);
967*da58b97aSjoerg   ReplaceValueWith(SDValue(N, 0), Res);
968*da58b97aSjoerg   return SDValue();
969*da58b97aSjoerg }
970*da58b97aSjoerg 
SoftenFloatOp_FP_TO_XINT_SAT(SDNode * N)971*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_XINT_SAT(SDNode *N) {
972*da58b97aSjoerg   SDValue Res = TLI.expandFP_TO_INT_SAT(N, DAG);
973*da58b97aSjoerg   return Res;
97406f32e7eSjoerg }
97506f32e7eSjoerg 
SoftenFloatOp_SELECT_CC(SDNode * N)97606f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatOp_SELECT_CC(SDNode *N) {
97706f32e7eSjoerg   SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
97806f32e7eSjoerg   ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(4))->get();
97906f32e7eSjoerg 
98006f32e7eSjoerg   EVT VT = NewLHS.getValueType();
98106f32e7eSjoerg   NewLHS = GetSoftenedFloat(NewLHS);
98206f32e7eSjoerg   NewRHS = GetSoftenedFloat(NewRHS);
98306f32e7eSjoerg   TLI.softenSetCCOperands(DAG, VT, NewLHS, NewRHS, CCCode, SDLoc(N),
98406f32e7eSjoerg                           N->getOperand(0), N->getOperand(1));
98506f32e7eSjoerg 
98606f32e7eSjoerg   // If softenSetCCOperands returned a scalar, we need to compare the result
98706f32e7eSjoerg   // against zero to select between true and false values.
98806f32e7eSjoerg   if (!NewRHS.getNode()) {
98906f32e7eSjoerg     NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
99006f32e7eSjoerg     CCCode = ISD::SETNE;
99106f32e7eSjoerg   }
99206f32e7eSjoerg 
99306f32e7eSjoerg   // Update N to have the operands specified.
99406f32e7eSjoerg   return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
99506f32e7eSjoerg                                 N->getOperand(2), N->getOperand(3),
99606f32e7eSjoerg                                 DAG.getCondCode(CCCode)),
99706f32e7eSjoerg                  0);
99806f32e7eSjoerg }
99906f32e7eSjoerg 
SoftenFloatOp_SETCC(SDNode * N)100006f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatOp_SETCC(SDNode *N) {
1001*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
1002*da58b97aSjoerg   SDValue Op0 = N->getOperand(IsStrict ? 1 : 0);
1003*da58b97aSjoerg   SDValue Op1 = N->getOperand(IsStrict ? 2 : 1);
1004*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1005*da58b97aSjoerg   ISD::CondCode CCCode =
1006*da58b97aSjoerg       cast<CondCodeSDNode>(N->getOperand(IsStrict ? 3 : 2))->get();
100706f32e7eSjoerg 
1008*da58b97aSjoerg   EVT VT = Op0.getValueType();
1009*da58b97aSjoerg   SDValue NewLHS = GetSoftenedFloat(Op0);
1010*da58b97aSjoerg   SDValue NewRHS = GetSoftenedFloat(Op1);
1011*da58b97aSjoerg   TLI.softenSetCCOperands(DAG, VT, NewLHS, NewRHS, CCCode, SDLoc(N), Op0, Op1,
1012*da58b97aSjoerg                           Chain, N->getOpcode() == ISD::STRICT_FSETCCS);
101306f32e7eSjoerg 
1014*da58b97aSjoerg   // Update N to have the operands specified.
1015*da58b97aSjoerg   if (NewRHS.getNode()) {
1016*da58b97aSjoerg     if (IsStrict)
1017*da58b97aSjoerg       NewLHS = DAG.getNode(ISD::SETCC, SDLoc(N), N->getValueType(0), NewLHS,
1018*da58b97aSjoerg                            NewRHS, DAG.getCondCode(CCCode));
1019*da58b97aSjoerg     else
1020*da58b97aSjoerg       return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
1021*da58b97aSjoerg                                             DAG.getCondCode(CCCode)), 0);
102206f32e7eSjoerg   }
102306f32e7eSjoerg 
1024*da58b97aSjoerg   // Otherwise, softenSetCCOperands returned a scalar, use it.
1025*da58b97aSjoerg   assert((NewRHS.getNode() || NewLHS.getValueType() == N->getValueType(0)) &&
1026*da58b97aSjoerg          "Unexpected setcc expansion!");
1027*da58b97aSjoerg 
1028*da58b97aSjoerg   if (IsStrict) {
1029*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 0), NewLHS);
1030*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Chain);
1031*da58b97aSjoerg     return SDValue();
1032*da58b97aSjoerg   }
1033*da58b97aSjoerg   return NewLHS;
103406f32e7eSjoerg }
103506f32e7eSjoerg 
SoftenFloatOp_STORE(SDNode * N,unsigned OpNo)103606f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatOp_STORE(SDNode *N, unsigned OpNo) {
103706f32e7eSjoerg   assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!");
103806f32e7eSjoerg   assert(OpNo == 1 && "Can only soften the stored value!");
103906f32e7eSjoerg   StoreSDNode *ST = cast<StoreSDNode>(N);
104006f32e7eSjoerg   SDValue Val = ST->getValue();
104106f32e7eSjoerg   SDLoc dl(N);
104206f32e7eSjoerg 
104306f32e7eSjoerg   if (ST->isTruncatingStore())
104406f32e7eSjoerg     // Do an FP_ROUND followed by a non-truncating store.
104506f32e7eSjoerg     Val = BitConvertToInteger(DAG.getNode(ISD::FP_ROUND, dl, ST->getMemoryVT(),
104606f32e7eSjoerg                                           Val, DAG.getIntPtrConstant(0, dl)));
104706f32e7eSjoerg   else
104806f32e7eSjoerg     Val = GetSoftenedFloat(Val);
104906f32e7eSjoerg 
105006f32e7eSjoerg   return DAG.getStore(ST->getChain(), dl, Val, ST->getBasePtr(),
105106f32e7eSjoerg                       ST->getMemOperand());
105206f32e7eSjoerg }
105306f32e7eSjoerg 
SoftenFloatOp_FCOPYSIGN(SDNode * N)1054*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftenFloatOp_FCOPYSIGN(SDNode *N) {
1055*da58b97aSjoerg   SDValue LHS = N->getOperand(0);
1056*da58b97aSjoerg   SDValue RHS = BitConvertToInteger(N->getOperand(1));
1057*da58b97aSjoerg   SDLoc dl(N);
105806f32e7eSjoerg 
1059*da58b97aSjoerg   EVT LVT = LHS.getValueType();
1060*da58b97aSjoerg   EVT ILVT = EVT::getIntegerVT(*DAG.getContext(), LVT.getSizeInBits());
1061*da58b97aSjoerg   EVT RVT = RHS.getValueType();
1062*da58b97aSjoerg 
1063*da58b97aSjoerg   unsigned LSize = LVT.getSizeInBits();
1064*da58b97aSjoerg   unsigned RSize = RVT.getSizeInBits();
1065*da58b97aSjoerg 
1066*da58b97aSjoerg   // Shift right or sign-extend it if the two operands have different types.
1067*da58b97aSjoerg   int SizeDiff = RSize - LSize;
1068*da58b97aSjoerg   if (SizeDiff > 0) {
1069*da58b97aSjoerg     RHS =
1070*da58b97aSjoerg         DAG.getNode(ISD::SRL, dl, RVT, RHS,
1071*da58b97aSjoerg                     DAG.getConstant(SizeDiff, dl,
1072*da58b97aSjoerg                                     TLI.getShiftAmountTy(RHS.getValueType(),
1073*da58b97aSjoerg                                                          DAG.getDataLayout())));
1074*da58b97aSjoerg     RHS = DAG.getNode(ISD::TRUNCATE, dl, ILVT, RHS);
1075*da58b97aSjoerg   } else if (SizeDiff < 0) {
1076*da58b97aSjoerg     RHS = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, RHS);
1077*da58b97aSjoerg     RHS =
1078*da58b97aSjoerg         DAG.getNode(ISD::SHL, dl, ILVT, RHS,
1079*da58b97aSjoerg                     DAG.getConstant(-SizeDiff, dl,
1080*da58b97aSjoerg                                     TLI.getShiftAmountTy(RHS.getValueType(),
1081*da58b97aSjoerg                                                          DAG.getDataLayout())));
1082*da58b97aSjoerg   }
1083*da58b97aSjoerg 
1084*da58b97aSjoerg   RHS = DAG.getBitcast(LVT, RHS);
1085*da58b97aSjoerg   return DAG.getNode(ISD::FCOPYSIGN, dl, LVT, LHS, RHS);
1086*da58b97aSjoerg }
1087*da58b97aSjoerg 
SoftenFloatOp_Unary(SDNode * N,RTLIB::Libcall LC)1088*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftenFloatOp_Unary(SDNode *N, RTLIB::Libcall LC) {
1089*da58b97aSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
1090*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
1091*da58b97aSjoerg   unsigned Offset = IsStrict ? 1 : 0;
1092*da58b97aSjoerg   SDValue Op = GetSoftenedFloat(N->getOperand(0 + Offset));
1093*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
109406f32e7eSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
1095*da58b97aSjoerg   EVT OpVT = N->getOperand(0 + Offset).getValueType();
1096*da58b97aSjoerg   CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0), true);
1097*da58b97aSjoerg   std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, NVT, Op,
1098*da58b97aSjoerg                                                     CallOptions, SDLoc(N),
1099*da58b97aSjoerg                                                     Chain);
1100*da58b97aSjoerg   if (IsStrict) {
1101*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Tmp.second);
1102*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 0), Tmp.first);
1103*da58b97aSjoerg     return SDValue();
1104*da58b97aSjoerg   }
1105*da58b97aSjoerg 
1106*da58b97aSjoerg   return Tmp.first;
1107*da58b97aSjoerg }
1108*da58b97aSjoerg 
SoftenFloatOp_LROUND(SDNode * N)1109*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftenFloatOp_LROUND(SDNode *N) {
1110*da58b97aSjoerg   EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1111*da58b97aSjoerg   return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
111206f32e7eSjoerg                                              RTLIB::LROUND_F32,
111306f32e7eSjoerg                                              RTLIB::LROUND_F64,
111406f32e7eSjoerg                                              RTLIB::LROUND_F80,
111506f32e7eSjoerg                                              RTLIB::LROUND_F128,
1116*da58b97aSjoerg                                              RTLIB::LROUND_PPCF128));
111706f32e7eSjoerg }
111806f32e7eSjoerg 
SoftenFloatOp_LLROUND(SDNode * N)111906f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatOp_LLROUND(SDNode *N) {
1120*da58b97aSjoerg   EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1121*da58b97aSjoerg   return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
112206f32e7eSjoerg                                              RTLIB::LLROUND_F32,
112306f32e7eSjoerg                                              RTLIB::LLROUND_F64,
112406f32e7eSjoerg                                              RTLIB::LLROUND_F80,
112506f32e7eSjoerg                                              RTLIB::LLROUND_F128,
1126*da58b97aSjoerg                                              RTLIB::LLROUND_PPCF128));
112706f32e7eSjoerg }
112806f32e7eSjoerg 
SoftenFloatOp_LRINT(SDNode * N)112906f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatOp_LRINT(SDNode *N) {
1130*da58b97aSjoerg   EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1131*da58b97aSjoerg   return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
113206f32e7eSjoerg                                              RTLIB::LRINT_F32,
113306f32e7eSjoerg                                              RTLIB::LRINT_F64,
113406f32e7eSjoerg                                              RTLIB::LRINT_F80,
113506f32e7eSjoerg                                              RTLIB::LRINT_F128,
1136*da58b97aSjoerg                                              RTLIB::LRINT_PPCF128));
113706f32e7eSjoerg }
113806f32e7eSjoerg 
SoftenFloatOp_LLRINT(SDNode * N)113906f32e7eSjoerg SDValue DAGTypeLegalizer::SoftenFloatOp_LLRINT(SDNode *N) {
1140*da58b97aSjoerg   EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1141*da58b97aSjoerg   return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
114206f32e7eSjoerg                                              RTLIB::LLRINT_F32,
114306f32e7eSjoerg                                              RTLIB::LLRINT_F64,
114406f32e7eSjoerg                                              RTLIB::LLRINT_F80,
114506f32e7eSjoerg                                              RTLIB::LLRINT_F128,
1146*da58b97aSjoerg                                              RTLIB::LLRINT_PPCF128));
114706f32e7eSjoerg }
114806f32e7eSjoerg 
114906f32e7eSjoerg //===----------------------------------------------------------------------===//
115006f32e7eSjoerg //  Float Result Expansion
115106f32e7eSjoerg //===----------------------------------------------------------------------===//
115206f32e7eSjoerg 
115306f32e7eSjoerg /// ExpandFloatResult - This method is called when the specified result of the
115406f32e7eSjoerg /// specified node is found to need expansion.  At this point, the node may also
115506f32e7eSjoerg /// have invalid operands or may have other results that need promotion, we just
115606f32e7eSjoerg /// know that (at least) one result needs expansion.
ExpandFloatResult(SDNode * N,unsigned ResNo)115706f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) {
115806f32e7eSjoerg   LLVM_DEBUG(dbgs() << "Expand float result: "; N->dump(&DAG); dbgs() << "\n");
115906f32e7eSjoerg   SDValue Lo, Hi;
116006f32e7eSjoerg   Lo = Hi = SDValue();
116106f32e7eSjoerg 
116206f32e7eSjoerg   // See if the target wants to custom expand this node.
116306f32e7eSjoerg   if (CustomLowerNode(N, N->getValueType(ResNo), true))
116406f32e7eSjoerg     return;
116506f32e7eSjoerg 
116606f32e7eSjoerg   switch (N->getOpcode()) {
116706f32e7eSjoerg   default:
116806f32e7eSjoerg #ifndef NDEBUG
116906f32e7eSjoerg     dbgs() << "ExpandFloatResult #" << ResNo << ": ";
117006f32e7eSjoerg     N->dump(&DAG); dbgs() << "\n";
117106f32e7eSjoerg #endif
117206f32e7eSjoerg     llvm_unreachable("Do not know how to expand the result of this operator!");
117306f32e7eSjoerg 
117406f32e7eSjoerg   case ISD::UNDEF:        SplitRes_UNDEF(N, Lo, Hi); break;
117506f32e7eSjoerg   case ISD::SELECT:       SplitRes_SELECT(N, Lo, Hi); break;
117606f32e7eSjoerg   case ISD::SELECT_CC:    SplitRes_SELECT_CC(N, Lo, Hi); break;
117706f32e7eSjoerg 
117806f32e7eSjoerg   case ISD::MERGE_VALUES:       ExpandRes_MERGE_VALUES(N, ResNo, Lo, Hi); break;
117906f32e7eSjoerg   case ISD::BITCAST:            ExpandRes_BITCAST(N, Lo, Hi); break;
118006f32e7eSjoerg   case ISD::BUILD_PAIR:         ExpandRes_BUILD_PAIR(N, Lo, Hi); break;
118106f32e7eSjoerg   case ISD::EXTRACT_ELEMENT:    ExpandRes_EXTRACT_ELEMENT(N, Lo, Hi); break;
118206f32e7eSjoerg   case ISD::EXTRACT_VECTOR_ELT: ExpandRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); break;
118306f32e7eSjoerg   case ISD::VAARG:              ExpandRes_VAARG(N, Lo, Hi); break;
118406f32e7eSjoerg 
118506f32e7eSjoerg   case ISD::ConstantFP: ExpandFloatRes_ConstantFP(N, Lo, Hi); break;
118606f32e7eSjoerg   case ISD::FABS:       ExpandFloatRes_FABS(N, Lo, Hi); break;
1187*da58b97aSjoerg   case ISD::STRICT_FMINNUM:
118806f32e7eSjoerg   case ISD::FMINNUM:    ExpandFloatRes_FMINNUM(N, Lo, Hi); break;
1189*da58b97aSjoerg   case ISD::STRICT_FMAXNUM:
119006f32e7eSjoerg   case ISD::FMAXNUM:    ExpandFloatRes_FMAXNUM(N, Lo, Hi); break;
1191*da58b97aSjoerg   case ISD::STRICT_FADD:
119206f32e7eSjoerg   case ISD::FADD:       ExpandFloatRes_FADD(N, Lo, Hi); break;
119306f32e7eSjoerg   case ISD::FCBRT:      ExpandFloatRes_FCBRT(N, Lo, Hi); break;
1194*da58b97aSjoerg   case ISD::STRICT_FCEIL:
119506f32e7eSjoerg   case ISD::FCEIL:      ExpandFloatRes_FCEIL(N, Lo, Hi); break;
119606f32e7eSjoerg   case ISD::FCOPYSIGN:  ExpandFloatRes_FCOPYSIGN(N, Lo, Hi); break;
1197*da58b97aSjoerg   case ISD::STRICT_FCOS:
119806f32e7eSjoerg   case ISD::FCOS:       ExpandFloatRes_FCOS(N, Lo, Hi); break;
1199*da58b97aSjoerg   case ISD::STRICT_FDIV:
120006f32e7eSjoerg   case ISD::FDIV:       ExpandFloatRes_FDIV(N, Lo, Hi); break;
1201*da58b97aSjoerg   case ISD::STRICT_FEXP:
120206f32e7eSjoerg   case ISD::FEXP:       ExpandFloatRes_FEXP(N, Lo, Hi); break;
1203*da58b97aSjoerg   case ISD::STRICT_FEXP2:
120406f32e7eSjoerg   case ISD::FEXP2:      ExpandFloatRes_FEXP2(N, Lo, Hi); break;
1205*da58b97aSjoerg   case ISD::STRICT_FFLOOR:
120606f32e7eSjoerg   case ISD::FFLOOR:     ExpandFloatRes_FFLOOR(N, Lo, Hi); break;
1207*da58b97aSjoerg   case ISD::STRICT_FLOG:
120806f32e7eSjoerg   case ISD::FLOG:       ExpandFloatRes_FLOG(N, Lo, Hi); break;
1209*da58b97aSjoerg   case ISD::STRICT_FLOG2:
121006f32e7eSjoerg   case ISD::FLOG2:      ExpandFloatRes_FLOG2(N, Lo, Hi); break;
1211*da58b97aSjoerg   case ISD::STRICT_FLOG10:
121206f32e7eSjoerg   case ISD::FLOG10:     ExpandFloatRes_FLOG10(N, Lo, Hi); break;
1213*da58b97aSjoerg   case ISD::STRICT_FMA:
121406f32e7eSjoerg   case ISD::FMA:        ExpandFloatRes_FMA(N, Lo, Hi); break;
1215*da58b97aSjoerg   case ISD::STRICT_FMUL:
121606f32e7eSjoerg   case ISD::FMUL:       ExpandFloatRes_FMUL(N, Lo, Hi); break;
1217*da58b97aSjoerg   case ISD::STRICT_FNEARBYINT:
121806f32e7eSjoerg   case ISD::FNEARBYINT: ExpandFloatRes_FNEARBYINT(N, Lo, Hi); break;
121906f32e7eSjoerg   case ISD::FNEG:       ExpandFloatRes_FNEG(N, Lo, Hi); break;
1220*da58b97aSjoerg   case ISD::STRICT_FP_EXTEND:
122106f32e7eSjoerg   case ISD::FP_EXTEND:  ExpandFloatRes_FP_EXTEND(N, Lo, Hi); break;
1222*da58b97aSjoerg   case ISD::STRICT_FPOW:
122306f32e7eSjoerg   case ISD::FPOW:       ExpandFloatRes_FPOW(N, Lo, Hi); break;
1224*da58b97aSjoerg   case ISD::STRICT_FPOWI:
122506f32e7eSjoerg   case ISD::FPOWI:      ExpandFloatRes_FPOWI(N, Lo, Hi); break;
1226*da58b97aSjoerg   case ISD::FREEZE:     ExpandFloatRes_FREEZE(N, Lo, Hi); break;
1227*da58b97aSjoerg   case ISD::STRICT_FRINT:
122806f32e7eSjoerg   case ISD::FRINT:      ExpandFloatRes_FRINT(N, Lo, Hi); break;
1229*da58b97aSjoerg   case ISD::STRICT_FROUND:
123006f32e7eSjoerg   case ISD::FROUND:     ExpandFloatRes_FROUND(N, Lo, Hi); break;
1231*da58b97aSjoerg   case ISD::STRICT_FROUNDEVEN:
1232*da58b97aSjoerg   case ISD::FROUNDEVEN: ExpandFloatRes_FROUNDEVEN(N, Lo, Hi); break;
1233*da58b97aSjoerg   case ISD::STRICT_FSIN:
123406f32e7eSjoerg   case ISD::FSIN:       ExpandFloatRes_FSIN(N, Lo, Hi); break;
1235*da58b97aSjoerg   case ISD::STRICT_FSQRT:
123606f32e7eSjoerg   case ISD::FSQRT:      ExpandFloatRes_FSQRT(N, Lo, Hi); break;
1237*da58b97aSjoerg   case ISD::STRICT_FSUB:
123806f32e7eSjoerg   case ISD::FSUB:       ExpandFloatRes_FSUB(N, Lo, Hi); break;
1239*da58b97aSjoerg   case ISD::STRICT_FTRUNC:
124006f32e7eSjoerg   case ISD::FTRUNC:     ExpandFloatRes_FTRUNC(N, Lo, Hi); break;
124106f32e7eSjoerg   case ISD::LOAD:       ExpandFloatRes_LOAD(N, Lo, Hi); break;
1242*da58b97aSjoerg   case ISD::STRICT_SINT_TO_FP:
1243*da58b97aSjoerg   case ISD::STRICT_UINT_TO_FP:
124406f32e7eSjoerg   case ISD::SINT_TO_FP:
124506f32e7eSjoerg   case ISD::UINT_TO_FP: ExpandFloatRes_XINT_TO_FP(N, Lo, Hi); break;
1246*da58b97aSjoerg   case ISD::STRICT_FREM:
124706f32e7eSjoerg   case ISD::FREM:       ExpandFloatRes_FREM(N, Lo, Hi); break;
124806f32e7eSjoerg   }
124906f32e7eSjoerg 
125006f32e7eSjoerg   // If Lo/Hi is null, the sub-method took care of registering results etc.
125106f32e7eSjoerg   if (Lo.getNode())
125206f32e7eSjoerg     SetExpandedFloat(SDValue(N, ResNo), Lo, Hi);
125306f32e7eSjoerg }
125406f32e7eSjoerg 
ExpandFloatRes_ConstantFP(SDNode * N,SDValue & Lo,SDValue & Hi)125506f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_ConstantFP(SDNode *N, SDValue &Lo,
125606f32e7eSjoerg                                                  SDValue &Hi) {
125706f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
125806f32e7eSjoerg   assert(NVT.getSizeInBits() == 64 &&
125906f32e7eSjoerg          "Do not know how to expand this float constant!");
126006f32e7eSjoerg   APInt C = cast<ConstantFPSDNode>(N)->getValueAPF().bitcastToAPInt();
126106f32e7eSjoerg   SDLoc dl(N);
126206f32e7eSjoerg   Lo = DAG.getConstantFP(APFloat(DAG.EVTToAPFloatSemantics(NVT),
126306f32e7eSjoerg                                  APInt(64, C.getRawData()[1])),
126406f32e7eSjoerg                          dl, NVT);
126506f32e7eSjoerg   Hi = DAG.getConstantFP(APFloat(DAG.EVTToAPFloatSemantics(NVT),
126606f32e7eSjoerg                                  APInt(64, C.getRawData()[0])),
126706f32e7eSjoerg                          dl, NVT);
126806f32e7eSjoerg }
126906f32e7eSjoerg 
ExpandFloatRes_Unary(SDNode * N,RTLIB::Libcall LC,SDValue & Lo,SDValue & Hi)1270*da58b97aSjoerg void DAGTypeLegalizer::ExpandFloatRes_Unary(SDNode *N, RTLIB::Libcall LC,
1271*da58b97aSjoerg                                             SDValue &Lo, SDValue &Hi) {
1272*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
1273*da58b97aSjoerg   unsigned Offset = IsStrict ? 1 : 0;
1274*da58b97aSjoerg   SDValue Op = N->getOperand(0 + Offset);
1275*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1276*da58b97aSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
1277*da58b97aSjoerg   std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, N->getValueType(0),
1278*da58b97aSjoerg                                                     Op, CallOptions, SDLoc(N),
1279*da58b97aSjoerg                                                     Chain);
1280*da58b97aSjoerg   if (IsStrict)
1281*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Tmp.second);
1282*da58b97aSjoerg   GetPairElements(Tmp.first, Lo, Hi);
1283*da58b97aSjoerg }
1284*da58b97aSjoerg 
ExpandFloatRes_Binary(SDNode * N,RTLIB::Libcall LC,SDValue & Lo,SDValue & Hi)1285*da58b97aSjoerg void DAGTypeLegalizer::ExpandFloatRes_Binary(SDNode *N, RTLIB::Libcall LC,
1286*da58b97aSjoerg                                              SDValue &Lo, SDValue &Hi) {
1287*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
1288*da58b97aSjoerg   unsigned Offset = IsStrict ? 1 : 0;
1289*da58b97aSjoerg   SDValue Ops[] = { N->getOperand(0 + Offset), N->getOperand(1 + Offset) };
1290*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1291*da58b97aSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
1292*da58b97aSjoerg   std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, N->getValueType(0),
1293*da58b97aSjoerg                                                     Ops, CallOptions, SDLoc(N),
1294*da58b97aSjoerg                                                     Chain);
1295*da58b97aSjoerg   if (IsStrict)
1296*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Tmp.second);
1297*da58b97aSjoerg   GetPairElements(Tmp.first, Lo, Hi);
1298*da58b97aSjoerg }
1299*da58b97aSjoerg 
ExpandFloatRes_FABS(SDNode * N,SDValue & Lo,SDValue & Hi)130006f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FABS(SDNode *N, SDValue &Lo,
130106f32e7eSjoerg                                            SDValue &Hi) {
130206f32e7eSjoerg   assert(N->getValueType(0) == MVT::ppcf128 &&
130306f32e7eSjoerg          "Logic only correct for ppcf128!");
130406f32e7eSjoerg   SDLoc dl(N);
130506f32e7eSjoerg   SDValue Tmp;
130606f32e7eSjoerg   GetExpandedFloat(N->getOperand(0), Lo, Tmp);
130706f32e7eSjoerg   Hi = DAG.getNode(ISD::FABS, dl, Tmp.getValueType(), Tmp);
130806f32e7eSjoerg   // Lo = Hi==fabs(Hi) ? Lo : -Lo;
130906f32e7eSjoerg   Lo = DAG.getSelectCC(dl, Tmp, Hi, Lo,
131006f32e7eSjoerg                    DAG.getNode(ISD::FNEG, dl, Lo.getValueType(), Lo),
131106f32e7eSjoerg                    ISD::SETEQ);
131206f32e7eSjoerg }
131306f32e7eSjoerg 
ExpandFloatRes_FMINNUM(SDNode * N,SDValue & Lo,SDValue & Hi)131406f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FMINNUM(SDNode *N, SDValue &Lo,
131506f32e7eSjoerg                                               SDValue &Hi) {
1316*da58b97aSjoerg   ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
131706f32e7eSjoerg                                        RTLIB::FMIN_F32, RTLIB::FMIN_F64,
131806f32e7eSjoerg                                        RTLIB::FMIN_F80, RTLIB::FMIN_F128,
1319*da58b97aSjoerg                                        RTLIB::FMIN_PPCF128), Lo, Hi);
132006f32e7eSjoerg }
132106f32e7eSjoerg 
ExpandFloatRes_FMAXNUM(SDNode * N,SDValue & Lo,SDValue & Hi)132206f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FMAXNUM(SDNode *N, SDValue &Lo,
132306f32e7eSjoerg                                               SDValue &Hi) {
1324*da58b97aSjoerg   ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
132506f32e7eSjoerg                                         RTLIB::FMAX_F32, RTLIB::FMAX_F64,
132606f32e7eSjoerg                                         RTLIB::FMAX_F80, RTLIB::FMAX_F128,
1327*da58b97aSjoerg                                         RTLIB::FMAX_PPCF128), Lo, Hi);
132806f32e7eSjoerg }
132906f32e7eSjoerg 
ExpandFloatRes_FADD(SDNode * N,SDValue & Lo,SDValue & Hi)133006f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FADD(SDNode *N, SDValue &Lo,
133106f32e7eSjoerg                                            SDValue &Hi) {
1332*da58b97aSjoerg   ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
133306f32e7eSjoerg                                         RTLIB::ADD_F32, RTLIB::ADD_F64,
133406f32e7eSjoerg                                         RTLIB::ADD_F80, RTLIB::ADD_F128,
1335*da58b97aSjoerg                                         RTLIB::ADD_PPCF128), Lo, Hi);
133606f32e7eSjoerg }
133706f32e7eSjoerg 
ExpandFloatRes_FCBRT(SDNode * N,SDValue & Lo,SDValue & Hi)133806f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FCBRT(SDNode *N, SDValue &Lo,
133906f32e7eSjoerg                                             SDValue &Hi) {
1340*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), RTLIB::CBRT_F32,
134106f32e7eSjoerg                                        RTLIB::CBRT_F64, RTLIB::CBRT_F80,
1342*da58b97aSjoerg                                        RTLIB::CBRT_F128,
1343*da58b97aSjoerg                                        RTLIB::CBRT_PPCF128), Lo, Hi);
134406f32e7eSjoerg }
134506f32e7eSjoerg 
ExpandFloatRes_FCEIL(SDNode * N,SDValue & Lo,SDValue & Hi)134606f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FCEIL(SDNode *N,
134706f32e7eSjoerg                                             SDValue &Lo, SDValue &Hi) {
1348*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
134906f32e7eSjoerg                                        RTLIB::CEIL_F32, RTLIB::CEIL_F64,
135006f32e7eSjoerg                                        RTLIB::CEIL_F80, RTLIB::CEIL_F128,
1351*da58b97aSjoerg                                        RTLIB::CEIL_PPCF128), Lo, Hi);
135206f32e7eSjoerg }
135306f32e7eSjoerg 
ExpandFloatRes_FCOPYSIGN(SDNode * N,SDValue & Lo,SDValue & Hi)135406f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FCOPYSIGN(SDNode *N,
135506f32e7eSjoerg                                                 SDValue &Lo, SDValue &Hi) {
1356*da58b97aSjoerg   ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
135706f32e7eSjoerg                                         RTLIB::COPYSIGN_F32,
135806f32e7eSjoerg                                         RTLIB::COPYSIGN_F64,
135906f32e7eSjoerg                                         RTLIB::COPYSIGN_F80,
136006f32e7eSjoerg                                         RTLIB::COPYSIGN_F128,
1361*da58b97aSjoerg                                         RTLIB::COPYSIGN_PPCF128), Lo, Hi);
136206f32e7eSjoerg }
136306f32e7eSjoerg 
ExpandFloatRes_FCOS(SDNode * N,SDValue & Lo,SDValue & Hi)136406f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FCOS(SDNode *N,
136506f32e7eSjoerg                                            SDValue &Lo, SDValue &Hi) {
1366*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
136706f32e7eSjoerg                                        RTLIB::COS_F32, RTLIB::COS_F64,
136806f32e7eSjoerg                                        RTLIB::COS_F80, RTLIB::COS_F128,
1369*da58b97aSjoerg                                        RTLIB::COS_PPCF128), Lo, Hi);
137006f32e7eSjoerg }
137106f32e7eSjoerg 
ExpandFloatRes_FDIV(SDNode * N,SDValue & Lo,SDValue & Hi)137206f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FDIV(SDNode *N, SDValue &Lo,
137306f32e7eSjoerg                                            SDValue &Hi) {
1374*da58b97aSjoerg   ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
137506f32e7eSjoerg                                         RTLIB::DIV_F32,
137606f32e7eSjoerg                                         RTLIB::DIV_F64,
137706f32e7eSjoerg                                         RTLIB::DIV_F80,
137806f32e7eSjoerg                                         RTLIB::DIV_F128,
1379*da58b97aSjoerg                                         RTLIB::DIV_PPCF128), Lo, Hi);
138006f32e7eSjoerg }
138106f32e7eSjoerg 
ExpandFloatRes_FEXP(SDNode * N,SDValue & Lo,SDValue & Hi)138206f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FEXP(SDNode *N,
138306f32e7eSjoerg                                            SDValue &Lo, SDValue &Hi) {
1384*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
138506f32e7eSjoerg                                        RTLIB::EXP_F32, RTLIB::EXP_F64,
138606f32e7eSjoerg                                        RTLIB::EXP_F80, RTLIB::EXP_F128,
1387*da58b97aSjoerg                                        RTLIB::EXP_PPCF128), Lo, Hi);
138806f32e7eSjoerg }
138906f32e7eSjoerg 
ExpandFloatRes_FEXP2(SDNode * N,SDValue & Lo,SDValue & Hi)139006f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FEXP2(SDNode *N,
139106f32e7eSjoerg                                             SDValue &Lo, SDValue &Hi) {
1392*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
139306f32e7eSjoerg                                        RTLIB::EXP2_F32, RTLIB::EXP2_F64,
139406f32e7eSjoerg                                        RTLIB::EXP2_F80, RTLIB::EXP2_F128,
1395*da58b97aSjoerg                                        RTLIB::EXP2_PPCF128), Lo, Hi);
139606f32e7eSjoerg }
139706f32e7eSjoerg 
ExpandFloatRes_FFLOOR(SDNode * N,SDValue & Lo,SDValue & Hi)139806f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FFLOOR(SDNode *N,
139906f32e7eSjoerg                                              SDValue &Lo, SDValue &Hi) {
1400*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
140106f32e7eSjoerg                                        RTLIB::FLOOR_F32, RTLIB::FLOOR_F64,
140206f32e7eSjoerg                                        RTLIB::FLOOR_F80, RTLIB::FLOOR_F128,
1403*da58b97aSjoerg                                        RTLIB::FLOOR_PPCF128), Lo, Hi);
140406f32e7eSjoerg }
140506f32e7eSjoerg 
ExpandFloatRes_FLOG(SDNode * N,SDValue & Lo,SDValue & Hi)140606f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FLOG(SDNode *N,
140706f32e7eSjoerg                                            SDValue &Lo, SDValue &Hi) {
1408*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
140906f32e7eSjoerg                                        RTLIB::LOG_F32, RTLIB::LOG_F64,
141006f32e7eSjoerg                                        RTLIB::LOG_F80, RTLIB::LOG_F128,
1411*da58b97aSjoerg                                        RTLIB::LOG_PPCF128), Lo, Hi);
141206f32e7eSjoerg }
141306f32e7eSjoerg 
ExpandFloatRes_FLOG2(SDNode * N,SDValue & Lo,SDValue & Hi)141406f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FLOG2(SDNode *N,
141506f32e7eSjoerg                                             SDValue &Lo, SDValue &Hi) {
1416*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
141706f32e7eSjoerg                                        RTLIB::LOG2_F32, RTLIB::LOG2_F64,
141806f32e7eSjoerg                                        RTLIB::LOG2_F80, RTLIB::LOG2_F128,
1419*da58b97aSjoerg                                        RTLIB::LOG2_PPCF128), Lo, Hi);
142006f32e7eSjoerg }
142106f32e7eSjoerg 
ExpandFloatRes_FLOG10(SDNode * N,SDValue & Lo,SDValue & Hi)142206f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FLOG10(SDNode *N,
142306f32e7eSjoerg                                              SDValue &Lo, SDValue &Hi) {
1424*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
142506f32e7eSjoerg                                        RTLIB::LOG10_F32, RTLIB::LOG10_F64,
142606f32e7eSjoerg                                        RTLIB::LOG10_F80, RTLIB::LOG10_F128,
1427*da58b97aSjoerg                                        RTLIB::LOG10_PPCF128), Lo, Hi);
142806f32e7eSjoerg }
142906f32e7eSjoerg 
ExpandFloatRes_FMA(SDNode * N,SDValue & Lo,SDValue & Hi)143006f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FMA(SDNode *N, SDValue &Lo,
143106f32e7eSjoerg                                           SDValue &Hi) {
1432*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
1433*da58b97aSjoerg   unsigned Offset = IsStrict ? 1 : 0;
1434*da58b97aSjoerg   SDValue Ops[3] = { N->getOperand(0 + Offset), N->getOperand(1 + Offset),
1435*da58b97aSjoerg                      N->getOperand(2 + Offset) };
1436*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
143706f32e7eSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
1438*da58b97aSjoerg   std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, GetFPLibCall(N->getValueType(0),
143906f32e7eSjoerg                                                    RTLIB::FMA_F32,
144006f32e7eSjoerg                                                    RTLIB::FMA_F64,
144106f32e7eSjoerg                                                    RTLIB::FMA_F80,
144206f32e7eSjoerg                                                    RTLIB::FMA_F128,
144306f32e7eSjoerg                                                    RTLIB::FMA_PPCF128),
144406f32e7eSjoerg                                  N->getValueType(0), Ops, CallOptions,
1445*da58b97aSjoerg                                  SDLoc(N), Chain);
1446*da58b97aSjoerg   if (IsStrict)
1447*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Tmp.second);
1448*da58b97aSjoerg   GetPairElements(Tmp.first, Lo, Hi);
144906f32e7eSjoerg }
145006f32e7eSjoerg 
ExpandFloatRes_FMUL(SDNode * N,SDValue & Lo,SDValue & Hi)145106f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FMUL(SDNode *N, SDValue &Lo,
145206f32e7eSjoerg                                            SDValue &Hi) {
1453*da58b97aSjoerg   ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
145406f32e7eSjoerg                                                    RTLIB::MUL_F32,
145506f32e7eSjoerg                                                    RTLIB::MUL_F64,
145606f32e7eSjoerg                                                    RTLIB::MUL_F80,
145706f32e7eSjoerg                                                    RTLIB::MUL_F128,
1458*da58b97aSjoerg                                                    RTLIB::MUL_PPCF128), Lo, Hi);
145906f32e7eSjoerg }
146006f32e7eSjoerg 
ExpandFloatRes_FNEARBYINT(SDNode * N,SDValue & Lo,SDValue & Hi)146106f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FNEARBYINT(SDNode *N,
146206f32e7eSjoerg                                                  SDValue &Lo, SDValue &Hi) {
1463*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
146406f32e7eSjoerg                                        RTLIB::NEARBYINT_F32,
146506f32e7eSjoerg                                        RTLIB::NEARBYINT_F64,
146606f32e7eSjoerg                                        RTLIB::NEARBYINT_F80,
146706f32e7eSjoerg                                        RTLIB::NEARBYINT_F128,
1468*da58b97aSjoerg                                        RTLIB::NEARBYINT_PPCF128), Lo, Hi);
146906f32e7eSjoerg }
147006f32e7eSjoerg 
ExpandFloatRes_FNEG(SDNode * N,SDValue & Lo,SDValue & Hi)147106f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FNEG(SDNode *N, SDValue &Lo,
147206f32e7eSjoerg                                            SDValue &Hi) {
147306f32e7eSjoerg   SDLoc dl(N);
147406f32e7eSjoerg   GetExpandedFloat(N->getOperand(0), Lo, Hi);
147506f32e7eSjoerg   Lo = DAG.getNode(ISD::FNEG, dl, Lo.getValueType(), Lo);
147606f32e7eSjoerg   Hi = DAG.getNode(ISD::FNEG, dl, Hi.getValueType(), Hi);
147706f32e7eSjoerg }
147806f32e7eSjoerg 
ExpandFloatRes_FP_EXTEND(SDNode * N,SDValue & Lo,SDValue & Hi)147906f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FP_EXTEND(SDNode *N, SDValue &Lo,
148006f32e7eSjoerg                                                 SDValue &Hi) {
148106f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
148206f32e7eSjoerg   SDLoc dl(N);
1483*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
1484*da58b97aSjoerg 
1485*da58b97aSjoerg   SDValue Chain;
1486*da58b97aSjoerg   if (IsStrict) {
1487*da58b97aSjoerg     // If the expanded type is the same as the input type, just bypass the node.
1488*da58b97aSjoerg     if (NVT == N->getOperand(1).getValueType()) {
1489*da58b97aSjoerg       Hi = N->getOperand(1);
1490*da58b97aSjoerg       Chain = N->getOperand(0);
1491*da58b97aSjoerg     } else {
1492*da58b97aSjoerg       // Other we need to extend.
1493*da58b97aSjoerg       Hi = DAG.getNode(ISD::STRICT_FP_EXTEND, dl, { NVT, MVT::Other },
1494*da58b97aSjoerg                        { N->getOperand(0), N->getOperand(1) });
1495*da58b97aSjoerg       Chain = Hi.getValue(1);
1496*da58b97aSjoerg     }
1497*da58b97aSjoerg   } else {
149806f32e7eSjoerg     Hi = DAG.getNode(ISD::FP_EXTEND, dl, NVT, N->getOperand(0));
1499*da58b97aSjoerg   }
1500*da58b97aSjoerg 
150106f32e7eSjoerg   Lo = DAG.getConstantFP(APFloat(DAG.EVTToAPFloatSemantics(NVT),
150206f32e7eSjoerg                                  APInt(NVT.getSizeInBits(), 0)), dl, NVT);
1503*da58b97aSjoerg 
1504*da58b97aSjoerg   if (IsStrict)
1505*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Chain);
150606f32e7eSjoerg }
150706f32e7eSjoerg 
ExpandFloatRes_FPOW(SDNode * N,SDValue & Lo,SDValue & Hi)150806f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FPOW(SDNode *N,
150906f32e7eSjoerg                                            SDValue &Lo, SDValue &Hi) {
1510*da58b97aSjoerg   ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
151106f32e7eSjoerg                                         RTLIB::POW_F32, RTLIB::POW_F64,
151206f32e7eSjoerg                                         RTLIB::POW_F80, RTLIB::POW_F128,
1513*da58b97aSjoerg                                         RTLIB::POW_PPCF128), Lo, Hi);
151406f32e7eSjoerg }
151506f32e7eSjoerg 
ExpandFloatRes_FPOWI(SDNode * N,SDValue & Lo,SDValue & Hi)151606f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FPOWI(SDNode *N,
151706f32e7eSjoerg                                             SDValue &Lo, SDValue &Hi) {
1518*da58b97aSjoerg   ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
151906f32e7eSjoerg                                         RTLIB::POWI_F32, RTLIB::POWI_F64,
152006f32e7eSjoerg                                         RTLIB::POWI_F80, RTLIB::POWI_F128,
1521*da58b97aSjoerg                                         RTLIB::POWI_PPCF128), Lo, Hi);
1522*da58b97aSjoerg }
1523*da58b97aSjoerg 
ExpandFloatRes_FREEZE(SDNode * N,SDValue & Lo,SDValue & Hi)1524*da58b97aSjoerg void DAGTypeLegalizer::ExpandFloatRes_FREEZE(SDNode *N,
1525*da58b97aSjoerg                                              SDValue &Lo, SDValue &Hi) {
1526*da58b97aSjoerg   assert(N->getValueType(0) == MVT::ppcf128 &&
1527*da58b97aSjoerg          "Logic only correct for ppcf128!");
1528*da58b97aSjoerg 
1529*da58b97aSjoerg   SDLoc dl(N);
1530*da58b97aSjoerg   GetExpandedFloat(N->getOperand(0), Lo, Hi);
1531*da58b97aSjoerg   Lo = DAG.getNode(ISD::FREEZE, dl, Lo.getValueType(), Lo);
1532*da58b97aSjoerg   Hi = DAG.getNode(ISD::FREEZE, dl, Hi.getValueType(), Hi);
153306f32e7eSjoerg }
153406f32e7eSjoerg 
ExpandFloatRes_FREM(SDNode * N,SDValue & Lo,SDValue & Hi)153506f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FREM(SDNode *N,
153606f32e7eSjoerg                                            SDValue &Lo, SDValue &Hi) {
1537*da58b97aSjoerg   ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
153806f32e7eSjoerg                                         RTLIB::REM_F32, RTLIB::REM_F64,
153906f32e7eSjoerg                                         RTLIB::REM_F80, RTLIB::REM_F128,
1540*da58b97aSjoerg                                         RTLIB::REM_PPCF128), Lo, Hi);
154106f32e7eSjoerg }
154206f32e7eSjoerg 
ExpandFloatRes_FRINT(SDNode * N,SDValue & Lo,SDValue & Hi)154306f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FRINT(SDNode *N,
154406f32e7eSjoerg                                             SDValue &Lo, SDValue &Hi) {
1545*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
154606f32e7eSjoerg                                        RTLIB::RINT_F32, RTLIB::RINT_F64,
154706f32e7eSjoerg                                        RTLIB::RINT_F80, RTLIB::RINT_F128,
1548*da58b97aSjoerg                                        RTLIB::RINT_PPCF128), Lo, Hi);
154906f32e7eSjoerg }
155006f32e7eSjoerg 
ExpandFloatRes_FROUND(SDNode * N,SDValue & Lo,SDValue & Hi)155106f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FROUND(SDNode *N,
155206f32e7eSjoerg                                              SDValue &Lo, SDValue &Hi) {
1553*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
155406f32e7eSjoerg                                        RTLIB::ROUND_F32,
155506f32e7eSjoerg                                        RTLIB::ROUND_F64,
155606f32e7eSjoerg                                        RTLIB::ROUND_F80,
155706f32e7eSjoerg                                        RTLIB::ROUND_F128,
1558*da58b97aSjoerg                                        RTLIB::ROUND_PPCF128), Lo, Hi);
1559*da58b97aSjoerg }
1560*da58b97aSjoerg 
ExpandFloatRes_FROUNDEVEN(SDNode * N,SDValue & Lo,SDValue & Hi)1561*da58b97aSjoerg void DAGTypeLegalizer::ExpandFloatRes_FROUNDEVEN(SDNode *N,
1562*da58b97aSjoerg                                              SDValue &Lo, SDValue &Hi) {
1563*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
1564*da58b97aSjoerg                                        RTLIB::ROUNDEVEN_F32,
1565*da58b97aSjoerg                                        RTLIB::ROUNDEVEN_F64,
1566*da58b97aSjoerg                                        RTLIB::ROUNDEVEN_F80,
1567*da58b97aSjoerg                                        RTLIB::ROUNDEVEN_F128,
1568*da58b97aSjoerg                                        RTLIB::ROUNDEVEN_PPCF128), Lo, Hi);
156906f32e7eSjoerg }
157006f32e7eSjoerg 
ExpandFloatRes_FSIN(SDNode * N,SDValue & Lo,SDValue & Hi)157106f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FSIN(SDNode *N,
157206f32e7eSjoerg                                            SDValue &Lo, SDValue &Hi) {
1573*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
157406f32e7eSjoerg                                        RTLIB::SIN_F32, RTLIB::SIN_F64,
157506f32e7eSjoerg                                        RTLIB::SIN_F80, RTLIB::SIN_F128,
1576*da58b97aSjoerg                                        RTLIB::SIN_PPCF128), Lo, Hi);
157706f32e7eSjoerg }
157806f32e7eSjoerg 
ExpandFloatRes_FSQRT(SDNode * N,SDValue & Lo,SDValue & Hi)157906f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FSQRT(SDNode *N,
158006f32e7eSjoerg                                             SDValue &Lo, SDValue &Hi) {
1581*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
158206f32e7eSjoerg                                        RTLIB::SQRT_F32, RTLIB::SQRT_F64,
158306f32e7eSjoerg                                        RTLIB::SQRT_F80, RTLIB::SQRT_F128,
1584*da58b97aSjoerg                                        RTLIB::SQRT_PPCF128), Lo, Hi);
158506f32e7eSjoerg }
158606f32e7eSjoerg 
ExpandFloatRes_FSUB(SDNode * N,SDValue & Lo,SDValue & Hi)158706f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FSUB(SDNode *N, SDValue &Lo,
158806f32e7eSjoerg                                            SDValue &Hi) {
1589*da58b97aSjoerg   ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
159006f32e7eSjoerg                                         RTLIB::SUB_F32,
159106f32e7eSjoerg                                         RTLIB::SUB_F64,
159206f32e7eSjoerg                                         RTLIB::SUB_F80,
159306f32e7eSjoerg                                         RTLIB::SUB_F128,
1594*da58b97aSjoerg                                         RTLIB::SUB_PPCF128), Lo, Hi);
159506f32e7eSjoerg }
159606f32e7eSjoerg 
ExpandFloatRes_FTRUNC(SDNode * N,SDValue & Lo,SDValue & Hi)159706f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_FTRUNC(SDNode *N,
159806f32e7eSjoerg                                              SDValue &Lo, SDValue &Hi) {
1599*da58b97aSjoerg   ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
160006f32e7eSjoerg                                        RTLIB::TRUNC_F32, RTLIB::TRUNC_F64,
160106f32e7eSjoerg                                        RTLIB::TRUNC_F80, RTLIB::TRUNC_F128,
1602*da58b97aSjoerg                                        RTLIB::TRUNC_PPCF128), Lo, Hi);
160306f32e7eSjoerg }
160406f32e7eSjoerg 
ExpandFloatRes_LOAD(SDNode * N,SDValue & Lo,SDValue & Hi)160506f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_LOAD(SDNode *N, SDValue &Lo,
160606f32e7eSjoerg                                            SDValue &Hi) {
160706f32e7eSjoerg   if (ISD::isNormalLoad(N)) {
160806f32e7eSjoerg     ExpandRes_NormalLoad(N, Lo, Hi);
160906f32e7eSjoerg     return;
161006f32e7eSjoerg   }
161106f32e7eSjoerg 
161206f32e7eSjoerg   assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!");
161306f32e7eSjoerg   LoadSDNode *LD = cast<LoadSDNode>(N);
161406f32e7eSjoerg   SDValue Chain = LD->getChain();
161506f32e7eSjoerg   SDValue Ptr = LD->getBasePtr();
161606f32e7eSjoerg   SDLoc dl(N);
161706f32e7eSjoerg 
161806f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0));
161906f32e7eSjoerg   assert(NVT.isByteSized() && "Expanded type not byte sized!");
162006f32e7eSjoerg   assert(LD->getMemoryVT().bitsLE(NVT) && "Float type not round?");
162106f32e7eSjoerg 
162206f32e7eSjoerg   Hi = DAG.getExtLoad(LD->getExtensionType(), dl, NVT, Chain, Ptr,
162306f32e7eSjoerg                       LD->getMemoryVT(), LD->getMemOperand());
162406f32e7eSjoerg 
162506f32e7eSjoerg   // Remember the chain.
162606f32e7eSjoerg   Chain = Hi.getValue(1);
162706f32e7eSjoerg 
162806f32e7eSjoerg   // The low part is zero.
162906f32e7eSjoerg   Lo = DAG.getConstantFP(APFloat(DAG.EVTToAPFloatSemantics(NVT),
163006f32e7eSjoerg                                  APInt(NVT.getSizeInBits(), 0)), dl, NVT);
163106f32e7eSjoerg 
163206f32e7eSjoerg   // Modified the chain - switch anything that used the old chain to use the
163306f32e7eSjoerg   // new one.
163406f32e7eSjoerg   ReplaceValueWith(SDValue(LD, 1), Chain);
163506f32e7eSjoerg }
163606f32e7eSjoerg 
ExpandFloatRes_XINT_TO_FP(SDNode * N,SDValue & Lo,SDValue & Hi)163706f32e7eSjoerg void DAGTypeLegalizer::ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo,
163806f32e7eSjoerg                                                  SDValue &Hi) {
163906f32e7eSjoerg   assert(N->getValueType(0) == MVT::ppcf128 && "Unsupported XINT_TO_FP!");
164006f32e7eSjoerg   EVT VT = N->getValueType(0);
164106f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
1642*da58b97aSjoerg   bool Strict = N->isStrictFPOpcode();
1643*da58b97aSjoerg   SDValue Src = N->getOperand(Strict ? 1 : 0);
164406f32e7eSjoerg   EVT SrcVT = Src.getValueType();
1645*da58b97aSjoerg   bool isSigned = N->getOpcode() == ISD::SINT_TO_FP ||
1646*da58b97aSjoerg                   N->getOpcode() == ISD::STRICT_SINT_TO_FP;
164706f32e7eSjoerg   SDLoc dl(N);
1648*da58b97aSjoerg   SDValue Chain = Strict ? N->getOperand(0) : DAG.getEntryNode();
1649*da58b97aSjoerg 
1650*da58b97aSjoerg   // TODO: Any other flags to propagate?
1651*da58b97aSjoerg   SDNodeFlags Flags;
1652*da58b97aSjoerg   Flags.setNoFPExcept(N->getFlags().hasNoFPExcept());
165306f32e7eSjoerg 
165406f32e7eSjoerg   // First do an SINT_TO_FP, whether the original was signed or unsigned.
165506f32e7eSjoerg   // When promoting partial word types to i32 we must honor the signedness,
165606f32e7eSjoerg   // though.
165706f32e7eSjoerg   if (SrcVT.bitsLE(MVT::i32)) {
165806f32e7eSjoerg     // The integer can be represented exactly in an f64.
165906f32e7eSjoerg     Lo = DAG.getConstantFP(APFloat(DAG.EVTToAPFloatSemantics(NVT),
166006f32e7eSjoerg                                    APInt(NVT.getSizeInBits(), 0)), dl, NVT);
1661*da58b97aSjoerg     if (Strict) {
1662*da58b97aSjoerg       Hi = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(NVT, MVT::Other),
1663*da58b97aSjoerg                        {Chain, Src}, Flags);
1664*da58b97aSjoerg       Chain = Hi.getValue(1);
1665*da58b97aSjoerg     } else
1666*da58b97aSjoerg       Hi = DAG.getNode(N->getOpcode(), dl, NVT, Src);
166706f32e7eSjoerg   } else {
166806f32e7eSjoerg     RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
166906f32e7eSjoerg     if (SrcVT.bitsLE(MVT::i64)) {
167006f32e7eSjoerg       Src = DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, dl,
167106f32e7eSjoerg                         MVT::i64, Src);
167206f32e7eSjoerg       LC = RTLIB::SINTTOFP_I64_PPCF128;
167306f32e7eSjoerg     } else if (SrcVT.bitsLE(MVT::i128)) {
167406f32e7eSjoerg       Src = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i128, Src);
167506f32e7eSjoerg       LC = RTLIB::SINTTOFP_I128_PPCF128;
167606f32e7eSjoerg     }
167706f32e7eSjoerg     assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!");
167806f32e7eSjoerg 
167906f32e7eSjoerg     TargetLowering::MakeLibCallOptions CallOptions;
168006f32e7eSjoerg     CallOptions.setSExt(true);
1681*da58b97aSjoerg     std::pair<SDValue, SDValue> Tmp =
1682*da58b97aSjoerg         TLI.makeLibCall(DAG, LC, VT, Src, CallOptions, dl, Chain);
1683*da58b97aSjoerg     if (Strict)
1684*da58b97aSjoerg       Chain = Tmp.second;
1685*da58b97aSjoerg     GetPairElements(Tmp.first, Lo, Hi);
168606f32e7eSjoerg   }
168706f32e7eSjoerg 
1688*da58b97aSjoerg   // No need to complement for unsigned 32-bit integers
1689*da58b97aSjoerg   if (isSigned || SrcVT.bitsLE(MVT::i32)) {
1690*da58b97aSjoerg     if (Strict)
1691*da58b97aSjoerg       ReplaceValueWith(SDValue(N, 1), Chain);
1692*da58b97aSjoerg 
169306f32e7eSjoerg     return;
1694*da58b97aSjoerg   }
169506f32e7eSjoerg 
169606f32e7eSjoerg   // Unsigned - fix up the SINT_TO_FP value just calculated.
1697*da58b97aSjoerg   // FIXME: For unsigned i128 to ppc_fp128 conversion, we need to carefully
1698*da58b97aSjoerg   // keep semantics correctness if the integer is not exactly representable
1699*da58b97aSjoerg   // here. See ExpandLegalINT_TO_FP.
170006f32e7eSjoerg   Hi = DAG.getNode(ISD::BUILD_PAIR, dl, VT, Lo, Hi);
170106f32e7eSjoerg   SrcVT = Src.getValueType();
170206f32e7eSjoerg 
170306f32e7eSjoerg   // x>=0 ? (ppcf128)(iN)x : (ppcf128)(iN)x + 2^N; N=32,64,128.
170406f32e7eSjoerg   static const uint64_t TwoE32[]  = { 0x41f0000000000000LL, 0 };
170506f32e7eSjoerg   static const uint64_t TwoE64[]  = { 0x43f0000000000000LL, 0 };
170606f32e7eSjoerg   static const uint64_t TwoE128[] = { 0x47f0000000000000LL, 0 };
170706f32e7eSjoerg   ArrayRef<uint64_t> Parts;
170806f32e7eSjoerg 
170906f32e7eSjoerg   switch (SrcVT.getSimpleVT().SimpleTy) {
171006f32e7eSjoerg   default:
171106f32e7eSjoerg     llvm_unreachable("Unsupported UINT_TO_FP!");
171206f32e7eSjoerg   case MVT::i32:
171306f32e7eSjoerg     Parts = TwoE32;
171406f32e7eSjoerg     break;
171506f32e7eSjoerg   case MVT::i64:
171606f32e7eSjoerg     Parts = TwoE64;
171706f32e7eSjoerg     break;
171806f32e7eSjoerg   case MVT::i128:
171906f32e7eSjoerg     Parts = TwoE128;
172006f32e7eSjoerg     break;
172106f32e7eSjoerg   }
172206f32e7eSjoerg 
1723*da58b97aSjoerg   // TODO: Are there other fast-math-flags to propagate to this FADD?
1724*da58b97aSjoerg   SDValue NewLo = DAG.getConstantFP(
1725*da58b97aSjoerg       APFloat(APFloat::PPCDoubleDouble(), APInt(128, Parts)), dl, MVT::ppcf128);
1726*da58b97aSjoerg   if (Strict) {
1727*da58b97aSjoerg     Lo = DAG.getNode(ISD::STRICT_FADD, dl, DAG.getVTList(VT, MVT::Other),
1728*da58b97aSjoerg                      {Chain, Hi, NewLo}, Flags);
1729*da58b97aSjoerg     Chain = Lo.getValue(1);
1730*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Chain);
1731*da58b97aSjoerg   } else
1732*da58b97aSjoerg     Lo = DAG.getNode(ISD::FADD, dl, VT, Hi, NewLo);
173306f32e7eSjoerg   Lo = DAG.getSelectCC(dl, Src, DAG.getConstant(0, dl, SrcVT),
173406f32e7eSjoerg                        Lo, Hi, ISD::SETLT);
173506f32e7eSjoerg   GetPairElements(Lo, Lo, Hi);
173606f32e7eSjoerg }
173706f32e7eSjoerg 
173806f32e7eSjoerg 
173906f32e7eSjoerg //===----------------------------------------------------------------------===//
174006f32e7eSjoerg //  Float Operand Expansion
174106f32e7eSjoerg //===----------------------------------------------------------------------===//
174206f32e7eSjoerg 
174306f32e7eSjoerg /// ExpandFloatOperand - This method is called when the specified operand of the
174406f32e7eSjoerg /// specified node is found to need expansion.  At this point, all of the result
174506f32e7eSjoerg /// types of the node are known to be legal, but other operands of the node may
174606f32e7eSjoerg /// need promotion or expansion as well as the specified one.
ExpandFloatOperand(SDNode * N,unsigned OpNo)174706f32e7eSjoerg bool DAGTypeLegalizer::ExpandFloatOperand(SDNode *N, unsigned OpNo) {
174806f32e7eSjoerg   LLVM_DEBUG(dbgs() << "Expand float operand: "; N->dump(&DAG); dbgs() << "\n");
174906f32e7eSjoerg   SDValue Res = SDValue();
175006f32e7eSjoerg 
175106f32e7eSjoerg   // See if the target wants to custom expand this node.
175206f32e7eSjoerg   if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
175306f32e7eSjoerg     return false;
175406f32e7eSjoerg 
175506f32e7eSjoerg   switch (N->getOpcode()) {
175606f32e7eSjoerg   default:
175706f32e7eSjoerg #ifndef NDEBUG
175806f32e7eSjoerg     dbgs() << "ExpandFloatOperand Op #" << OpNo << ": ";
175906f32e7eSjoerg     N->dump(&DAG); dbgs() << "\n";
176006f32e7eSjoerg #endif
176106f32e7eSjoerg     llvm_unreachable("Do not know how to expand this operator's operand!");
176206f32e7eSjoerg 
176306f32e7eSjoerg   case ISD::BITCAST:         Res = ExpandOp_BITCAST(N); break;
176406f32e7eSjoerg   case ISD::BUILD_VECTOR:    Res = ExpandOp_BUILD_VECTOR(N); break;
176506f32e7eSjoerg   case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break;
176606f32e7eSjoerg 
176706f32e7eSjoerg   case ISD::BR_CC:      Res = ExpandFloatOp_BR_CC(N); break;
176806f32e7eSjoerg   case ISD::FCOPYSIGN:  Res = ExpandFloatOp_FCOPYSIGN(N); break;
1769*da58b97aSjoerg   case ISD::STRICT_FP_ROUND:
177006f32e7eSjoerg   case ISD::FP_ROUND:   Res = ExpandFloatOp_FP_ROUND(N); break;
1771*da58b97aSjoerg   case ISD::STRICT_FP_TO_SINT:
1772*da58b97aSjoerg   case ISD::STRICT_FP_TO_UINT:
1773*da58b97aSjoerg   case ISD::FP_TO_SINT:
1774*da58b97aSjoerg   case ISD::FP_TO_UINT: Res = ExpandFloatOp_FP_TO_XINT(N); break;
177506f32e7eSjoerg   case ISD::LROUND:     Res = ExpandFloatOp_LROUND(N); break;
177606f32e7eSjoerg   case ISD::LLROUND:    Res = ExpandFloatOp_LLROUND(N); break;
177706f32e7eSjoerg   case ISD::LRINT:      Res = ExpandFloatOp_LRINT(N); break;
177806f32e7eSjoerg   case ISD::LLRINT:     Res = ExpandFloatOp_LLRINT(N); break;
177906f32e7eSjoerg   case ISD::SELECT_CC:  Res = ExpandFloatOp_SELECT_CC(N); break;
1780*da58b97aSjoerg   case ISD::STRICT_FSETCC:
1781*da58b97aSjoerg   case ISD::STRICT_FSETCCS:
178206f32e7eSjoerg   case ISD::SETCC:      Res = ExpandFloatOp_SETCC(N); break;
178306f32e7eSjoerg   case ISD::STORE:      Res = ExpandFloatOp_STORE(cast<StoreSDNode>(N),
178406f32e7eSjoerg                                                   OpNo); break;
178506f32e7eSjoerg   }
178606f32e7eSjoerg 
178706f32e7eSjoerg   // If the result is null, the sub-method took care of registering results etc.
178806f32e7eSjoerg   if (!Res.getNode()) return false;
178906f32e7eSjoerg 
179006f32e7eSjoerg   // If the result is N, the sub-method updated N in place.  Tell the legalizer
179106f32e7eSjoerg   // core about this.
179206f32e7eSjoerg   if (Res.getNode() == N)
179306f32e7eSjoerg     return true;
179406f32e7eSjoerg 
179506f32e7eSjoerg   assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
179606f32e7eSjoerg          "Invalid operand expansion");
179706f32e7eSjoerg 
179806f32e7eSjoerg   ReplaceValueWith(SDValue(N, 0), Res);
179906f32e7eSjoerg   return false;
180006f32e7eSjoerg }
180106f32e7eSjoerg 
180206f32e7eSjoerg /// FloatExpandSetCCOperands - Expand the operands of a comparison.  This code
180306f32e7eSjoerg /// is shared among BR_CC, SELECT_CC, and SETCC handlers.
FloatExpandSetCCOperands(SDValue & NewLHS,SDValue & NewRHS,ISD::CondCode & CCCode,const SDLoc & dl,SDValue & Chain,bool IsSignaling)180406f32e7eSjoerg void DAGTypeLegalizer::FloatExpandSetCCOperands(SDValue &NewLHS,
180506f32e7eSjoerg                                                 SDValue &NewRHS,
180606f32e7eSjoerg                                                 ISD::CondCode &CCCode,
1807*da58b97aSjoerg                                                 const SDLoc &dl, SDValue &Chain,
1808*da58b97aSjoerg                                                 bool IsSignaling) {
180906f32e7eSjoerg   SDValue LHSLo, LHSHi, RHSLo, RHSHi;
181006f32e7eSjoerg   GetExpandedFloat(NewLHS, LHSLo, LHSHi);
181106f32e7eSjoerg   GetExpandedFloat(NewRHS, RHSLo, RHSHi);
181206f32e7eSjoerg 
181306f32e7eSjoerg   assert(NewLHS.getValueType() == MVT::ppcf128 && "Unsupported setcc type!");
181406f32e7eSjoerg 
181506f32e7eSjoerg   // FIXME:  This generated code sucks.  We want to generate
181606f32e7eSjoerg   //         FCMPU crN, hi1, hi2
181706f32e7eSjoerg   //         BNE crN, L:
181806f32e7eSjoerg   //         FCMPU crN, lo1, lo2
181906f32e7eSjoerg   // The following can be improved, but not that much.
1820*da58b97aSjoerg   SDValue Tmp1, Tmp2, Tmp3, OutputChain;
1821*da58b97aSjoerg   Tmp1 = DAG.getSetCC(dl, getSetCCResultType(LHSHi.getValueType()), LHSHi,
1822*da58b97aSjoerg                       RHSHi, ISD::SETOEQ, Chain, IsSignaling);
1823*da58b97aSjoerg   OutputChain = Tmp1->getNumValues() > 1 ? Tmp1.getValue(1) : SDValue();
1824*da58b97aSjoerg   Tmp2 = DAG.getSetCC(dl, getSetCCResultType(LHSLo.getValueType()), LHSLo,
1825*da58b97aSjoerg                       RHSLo, CCCode, OutputChain, IsSignaling);
1826*da58b97aSjoerg   OutputChain = Tmp2->getNumValues() > 1 ? Tmp2.getValue(1) : SDValue();
182706f32e7eSjoerg   Tmp3 = DAG.getNode(ISD::AND, dl, Tmp1.getValueType(), Tmp1, Tmp2);
1828*da58b97aSjoerg   Tmp1 =
1829*da58b97aSjoerg       DAG.getSetCC(dl, getSetCCResultType(LHSHi.getValueType()), LHSHi, RHSHi,
1830*da58b97aSjoerg                    ISD::SETUNE, OutputChain, IsSignaling);
1831*da58b97aSjoerg   OutputChain = Tmp1->getNumValues() > 1 ? Tmp1.getValue(1) : SDValue();
1832*da58b97aSjoerg   Tmp2 = DAG.getSetCC(dl, getSetCCResultType(LHSHi.getValueType()), LHSHi,
1833*da58b97aSjoerg                       RHSHi, CCCode, OutputChain, IsSignaling);
1834*da58b97aSjoerg   OutputChain = Tmp2->getNumValues() > 1 ? Tmp2.getValue(1) : SDValue();
183506f32e7eSjoerg   Tmp1 = DAG.getNode(ISD::AND, dl, Tmp1.getValueType(), Tmp1, Tmp2);
183606f32e7eSjoerg   NewLHS = DAG.getNode(ISD::OR, dl, Tmp1.getValueType(), Tmp1, Tmp3);
183706f32e7eSjoerg   NewRHS = SDValue();   // LHS is the result, not a compare.
1838*da58b97aSjoerg   Chain = OutputChain;
183906f32e7eSjoerg }
184006f32e7eSjoerg 
ExpandFloatOp_BR_CC(SDNode * N)184106f32e7eSjoerg SDValue DAGTypeLegalizer::ExpandFloatOp_BR_CC(SDNode *N) {
184206f32e7eSjoerg   SDValue NewLHS = N->getOperand(2), NewRHS = N->getOperand(3);
184306f32e7eSjoerg   ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(1))->get();
1844*da58b97aSjoerg   SDValue Chain;
1845*da58b97aSjoerg   FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, SDLoc(N), Chain);
184606f32e7eSjoerg 
184706f32e7eSjoerg   // If ExpandSetCCOperands returned a scalar, we need to compare the result
184806f32e7eSjoerg   // against zero to select between true and false values.
184906f32e7eSjoerg   if (!NewRHS.getNode()) {
185006f32e7eSjoerg     NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
185106f32e7eSjoerg     CCCode = ISD::SETNE;
185206f32e7eSjoerg   }
185306f32e7eSjoerg 
185406f32e7eSjoerg   // Update N to have the operands specified.
185506f32e7eSjoerg   return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0),
185606f32e7eSjoerg                                 DAG.getCondCode(CCCode), NewLHS, NewRHS,
185706f32e7eSjoerg                                 N->getOperand(4)), 0);
185806f32e7eSjoerg }
185906f32e7eSjoerg 
ExpandFloatOp_FCOPYSIGN(SDNode * N)186006f32e7eSjoerg SDValue DAGTypeLegalizer::ExpandFloatOp_FCOPYSIGN(SDNode *N) {
186106f32e7eSjoerg   assert(N->getOperand(1).getValueType() == MVT::ppcf128 &&
186206f32e7eSjoerg          "Logic only correct for ppcf128!");
186306f32e7eSjoerg   SDValue Lo, Hi;
186406f32e7eSjoerg   GetExpandedFloat(N->getOperand(1), Lo, Hi);
186506f32e7eSjoerg   // The ppcf128 value is providing only the sign; take it from the
186606f32e7eSjoerg   // higher-order double (which must have the larger magnitude).
186706f32e7eSjoerg   return DAG.getNode(ISD::FCOPYSIGN, SDLoc(N),
186806f32e7eSjoerg                      N->getValueType(0), N->getOperand(0), Hi);
186906f32e7eSjoerg }
187006f32e7eSjoerg 
ExpandFloatOp_FP_ROUND(SDNode * N)187106f32e7eSjoerg SDValue DAGTypeLegalizer::ExpandFloatOp_FP_ROUND(SDNode *N) {
1872*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
1873*da58b97aSjoerg   assert(N->getOperand(IsStrict ? 1 : 0).getValueType() == MVT::ppcf128 &&
187406f32e7eSjoerg          "Logic only correct for ppcf128!");
187506f32e7eSjoerg   SDValue Lo, Hi;
1876*da58b97aSjoerg   GetExpandedFloat(N->getOperand(IsStrict ? 1 : 0), Lo, Hi);
1877*da58b97aSjoerg 
1878*da58b97aSjoerg   if (!IsStrict)
187906f32e7eSjoerg     // Round it the rest of the way (e.g. to f32) if needed.
188006f32e7eSjoerg     return DAG.getNode(ISD::FP_ROUND, SDLoc(N),
188106f32e7eSjoerg                        N->getValueType(0), Hi, N->getOperand(1));
1882*da58b97aSjoerg 
1883*da58b97aSjoerg   // Eliminate the node if the input float type is the same as the output float
1884*da58b97aSjoerg   // type.
1885*da58b97aSjoerg   if (Hi.getValueType() == N->getValueType(0)) {
1886*da58b97aSjoerg     // Connect the output chain to the input chain, unlinking the node.
1887*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
1888*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 0), Hi);
1889*da58b97aSjoerg     return SDValue();
189006f32e7eSjoerg   }
189106f32e7eSjoerg 
1892*da58b97aSjoerg   SDValue Expansion = DAG.getNode(ISD::STRICT_FP_ROUND, SDLoc(N),
1893*da58b97aSjoerg                                   {N->getValueType(0), MVT::Other},
1894*da58b97aSjoerg                                   {N->getOperand(0), Hi, N->getOperand(2)});
1895*da58b97aSjoerg   ReplaceValueWith(SDValue(N, 1), Expansion.getValue(1));
1896*da58b97aSjoerg   ReplaceValueWith(SDValue(N, 0), Expansion);
1897*da58b97aSjoerg   return SDValue();
1898*da58b97aSjoerg }
1899*da58b97aSjoerg 
ExpandFloatOp_FP_TO_XINT(SDNode * N)1900*da58b97aSjoerg SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_XINT(SDNode *N) {
190106f32e7eSjoerg   EVT RVT = N->getValueType(0);
190206f32e7eSjoerg   SDLoc dl(N);
190306f32e7eSjoerg 
1904*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
1905*da58b97aSjoerg   bool Signed = N->getOpcode() == ISD::FP_TO_SINT ||
1906*da58b97aSjoerg                 N->getOpcode() == ISD::STRICT_FP_TO_SINT;
1907*da58b97aSjoerg   SDValue Op = N->getOperand(IsStrict ? 1 : 0);
1908*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
190906f32e7eSjoerg 
1910*da58b97aSjoerg   EVT NVT;
1911*da58b97aSjoerg   RTLIB::Libcall LC = findFPToIntLibcall(Op.getValueType(), RVT, NVT, Signed);
1912*da58b97aSjoerg   assert(LC != RTLIB::UNKNOWN_LIBCALL && NVT.isSimple() &&
1913*da58b97aSjoerg          "Unsupported FP_TO_XINT!");
191406f32e7eSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
1915*da58b97aSjoerg   std::pair<SDValue, SDValue> Tmp =
1916*da58b97aSjoerg       TLI.makeLibCall(DAG, LC, NVT, Op, CallOptions, dl, Chain);
1917*da58b97aSjoerg   if (!IsStrict)
1918*da58b97aSjoerg     return Tmp.first;
1919*da58b97aSjoerg 
1920*da58b97aSjoerg   ReplaceValueWith(SDValue(N, 1), Tmp.second);
1921*da58b97aSjoerg   ReplaceValueWith(SDValue(N, 0), Tmp.first);
1922*da58b97aSjoerg   return SDValue();
192306f32e7eSjoerg }
192406f32e7eSjoerg 
ExpandFloatOp_SELECT_CC(SDNode * N)192506f32e7eSjoerg SDValue DAGTypeLegalizer::ExpandFloatOp_SELECT_CC(SDNode *N) {
192606f32e7eSjoerg   SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
192706f32e7eSjoerg   ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(4))->get();
1928*da58b97aSjoerg   SDValue Chain;
1929*da58b97aSjoerg   FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, SDLoc(N), Chain);
193006f32e7eSjoerg 
193106f32e7eSjoerg   // If ExpandSetCCOperands returned a scalar, we need to compare the result
193206f32e7eSjoerg   // against zero to select between true and false values.
193306f32e7eSjoerg   if (!NewRHS.getNode()) {
193406f32e7eSjoerg     NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
193506f32e7eSjoerg     CCCode = ISD::SETNE;
193606f32e7eSjoerg   }
193706f32e7eSjoerg 
193806f32e7eSjoerg   // Update N to have the operands specified.
193906f32e7eSjoerg   return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
194006f32e7eSjoerg                                 N->getOperand(2), N->getOperand(3),
194106f32e7eSjoerg                                 DAG.getCondCode(CCCode)), 0);
194206f32e7eSjoerg }
194306f32e7eSjoerg 
ExpandFloatOp_SETCC(SDNode * N)194406f32e7eSjoerg SDValue DAGTypeLegalizer::ExpandFloatOp_SETCC(SDNode *N) {
1945*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
1946*da58b97aSjoerg   SDValue NewLHS = N->getOperand(IsStrict ? 1 : 0);
1947*da58b97aSjoerg   SDValue NewRHS = N->getOperand(IsStrict ? 2 : 1);
1948*da58b97aSjoerg   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1949*da58b97aSjoerg   ISD::CondCode CCCode =
1950*da58b97aSjoerg       cast<CondCodeSDNode>(N->getOperand(IsStrict ? 3 : 2))->get();
1951*da58b97aSjoerg   FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, SDLoc(N), Chain,
1952*da58b97aSjoerg                            N->getOpcode() == ISD::STRICT_FSETCCS);
195306f32e7eSjoerg 
1954*da58b97aSjoerg   // FloatExpandSetCCOperands always returned a scalar.
1955*da58b97aSjoerg   assert(!NewRHS.getNode() && "Expect to return scalar");
195606f32e7eSjoerg   assert(NewLHS.getValueType() == N->getValueType(0) &&
195706f32e7eSjoerg          "Unexpected setcc expansion!");
1958*da58b97aSjoerg   if (Chain) {
1959*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 0), NewLHS);
1960*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Chain);
1961*da58b97aSjoerg     return SDValue();
196206f32e7eSjoerg   }
1963*da58b97aSjoerg   return NewLHS;
196406f32e7eSjoerg }
196506f32e7eSjoerg 
ExpandFloatOp_STORE(SDNode * N,unsigned OpNo)196606f32e7eSjoerg SDValue DAGTypeLegalizer::ExpandFloatOp_STORE(SDNode *N, unsigned OpNo) {
196706f32e7eSjoerg   if (ISD::isNormalStore(N))
196806f32e7eSjoerg     return ExpandOp_NormalStore(N, OpNo);
196906f32e7eSjoerg 
197006f32e7eSjoerg   assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!");
197106f32e7eSjoerg   assert(OpNo == 1 && "Can only expand the stored value so far");
197206f32e7eSjoerg   StoreSDNode *ST = cast<StoreSDNode>(N);
197306f32e7eSjoerg 
197406f32e7eSjoerg   SDValue Chain = ST->getChain();
197506f32e7eSjoerg   SDValue Ptr = ST->getBasePtr();
197606f32e7eSjoerg 
197706f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(),
197806f32e7eSjoerg                                      ST->getValue().getValueType());
197906f32e7eSjoerg   assert(NVT.isByteSized() && "Expanded type not byte sized!");
198006f32e7eSjoerg   assert(ST->getMemoryVT().bitsLE(NVT) && "Float type not round?");
198106f32e7eSjoerg   (void)NVT;
198206f32e7eSjoerg 
198306f32e7eSjoerg   SDValue Lo, Hi;
198406f32e7eSjoerg   GetExpandedOp(ST->getValue(), Lo, Hi);
198506f32e7eSjoerg 
198606f32e7eSjoerg   return DAG.getTruncStore(Chain, SDLoc(N), Hi, Ptr,
198706f32e7eSjoerg                            ST->getMemoryVT(), ST->getMemOperand());
198806f32e7eSjoerg }
198906f32e7eSjoerg 
ExpandFloatOp_LROUND(SDNode * N)199006f32e7eSjoerg SDValue DAGTypeLegalizer::ExpandFloatOp_LROUND(SDNode *N) {
199106f32e7eSjoerg   EVT RVT = N->getValueType(0);
1992*da58b97aSjoerg   EVT RetVT = N->getOperand(0).getValueType();
199306f32e7eSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
199406f32e7eSjoerg   return TLI.makeLibCall(DAG, GetFPLibCall(RetVT,
199506f32e7eSjoerg                                            RTLIB::LROUND_F32,
199606f32e7eSjoerg                                            RTLIB::LROUND_F64,
199706f32e7eSjoerg                                            RTLIB::LROUND_F80,
199806f32e7eSjoerg                                            RTLIB::LROUND_F128,
199906f32e7eSjoerg                                            RTLIB::LROUND_PPCF128),
200006f32e7eSjoerg                          RVT, N->getOperand(0), CallOptions, SDLoc(N)).first;
200106f32e7eSjoerg }
200206f32e7eSjoerg 
ExpandFloatOp_LLROUND(SDNode * N)200306f32e7eSjoerg SDValue DAGTypeLegalizer::ExpandFloatOp_LLROUND(SDNode *N) {
200406f32e7eSjoerg   EVT RVT = N->getValueType(0);
2005*da58b97aSjoerg   EVT RetVT = N->getOperand(0).getValueType();
200606f32e7eSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
200706f32e7eSjoerg   return TLI.makeLibCall(DAG, GetFPLibCall(RetVT,
200806f32e7eSjoerg                                            RTLIB::LLROUND_F32,
200906f32e7eSjoerg                                            RTLIB::LLROUND_F64,
201006f32e7eSjoerg                                            RTLIB::LLROUND_F80,
201106f32e7eSjoerg                                            RTLIB::LLROUND_F128,
201206f32e7eSjoerg                                            RTLIB::LLROUND_PPCF128),
201306f32e7eSjoerg                          RVT, N->getOperand(0), CallOptions, SDLoc(N)).first;
201406f32e7eSjoerg }
201506f32e7eSjoerg 
ExpandFloatOp_LRINT(SDNode * N)201606f32e7eSjoerg SDValue DAGTypeLegalizer::ExpandFloatOp_LRINT(SDNode *N) {
201706f32e7eSjoerg   EVT RVT = N->getValueType(0);
2018*da58b97aSjoerg   EVT RetVT = N->getOperand(0).getValueType();
201906f32e7eSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
202006f32e7eSjoerg   return TLI.makeLibCall(DAG, GetFPLibCall(RetVT,
202106f32e7eSjoerg                                            RTLIB::LRINT_F32,
202206f32e7eSjoerg                                            RTLIB::LRINT_F64,
202306f32e7eSjoerg                                            RTLIB::LRINT_F80,
202406f32e7eSjoerg                                            RTLIB::LRINT_F128,
202506f32e7eSjoerg                                            RTLIB::LRINT_PPCF128),
202606f32e7eSjoerg                          RVT, N->getOperand(0), CallOptions, SDLoc(N)).first;
202706f32e7eSjoerg }
202806f32e7eSjoerg 
ExpandFloatOp_LLRINT(SDNode * N)202906f32e7eSjoerg SDValue DAGTypeLegalizer::ExpandFloatOp_LLRINT(SDNode *N) {
203006f32e7eSjoerg   EVT RVT = N->getValueType(0);
2031*da58b97aSjoerg   EVT RetVT = N->getOperand(0).getValueType();
203206f32e7eSjoerg   TargetLowering::MakeLibCallOptions CallOptions;
203306f32e7eSjoerg   return TLI.makeLibCall(DAG, GetFPLibCall(RetVT,
203406f32e7eSjoerg                                            RTLIB::LLRINT_F32,
203506f32e7eSjoerg                                            RTLIB::LLRINT_F64,
203606f32e7eSjoerg                                            RTLIB::LLRINT_F80,
203706f32e7eSjoerg                                            RTLIB::LLRINT_F128,
203806f32e7eSjoerg                                            RTLIB::LLRINT_PPCF128),
203906f32e7eSjoerg                          RVT, N->getOperand(0), CallOptions, SDLoc(N)).first;
204006f32e7eSjoerg }
204106f32e7eSjoerg 
204206f32e7eSjoerg //===----------------------------------------------------------------------===//
204306f32e7eSjoerg //  Float Operand Promotion
204406f32e7eSjoerg //===----------------------------------------------------------------------===//
204506f32e7eSjoerg //
204606f32e7eSjoerg 
GetPromotionOpcode(EVT OpVT,EVT RetVT)204706f32e7eSjoerg static ISD::NodeType GetPromotionOpcode(EVT OpVT, EVT RetVT) {
204806f32e7eSjoerg   if (OpVT == MVT::f16) {
204906f32e7eSjoerg       return ISD::FP16_TO_FP;
205006f32e7eSjoerg   } else if (RetVT == MVT::f16) {
205106f32e7eSjoerg       return ISD::FP_TO_FP16;
205206f32e7eSjoerg   }
205306f32e7eSjoerg 
205406f32e7eSjoerg   report_fatal_error("Attempt at an invalid promotion-related conversion");
205506f32e7eSjoerg }
205606f32e7eSjoerg 
PromoteFloatOperand(SDNode * N,unsigned OpNo)205706f32e7eSjoerg bool DAGTypeLegalizer::PromoteFloatOperand(SDNode *N, unsigned OpNo) {
205806f32e7eSjoerg   LLVM_DEBUG(dbgs() << "Promote float operand " << OpNo << ": "; N->dump(&DAG);
205906f32e7eSjoerg              dbgs() << "\n");
206006f32e7eSjoerg   SDValue R = SDValue();
206106f32e7eSjoerg 
206206f32e7eSjoerg   if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false)) {
206306f32e7eSjoerg     LLVM_DEBUG(dbgs() << "Node has been custom lowered, done\n");
206406f32e7eSjoerg     return false;
206506f32e7eSjoerg   }
206606f32e7eSjoerg 
206706f32e7eSjoerg   // Nodes that use a promotion-requiring floating point operand, but doesn't
206806f32e7eSjoerg   // produce a promotion-requiring floating point result, need to be legalized
206906f32e7eSjoerg   // to use the promoted float operand.  Nodes that produce at least one
207006f32e7eSjoerg   // promotion-requiring floating point result have their operands legalized as
207106f32e7eSjoerg   // a part of PromoteFloatResult.
207206f32e7eSjoerg   switch (N->getOpcode()) {
207306f32e7eSjoerg     default:
207406f32e7eSjoerg   #ifndef NDEBUG
207506f32e7eSjoerg       dbgs() << "PromoteFloatOperand Op #" << OpNo << ": ";
207606f32e7eSjoerg       N->dump(&DAG); dbgs() << "\n";
207706f32e7eSjoerg   #endif
207806f32e7eSjoerg       llvm_unreachable("Do not know how to promote this operator's operand!");
207906f32e7eSjoerg 
208006f32e7eSjoerg     case ISD::BITCAST:    R = PromoteFloatOp_BITCAST(N, OpNo); break;
208106f32e7eSjoerg     case ISD::FCOPYSIGN:  R = PromoteFloatOp_FCOPYSIGN(N, OpNo); break;
208206f32e7eSjoerg     case ISD::FP_TO_SINT:
208306f32e7eSjoerg     case ISD::FP_TO_UINT: R = PromoteFloatOp_FP_TO_XINT(N, OpNo); break;
2084*da58b97aSjoerg     case ISD::FP_TO_SINT_SAT:
2085*da58b97aSjoerg     case ISD::FP_TO_UINT_SAT:
2086*da58b97aSjoerg                           R = PromoteFloatOp_FP_TO_XINT_SAT(N, OpNo); break;
208706f32e7eSjoerg     case ISD::FP_EXTEND:  R = PromoteFloatOp_FP_EXTEND(N, OpNo); break;
208806f32e7eSjoerg     case ISD::SELECT_CC:  R = PromoteFloatOp_SELECT_CC(N, OpNo); break;
208906f32e7eSjoerg     case ISD::SETCC:      R = PromoteFloatOp_SETCC(N, OpNo); break;
209006f32e7eSjoerg     case ISD::STORE:      R = PromoteFloatOp_STORE(N, OpNo); break;
209106f32e7eSjoerg   }
209206f32e7eSjoerg 
209306f32e7eSjoerg   if (R.getNode())
209406f32e7eSjoerg     ReplaceValueWith(SDValue(N, 0), R);
209506f32e7eSjoerg   return false;
209606f32e7eSjoerg }
209706f32e7eSjoerg 
PromoteFloatOp_BITCAST(SDNode * N,unsigned OpNo)209806f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatOp_BITCAST(SDNode *N, unsigned OpNo) {
209906f32e7eSjoerg   SDValue Op = N->getOperand(0);
210006f32e7eSjoerg   EVT OpVT = Op->getValueType(0);
210106f32e7eSjoerg 
210206f32e7eSjoerg   SDValue Promoted = GetPromotedFloat(N->getOperand(0));
210306f32e7eSjoerg   EVT PromotedVT = Promoted->getValueType(0);
210406f32e7eSjoerg 
210506f32e7eSjoerg   // Convert the promoted float value to the desired IVT.
210606f32e7eSjoerg   EVT IVT = EVT::getIntegerVT(*DAG.getContext(), OpVT.getSizeInBits());
210706f32e7eSjoerg   SDValue Convert = DAG.getNode(GetPromotionOpcode(PromotedVT, OpVT), SDLoc(N),
210806f32e7eSjoerg                                 IVT, Promoted);
210906f32e7eSjoerg   // The final result type might not be an scalar so we need a bitcast. The
211006f32e7eSjoerg   // bitcast will be further legalized if needed.
211106f32e7eSjoerg   return DAG.getBitcast(N->getValueType(0), Convert);
211206f32e7eSjoerg }
211306f32e7eSjoerg 
211406f32e7eSjoerg // Promote Operand 1 of FCOPYSIGN.  Operand 0 ought to be handled by
211506f32e7eSjoerg // PromoteFloatRes_FCOPYSIGN.
PromoteFloatOp_FCOPYSIGN(SDNode * N,unsigned OpNo)211606f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatOp_FCOPYSIGN(SDNode *N, unsigned OpNo) {
211706f32e7eSjoerg   assert (OpNo == 1 && "Only Operand 1 must need promotion here");
211806f32e7eSjoerg   SDValue Op1 = GetPromotedFloat(N->getOperand(1));
211906f32e7eSjoerg 
212006f32e7eSjoerg   return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
212106f32e7eSjoerg                      N->getOperand(0), Op1);
212206f32e7eSjoerg }
212306f32e7eSjoerg 
212406f32e7eSjoerg // Convert the promoted float value to the desired integer type
PromoteFloatOp_FP_TO_XINT(SDNode * N,unsigned OpNo)212506f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatOp_FP_TO_XINT(SDNode *N, unsigned OpNo) {
212606f32e7eSjoerg   SDValue Op = GetPromotedFloat(N->getOperand(0));
212706f32e7eSjoerg   return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), Op);
212806f32e7eSjoerg }
212906f32e7eSjoerg 
PromoteFloatOp_FP_TO_XINT_SAT(SDNode * N,unsigned OpNo)2130*da58b97aSjoerg SDValue DAGTypeLegalizer::PromoteFloatOp_FP_TO_XINT_SAT(SDNode *N,
2131*da58b97aSjoerg                                                         unsigned OpNo) {
2132*da58b97aSjoerg   SDValue Op = GetPromotedFloat(N->getOperand(0));
2133*da58b97aSjoerg   return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), Op,
2134*da58b97aSjoerg                      N->getOperand(1));
2135*da58b97aSjoerg }
2136*da58b97aSjoerg 
PromoteFloatOp_FP_EXTEND(SDNode * N,unsigned OpNo)213706f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatOp_FP_EXTEND(SDNode *N, unsigned OpNo) {
213806f32e7eSjoerg   SDValue Op = GetPromotedFloat(N->getOperand(0));
213906f32e7eSjoerg   EVT VT = N->getValueType(0);
214006f32e7eSjoerg 
214106f32e7eSjoerg   // Desired VT is same as promoted type.  Use promoted float directly.
214206f32e7eSjoerg   if (VT == Op->getValueType(0))
214306f32e7eSjoerg     return Op;
214406f32e7eSjoerg 
214506f32e7eSjoerg   // Else, extend the promoted float value to the desired VT.
214606f32e7eSjoerg   return DAG.getNode(ISD::FP_EXTEND, SDLoc(N), VT, Op);
214706f32e7eSjoerg }
214806f32e7eSjoerg 
214906f32e7eSjoerg // Promote the float operands used for comparison.  The true- and false-
215006f32e7eSjoerg // operands have the same type as the result and are promoted, if needed, by
215106f32e7eSjoerg // PromoteFloatRes_SELECT_CC
PromoteFloatOp_SELECT_CC(SDNode * N,unsigned OpNo)215206f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatOp_SELECT_CC(SDNode *N, unsigned OpNo) {
215306f32e7eSjoerg   SDValue LHS = GetPromotedFloat(N->getOperand(0));
215406f32e7eSjoerg   SDValue RHS = GetPromotedFloat(N->getOperand(1));
215506f32e7eSjoerg 
215606f32e7eSjoerg   return DAG.getNode(ISD::SELECT_CC, SDLoc(N), N->getValueType(0),
215706f32e7eSjoerg                      LHS, RHS, N->getOperand(2), N->getOperand(3),
215806f32e7eSjoerg                      N->getOperand(4));
215906f32e7eSjoerg }
216006f32e7eSjoerg 
216106f32e7eSjoerg // Construct a SETCC that compares the promoted values and sets the conditional
216206f32e7eSjoerg // code.
PromoteFloatOp_SETCC(SDNode * N,unsigned OpNo)216306f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatOp_SETCC(SDNode *N, unsigned OpNo) {
216406f32e7eSjoerg   EVT VT = N->getValueType(0);
216506f32e7eSjoerg   SDValue Op0 = GetPromotedFloat(N->getOperand(0));
216606f32e7eSjoerg   SDValue Op1 = GetPromotedFloat(N->getOperand(1));
216706f32e7eSjoerg   ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(2))->get();
216806f32e7eSjoerg 
2169*da58b97aSjoerg   return DAG.getSetCC(SDLoc(N), VT, Op0, Op1, CCCode);
217006f32e7eSjoerg 
217106f32e7eSjoerg }
217206f32e7eSjoerg 
217306f32e7eSjoerg // Lower the promoted Float down to the integer value of same size and construct
217406f32e7eSjoerg // a STORE of the integer value.
PromoteFloatOp_STORE(SDNode * N,unsigned OpNo)217506f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatOp_STORE(SDNode *N, unsigned OpNo) {
217606f32e7eSjoerg   StoreSDNode *ST = cast<StoreSDNode>(N);
217706f32e7eSjoerg   SDValue Val = ST->getValue();
217806f32e7eSjoerg   SDLoc DL(N);
217906f32e7eSjoerg 
218006f32e7eSjoerg   SDValue Promoted = GetPromotedFloat(Val);
218106f32e7eSjoerg   EVT VT = ST->getOperand(1).getValueType();
218206f32e7eSjoerg   EVT IVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
218306f32e7eSjoerg 
218406f32e7eSjoerg   SDValue NewVal;
218506f32e7eSjoerg   NewVal = DAG.getNode(GetPromotionOpcode(Promoted.getValueType(), VT), DL,
218606f32e7eSjoerg                        IVT, Promoted);
218706f32e7eSjoerg 
218806f32e7eSjoerg   return DAG.getStore(ST->getChain(), DL, NewVal, ST->getBasePtr(),
218906f32e7eSjoerg                       ST->getMemOperand());
219006f32e7eSjoerg }
219106f32e7eSjoerg 
219206f32e7eSjoerg //===----------------------------------------------------------------------===//
219306f32e7eSjoerg //  Float Result Promotion
219406f32e7eSjoerg //===----------------------------------------------------------------------===//
219506f32e7eSjoerg 
PromoteFloatResult(SDNode * N,unsigned ResNo)219606f32e7eSjoerg void DAGTypeLegalizer::PromoteFloatResult(SDNode *N, unsigned ResNo) {
219706f32e7eSjoerg   LLVM_DEBUG(dbgs() << "Promote float result " << ResNo << ": "; N->dump(&DAG);
219806f32e7eSjoerg              dbgs() << "\n");
219906f32e7eSjoerg   SDValue R = SDValue();
220006f32e7eSjoerg 
220106f32e7eSjoerg   // See if the target wants to custom expand this node.
220206f32e7eSjoerg   if (CustomLowerNode(N, N->getValueType(ResNo), true)) {
220306f32e7eSjoerg     LLVM_DEBUG(dbgs() << "Node has been custom expanded, done\n");
220406f32e7eSjoerg     return;
220506f32e7eSjoerg   }
220606f32e7eSjoerg 
220706f32e7eSjoerg   switch (N->getOpcode()) {
220806f32e7eSjoerg     // These opcodes cannot appear if promotion of FP16 is done in the backend
220906f32e7eSjoerg     // instead of Clang
221006f32e7eSjoerg     case ISD::FP16_TO_FP:
221106f32e7eSjoerg     case ISD::FP_TO_FP16:
221206f32e7eSjoerg     default:
221306f32e7eSjoerg #ifndef NDEBUG
221406f32e7eSjoerg       dbgs() << "PromoteFloatResult #" << ResNo << ": ";
221506f32e7eSjoerg       N->dump(&DAG); dbgs() << "\n";
221606f32e7eSjoerg #endif
221706f32e7eSjoerg       llvm_unreachable("Do not know how to promote this operator's result!");
221806f32e7eSjoerg 
221906f32e7eSjoerg     case ISD::BITCAST:    R = PromoteFloatRes_BITCAST(N); break;
222006f32e7eSjoerg     case ISD::ConstantFP: R = PromoteFloatRes_ConstantFP(N); break;
222106f32e7eSjoerg     case ISD::EXTRACT_VECTOR_ELT:
222206f32e7eSjoerg                           R = PromoteFloatRes_EXTRACT_VECTOR_ELT(N); break;
222306f32e7eSjoerg     case ISD::FCOPYSIGN:  R = PromoteFloatRes_FCOPYSIGN(N); break;
222406f32e7eSjoerg 
222506f32e7eSjoerg     // Unary FP Operations
222606f32e7eSjoerg     case ISD::FABS:
222706f32e7eSjoerg     case ISD::FCBRT:
222806f32e7eSjoerg     case ISD::FCEIL:
222906f32e7eSjoerg     case ISD::FCOS:
223006f32e7eSjoerg     case ISD::FEXP:
223106f32e7eSjoerg     case ISD::FEXP2:
223206f32e7eSjoerg     case ISD::FFLOOR:
223306f32e7eSjoerg     case ISD::FLOG:
223406f32e7eSjoerg     case ISD::FLOG2:
223506f32e7eSjoerg     case ISD::FLOG10:
223606f32e7eSjoerg     case ISD::FNEARBYINT:
223706f32e7eSjoerg     case ISD::FNEG:
223806f32e7eSjoerg     case ISD::FRINT:
223906f32e7eSjoerg     case ISD::FROUND:
2240*da58b97aSjoerg     case ISD::FROUNDEVEN:
224106f32e7eSjoerg     case ISD::FSIN:
224206f32e7eSjoerg     case ISD::FSQRT:
224306f32e7eSjoerg     case ISD::FTRUNC:
224406f32e7eSjoerg     case ISD::FCANONICALIZE: R = PromoteFloatRes_UnaryOp(N); break;
224506f32e7eSjoerg 
224606f32e7eSjoerg     // Binary FP Operations
224706f32e7eSjoerg     case ISD::FADD:
224806f32e7eSjoerg     case ISD::FDIV:
224906f32e7eSjoerg     case ISD::FMAXIMUM:
225006f32e7eSjoerg     case ISD::FMINIMUM:
225106f32e7eSjoerg     case ISD::FMAXNUM:
225206f32e7eSjoerg     case ISD::FMINNUM:
225306f32e7eSjoerg     case ISD::FMUL:
225406f32e7eSjoerg     case ISD::FPOW:
225506f32e7eSjoerg     case ISD::FREM:
225606f32e7eSjoerg     case ISD::FSUB:       R = PromoteFloatRes_BinOp(N); break;
225706f32e7eSjoerg 
225806f32e7eSjoerg     case ISD::FMA:        // FMA is same as FMAD
225906f32e7eSjoerg     case ISD::FMAD:       R = PromoteFloatRes_FMAD(N); break;
226006f32e7eSjoerg 
226106f32e7eSjoerg     case ISD::FPOWI:      R = PromoteFloatRes_FPOWI(N); break;
226206f32e7eSjoerg 
226306f32e7eSjoerg     case ISD::FP_ROUND:   R = PromoteFloatRes_FP_ROUND(N); break;
226406f32e7eSjoerg     case ISD::LOAD:       R = PromoteFloatRes_LOAD(N); break;
226506f32e7eSjoerg     case ISD::SELECT:     R = PromoteFloatRes_SELECT(N); break;
226606f32e7eSjoerg     case ISD::SELECT_CC:  R = PromoteFloatRes_SELECT_CC(N); break;
226706f32e7eSjoerg 
226806f32e7eSjoerg     case ISD::SINT_TO_FP:
226906f32e7eSjoerg     case ISD::UINT_TO_FP: R = PromoteFloatRes_XINT_TO_FP(N); break;
227006f32e7eSjoerg     case ISD::UNDEF:      R = PromoteFloatRes_UNDEF(N); break;
227106f32e7eSjoerg     case ISD::ATOMIC_SWAP: R = BitcastToInt_ATOMIC_SWAP(N); break;
2272*da58b97aSjoerg     case ISD::VECREDUCE_FADD:
2273*da58b97aSjoerg     case ISD::VECREDUCE_FMUL:
2274*da58b97aSjoerg     case ISD::VECREDUCE_FMIN:
2275*da58b97aSjoerg     case ISD::VECREDUCE_FMAX:
2276*da58b97aSjoerg       R = PromoteFloatRes_VECREDUCE(N);
2277*da58b97aSjoerg       break;
2278*da58b97aSjoerg     case ISD::VECREDUCE_SEQ_FADD:
2279*da58b97aSjoerg     case ISD::VECREDUCE_SEQ_FMUL:
2280*da58b97aSjoerg       R = PromoteFloatRes_VECREDUCE_SEQ(N);
2281*da58b97aSjoerg       break;
228206f32e7eSjoerg   }
228306f32e7eSjoerg 
228406f32e7eSjoerg   if (R.getNode())
228506f32e7eSjoerg     SetPromotedFloat(SDValue(N, ResNo), R);
228606f32e7eSjoerg }
228706f32e7eSjoerg 
228806f32e7eSjoerg // Bitcast from i16 to f16:  convert the i16 to a f32 value instead.
228906f32e7eSjoerg // At this point, it is not possible to determine if the bitcast value is
229006f32e7eSjoerg // eventually stored to memory or promoted to f32 or promoted to a floating
229106f32e7eSjoerg // point at a higher precision.  Some of these cases are handled by FP_EXTEND,
229206f32e7eSjoerg // STORE promotion handlers.
PromoteFloatRes_BITCAST(SDNode * N)229306f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_BITCAST(SDNode *N) {
229406f32e7eSjoerg   EVT VT = N->getValueType(0);
229506f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
229606f32e7eSjoerg   // Input type isn't guaranteed to be a scalar int so bitcast if not. The
229706f32e7eSjoerg   // bitcast will be legalized further if necessary.
229806f32e7eSjoerg   EVT IVT = EVT::getIntegerVT(*DAG.getContext(),
229906f32e7eSjoerg                               N->getOperand(0).getValueType().getSizeInBits());
230006f32e7eSjoerg   SDValue Cast = DAG.getBitcast(IVT, N->getOperand(0));
230106f32e7eSjoerg   return DAG.getNode(GetPromotionOpcode(VT, NVT), SDLoc(N), NVT, Cast);
230206f32e7eSjoerg }
230306f32e7eSjoerg 
PromoteFloatRes_ConstantFP(SDNode * N)230406f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_ConstantFP(SDNode *N) {
230506f32e7eSjoerg   ConstantFPSDNode *CFPNode = cast<ConstantFPSDNode>(N);
230606f32e7eSjoerg   EVT VT = N->getValueType(0);
230706f32e7eSjoerg   SDLoc DL(N);
230806f32e7eSjoerg 
230906f32e7eSjoerg   // Get the (bit-cast) APInt of the APFloat and build an integer constant
231006f32e7eSjoerg   EVT IVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
231106f32e7eSjoerg   SDValue C = DAG.getConstant(CFPNode->getValueAPF().bitcastToAPInt(), DL,
231206f32e7eSjoerg                               IVT);
231306f32e7eSjoerg 
231406f32e7eSjoerg   // Convert the Constant to the desired FP type
231506f32e7eSjoerg   // FIXME We might be able to do the conversion during compilation and get rid
231606f32e7eSjoerg   // of it from the object code
231706f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
231806f32e7eSjoerg   return DAG.getNode(GetPromotionOpcode(VT, NVT), DL, NVT, C);
231906f32e7eSjoerg }
232006f32e7eSjoerg 
232106f32e7eSjoerg // If the Index operand is a constant, try to redirect the extract operation to
232206f32e7eSjoerg // the correct legalized vector.  If not, bit-convert the input vector to
232306f32e7eSjoerg // equivalent integer vector.  Extract the element as an (bit-cast) integer
232406f32e7eSjoerg // value and convert it to the promoted type.
PromoteFloatRes_EXTRACT_VECTOR_ELT(SDNode * N)232506f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_EXTRACT_VECTOR_ELT(SDNode *N) {
232606f32e7eSjoerg   SDLoc DL(N);
232706f32e7eSjoerg 
232806f32e7eSjoerg   // If the index is constant, try to extract the value from the legalized
232906f32e7eSjoerg   // vector type.
233006f32e7eSjoerg   if (isa<ConstantSDNode>(N->getOperand(1))) {
233106f32e7eSjoerg     SDValue Vec = N->getOperand(0);
233206f32e7eSjoerg     SDValue Idx = N->getOperand(1);
233306f32e7eSjoerg     EVT VecVT = Vec->getValueType(0);
233406f32e7eSjoerg     EVT EltVT = VecVT.getVectorElementType();
233506f32e7eSjoerg 
233606f32e7eSjoerg     uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
233706f32e7eSjoerg 
233806f32e7eSjoerg     switch (getTypeAction(VecVT)) {
233906f32e7eSjoerg     default: break;
234006f32e7eSjoerg     case TargetLowering::TypeScalarizeVector: {
234106f32e7eSjoerg       SDValue Res = GetScalarizedVector(N->getOperand(0));
234206f32e7eSjoerg       ReplaceValueWith(SDValue(N, 0), Res);
234306f32e7eSjoerg       return SDValue();
234406f32e7eSjoerg     }
234506f32e7eSjoerg     case TargetLowering::TypeWidenVector: {
234606f32e7eSjoerg       Vec = GetWidenedVector(Vec);
234706f32e7eSjoerg       SDValue Res = DAG.getNode(N->getOpcode(), DL, EltVT, Vec, Idx);
234806f32e7eSjoerg       ReplaceValueWith(SDValue(N, 0), Res);
234906f32e7eSjoerg       return SDValue();
235006f32e7eSjoerg     }
235106f32e7eSjoerg     case TargetLowering::TypeSplitVector: {
235206f32e7eSjoerg       SDValue Lo, Hi;
235306f32e7eSjoerg       GetSplitVector(Vec, Lo, Hi);
235406f32e7eSjoerg 
235506f32e7eSjoerg       uint64_t LoElts = Lo.getValueType().getVectorNumElements();
235606f32e7eSjoerg       SDValue Res;
235706f32e7eSjoerg       if (IdxVal < LoElts)
235806f32e7eSjoerg         Res = DAG.getNode(N->getOpcode(), DL, EltVT, Lo, Idx);
235906f32e7eSjoerg       else
236006f32e7eSjoerg         Res = DAG.getNode(N->getOpcode(), DL, EltVT, Hi,
236106f32e7eSjoerg                           DAG.getConstant(IdxVal - LoElts, DL,
236206f32e7eSjoerg                                           Idx.getValueType()));
236306f32e7eSjoerg       ReplaceValueWith(SDValue(N, 0), Res);
236406f32e7eSjoerg       return SDValue();
236506f32e7eSjoerg     }
236606f32e7eSjoerg 
236706f32e7eSjoerg     }
236806f32e7eSjoerg   }
236906f32e7eSjoerg 
237006f32e7eSjoerg   // Bit-convert the input vector to the equivalent integer vector
237106f32e7eSjoerg   SDValue NewOp = BitConvertVectorToIntegerVector(N->getOperand(0));
237206f32e7eSjoerg   EVT IVT = NewOp.getValueType().getVectorElementType();
237306f32e7eSjoerg 
237406f32e7eSjoerg   // Extract the element as an (bit-cast) integer value
237506f32e7eSjoerg   SDValue NewVal = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, IVT,
237606f32e7eSjoerg                                NewOp, N->getOperand(1));
237706f32e7eSjoerg 
237806f32e7eSjoerg   // Convert the element to the desired FP type
237906f32e7eSjoerg   EVT VT = N->getValueType(0);
238006f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
238106f32e7eSjoerg   return DAG.getNode(GetPromotionOpcode(VT, NVT), SDLoc(N), NVT, NewVal);
238206f32e7eSjoerg }
238306f32e7eSjoerg 
238406f32e7eSjoerg // FCOPYSIGN(X, Y) returns the value of X with the sign of Y.  If the result
238506f32e7eSjoerg // needs promotion, so does the argument X.  Note that Y, if needed, will be
238606f32e7eSjoerg // handled during operand promotion.
PromoteFloatRes_FCOPYSIGN(SDNode * N)238706f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_FCOPYSIGN(SDNode *N) {
238806f32e7eSjoerg   EVT VT = N->getValueType(0);
238906f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
239006f32e7eSjoerg   SDValue Op0 = GetPromotedFloat(N->getOperand(0));
239106f32e7eSjoerg 
239206f32e7eSjoerg   SDValue Op1 = N->getOperand(1);
239306f32e7eSjoerg 
239406f32e7eSjoerg   return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op0, Op1);
239506f32e7eSjoerg }
239606f32e7eSjoerg 
239706f32e7eSjoerg // Unary operation where the result and the operand have PromoteFloat type
239806f32e7eSjoerg // action.  Construct a new SDNode with the promoted float value of the old
239906f32e7eSjoerg // operand.
PromoteFloatRes_UnaryOp(SDNode * N)240006f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_UnaryOp(SDNode *N) {
240106f32e7eSjoerg   EVT VT = N->getValueType(0);
240206f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
240306f32e7eSjoerg   SDValue Op = GetPromotedFloat(N->getOperand(0));
240406f32e7eSjoerg 
240506f32e7eSjoerg   return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op);
240606f32e7eSjoerg }
240706f32e7eSjoerg 
240806f32e7eSjoerg // Binary operations where the result and both operands have PromoteFloat type
240906f32e7eSjoerg // action.  Construct a new SDNode with the promoted float values of the old
241006f32e7eSjoerg // operands.
PromoteFloatRes_BinOp(SDNode * N)241106f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_BinOp(SDNode *N) {
241206f32e7eSjoerg   EVT VT = N->getValueType(0);
241306f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
241406f32e7eSjoerg   SDValue Op0 = GetPromotedFloat(N->getOperand(0));
241506f32e7eSjoerg   SDValue Op1 = GetPromotedFloat(N->getOperand(1));
241606f32e7eSjoerg   return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op0, Op1, N->getFlags());
241706f32e7eSjoerg }
241806f32e7eSjoerg 
PromoteFloatRes_FMAD(SDNode * N)241906f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_FMAD(SDNode *N) {
242006f32e7eSjoerg   EVT VT = N->getValueType(0);
242106f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
242206f32e7eSjoerg   SDValue Op0 = GetPromotedFloat(N->getOperand(0));
242306f32e7eSjoerg   SDValue Op1 = GetPromotedFloat(N->getOperand(1));
242406f32e7eSjoerg   SDValue Op2 = GetPromotedFloat(N->getOperand(2));
242506f32e7eSjoerg 
242606f32e7eSjoerg   return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op0, Op1, Op2);
242706f32e7eSjoerg }
242806f32e7eSjoerg 
242906f32e7eSjoerg // Promote the Float (first) operand and retain the Integer (second) operand
PromoteFloatRes_FPOWI(SDNode * N)243006f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_FPOWI(SDNode *N) {
243106f32e7eSjoerg   EVT VT = N->getValueType(0);
243206f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
243306f32e7eSjoerg   SDValue Op0 = GetPromotedFloat(N->getOperand(0));
243406f32e7eSjoerg   SDValue Op1 = N->getOperand(1);
243506f32e7eSjoerg 
243606f32e7eSjoerg   return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op0, Op1);
243706f32e7eSjoerg }
243806f32e7eSjoerg 
243906f32e7eSjoerg // Explicit operation to reduce precision.  Reduce the value to half precision
244006f32e7eSjoerg // and promote it back to the legal type.
PromoteFloatRes_FP_ROUND(SDNode * N)244106f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_FP_ROUND(SDNode *N) {
244206f32e7eSjoerg   SDLoc DL(N);
244306f32e7eSjoerg 
244406f32e7eSjoerg   SDValue Op = N->getOperand(0);
244506f32e7eSjoerg   EVT VT = N->getValueType(0);
244606f32e7eSjoerg   EVT OpVT = Op->getValueType(0);
244706f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
244806f32e7eSjoerg   EVT IVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
244906f32e7eSjoerg 
245006f32e7eSjoerg   // Round promoted float to desired precision
245106f32e7eSjoerg   SDValue Round = DAG.getNode(GetPromotionOpcode(OpVT, VT), DL, IVT, Op);
245206f32e7eSjoerg   // Promote it back to the legal output type
245306f32e7eSjoerg   return DAG.getNode(GetPromotionOpcode(VT, NVT), DL, NVT, Round);
245406f32e7eSjoerg }
245506f32e7eSjoerg 
PromoteFloatRes_LOAD(SDNode * N)245606f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_LOAD(SDNode *N) {
245706f32e7eSjoerg   LoadSDNode *L = cast<LoadSDNode>(N);
245806f32e7eSjoerg   EVT VT = N->getValueType(0);
245906f32e7eSjoerg 
246006f32e7eSjoerg   // Load the value as an integer value with the same number of bits.
246106f32e7eSjoerg   EVT IVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
2462*da58b97aSjoerg   SDValue newL = DAG.getLoad(
2463*da58b97aSjoerg       L->getAddressingMode(), L->getExtensionType(), IVT, SDLoc(N),
2464*da58b97aSjoerg       L->getChain(), L->getBasePtr(), L->getOffset(), L->getPointerInfo(), IVT,
2465*da58b97aSjoerg       L->getOriginalAlign(), L->getMemOperand()->getFlags(), L->getAAInfo());
246606f32e7eSjoerg   // Legalize the chain result by replacing uses of the old value chain with the
246706f32e7eSjoerg   // new one
246806f32e7eSjoerg   ReplaceValueWith(SDValue(N, 1), newL.getValue(1));
246906f32e7eSjoerg 
247006f32e7eSjoerg   // Convert the integer value to the desired FP type
247106f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
247206f32e7eSjoerg   return DAG.getNode(GetPromotionOpcode(VT, NVT), SDLoc(N), NVT, newL);
247306f32e7eSjoerg }
247406f32e7eSjoerg 
247506f32e7eSjoerg // Construct a new SELECT node with the promoted true- and false- values.
PromoteFloatRes_SELECT(SDNode * N)247606f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_SELECT(SDNode *N) {
247706f32e7eSjoerg   SDValue TrueVal = GetPromotedFloat(N->getOperand(1));
247806f32e7eSjoerg   SDValue FalseVal = GetPromotedFloat(N->getOperand(2));
247906f32e7eSjoerg 
248006f32e7eSjoerg   return DAG.getNode(ISD::SELECT, SDLoc(N), TrueVal->getValueType(0),
248106f32e7eSjoerg                      N->getOperand(0), TrueVal, FalseVal);
248206f32e7eSjoerg }
248306f32e7eSjoerg 
248406f32e7eSjoerg // Construct a new SELECT_CC node with the promoted true- and false- values.
248506f32e7eSjoerg // The operands used for comparison are promoted by PromoteFloatOp_SELECT_CC.
PromoteFloatRes_SELECT_CC(SDNode * N)248606f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_SELECT_CC(SDNode *N) {
248706f32e7eSjoerg   SDValue TrueVal = GetPromotedFloat(N->getOperand(2));
248806f32e7eSjoerg   SDValue FalseVal = GetPromotedFloat(N->getOperand(3));
248906f32e7eSjoerg 
249006f32e7eSjoerg   return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
249106f32e7eSjoerg                      TrueVal.getNode()->getValueType(0), N->getOperand(0),
249206f32e7eSjoerg                      N->getOperand(1), TrueVal, FalseVal, N->getOperand(4));
249306f32e7eSjoerg }
249406f32e7eSjoerg 
249506f32e7eSjoerg // Construct a SDNode that transforms the SINT or UINT operand to the promoted
249606f32e7eSjoerg // float type.
PromoteFloatRes_XINT_TO_FP(SDNode * N)249706f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_XINT_TO_FP(SDNode *N) {
249806f32e7eSjoerg   SDLoc DL(N);
249906f32e7eSjoerg   EVT VT = N->getValueType(0);
250006f32e7eSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
250106f32e7eSjoerg   SDValue NV = DAG.getNode(N->getOpcode(), DL, NVT, N->getOperand(0));
250206f32e7eSjoerg   // Round the value to the desired precision (that of the source type).
250306f32e7eSjoerg   return DAG.getNode(
250406f32e7eSjoerg       ISD::FP_EXTEND, DL, NVT,
250506f32e7eSjoerg       DAG.getNode(ISD::FP_ROUND, DL, VT, NV, DAG.getIntPtrConstant(0, DL)));
250606f32e7eSjoerg }
250706f32e7eSjoerg 
PromoteFloatRes_UNDEF(SDNode * N)250806f32e7eSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_UNDEF(SDNode *N) {
250906f32e7eSjoerg   return DAG.getUNDEF(TLI.getTypeToTransformTo(*DAG.getContext(),
251006f32e7eSjoerg                                                N->getValueType(0)));
251106f32e7eSjoerg }
251206f32e7eSjoerg 
PromoteFloatRes_VECREDUCE(SDNode * N)2513*da58b97aSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_VECREDUCE(SDNode *N) {
2514*da58b97aSjoerg   // Expand and promote recursively.
2515*da58b97aSjoerg   // TODO: This is non-optimal, but dealing with the concurrently happening
2516*da58b97aSjoerg   // vector-legalization is non-trivial. We could do something similar to
2517*da58b97aSjoerg   // PromoteFloatRes_EXTRACT_VECTOR_ELT here.
2518*da58b97aSjoerg   ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduce(N, DAG));
2519*da58b97aSjoerg   return SDValue();
2520*da58b97aSjoerg }
2521*da58b97aSjoerg 
PromoteFloatRes_VECREDUCE_SEQ(SDNode * N)2522*da58b97aSjoerg SDValue DAGTypeLegalizer::PromoteFloatRes_VECREDUCE_SEQ(SDNode *N) {
2523*da58b97aSjoerg   ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduceSeq(N, DAG));
2524*da58b97aSjoerg   return SDValue();
2525*da58b97aSjoerg }
2526*da58b97aSjoerg 
BitcastToInt_ATOMIC_SWAP(SDNode * N)252706f32e7eSjoerg SDValue DAGTypeLegalizer::BitcastToInt_ATOMIC_SWAP(SDNode *N) {
252806f32e7eSjoerg   EVT VT = N->getValueType(0);
252906f32e7eSjoerg 
253006f32e7eSjoerg   AtomicSDNode *AM = cast<AtomicSDNode>(N);
253106f32e7eSjoerg   SDLoc SL(N);
253206f32e7eSjoerg 
253306f32e7eSjoerg   SDValue CastVal = BitConvertToInteger(AM->getVal());
253406f32e7eSjoerg   EVT CastVT = CastVal.getValueType();
253506f32e7eSjoerg 
253606f32e7eSjoerg   SDValue NewAtomic
253706f32e7eSjoerg     = DAG.getAtomic(ISD::ATOMIC_SWAP, SL, CastVT,
253806f32e7eSjoerg                     DAG.getVTList(CastVT, MVT::Other),
253906f32e7eSjoerg                     { AM->getChain(), AM->getBasePtr(), CastVal },
254006f32e7eSjoerg                     AM->getMemOperand());
254106f32e7eSjoerg 
2542*da58b97aSjoerg   SDValue Result = NewAtomic;
2543*da58b97aSjoerg 
2544*da58b97aSjoerg   if (getTypeAction(VT) == TargetLowering::TypePromoteFloat) {
2545*da58b97aSjoerg     EVT NFPVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
2546*da58b97aSjoerg     Result = DAG.getNode(GetPromotionOpcode(VT, NFPVT), SL, NFPVT,
254706f32e7eSjoerg                                      NewAtomic);
2548*da58b97aSjoerg   }
2549*da58b97aSjoerg 
255006f32e7eSjoerg   // Legalize the chain result by replacing uses of the old value chain with the
255106f32e7eSjoerg   // new one
255206f32e7eSjoerg   ReplaceValueWith(SDValue(N, 1), NewAtomic.getValue(1));
255306f32e7eSjoerg 
2554*da58b97aSjoerg   return Result;
255506f32e7eSjoerg 
255606f32e7eSjoerg }
255706f32e7eSjoerg 
2558*da58b97aSjoerg //===----------------------------------------------------------------------===//
2559*da58b97aSjoerg //  Half Result Soft Promotion
2560*da58b97aSjoerg //===----------------------------------------------------------------------===//
2561*da58b97aSjoerg 
SoftPromoteHalfResult(SDNode * N,unsigned ResNo)2562*da58b97aSjoerg void DAGTypeLegalizer::SoftPromoteHalfResult(SDNode *N, unsigned ResNo) {
2563*da58b97aSjoerg   LLVM_DEBUG(dbgs() << "Soft promote half result " << ResNo << ": ";
2564*da58b97aSjoerg              N->dump(&DAG); dbgs() << "\n");
2565*da58b97aSjoerg   SDValue R = SDValue();
2566*da58b97aSjoerg 
2567*da58b97aSjoerg   // See if the target wants to custom expand this node.
2568*da58b97aSjoerg   if (CustomLowerNode(N, N->getValueType(ResNo), true)) {
2569*da58b97aSjoerg     LLVM_DEBUG(dbgs() << "Node has been custom expanded, done\n");
2570*da58b97aSjoerg     return;
2571*da58b97aSjoerg   }
2572*da58b97aSjoerg 
2573*da58b97aSjoerg   switch (N->getOpcode()) {
2574*da58b97aSjoerg   default:
2575*da58b97aSjoerg #ifndef NDEBUG
2576*da58b97aSjoerg     dbgs() << "SoftPromoteHalfResult #" << ResNo << ": ";
2577*da58b97aSjoerg     N->dump(&DAG); dbgs() << "\n";
2578*da58b97aSjoerg #endif
2579*da58b97aSjoerg     llvm_unreachable("Do not know how to soft promote this operator's result!");
2580*da58b97aSjoerg 
2581*da58b97aSjoerg   case ISD::BITCAST:    R = SoftPromoteHalfRes_BITCAST(N); break;
2582*da58b97aSjoerg   case ISD::ConstantFP: R = SoftPromoteHalfRes_ConstantFP(N); break;
2583*da58b97aSjoerg   case ISD::EXTRACT_VECTOR_ELT:
2584*da58b97aSjoerg     R = SoftPromoteHalfRes_EXTRACT_VECTOR_ELT(N); break;
2585*da58b97aSjoerg   case ISD::FCOPYSIGN:  R = SoftPromoteHalfRes_FCOPYSIGN(N); break;
2586*da58b97aSjoerg   case ISD::STRICT_FP_ROUND:
2587*da58b97aSjoerg   case ISD::FP_ROUND:   R = SoftPromoteHalfRes_FP_ROUND(N); break;
2588*da58b97aSjoerg 
2589*da58b97aSjoerg   // Unary FP Operations
2590*da58b97aSjoerg   case ISD::FABS:
2591*da58b97aSjoerg   case ISD::FCBRT:
2592*da58b97aSjoerg   case ISD::FCEIL:
2593*da58b97aSjoerg   case ISD::FCOS:
2594*da58b97aSjoerg   case ISD::FEXP:
2595*da58b97aSjoerg   case ISD::FEXP2:
2596*da58b97aSjoerg   case ISD::FFLOOR:
2597*da58b97aSjoerg   case ISD::FLOG:
2598*da58b97aSjoerg   case ISD::FLOG2:
2599*da58b97aSjoerg   case ISD::FLOG10:
2600*da58b97aSjoerg   case ISD::FNEARBYINT:
2601*da58b97aSjoerg   case ISD::FNEG:
2602*da58b97aSjoerg   case ISD::FREEZE:
2603*da58b97aSjoerg   case ISD::FRINT:
2604*da58b97aSjoerg   case ISD::FROUND:
2605*da58b97aSjoerg   case ISD::FROUNDEVEN:
2606*da58b97aSjoerg   case ISD::FSIN:
2607*da58b97aSjoerg   case ISD::FSQRT:
2608*da58b97aSjoerg   case ISD::FTRUNC:
2609*da58b97aSjoerg   case ISD::FCANONICALIZE: R = SoftPromoteHalfRes_UnaryOp(N); break;
2610*da58b97aSjoerg 
2611*da58b97aSjoerg   // Binary FP Operations
2612*da58b97aSjoerg   case ISD::FADD:
2613*da58b97aSjoerg   case ISD::FDIV:
2614*da58b97aSjoerg   case ISD::FMAXIMUM:
2615*da58b97aSjoerg   case ISD::FMINIMUM:
2616*da58b97aSjoerg   case ISD::FMAXNUM:
2617*da58b97aSjoerg   case ISD::FMINNUM:
2618*da58b97aSjoerg   case ISD::FMUL:
2619*da58b97aSjoerg   case ISD::FPOW:
2620*da58b97aSjoerg   case ISD::FREM:
2621*da58b97aSjoerg   case ISD::FSUB:        R = SoftPromoteHalfRes_BinOp(N); break;
2622*da58b97aSjoerg 
2623*da58b97aSjoerg   case ISD::FMA:         // FMA is same as FMAD
2624*da58b97aSjoerg   case ISD::FMAD:        R = SoftPromoteHalfRes_FMAD(N); break;
2625*da58b97aSjoerg 
2626*da58b97aSjoerg   case ISD::FPOWI:       R = SoftPromoteHalfRes_FPOWI(N); break;
2627*da58b97aSjoerg 
2628*da58b97aSjoerg   case ISD::LOAD:        R = SoftPromoteHalfRes_LOAD(N); break;
2629*da58b97aSjoerg   case ISD::SELECT:      R = SoftPromoteHalfRes_SELECT(N); break;
2630*da58b97aSjoerg   case ISD::SELECT_CC:   R = SoftPromoteHalfRes_SELECT_CC(N); break;
2631*da58b97aSjoerg   case ISD::SINT_TO_FP:
2632*da58b97aSjoerg   case ISD::UINT_TO_FP:  R = SoftPromoteHalfRes_XINT_TO_FP(N); break;
2633*da58b97aSjoerg   case ISD::UNDEF:       R = SoftPromoteHalfRes_UNDEF(N); break;
2634*da58b97aSjoerg   case ISD::ATOMIC_SWAP: R = BitcastToInt_ATOMIC_SWAP(N); break;
2635*da58b97aSjoerg   case ISD::VECREDUCE_FADD:
2636*da58b97aSjoerg   case ISD::VECREDUCE_FMUL:
2637*da58b97aSjoerg   case ISD::VECREDUCE_FMIN:
2638*da58b97aSjoerg   case ISD::VECREDUCE_FMAX:
2639*da58b97aSjoerg     R = SoftPromoteHalfRes_VECREDUCE(N);
2640*da58b97aSjoerg     break;
2641*da58b97aSjoerg   case ISD::VECREDUCE_SEQ_FADD:
2642*da58b97aSjoerg   case ISD::VECREDUCE_SEQ_FMUL:
2643*da58b97aSjoerg     R = SoftPromoteHalfRes_VECREDUCE_SEQ(N);
2644*da58b97aSjoerg     break;
2645*da58b97aSjoerg   }
2646*da58b97aSjoerg 
2647*da58b97aSjoerg   if (R.getNode())
2648*da58b97aSjoerg     SetSoftPromotedHalf(SDValue(N, ResNo), R);
2649*da58b97aSjoerg }
2650*da58b97aSjoerg 
SoftPromoteHalfRes_BITCAST(SDNode * N)2651*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_BITCAST(SDNode *N) {
2652*da58b97aSjoerg   return BitConvertToInteger(N->getOperand(0));
2653*da58b97aSjoerg }
2654*da58b97aSjoerg 
SoftPromoteHalfRes_ConstantFP(SDNode * N)2655*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_ConstantFP(SDNode *N) {
2656*da58b97aSjoerg   ConstantFPSDNode *CN = cast<ConstantFPSDNode>(N);
2657*da58b97aSjoerg 
2658*da58b97aSjoerg   // Get the (bit-cast) APInt of the APFloat and build an integer constant
2659*da58b97aSjoerg   return DAG.getConstant(CN->getValueAPF().bitcastToAPInt(), SDLoc(CN),
2660*da58b97aSjoerg                          MVT::i16);
2661*da58b97aSjoerg }
2662*da58b97aSjoerg 
SoftPromoteHalfRes_EXTRACT_VECTOR_ELT(SDNode * N)2663*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_EXTRACT_VECTOR_ELT(SDNode *N) {
2664*da58b97aSjoerg   SDValue NewOp = BitConvertVectorToIntegerVector(N->getOperand(0));
2665*da58b97aSjoerg   return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
2666*da58b97aSjoerg                      NewOp.getValueType().getVectorElementType(), NewOp,
2667*da58b97aSjoerg                      N->getOperand(1));
2668*da58b97aSjoerg }
2669*da58b97aSjoerg 
SoftPromoteHalfRes_FCOPYSIGN(SDNode * N)2670*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FCOPYSIGN(SDNode *N) {
2671*da58b97aSjoerg   SDValue LHS = GetSoftPromotedHalf(N->getOperand(0));
2672*da58b97aSjoerg   SDValue RHS = BitConvertToInteger(N->getOperand(1));
2673*da58b97aSjoerg   SDLoc dl(N);
2674*da58b97aSjoerg 
2675*da58b97aSjoerg   EVT LVT = LHS.getValueType();
2676*da58b97aSjoerg   EVT RVT = RHS.getValueType();
2677*da58b97aSjoerg 
2678*da58b97aSjoerg   unsigned LSize = LVT.getSizeInBits();
2679*da58b97aSjoerg   unsigned RSize = RVT.getSizeInBits();
2680*da58b97aSjoerg 
2681*da58b97aSjoerg   // First get the sign bit of second operand.
2682*da58b97aSjoerg   SDValue SignBit = DAG.getNode(
2683*da58b97aSjoerg       ISD::SHL, dl, RVT, DAG.getConstant(1, dl, RVT),
2684*da58b97aSjoerg       DAG.getConstant(RSize - 1, dl,
2685*da58b97aSjoerg                       TLI.getShiftAmountTy(RVT, DAG.getDataLayout())));
2686*da58b97aSjoerg   SignBit = DAG.getNode(ISD::AND, dl, RVT, RHS, SignBit);
2687*da58b97aSjoerg 
2688*da58b97aSjoerg   // Shift right or sign-extend it if the two operands have different types.
2689*da58b97aSjoerg   int SizeDiff = RVT.getSizeInBits() - LVT.getSizeInBits();
2690*da58b97aSjoerg   if (SizeDiff > 0) {
2691*da58b97aSjoerg     SignBit =
2692*da58b97aSjoerg         DAG.getNode(ISD::SRL, dl, RVT, SignBit,
2693*da58b97aSjoerg                     DAG.getConstant(SizeDiff, dl,
2694*da58b97aSjoerg                                     TLI.getShiftAmountTy(SignBit.getValueType(),
2695*da58b97aSjoerg                                                          DAG.getDataLayout())));
2696*da58b97aSjoerg     SignBit = DAG.getNode(ISD::TRUNCATE, dl, LVT, SignBit);
2697*da58b97aSjoerg   } else if (SizeDiff < 0) {
2698*da58b97aSjoerg     SignBit = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, SignBit);
2699*da58b97aSjoerg     SignBit =
2700*da58b97aSjoerg         DAG.getNode(ISD::SHL, dl, LVT, SignBit,
2701*da58b97aSjoerg                     DAG.getConstant(-SizeDiff, dl,
2702*da58b97aSjoerg                                     TLI.getShiftAmountTy(SignBit.getValueType(),
2703*da58b97aSjoerg                                                          DAG.getDataLayout())));
2704*da58b97aSjoerg   }
2705*da58b97aSjoerg 
2706*da58b97aSjoerg   // Clear the sign bit of the first operand.
2707*da58b97aSjoerg   SDValue Mask = DAG.getNode(
2708*da58b97aSjoerg       ISD::SHL, dl, LVT, DAG.getConstant(1, dl, LVT),
2709*da58b97aSjoerg       DAG.getConstant(LSize - 1, dl,
2710*da58b97aSjoerg                       TLI.getShiftAmountTy(LVT, DAG.getDataLayout())));
2711*da58b97aSjoerg   Mask = DAG.getNode(ISD::SUB, dl, LVT, Mask, DAG.getConstant(1, dl, LVT));
2712*da58b97aSjoerg   LHS = DAG.getNode(ISD::AND, dl, LVT, LHS, Mask);
2713*da58b97aSjoerg 
2714*da58b97aSjoerg   // Or the value with the sign bit.
2715*da58b97aSjoerg   return DAG.getNode(ISD::OR, dl, LVT, LHS, SignBit);
2716*da58b97aSjoerg }
2717*da58b97aSjoerg 
SoftPromoteHalfRes_FMAD(SDNode * N)2718*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FMAD(SDNode *N) {
2719*da58b97aSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
2720*da58b97aSjoerg   SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
2721*da58b97aSjoerg   SDValue Op1 = GetSoftPromotedHalf(N->getOperand(1));
2722*da58b97aSjoerg   SDValue Op2 = GetSoftPromotedHalf(N->getOperand(2));
2723*da58b97aSjoerg   SDLoc dl(N);
2724*da58b97aSjoerg 
2725*da58b97aSjoerg   // Promote to the larger FP type.
2726*da58b97aSjoerg   Op0 = DAG.getNode(ISD::FP16_TO_FP, dl, NVT, Op0);
2727*da58b97aSjoerg   Op1 = DAG.getNode(ISD::FP16_TO_FP, dl, NVT, Op1);
2728*da58b97aSjoerg   Op2 = DAG.getNode(ISD::FP16_TO_FP, dl, NVT, Op2);
2729*da58b97aSjoerg 
2730*da58b97aSjoerg   SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, Op0, Op1, Op2);
2731*da58b97aSjoerg 
2732*da58b97aSjoerg   // Convert back to FP16 as an integer.
2733*da58b97aSjoerg   return DAG.getNode(ISD::FP_TO_FP16, dl, MVT::i16, Res);
2734*da58b97aSjoerg }
2735*da58b97aSjoerg 
SoftPromoteHalfRes_FPOWI(SDNode * N)2736*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FPOWI(SDNode *N) {
2737*da58b97aSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
2738*da58b97aSjoerg   SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
2739*da58b97aSjoerg   SDValue Op1 = N->getOperand(1);
2740*da58b97aSjoerg   SDLoc dl(N);
2741*da58b97aSjoerg 
2742*da58b97aSjoerg   Op0 = DAG.getNode(ISD::FP16_TO_FP, dl, NVT, Op0);
2743*da58b97aSjoerg 
2744*da58b97aSjoerg   SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, Op0, Op1);
2745*da58b97aSjoerg 
2746*da58b97aSjoerg   // Convert back to FP16 as an integer.
2747*da58b97aSjoerg   return DAG.getNode(ISD::FP_TO_FP16, dl, MVT::i16, Res);
2748*da58b97aSjoerg }
2749*da58b97aSjoerg 
SoftPromoteHalfRes_FP_ROUND(SDNode * N)2750*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FP_ROUND(SDNode *N) {
2751*da58b97aSjoerg   if (N->isStrictFPOpcode()) {
2752*da58b97aSjoerg     SDValue Res =
2753*da58b97aSjoerg         DAG.getNode(ISD::STRICT_FP_TO_FP16, SDLoc(N), {MVT::i16, MVT::Other},
2754*da58b97aSjoerg                     {N->getOperand(0), N->getOperand(1)});
2755*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
2756*da58b97aSjoerg     return Res;
2757*da58b97aSjoerg   }
2758*da58b97aSjoerg 
2759*da58b97aSjoerg   return DAG.getNode(ISD::FP_TO_FP16, SDLoc(N), MVT::i16, N->getOperand(0));
2760*da58b97aSjoerg }
2761*da58b97aSjoerg 
SoftPromoteHalfRes_LOAD(SDNode * N)2762*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_LOAD(SDNode *N) {
2763*da58b97aSjoerg   LoadSDNode *L = cast<LoadSDNode>(N);
2764*da58b97aSjoerg 
2765*da58b97aSjoerg   // Load the value as an integer value with the same number of bits.
2766*da58b97aSjoerg   assert(L->getExtensionType() == ISD::NON_EXTLOAD && "Unexpected extension!");
2767*da58b97aSjoerg   SDValue NewL =
2768*da58b97aSjoerg       DAG.getLoad(L->getAddressingMode(), L->getExtensionType(), MVT::i16,
2769*da58b97aSjoerg                   SDLoc(N), L->getChain(), L->getBasePtr(), L->getOffset(),
2770*da58b97aSjoerg                   L->getPointerInfo(), MVT::i16, L->getOriginalAlign(),
2771*da58b97aSjoerg                   L->getMemOperand()->getFlags(), L->getAAInfo());
2772*da58b97aSjoerg   // Legalize the chain result by replacing uses of the old value chain with the
2773*da58b97aSjoerg   // new one
2774*da58b97aSjoerg   ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
2775*da58b97aSjoerg   return NewL;
2776*da58b97aSjoerg }
2777*da58b97aSjoerg 
SoftPromoteHalfRes_SELECT(SDNode * N)2778*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_SELECT(SDNode *N) {
2779*da58b97aSjoerg   SDValue Op1 = GetSoftPromotedHalf(N->getOperand(1));
2780*da58b97aSjoerg   SDValue Op2 = GetSoftPromotedHalf(N->getOperand(2));
2781*da58b97aSjoerg   return DAG.getSelect(SDLoc(N), Op1.getValueType(), N->getOperand(0), Op1,
2782*da58b97aSjoerg                        Op2);
2783*da58b97aSjoerg }
2784*da58b97aSjoerg 
SoftPromoteHalfRes_SELECT_CC(SDNode * N)2785*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_SELECT_CC(SDNode *N) {
2786*da58b97aSjoerg   SDValue Op2 = GetSoftPromotedHalf(N->getOperand(2));
2787*da58b97aSjoerg   SDValue Op3 = GetSoftPromotedHalf(N->getOperand(3));
2788*da58b97aSjoerg   return DAG.getNode(ISD::SELECT_CC, SDLoc(N), Op2.getValueType(),
2789*da58b97aSjoerg                      N->getOperand(0), N->getOperand(1), Op2, Op3,
2790*da58b97aSjoerg                      N->getOperand(4));
2791*da58b97aSjoerg }
2792*da58b97aSjoerg 
SoftPromoteHalfRes_XINT_TO_FP(SDNode * N)2793*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_XINT_TO_FP(SDNode *N) {
2794*da58b97aSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
2795*da58b97aSjoerg   SDLoc dl(N);
2796*da58b97aSjoerg 
2797*da58b97aSjoerg   SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, N->getOperand(0));
2798*da58b97aSjoerg 
2799*da58b97aSjoerg   // Round the value to the softened type.
2800*da58b97aSjoerg   return DAG.getNode(ISD::FP_TO_FP16, dl, MVT::i16, Res);
2801*da58b97aSjoerg }
2802*da58b97aSjoerg 
SoftPromoteHalfRes_UNDEF(SDNode * N)2803*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_UNDEF(SDNode *N) {
2804*da58b97aSjoerg   return DAG.getUNDEF(MVT::i16);
2805*da58b97aSjoerg }
2806*da58b97aSjoerg 
SoftPromoteHalfRes_UnaryOp(SDNode * N)2807*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_UnaryOp(SDNode *N) {
2808*da58b97aSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
2809*da58b97aSjoerg   SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
2810*da58b97aSjoerg   SDLoc dl(N);
2811*da58b97aSjoerg 
2812*da58b97aSjoerg   // Promote to the larger FP type.
2813*da58b97aSjoerg   Op = DAG.getNode(ISD::FP16_TO_FP, dl, NVT, Op);
2814*da58b97aSjoerg 
2815*da58b97aSjoerg   SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, Op);
2816*da58b97aSjoerg 
2817*da58b97aSjoerg   // Convert back to FP16 as an integer.
2818*da58b97aSjoerg   return DAG.getNode(ISD::FP_TO_FP16, dl, MVT::i16, Res);
2819*da58b97aSjoerg }
2820*da58b97aSjoerg 
SoftPromoteHalfRes_BinOp(SDNode * N)2821*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_BinOp(SDNode *N) {
2822*da58b97aSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
2823*da58b97aSjoerg   SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
2824*da58b97aSjoerg   SDValue Op1 = GetSoftPromotedHalf(N->getOperand(1));
2825*da58b97aSjoerg   SDLoc dl(N);
2826*da58b97aSjoerg 
2827*da58b97aSjoerg   // Promote to the larger FP type.
2828*da58b97aSjoerg   Op0 = DAG.getNode(ISD::FP16_TO_FP, dl, NVT, Op0);
2829*da58b97aSjoerg   Op1 = DAG.getNode(ISD::FP16_TO_FP, dl, NVT, Op1);
2830*da58b97aSjoerg 
2831*da58b97aSjoerg   SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, Op0, Op1);
2832*da58b97aSjoerg 
2833*da58b97aSjoerg   // Convert back to FP16 as an integer.
2834*da58b97aSjoerg   return DAG.getNode(ISD::FP_TO_FP16, dl, MVT::i16, Res);
2835*da58b97aSjoerg }
2836*da58b97aSjoerg 
SoftPromoteHalfRes_VECREDUCE(SDNode * N)2837*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_VECREDUCE(SDNode *N) {
2838*da58b97aSjoerg   // Expand and soften recursively.
2839*da58b97aSjoerg   ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduce(N, DAG));
2840*da58b97aSjoerg   return SDValue();
2841*da58b97aSjoerg }
2842*da58b97aSjoerg 
SoftPromoteHalfRes_VECREDUCE_SEQ(SDNode * N)2843*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfRes_VECREDUCE_SEQ(SDNode *N) {
2844*da58b97aSjoerg   // Expand and soften.
2845*da58b97aSjoerg   ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduceSeq(N, DAG));
2846*da58b97aSjoerg   return SDValue();
2847*da58b97aSjoerg }
2848*da58b97aSjoerg 
2849*da58b97aSjoerg //===----------------------------------------------------------------------===//
2850*da58b97aSjoerg //  Half Operand Soft Promotion
2851*da58b97aSjoerg //===----------------------------------------------------------------------===//
2852*da58b97aSjoerg 
SoftPromoteHalfOperand(SDNode * N,unsigned OpNo)2853*da58b97aSjoerg bool DAGTypeLegalizer::SoftPromoteHalfOperand(SDNode *N, unsigned OpNo) {
2854*da58b97aSjoerg   LLVM_DEBUG(dbgs() << "Soft promote half operand " << OpNo << ": ";
2855*da58b97aSjoerg              N->dump(&DAG); dbgs() << "\n");
2856*da58b97aSjoerg   SDValue Res = SDValue();
2857*da58b97aSjoerg 
2858*da58b97aSjoerg   if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false)) {
2859*da58b97aSjoerg     LLVM_DEBUG(dbgs() << "Node has been custom lowered, done\n");
2860*da58b97aSjoerg     return false;
2861*da58b97aSjoerg   }
2862*da58b97aSjoerg 
2863*da58b97aSjoerg   // Nodes that use a promotion-requiring floating point operand, but doesn't
2864*da58b97aSjoerg   // produce a soft promotion-requiring floating point result, need to be
2865*da58b97aSjoerg   // legalized to use the soft promoted float operand.  Nodes that produce at
2866*da58b97aSjoerg   // least one soft promotion-requiring floating point result have their
2867*da58b97aSjoerg   // operands legalized as a part of PromoteFloatResult.
2868*da58b97aSjoerg   switch (N->getOpcode()) {
2869*da58b97aSjoerg   default:
2870*da58b97aSjoerg   #ifndef NDEBUG
2871*da58b97aSjoerg     dbgs() << "SoftPromoteHalfOperand Op #" << OpNo << ": ";
2872*da58b97aSjoerg     N->dump(&DAG); dbgs() << "\n";
2873*da58b97aSjoerg   #endif
2874*da58b97aSjoerg     llvm_unreachable("Do not know how to soft promote this operator's operand!");
2875*da58b97aSjoerg 
2876*da58b97aSjoerg   case ISD::BITCAST:    Res = SoftPromoteHalfOp_BITCAST(N); break;
2877*da58b97aSjoerg   case ISD::FCOPYSIGN:  Res = SoftPromoteHalfOp_FCOPYSIGN(N, OpNo); break;
2878*da58b97aSjoerg   case ISD::FP_TO_SINT:
2879*da58b97aSjoerg   case ISD::FP_TO_UINT: Res = SoftPromoteHalfOp_FP_TO_XINT(N); break;
2880*da58b97aSjoerg   case ISD::FP_TO_SINT_SAT:
2881*da58b97aSjoerg   case ISD::FP_TO_UINT_SAT:
2882*da58b97aSjoerg                         Res = SoftPromoteHalfOp_FP_TO_XINT_SAT(N); break;
2883*da58b97aSjoerg   case ISD::STRICT_FP_EXTEND:
2884*da58b97aSjoerg   case ISD::FP_EXTEND:  Res = SoftPromoteHalfOp_FP_EXTEND(N); break;
2885*da58b97aSjoerg   case ISD::SELECT_CC:  Res = SoftPromoteHalfOp_SELECT_CC(N, OpNo); break;
2886*da58b97aSjoerg   case ISD::SETCC:      Res = SoftPromoteHalfOp_SETCC(N); break;
2887*da58b97aSjoerg   case ISD::STORE:      Res = SoftPromoteHalfOp_STORE(N, OpNo); break;
2888*da58b97aSjoerg   }
2889*da58b97aSjoerg 
2890*da58b97aSjoerg   if (!Res.getNode())
2891*da58b97aSjoerg     return false;
2892*da58b97aSjoerg 
2893*da58b97aSjoerg   assert(Res.getNode() != N && "Expected a new node!");
2894*da58b97aSjoerg 
2895*da58b97aSjoerg   assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
2896*da58b97aSjoerg          "Invalid operand expansion");
2897*da58b97aSjoerg 
2898*da58b97aSjoerg   ReplaceValueWith(SDValue(N, 0), Res);
2899*da58b97aSjoerg   return false;
2900*da58b97aSjoerg }
2901*da58b97aSjoerg 
SoftPromoteHalfOp_BITCAST(SDNode * N)2902*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfOp_BITCAST(SDNode *N) {
2903*da58b97aSjoerg   SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
2904*da58b97aSjoerg 
2905*da58b97aSjoerg   return DAG.getNode(ISD::BITCAST, SDLoc(N), N->getValueType(0), Op0);
2906*da58b97aSjoerg }
2907*da58b97aSjoerg 
SoftPromoteHalfOp_FCOPYSIGN(SDNode * N,unsigned OpNo)2908*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FCOPYSIGN(SDNode *N,
2909*da58b97aSjoerg                                                       unsigned OpNo) {
2910*da58b97aSjoerg   assert(OpNo == 1 && "Only Operand 1 must need promotion here");
2911*da58b97aSjoerg   SDValue Op1 = N->getOperand(1);
2912*da58b97aSjoerg   SDLoc dl(N);
2913*da58b97aSjoerg 
2914*da58b97aSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op1.getValueType());
2915*da58b97aSjoerg 
2916*da58b97aSjoerg   Op1 = GetSoftPromotedHalf(Op1);
2917*da58b97aSjoerg   Op1 = DAG.getNode(ISD::FP16_TO_FP, dl, NVT, Op1);
2918*da58b97aSjoerg 
2919*da58b97aSjoerg   return DAG.getNode(N->getOpcode(), dl, N->getValueType(0), N->getOperand(0),
2920*da58b97aSjoerg                      Op1);
2921*da58b97aSjoerg }
2922*da58b97aSjoerg 
SoftPromoteHalfOp_FP_EXTEND(SDNode * N)2923*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_EXTEND(SDNode *N) {
2924*da58b97aSjoerg   bool IsStrict = N->isStrictFPOpcode();
2925*da58b97aSjoerg   SDValue Op = GetSoftPromotedHalf(N->getOperand(IsStrict ? 1 : 0));
2926*da58b97aSjoerg 
2927*da58b97aSjoerg   if (IsStrict) {
2928*da58b97aSjoerg     SDValue Res =
2929*da58b97aSjoerg         DAG.getNode(ISD::STRICT_FP16_TO_FP, SDLoc(N),
2930*da58b97aSjoerg                     {N->getValueType(0), MVT::Other}, {N->getOperand(0), Op});
2931*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
2932*da58b97aSjoerg     ReplaceValueWith(SDValue(N, 0), Res);
2933*da58b97aSjoerg     return SDValue();
2934*da58b97aSjoerg   }
2935*da58b97aSjoerg 
2936*da58b97aSjoerg   return DAG.getNode(ISD::FP16_TO_FP, SDLoc(N), N->getValueType(0), Op);
2937*da58b97aSjoerg }
2938*da58b97aSjoerg 
SoftPromoteHalfOp_FP_TO_XINT(SDNode * N)2939*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_TO_XINT(SDNode *N) {
2940*da58b97aSjoerg   SDValue Op = N->getOperand(0);
2941*da58b97aSjoerg   SDLoc dl(N);
2942*da58b97aSjoerg 
2943*da58b97aSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType());
2944*da58b97aSjoerg 
2945*da58b97aSjoerg   Op = GetSoftPromotedHalf(Op);
2946*da58b97aSjoerg 
2947*da58b97aSjoerg   SDValue Res = DAG.getNode(ISD::FP16_TO_FP, dl, NVT, Op);
2948*da58b97aSjoerg 
2949*da58b97aSjoerg   return DAG.getNode(N->getOpcode(), dl, N->getValueType(0), Res);
2950*da58b97aSjoerg }
2951*da58b97aSjoerg 
SoftPromoteHalfOp_FP_TO_XINT_SAT(SDNode * N)2952*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_TO_XINT_SAT(SDNode *N) {
2953*da58b97aSjoerg   SDValue Op = N->getOperand(0);
2954*da58b97aSjoerg   SDLoc dl(N);
2955*da58b97aSjoerg 
2956*da58b97aSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType());
2957*da58b97aSjoerg 
2958*da58b97aSjoerg   Op = GetSoftPromotedHalf(Op);
2959*da58b97aSjoerg 
2960*da58b97aSjoerg   SDValue Res = DAG.getNode(ISD::FP16_TO_FP, dl, NVT, Op);
2961*da58b97aSjoerg 
2962*da58b97aSjoerg   return DAG.getNode(N->getOpcode(), dl, N->getValueType(0), Res,
2963*da58b97aSjoerg                      N->getOperand(1));
2964*da58b97aSjoerg }
2965*da58b97aSjoerg 
SoftPromoteHalfOp_SELECT_CC(SDNode * N,unsigned OpNo)2966*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfOp_SELECT_CC(SDNode *N,
2967*da58b97aSjoerg                                                       unsigned OpNo) {
2968*da58b97aSjoerg   assert(OpNo == 0 && "Can only soften the comparison values");
2969*da58b97aSjoerg   SDValue Op0 = N->getOperand(0);
2970*da58b97aSjoerg   SDValue Op1 = N->getOperand(1);
2971*da58b97aSjoerg   SDLoc dl(N);
2972*da58b97aSjoerg 
2973*da58b97aSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op0.getValueType());
2974*da58b97aSjoerg 
2975*da58b97aSjoerg   Op0 = GetSoftPromotedHalf(Op0);
2976*da58b97aSjoerg   Op1 = GetSoftPromotedHalf(Op1);
2977*da58b97aSjoerg 
2978*da58b97aSjoerg   // Promote to the larger FP type.
2979*da58b97aSjoerg   Op0 = DAG.getNode(ISD::FP16_TO_FP, dl, NVT, Op0);
2980*da58b97aSjoerg   Op1 = DAG.getNode(ISD::FP16_TO_FP, dl, NVT, Op1);
2981*da58b97aSjoerg 
2982*da58b97aSjoerg   return DAG.getNode(ISD::SELECT_CC, SDLoc(N), N->getValueType(0), Op0, Op1,
2983*da58b97aSjoerg                      N->getOperand(2), N->getOperand(3), N->getOperand(4));
2984*da58b97aSjoerg }
2985*da58b97aSjoerg 
SoftPromoteHalfOp_SETCC(SDNode * N)2986*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfOp_SETCC(SDNode *N) {
2987*da58b97aSjoerg   SDValue Op0 = N->getOperand(0);
2988*da58b97aSjoerg   SDValue Op1 = N->getOperand(1);
2989*da58b97aSjoerg   ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(2))->get();
2990*da58b97aSjoerg   SDLoc dl(N);
2991*da58b97aSjoerg 
2992*da58b97aSjoerg   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op0.getValueType());
2993*da58b97aSjoerg 
2994*da58b97aSjoerg   Op0 = GetSoftPromotedHalf(Op0);
2995*da58b97aSjoerg   Op1 = GetSoftPromotedHalf(Op1);
2996*da58b97aSjoerg 
2997*da58b97aSjoerg   // Promote to the larger FP type.
2998*da58b97aSjoerg   Op0 = DAG.getNode(ISD::FP16_TO_FP, dl, NVT, Op0);
2999*da58b97aSjoerg   Op1 = DAG.getNode(ISD::FP16_TO_FP, dl, NVT, Op1);
3000*da58b97aSjoerg 
3001*da58b97aSjoerg   return DAG.getSetCC(SDLoc(N), N->getValueType(0), Op0, Op1, CCCode);
3002*da58b97aSjoerg }
3003*da58b97aSjoerg 
SoftPromoteHalfOp_STORE(SDNode * N,unsigned OpNo)3004*da58b97aSjoerg SDValue DAGTypeLegalizer::SoftPromoteHalfOp_STORE(SDNode *N, unsigned OpNo) {
3005*da58b97aSjoerg   assert(OpNo == 1 && "Can only soften the stored value!");
3006*da58b97aSjoerg   StoreSDNode *ST = cast<StoreSDNode>(N);
3007*da58b97aSjoerg   SDValue Val = ST->getValue();
3008*da58b97aSjoerg   SDLoc dl(N);
3009*da58b97aSjoerg 
3010*da58b97aSjoerg   assert(!ST->isTruncatingStore() && "Unexpected truncating store.");
3011*da58b97aSjoerg   SDValue Promoted = GetSoftPromotedHalf(Val);
3012*da58b97aSjoerg   return DAG.getStore(ST->getChain(), dl, Promoted, ST->getBasePtr(),
3013*da58b97aSjoerg                       ST->getMemOperand());
3014*da58b97aSjoerg }
3015