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