LLVM 24.0.0git
LegalizeFloatTypes.cpp
Go to the documentation of this file.
1//===-------- LegalizeFloatTypes.cpp - Legalization of float types --------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements float type expansion and softening for LegalizeTypes.
10// Softening is the act of turning a computation in an illegal floating point
11// type into a computation in an integer type of the same size; also known as
12// "soft float". For example, turning f32 arithmetic into operations using i32.
13// The resulting integer value is the same as what you would get by performing
14// the floating point operation and bitcasting the result to the integer type.
15// Expansion is the act of changing a computation in an illegal type to be a
16// computation in two identical registers of a smaller type. For example,
17// implementing ppcf128 arithmetic in two f64 registers.
18//
19//===----------------------------------------------------------------------===//
20
21#include "LegalizeTypes.h"
25using namespace llvm;
26
27#define DEBUG_TYPE "legalize-types"
28
29/// GetFPLibCall - Return the right libcall for the given floating point type.
30/// FIXME: This is a local version of RTLIB::getFPLibCall that should be
31/// refactored away (see RTLIB::getPOWI for an example).
32static RTLIB::Libcall GetFPLibCall(EVT VT,
33 RTLIB::Libcall Call_F32,
34 RTLIB::Libcall Call_F64,
35 RTLIB::Libcall Call_F80,
36 RTLIB::Libcall Call_F128,
37 RTLIB::Libcall Call_PPCF128) {
38 return
39 VT == MVT::f32 ? Call_F32 :
40 VT == MVT::f64 ? Call_F64 :
41 VT == MVT::f80 ? Call_F80 :
42 VT == MVT::f128 ? Call_F128 :
43 VT == MVT::ppcf128 ? Call_PPCF128 :
44 RTLIB::UNKNOWN_LIBCALL;
45}
46
47//===----------------------------------------------------------------------===//
48// Convert Float Results to Integer
49//===----------------------------------------------------------------------===//
50
51void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) {
52 LLVM_DEBUG(dbgs() << "Soften float result " << ResNo << ": "; N->dump(&DAG));
53 SDValue R = SDValue();
54
55 switch (N->getOpcode()) {
56 // clang-format off
57 default:
58#ifndef NDEBUG
59 dbgs() << "SoftenFloatResult #" << ResNo << ": ";
60 N->dump(&DAG); dbgs() << "\n";
61#endif
62 report_fatal_error("Do not know how to soften the result of this "
63 "operator!");
64 case ISD::EXTRACT_ELEMENT: R = SoftenFloatRes_EXTRACT_ELEMENT(N); break;
65 case ISD::ARITH_FENCE: R = SoftenFloatRes_ARITH_FENCE(N); break;
66 case ISD::MERGE_VALUES:R = SoftenFloatRes_MERGE_VALUES(N, ResNo); break;
67 case ISD::BITCAST: R = SoftenFloatRes_BITCAST(N); break;
68 case ISD::BUILD_PAIR: R = SoftenFloatRes_BUILD_PAIR(N); break;
69 case ISD::ConstantFP: R = SoftenFloatRes_ConstantFP(N); break;
71 R = SoftenFloatRes_EXTRACT_VECTOR_ELT(N, ResNo); break;
72 case ISD::FABS: R = SoftenFloatRes_FABS(N); break;
74 R = SoftenFloatRes_FCANONICALIZE(N); break;
76 case ISD::FMINNUM: R = SoftenFloatRes_FMINNUM(N); break;
78 case ISD::FMAXNUM: R = SoftenFloatRes_FMAXNUM(N); break;
79 case ISD::FMINIMUMNUM: R = SoftenFloatRes_FMINIMUMNUM(N); break;
80 case ISD::FMAXIMUMNUM: R = SoftenFloatRes_FMAXIMUMNUM(N); break;
81 case ISD::FMINIMUM: R = SoftenFloatRes_FMINIMUM(N); break;
82 case ISD::FMAXIMUM: R = SoftenFloatRes_FMAXIMUM(N); break;
84 case ISD::FADD: R = SoftenFloatRes_FADD(N); break;
86 case ISD::FACOS: R = SoftenFloatRes_FACOS(N); break;
88 case ISD::FASIN: R = SoftenFloatRes_FASIN(N); break;
90 case ISD::FATAN: R = SoftenFloatRes_FATAN(N); break;
92 case ISD::FATAN2: R = SoftenFloatRes_FATAN2(N); break;
93 case ISD::FCBRT: R = SoftenFloatRes_FCBRT(N); break;
95 case ISD::FCEIL: R = SoftenFloatRes_FCEIL(N); break;
96 case ISD::FCOPYSIGN: R = SoftenFloatRes_FCOPYSIGN(N); break;
98 case ISD::FCOS: R = SoftenFloatRes_FCOS(N); break;
100 case ISD::FCOSH: R = SoftenFloatRes_FCOSH(N); break;
101 case ISD::STRICT_FDIV:
102 case ISD::FDIV: R = SoftenFloatRes_FDIV(N); break;
103 case ISD::STRICT_FEXP:
104 case ISD::FEXP: R = SoftenFloatRes_FEXP(N); break;
106 case ISD::FEXP2: R = SoftenFloatRes_FEXP2(N); break;
107 case ISD::FEXP10: R = SoftenFloatRes_FEXP10(N); break;
109 case ISD::FFLOOR: R = SoftenFloatRes_FFLOOR(N); break;
110 case ISD::STRICT_FLOG:
111 case ISD::FLOG: R = SoftenFloatRes_FLOG(N); break;
113 case ISD::FLOG2: R = SoftenFloatRes_FLOG2(N); break;
115 case ISD::FLOG10: R = SoftenFloatRes_FLOG10(N); break;
116 case ISD::STRICT_FMA:
117 case ISD::FMA: R = SoftenFloatRes_FMA(N); break;
118 case ISD::STRICT_FMUL:
119 case ISD::FMUL: R = SoftenFloatRes_FMUL(N); break;
121 case ISD::FNEARBYINT: R = SoftenFloatRes_FNEARBYINT(N); break;
122 case ISD::FNEG: R = SoftenFloatRes_FNEG(N); break;
124 case ISD::FP_EXTEND: R = SoftenFloatRes_FP_EXTEND(N); break;
126 case ISD::FP_ROUND: R = SoftenFloatRes_FP_ROUND(N); break;
127 case ISD::FP16_TO_FP: R = SoftenFloatRes_FP16_TO_FP(N); break;
128 case ISD::BF16_TO_FP: R = SoftenFloatRes_BF16_TO_FP(N); break;
129 case ISD::STRICT_FPOW:
130 case ISD::FPOW: R = SoftenFloatRes_FPOW(N); break;
132 case ISD::FPOWI:
133 case ISD::FLDEXP:
134 case ISD::STRICT_FLDEXP: R = SoftenFloatRes_ExpOp(N); break;
135 case ISD::FFREXP: R = SoftenFloatRes_FFREXP(N); break;
136 case ISD::FSINCOS: R = SoftenFloatRes_FSINCOS(N); break;
137 case ISD::FMODF: R = SoftenFloatRes_FMODF(N); break;
138 case ISD::STRICT_FREM:
139 case ISD::FREM: R = SoftenFloatRes_FREM(N); break;
141 case ISD::FRINT: R = SoftenFloatRes_FRINT(N); break;
143 case ISD::FROUND: R = SoftenFloatRes_FROUND(N); break;
145 case ISD::FROUNDEVEN: R = SoftenFloatRes_FROUNDEVEN(N); break;
146 case ISD::STRICT_FSIN:
147 case ISD::FSIN: R = SoftenFloatRes_FSIN(N); break;
149 case ISD::FSINH: R = SoftenFloatRes_FSINH(N); break;
151 case ISD::FSQRT: R = SoftenFloatRes_FSQRT(N); break;
152 case ISD::STRICT_FSUB:
153 case ISD::FSUB: R = SoftenFloatRes_FSUB(N); break;
154 case ISD::STRICT_FTAN:
155 case ISD::FTAN: R = SoftenFloatRes_FTAN(N); break;
157 case ISD::FTANH: R = SoftenFloatRes_FTANH(N); break;
159 case ISD::FTRUNC: R = SoftenFloatRes_FTRUNC(N); break;
160 case ISD::LOAD: R = SoftenFloatRes_LOAD(N); break;
161 case ISD::ATOMIC_LOAD: R = SoftenFloatRes_ATOMIC_LOAD(N); break;
162 case ISD::ATOMIC_SWAP: R = BitcastToInt_ATOMIC_SWAP(N); break;
163 case ISD::SELECT: R = SoftenFloatRes_SELECT(N); break;
164 case ISD::SELECT_CC: R = SoftenFloatRes_SELECT_CC(N); break;
165 case ISD::FREEZE: R = SoftenFloatRes_FREEZE(N); break;
168 case ISD::SINT_TO_FP:
169 case ISD::UINT_TO_FP: R = SoftenFloatRes_XINT_TO_FP(N); break;
170 case ISD::POISON:
171 case ISD::UNDEF: R = SoftenFloatRes_UNDEF(N); break;
172 case ISD::VAARG: R = SoftenFloatRes_VAARG(N); break;
173 case ISD::AssertNoFPClass: R = GetSoftenedFloat(N->getOperand(0)); break;
181 case ISD::VECREDUCE_FMINIMUMNUM: R = SoftenFloatRes_VECREDUCE(N); break;
183 case ISD::VECREDUCE_SEQ_FMUL: R = SoftenFloatRes_VECREDUCE_SEQ(N); break;
184 // clang-format on
185 }
186
187 // If R is null, the sub-method took care of registering the result.
188 if (R.getNode()) {
189 assert(R.getNode() != N);
190 SetSoftenedFloat(SDValue(N, ResNo), R);
191 }
192}
193
194// No libcall is available to soften this operation. Emit a diagnostic and
195// produce a poison result of the softened type \p NVT.
196SDValue DAGTypeLegalizer::SoftenFloatRes_NoLibcall(SDNode *N, EVT NVT) {
197 DAG.getContext()->emitError(Twine("no libcall available for ") +
198 N->getOperationName(&DAG));
199 if (N->isStrictFPOpcode())
200 ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
201 return DAG.getPOISON(NVT);
202}
203
204SDValue DAGTypeLegalizer::SoftenFloatRes_Unary(SDNode *N, RTLIB::Libcall LC) {
205 bool IsStrict = N->isStrictFPOpcode();
206 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
207 unsigned Offset = IsStrict ? 1 : 0;
208 assert(N->getNumOperands() == (1 + Offset) &&
209 "Unexpected number of operands!");
210 SDValue Op = GetSoftenedFloat(N->getOperand(0 + Offset));
211 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
212 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
213 if (LCImpl == RTLIB::Unsupported)
214 return SoftenFloatRes_NoLibcall(N, NVT);
215 TargetLowering::MakeLibCallOptions CallOptions;
216 EVT OpVT = N->getOperand(0 + Offset).getValueType();
217 CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0));
218 std::pair<SDValue, SDValue> Tmp =
219 TLI.makeLibCall(DAG, LCImpl, NVT, Op, CallOptions, SDLoc(N), Chain);
220 if (IsStrict)
221 ReplaceValueWith(SDValue(N, 1), Tmp.second);
222 return Tmp.first;
223}
224
225SDValue DAGTypeLegalizer::SoftenFloatRes_Binary(SDNode *N, RTLIB::Libcall LC) {
226 bool IsStrict = N->isStrictFPOpcode();
227 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
228 unsigned Offset = IsStrict ? 1 : 0;
229 assert(N->getNumOperands() == (2 + Offset) &&
230 "Unexpected number of operands!");
231 SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0 + Offset)),
232 GetSoftenedFloat(N->getOperand(1 + Offset)) };
233 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
234 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
235 if (LCImpl == RTLIB::Unsupported)
236 return SoftenFloatRes_NoLibcall(N, NVT);
237 TargetLowering::MakeLibCallOptions CallOptions;
238 EVT OpsVT[2] = { N->getOperand(0 + Offset).getValueType(),
239 N->getOperand(1 + Offset).getValueType() };
240 CallOptions.setTypeListBeforeSoften(OpsVT, N->getValueType(0));
241 std::pair<SDValue, SDValue> Tmp =
242 TLI.makeLibCall(DAG, LCImpl, NVT, Ops, CallOptions, SDLoc(N), Chain);
243 if (IsStrict)
244 ReplaceValueWith(SDValue(N, 1), Tmp.second);
245 return Tmp.first;
246}
247
248SDValue DAGTypeLegalizer::SoftenFloatRes_BITCAST(SDNode *N) {
249 return BitConvertToInteger(N->getOperand(0));
250}
251
252SDValue DAGTypeLegalizer::SoftenFloatRes_FREEZE(SDNode *N) {
253 EVT Ty = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
254 return DAG.getNode(ISD::FREEZE, SDLoc(N), Ty,
255 GetSoftenedFloat(N->getOperand(0)));
256}
257
258SDValue DAGTypeLegalizer::SoftenFloatRes_ARITH_FENCE(SDNode *N) {
259 EVT Ty = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
260 SDValue NewFence = DAG.getNode(ISD::ARITH_FENCE, SDLoc(N), Ty,
261 GetSoftenedFloat(N->getOperand(0)));
262 return NewFence;
263}
264
265SDValue DAGTypeLegalizer::SoftenFloatRes_MERGE_VALUES(SDNode *N,
266 unsigned ResNo) {
267 SDValue Op = DisintegrateMERGE_VALUES(N, ResNo);
268 return BitConvertToInteger(Op);
269}
270
271SDValue DAGTypeLegalizer::SoftenFloatRes_BUILD_PAIR(SDNode *N) {
272 // Convert the inputs to integers, and build a new pair out of them.
273 return DAG.getNode(ISD::BUILD_PAIR, SDLoc(N),
274 TLI.getTypeToTransformTo(*DAG.getContext(),
275 N->getValueType(0)),
276 BitConvertToInteger(N->getOperand(0)),
277 BitConvertToInteger(N->getOperand(1)));
278}
279
280SDValue DAGTypeLegalizer::SoftenFloatRes_ConstantFP(SDNode *N) {
281 ConstantFPSDNode *CN = cast<ConstantFPSDNode>(N);
282 // In ppcf128, the high 64 bits are always first in memory regardless
283 // of Endianness. LLVM's APFloat representation is not Endian sensitive,
284 // and so always converts into a 128-bit APInt in a non-Endian-sensitive
285 // way. However, APInt's are serialized in an Endian-sensitive fashion,
286 // so on big-Endian targets, the two doubles are output in the wrong
287 // order. Fix this by manually flipping the order of the high 64 bits
288 // and the low 64 bits here.
289 if (DAG.getDataLayout().isBigEndian() &&
290 CN->getValueType(0).getSimpleVT() == llvm::MVT::ppcf128) {
291 uint64_t words[2] = { CN->getValueAPF().bitcastToAPInt().getRawData()[1],
293 APInt Val(128, words);
294 return DAG.getConstant(Val, SDLoc(CN),
295 TLI.getTypeToTransformTo(*DAG.getContext(),
296 CN->getValueType(0)));
297 } else {
298 return DAG.getConstant(CN->getValueAPF().bitcastToAPInt(), SDLoc(CN),
299 TLI.getTypeToTransformTo(*DAG.getContext(),
300 CN->getValueType(0)));
301 }
302}
303
304SDValue DAGTypeLegalizer::SoftenFloatRes_EXTRACT_ELEMENT(SDNode *N) {
305 SDValue Src = N->getOperand(0);
306 assert(Src.getValueType() == MVT::ppcf128 &&
307 "In floats only ppcf128 can be extracted by element!");
308 return DAG.getNode(ISD::EXTRACT_ELEMENT, SDLoc(N),
309 N->getValueType(0).changeTypeToInteger(),
310 DAG.getBitcast(MVT::i128, Src), N->getOperand(1));
311}
312
313SDValue DAGTypeLegalizer::SoftenFloatRes_EXTRACT_VECTOR_ELT(SDNode *N, unsigned ResNo) {
314 SDValue NewOp = BitConvertVectorToIntegerVector(N->getOperand(0));
315 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
317 NewOp, N->getOperand(1));
318}
319
320SDValue DAGTypeLegalizer::SoftenFloatRes_FABS(SDNode *N) {
321 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
322 unsigned Size = NVT.getSizeInBits();
323
324 // Mask = ~(1 << (Size-1))
325 APInt API = APInt::getAllOnes(Size);
326 API.clearBit(Size - 1);
327 SDValue Mask = DAG.getConstant(API, SDLoc(N), NVT);
328 SDValue Op = GetSoftenedFloat(N->getOperand(0));
329 return DAG.getNode(ISD::AND, SDLoc(N), NVT, Op, Mask);
330}
331
332SDValue DAGTypeLegalizer::SoftenFloatRes_FCANONICALIZE(SDNode *N) {
333 SDLoc dl(N);
334
335 // This implements llvm.canonicalize.f* by multiplication with 1.0, as
336 // suggested in
337 // https://llvm.org/docs/LangRef.html#llvm-canonicalize-intrinsic.
338 // It uses strict_fp operations even outside a strict_fp context in order
339 // to guarantee that the canonicalization is not optimized away by later
340 // passes. The result chain introduced by that is intentionally ignored
341 // since no ordering requirement is intended here.
342
343 // Create strict multiplication by 1.0.
344 SDValue Operand = N->getOperand(0);
345 EVT VT = Operand.getValueType();
346 SDValue One = DAG.getConstantFP(1.0, dl, VT);
347 SDValue Chain = DAG.getEntryNode();
348 // Propagate existing flags on canonicalize, and additionally set
349 // NoFPExcept.
350 SDNodeFlags CanonicalizeFlags = N->getFlags();
351 CanonicalizeFlags.setNoFPExcept(true);
352 SDValue Mul = DAG.getNode(ISD::STRICT_FMUL, dl, {VT, MVT::Other},
353 {Chain, Operand, One}, CanonicalizeFlags);
354 return BitConvertToInteger(Mul);
355}
356
357SDValue DAGTypeLegalizer::SoftenFloatRes_FMINNUM(SDNode *N) {
358 if (SDValue SelCC = TLI.createSelectForFMINNUM_FMAXNUM(N, DAG))
359 return SoftenFloatRes_SELECT_CC(SelCC.getNode());
360 return SoftenFloatRes_Binary(N, RTLIB::getFMIN(N->getValueType(0)));
361}
362
363SDValue DAGTypeLegalizer::SoftenFloatRes_FMAXNUM(SDNode *N) {
364 if (SDValue SelCC = TLI.createSelectForFMINNUM_FMAXNUM(N, DAG))
365 return SoftenFloatRes_SELECT_CC(SelCC.getNode());
366 return SoftenFloatRes_Binary(N, RTLIB::getFMAX(N->getValueType(0)));
367}
368
369SDValue DAGTypeLegalizer::SoftenFloatRes_FMINIMUMNUM(SDNode *N) {
370 return SoftenFloatRes_Binary(N, RTLIB::getFMINIMUM_NUM(N->getValueType(0)));
371}
372
373SDValue DAGTypeLegalizer::SoftenFloatRes_FMAXIMUMNUM(SDNode *N) {
374 return SoftenFloatRes_Binary(N, RTLIB::getFMAXIMUM_NUM(N->getValueType(0)));
375}
376
377SDValue DAGTypeLegalizer::SoftenFloatRes_FMINIMUM(SDNode *N) {
378 return SoftenFloatRes_Binary(N, RTLIB::getFMINIMUM(N->getValueType(0)));
379}
380
381SDValue DAGTypeLegalizer::SoftenFloatRes_FMAXIMUM(SDNode *N) {
382 return SoftenFloatRes_Binary(N, RTLIB::getFMAXIMUM(N->getValueType(0)));
383}
384
385SDValue DAGTypeLegalizer::SoftenFloatRes_FADD(SDNode *N) {
386 return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
387 RTLIB::ADD_F32,
388 RTLIB::ADD_F64,
389 RTLIB::ADD_F80,
390 RTLIB::ADD_F128,
391 RTLIB::ADD_PPCF128));
392}
393
394SDValue DAGTypeLegalizer::SoftenFloatRes_FACOS(SDNode *N) {
395 return SoftenFloatRes_Unary(N, RTLIB::getACOS(N->getValueType(0)));
396}
397
398SDValue DAGTypeLegalizer::SoftenFloatRes_FASIN(SDNode *N) {
399 return SoftenFloatRes_Unary(N, RTLIB::getASIN(N->getValueType(0)));
400}
401
402SDValue DAGTypeLegalizer::SoftenFloatRes_FATAN(SDNode *N) {
403 return SoftenFloatRes_Unary(N, RTLIB::getATAN(N->getValueType(0)));
404}
405
406SDValue DAGTypeLegalizer::SoftenFloatRes_FATAN2(SDNode *N) {
407 return SoftenFloatRes_Binary(N, RTLIB::getATAN2(N->getValueType(0)));
408}
409
410SDValue DAGTypeLegalizer::SoftenFloatRes_FCBRT(SDNode *N) {
411 return SoftenFloatRes_Unary(N, RTLIB::getCBRT(N->getValueType(0)));
412}
413
414SDValue DAGTypeLegalizer::SoftenFloatRes_FCEIL(SDNode *N) {
415 return SoftenFloatRes_Unary(N, RTLIB::getCEIL(N->getValueType(0)));
416}
417
418SDValue DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN(SDNode *N) {
419 SDValue LHS = GetSoftenedFloat(N->getOperand(0));
420 SDValue RHS = BitConvertToInteger(N->getOperand(1));
421 SDLoc dl(N);
422
423 EVT LVT = LHS.getValueType();
424 EVT RVT = RHS.getValueType();
425
426 unsigned LSize = LVT.getSizeInBits();
427 unsigned RSize = RVT.getSizeInBits();
428
429 // First get the sign bit of second operand.
430 SDValue SignBit = DAG.getNode(
431 ISD::SHL, dl, RVT, DAG.getConstant(1, dl, RVT),
432 DAG.getConstant(RSize - 1, dl,
433 TLI.getShiftAmountTy(RVT, DAG.getDataLayout())));
434 SignBit = DAG.getNode(ISD::AND, dl, RVT, RHS, SignBit);
435
436 // Shift right or sign-extend it if the two operands have different types.
437 int SizeDiff = RVT.getSizeInBits() - LVT.getSizeInBits();
438 if (SizeDiff > 0) {
439 SignBit =
440 DAG.getNode(ISD::SRL, dl, RVT, SignBit,
441 DAG.getConstant(SizeDiff, dl,
442 TLI.getShiftAmountTy(SignBit.getValueType(),
443 DAG.getDataLayout())));
444 SignBit = DAG.getNode(ISD::TRUNCATE, dl, LVT, SignBit);
445 } else if (SizeDiff < 0) {
446 SignBit = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, SignBit);
447 SignBit =
448 DAG.getNode(ISD::SHL, dl, LVT, SignBit,
449 DAG.getConstant(-SizeDiff, dl,
450 TLI.getShiftAmountTy(SignBit.getValueType(),
451 DAG.getDataLayout())));
452 }
453
454 // Clear the sign bit of the first operand.
455 SDValue Mask = DAG.getNode(
456 ISD::SHL, dl, LVT, DAG.getConstant(1, dl, LVT),
457 DAG.getConstant(LSize - 1, dl,
458 TLI.getShiftAmountTy(LVT, DAG.getDataLayout())));
459 Mask = DAG.getNode(ISD::SUB, dl, LVT, Mask, DAG.getConstant(1, dl, LVT));
460 LHS = DAG.getNode(ISD::AND, dl, LVT, LHS, Mask);
461
462 // Or the value with the sign bit.
463 return DAG.getNode(ISD::OR, dl, LVT, LHS, SignBit);
464}
465
466SDValue DAGTypeLegalizer::SoftenFloatRes_FCOS(SDNode *N) {
467 return SoftenFloatRes_Unary(N, RTLIB::getCOS(N->getValueType(0)));
468}
469
470SDValue DAGTypeLegalizer::SoftenFloatRes_FCOSH(SDNode *N) {
471 return SoftenFloatRes_Unary(N, RTLIB::getCOSH(N->getValueType(0)));
472}
473
474SDValue DAGTypeLegalizer::SoftenFloatRes_FDIV(SDNode *N) {
475 return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
476 RTLIB::DIV_F32,
477 RTLIB::DIV_F64,
478 RTLIB::DIV_F80,
479 RTLIB::DIV_F128,
480 RTLIB::DIV_PPCF128));
481}
482
483SDValue DAGTypeLegalizer::SoftenFloatRes_FEXP(SDNode *N) {
484 return SoftenFloatRes_Unary(N, RTLIB::getEXP(N->getValueType(0)));
485}
486
487SDValue DAGTypeLegalizer::SoftenFloatRes_FEXP2(SDNode *N) {
488 return SoftenFloatRes_Unary(N, RTLIB::getEXP2(N->getValueType(0)));
489}
490
491SDValue DAGTypeLegalizer::SoftenFloatRes_FEXP10(SDNode *N) {
492 return SoftenFloatRes_Unary(N, RTLIB::getEXP10(N->getValueType(0)));
493}
494
495SDValue DAGTypeLegalizer::SoftenFloatRes_FFLOOR(SDNode *N) {
496 return SoftenFloatRes_Unary(N, RTLIB::getFLOOR(N->getValueType(0)));
497}
498
499SDValue DAGTypeLegalizer::SoftenFloatRes_FLOG(SDNode *N) {
500 return SoftenFloatRes_Unary(N, RTLIB::getLOG(N->getValueType(0)));
501}
502
503SDValue DAGTypeLegalizer::SoftenFloatRes_FLOG2(SDNode *N) {
504 return SoftenFloatRes_Unary(N, RTLIB::getLOG2(N->getValueType(0)));
505}
506
507SDValue DAGTypeLegalizer::SoftenFloatRes_FLOG10(SDNode *N) {
508 return SoftenFloatRes_Unary(N, RTLIB::getLOG10(N->getValueType(0)));
509}
510
511SDValue DAGTypeLegalizer::SoftenFloatRes_FMA(SDNode *N) {
512 bool IsStrict = N->isStrictFPOpcode();
513 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
514 unsigned Offset = IsStrict ? 1 : 0;
515 SDValue Ops[3] = { GetSoftenedFloat(N->getOperand(0 + Offset)),
516 GetSoftenedFloat(N->getOperand(1 + Offset)),
517 GetSoftenedFloat(N->getOperand(2 + Offset)) };
518 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
519 TargetLowering::MakeLibCallOptions CallOptions;
520 EVT OpsVT[3] = { N->getOperand(0 + Offset).getValueType(),
521 N->getOperand(1 + Offset).getValueType(),
522 N->getOperand(2 + Offset).getValueType() };
523 CallOptions.setTypeListBeforeSoften(OpsVT, N->getValueType(0));
524 std::pair<SDValue, SDValue> Tmp =
525 TLI.makeLibCall(DAG, RTLIB::getFMA(N->getValueType(0)), NVT, Ops,
526 CallOptions, SDLoc(N), Chain);
527 if (IsStrict)
528 ReplaceValueWith(SDValue(N, 1), Tmp.second);
529 return Tmp.first;
530}
531
532SDValue DAGTypeLegalizer::SoftenFloatRes_FMUL(SDNode *N) {
533 return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
534 RTLIB::MUL_F32,
535 RTLIB::MUL_F64,
536 RTLIB::MUL_F80,
537 RTLIB::MUL_F128,
538 RTLIB::MUL_PPCF128));
539}
540
541SDValue DAGTypeLegalizer::SoftenFloatRes_FNEARBYINT(SDNode *N) {
542 return SoftenFloatRes_Unary(N, RTLIB::getNEARBYINT(N->getValueType(0)));
543}
544
545SDValue DAGTypeLegalizer::SoftenFloatRes_FNEG(SDNode *N) {
546 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
547 SDLoc dl(N);
548
549 // Expand Y = FNEG(X) -> Y = X ^ sign mask
550 APInt SignMask = APInt::getSignMask(NVT.getSizeInBits());
551 return DAG.getNode(ISD::XOR, dl, NVT, GetSoftenedFloat(N->getOperand(0)),
552 DAG.getConstant(SignMask, dl, NVT));
553}
554
555SDValue DAGTypeLegalizer::SoftenFloatRes_FP_EXTEND(SDNode *N) {
556 bool IsStrict = N->isStrictFPOpcode();
557 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
558 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
559
560 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
561
562 // There's only a libcall for f16 -> f32 and shifting is only valid for bf16
563 // -> f32, so proceed in two stages. Also, it's entirely possible for both
564 // f16 and f32 to be legal, so use the fully hard-float FP_EXTEND rather
565 // than FP16_TO_FP.
566 if ((Op.getValueType() == MVT::f16 || Op.getValueType() == MVT::bf16) &&
567 N->getValueType(0) != MVT::f32) {
568 if (IsStrict) {
569 Op = DAG.getNode(ISD::STRICT_FP_EXTEND, SDLoc(N),
570 { MVT::f32, MVT::Other }, { Chain, Op });
571 Chain = Op.getValue(1);
572 } else {
573 Op = DAG.getNode(ISD::FP_EXTEND, SDLoc(N), MVT::f32, Op);
574 }
575 }
576
577 if (Op.getValueType() == MVT::bf16) {
578 // FIXME: Need ReplaceValueWith on chain in strict case
579 return SoftenFloatRes_BF16_TO_FP(N);
580 }
581
582 RTLIB::Libcall LC = RTLIB::getFPEXT(Op.getValueType(), N->getValueType(0));
583 if (LC == RTLIB::UNKNOWN_LIBCALL) {
584 DAG.getContext()->emitError("do not know how to soften fp_extend");
585 if (IsStrict)
586 ReplaceValueWith(SDValue(N, 1), Chain);
587 return DAG.getPOISON(NVT);
588 }
589 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
590 if (LCImpl == RTLIB::Unsupported)
591 return SoftenFloatRes_NoLibcall(N, NVT);
592 TargetLowering::MakeLibCallOptions CallOptions;
593 EVT OpVT = N->getOperand(IsStrict ? 1 : 0).getValueType();
594 CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0));
595 std::pair<SDValue, SDValue> Tmp =
596 TLI.makeLibCall(DAG, LCImpl, NVT, Op, CallOptions, SDLoc(N), Chain);
597 if (IsStrict)
598 ReplaceValueWith(SDValue(N, 1), Tmp.second);
599 return Tmp.first;
600}
601
602// FIXME: Should we just use 'normal' FP_EXTEND / FP_TRUNC instead of special
603// nodes?
604SDValue DAGTypeLegalizer::SoftenFloatRes_FP16_TO_FP(SDNode *N) {
605 EVT MidVT = TLI.getTypeToTransformTo(*DAG.getContext(), MVT::f32);
606 SDValue Op = N->getOperand(0);
607 TargetLowering::MakeLibCallOptions CallOptions;
608 EVT OpsVT[1] = { N->getOperand(0).getValueType() };
609 CallOptions.setTypeListBeforeSoften(OpsVT, N->getValueType(0));
610 SDValue Res32 = TLI.makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MidVT, Op,
611 CallOptions, SDLoc(N)).first;
612 if (N->getValueType(0) == MVT::f32)
613 return Res32;
614
615 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
616 RTLIB::Libcall LC = RTLIB::getFPEXT(MVT::f32, N->getValueType(0));
617 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_EXTEND!");
618 return TLI.makeLibCall(DAG, LC, NVT, Res32, CallOptions, SDLoc(N)).first;
619}
620
621// FIXME: Should we just use 'normal' FP_EXTEND / FP_TRUNC instead of special
622// nodes?
623SDValue DAGTypeLegalizer::SoftenFloatRes_BF16_TO_FP(SDNode *N) {
624 assert(N->getValueType(0) == MVT::f32 &&
625 "Can only soften BF16_TO_FP with f32 result");
626 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), MVT::f32);
627 SDValue Op = N->getOperand(0);
628 SDLoc DL(N);
629 Op = DAG.getNode(ISD::ANY_EXTEND, DL, NVT,
630 DAG.getNode(ISD::BITCAST, DL, MVT::i16, Op));
631 SDValue Res = DAG.getNode(ISD::SHL, DL, NVT, Op,
632 DAG.getShiftAmountConstant(16, NVT, DL));
633 return Res;
634}
635
636SDValue DAGTypeLegalizer::SoftenFloatRes_FP_ROUND(SDNode *N) {
637 bool IsStrict = N->isStrictFPOpcode();
638 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
639 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
640 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
641 RTLIB::Libcall LC = RTLIB::getFPROUND(Op.getValueType(), N->getValueType(0));
642 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_ROUND!");
643 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
644 if (LCImpl == RTLIB::Unsupported)
645 return SoftenFloatRes_NoLibcall(N, NVT);
646 TargetLowering::MakeLibCallOptions CallOptions;
647 EVT OpVT = N->getOperand(IsStrict ? 1 : 0).getValueType();
648 CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0));
649 std::pair<SDValue, SDValue> Tmp =
650 TLI.makeLibCall(DAG, LCImpl, NVT, Op, CallOptions, SDLoc(N), Chain);
651 if (IsStrict)
652 ReplaceValueWith(SDValue(N, 1), Tmp.second);
653 return Tmp.first;
654}
655
656SDValue DAGTypeLegalizer::SoftenFloatRes_FPOW(SDNode *N) {
657 return SoftenFloatRes_Binary(N, RTLIB::getPOW(N->getValueType(0)));
658}
659
660SDValue DAGTypeLegalizer::SoftenFloatRes_ExpOp(SDNode *N) {
661 bool IsStrict = N->isStrictFPOpcode();
662 unsigned Offset = IsStrict ? 1 : 0;
663 bool IsPowI =
664 N->getOpcode() == ISD::FPOWI || N->getOpcode() == ISD::STRICT_FPOWI;
665 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
666
667 RTLIB::Libcall LC = IsPowI ? RTLIB::getPOWI(N->getValueType(0))
668 : RTLIB::getLDEXP(N->getValueType(0));
669 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fpowi.");
670 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
671 if (LCImpl == RTLIB::Unsupported) {
672 // Some targets don't have a powi libcall; use pow instead.
673 // FIXME: Implement this if some target needs it.
674 DAG.getContext()->emitError("do not know how to soften fpowi to fpow");
675 if (IsStrict)
676 ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
677 return DAG.getPOISON(NVT);
678 }
679
680 if (DAG.getLibInfo().getIntSize() !=
681 N->getOperand(1 + Offset).getValueType().getSizeInBits()) {
682 // If the exponent does not match with sizeof(int) a libcall to RTLIB::POWI
683 // would use the wrong type for the argument.
684 DAG.getContext()->emitError("powi exponent does not match sizeof(int)");
685 if (IsStrict)
686 ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
687 return DAG.getPOISON(NVT);
688 }
689
690 SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0 + Offset)),
691 N->getOperand(1 + Offset) };
692 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
693 TargetLowering::MakeLibCallOptions CallOptions;
694 EVT OpsVT[2] = { N->getOperand(0 + Offset).getValueType(),
695 N->getOperand(1 + Offset).getValueType() };
696 CallOptions.setTypeListBeforeSoften(OpsVT, N->getValueType(0));
697 std::pair<SDValue, SDValue> Tmp =
698 TLI.makeLibCall(DAG, LCImpl, NVT, Ops, CallOptions, SDLoc(N), Chain);
699 if (IsStrict)
700 ReplaceValueWith(SDValue(N, 1), Tmp.second);
701 return Tmp.first;
702}
703
704SDValue DAGTypeLegalizer::SoftenFloatRes_FFREXP(SDNode *N) {
705 assert(!N->isStrictFPOpcode() && "strictfp not implemented for frexp");
706 EVT VT0 = N->getValueType(0);
707 EVT VT1 = N->getValueType(1);
708 RTLIB::Libcall LC = RTLIB::getFREXP(VT0);
709 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
710 EVT NVT0 = TLI.getTypeToTransformTo(*DAG.getContext(), VT0);
711 SDLoc DL(N);
712
713 if (LCImpl == RTLIB::Unsupported) {
714 DAG.getContext()->emitError(Twine("no libcall available for ") +
715 N->getOperationName(&DAG));
716 SDValue PoisonExp = DAG.getPOISON(VT1);
717 ReplaceValueWith(SDValue(N, 1), PoisonExp);
718 return DAG.getMergeValues({DAG.getPOISON(NVT0), PoisonExp}, DL);
719 }
720
721 if (DAG.getLibInfo().getIntSize() != VT1.getSizeInBits()) {
722 // If the exponent does not match with sizeof(int) a libcall would use the
723 // wrong type for the argument.
724 // TODO: Should be able to handle mismatches.
725 DAG.getContext()->emitError("ffrexp exponent does not match sizeof(int)");
726 SDValue PoisonExp = DAG.getPOISON(VT1);
727 ReplaceValueWith(SDValue(N, 1), PoisonExp);
728 return DAG.getMergeValues({DAG.getPOISON(NVT0), PoisonExp}, DL);
729 }
730
731 SDValue StackSlot = DAG.CreateStackTemporary(VT1);
732
733 auto PointerTy = PointerType::getUnqual(*DAG.getContext());
734 TargetLowering::MakeLibCallOptions CallOptions;
735 SDValue Ops[2] = {GetSoftenedFloat(N->getOperand(0)), StackSlot};
736 EVT OpsVT[2] = {VT0, StackSlot.getValueType()};
737 Type *CallOpsTypeOverrides[2] = {nullptr, PointerTy};
738
739 // TODO: setTypeListBeforeSoften can't properly express multiple return types,
740 // but we only really need to handle the 0th one for softening anyway.
741 CallOptions.setTypeListBeforeSoften({OpsVT}, VT0)
742 .setOpsTypeOverrides(CallOpsTypeOverrides);
743
744 auto [ReturnVal, Chain] = TLI.makeLibCall(DAG, LCImpl, NVT0, Ops, CallOptions,
745 DL, /*Chain=*/SDValue());
746 int FrameIdx = cast<FrameIndexSDNode>(StackSlot)->getIndex();
747 auto PtrInfo =
748 MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FrameIdx);
749
750 SDValue LoadExp = DAG.getLoad(VT1, DL, Chain, StackSlot, PtrInfo);
751
752 ReplaceValueWith(SDValue(N, 1), LoadExp);
753 return ReturnVal;
754}
755
756bool DAGTypeLegalizer::SoftenFloatRes_UnaryWithTwoFPResults(
757 SDNode *N, RTLIB::Libcall LC, std::optional<unsigned> CallRetResNo) {
758 assert(!N->isStrictFPOpcode() && "strictfp not implemented");
759 EVT VT = N->getValueType(0);
760
761 assert(VT == N->getValueType(1) &&
762 "expected both return values to have the same type");
763
764 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
765 if (LCImpl == RTLIB::Unsupported)
766 return false;
767
768 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
769
770 SDLoc DL(N);
771
772 SmallVector<SDValue, 3> Ops = {GetSoftenedFloat(N->getOperand(0))};
773 SmallVector<EVT, 3> OpsVT = {VT};
774
775 std::array<SDValue, 2> StackSlots;
776 SmallVector<Type *, 3> CallOpsTypeOverrides = {nullptr};
777 auto PointerTy = PointerType::getUnqual(*DAG.getContext());
778 for (unsigned ResNum = 0; ResNum < N->getNumValues(); ++ResNum) {
779 if (ResNum == CallRetResNo)
780 continue;
781 SDValue StackSlot = DAG.CreateStackTemporary(NVT);
782 Ops.push_back(StackSlot);
783 OpsVT.push_back(StackSlot.getValueType());
784 StackSlots[ResNum] = StackSlot;
785 CallOpsTypeOverrides.push_back(PointerTy);
786 }
787
788 TargetLowering::MakeLibCallOptions CallOptions;
789 // TODO: setTypeListBeforeSoften can't properly express multiple return types,
790 // but since both returns have the same type it should be okay.
791 CallOptions.setTypeListBeforeSoften({OpsVT}, VT)
792 .setOpsTypeOverrides(CallOpsTypeOverrides);
793
794 auto [ReturnVal, Chain] =
795 TLI.makeLibCall(DAG, LCImpl, NVT, Ops, CallOptions, DL,
796 /*Chain=*/SDValue());
797
798 auto CreateStackLoad = [&, Chain = Chain](SDValue StackSlot) {
799 int FrameIdx = cast<FrameIndexSDNode>(StackSlot)->getIndex();
800 auto PtrInfo =
801 MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FrameIdx);
802 return DAG.getLoad(NVT, DL, Chain, StackSlot, PtrInfo);
803 };
804
805 for (auto [ResNum, SlackSlot] : enumerate(StackSlots)) {
806 if (CallRetResNo == ResNum) {
807 SetSoftenedFloat(SDValue(N, ResNum), ReturnVal);
808 continue;
809 }
810 SetSoftenedFloat(SDValue(N, ResNum), CreateStackLoad(SlackSlot));
811 }
812
813 return true;
814}
815
816SDValue DAGTypeLegalizer::SoftenFloatRes_FSINCOS(SDNode *N) {
817 EVT VT = N->getValueType(0);
818 if (SoftenFloatRes_UnaryWithTwoFPResults(N, RTLIB::getSINCOS(VT)))
819 return SDValue();
820
821 // Fall back on softening the separate sin and cos calls if available.
822 RTLIB::Libcall SinLC = RTLIB::getSIN(VT);
823 RTLIB::Libcall CosLC = RTLIB::getCOS(VT);
824
825 SDValue SoftSin, SoftCos;
826 if (DAG.getLibcalls().getLibcallImpl(SinLC) == RTLIB::Unsupported ||
827 DAG.getLibcalls().getLibcallImpl(CosLC) == RTLIB::Unsupported) {
828 DAG.getContext()->emitError("do not know how to soften fsincos");
829
830 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
831 SoftSin = SoftCos = DAG.getPOISON(NVT);
832 } else {
833 SoftSin = SoftenFloatRes_Unary(N, SinLC);
834 SoftCos = SoftenFloatRes_Unary(N, CosLC);
835 }
836
837 SetSoftenedFloat(SDValue(N, 0), SoftSin);
838 SetSoftenedFloat(SDValue(N, 1), SoftCos);
839 return SDValue();
840}
841
842SDValue DAGTypeLegalizer::SoftenFloatRes_FMODF(SDNode *N) {
843 EVT VT = N->getValueType(0);
844 if (SoftenFloatRes_UnaryWithTwoFPResults(N, RTLIB::getMODF(VT),
845 /*CallRetResNo=*/0))
846 return SDValue();
847
848 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
849 DAG.getContext()->emitError("do not know how to soften fmodf");
850 SDValue Poison = DAG.getPOISON(NVT);
851 SetSoftenedFloat(SDValue(N, 0), Poison);
852 SetSoftenedFloat(SDValue(N, 1), Poison);
853 return SDValue();
854}
855
856SDValue DAGTypeLegalizer::SoftenFloatRes_FREM(SDNode *N) {
857 return SoftenFloatRes_Binary(N, RTLIB::getREM(N->getValueType(0)));
858}
859
860SDValue DAGTypeLegalizer::SoftenFloatRes_FRINT(SDNode *N) {
861 return SoftenFloatRes_Unary(N, RTLIB::getRINT(N->getValueType(0)));
862}
863
864SDValue DAGTypeLegalizer::SoftenFloatRes_FROUND(SDNode *N) {
865 return SoftenFloatRes_Unary(N, RTLIB::getROUND(N->getValueType(0)));
866}
867
868SDValue DAGTypeLegalizer::SoftenFloatRes_FROUNDEVEN(SDNode *N) {
869 return SoftenFloatRes_Unary(N, RTLIB::getROUNDEVEN(N->getValueType(0)));
870}
871
872SDValue DAGTypeLegalizer::SoftenFloatRes_FSIN(SDNode *N) {
873 return SoftenFloatRes_Unary(N, RTLIB::getSIN(N->getValueType(0)));
874}
875
876SDValue DAGTypeLegalizer::SoftenFloatRes_FSINH(SDNode *N) {
877 return SoftenFloatRes_Unary(N, RTLIB::getSINH(N->getValueType(0)));
878}
879
880SDValue DAGTypeLegalizer::SoftenFloatRes_FSQRT(SDNode *N) {
881 return SoftenFloatRes_Unary(N, RTLIB::getSQRT(N->getValueType(0)));
882}
883
884SDValue DAGTypeLegalizer::SoftenFloatRes_FSUB(SDNode *N) {
885 return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
886 RTLIB::SUB_F32,
887 RTLIB::SUB_F64,
888 RTLIB::SUB_F80,
889 RTLIB::SUB_F128,
890 RTLIB::SUB_PPCF128));
891}
892
893SDValue DAGTypeLegalizer::SoftenFloatRes_FTAN(SDNode *N) {
894 return SoftenFloatRes_Unary(N, RTLIB::getTAN(N->getValueType(0)));
895}
896
897SDValue DAGTypeLegalizer::SoftenFloatRes_FTANH(SDNode *N) {
898 return SoftenFloatRes_Unary(N, RTLIB::getTANH(N->getValueType(0)));
899}
900
901SDValue DAGTypeLegalizer::SoftenFloatRes_FTRUNC(SDNode *N) {
902 return SoftenFloatRes_Unary(N, RTLIB::getTRUNC(N->getValueType(0)));
903}
904
905SDValue DAGTypeLegalizer::SoftenFloatRes_LOAD(SDNode *N) {
906 LoadSDNode *L = cast<LoadSDNode>(N);
907 EVT VT = N->getValueType(0);
908 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
909 SDLoc dl(N);
910
911 auto MMOFlags =
912 L->getMemOperand()->getFlags() &
914 SDValue NewL;
915 if (L->getExtensionType() == ISD::NON_EXTLOAD) {
916 // If softening widens the integer representation (e.g. x86_fp80 -> i96),
917 // load the original memory width and extend to the softened type.
918 EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
919 NewL = DAG.getLoad(L->getAddressingMode(), ISD::EXTLOAD, NVT, dl,
920 L->getChain(), L->getBasePtr(), L->getOffset(),
921 L->getPointerInfo(), MemVT, L->getBaseAlign(), MMOFlags,
922 L->getAAInfo());
923 // Legalized the chain result - switch anything that used the old chain to
924 // use the new one.
925 ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
926 return NewL;
927 }
928
929 // Do a non-extending load followed by FP_EXTEND.
930 NewL = DAG.getLoad(L->getAddressingMode(), ISD::NON_EXTLOAD, L->getMemoryVT(),
931 dl, L->getChain(), L->getBasePtr(), L->getOffset(),
932 L->getPointerInfo(), L->getMemoryVT(), L->getBaseAlign(),
933 MMOFlags, L->getAAInfo());
934 // Legalized the chain result - switch anything that used the old chain to
935 // use the new one.
936 ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
937 auto ExtendNode = DAG.getNode(ISD::FP_EXTEND, dl, VT, NewL);
938 return BitConvertToInteger(ExtendNode);
939}
940
941SDValue DAGTypeLegalizer::SoftenFloatRes_ATOMIC_LOAD(SDNode *N) {
942 AtomicSDNode *L = cast<AtomicSDNode>(N);
943 EVT VT = N->getValueType(0);
944 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
945 SDLoc dl(N);
946
947 if (L->getExtensionType() == ISD::NON_EXTLOAD) {
948 SDValue NewL =
949 DAG.getAtomic(ISD::ATOMIC_LOAD, dl, NVT, DAG.getVTList(NVT, MVT::Other),
950 {L->getChain(), L->getBasePtr()}, L->getMemOperand());
951
952 // Legalized the chain result - switch anything that used the old chain to
953 // use the new one.
954 ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
955 return NewL;
956 }
957
958 report_fatal_error("softening fp extending atomic load not handled");
959}
960
961SDValue DAGTypeLegalizer::SoftenFloatRes_SELECT(SDNode *N) {
962 SDValue LHS = GetSoftenedFloat(N->getOperand(1));
963 SDValue RHS = GetSoftenedFloat(N->getOperand(2));
964 return DAG.getSelect(SDLoc(N),
965 LHS.getValueType(), N->getOperand(0), LHS, RHS);
966}
967
968SDValue DAGTypeLegalizer::SoftenFloatRes_SELECT_CC(SDNode *N) {
969 SDValue LHS = GetSoftenedFloat(N->getOperand(2));
970 SDValue RHS = GetSoftenedFloat(N->getOperand(3));
971 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
972 LHS.getValueType(), N->getOperand(0),
973 N->getOperand(1), LHS, RHS, N->getOperand(4));
974}
975
976SDValue DAGTypeLegalizer::SoftenFloatRes_UNDEF(SDNode *N) {
977 return DAG.getUNDEF(TLI.getTypeToTransformTo(*DAG.getContext(),
978 N->getValueType(0)));
979}
980
981SDValue DAGTypeLegalizer::SoftenFloatRes_VAARG(SDNode *N) {
982 SDValue Chain = N->getOperand(0); // Get the chain.
983 SDValue Ptr = N->getOperand(1); // Get the pointer.
984 EVT VT = N->getValueType(0);
985 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
986 SDLoc dl(N);
987
988 SDValue NewVAARG;
989 NewVAARG = DAG.getVAArg(NVT, dl, Chain, Ptr, N->getOperand(2),
990 N->getConstantOperandVal(3));
991
992 // Legalized the chain result - switch anything that used the old chain to
993 // use the new one.
994 if (N != NewVAARG.getValue(1).getNode())
995 ReplaceValueWith(SDValue(N, 1), NewVAARG.getValue(1));
996 return NewVAARG;
997}
998
999SDValue DAGTypeLegalizer::SoftenFloatRes_XINT_TO_FP(SDNode *N) {
1000 bool IsStrict = N->isStrictFPOpcode();
1001 bool Signed = N->getOpcode() == ISD::SINT_TO_FP ||
1002 N->getOpcode() == ISD::STRICT_SINT_TO_FP;
1003 EVT SVT = N->getOperand(IsStrict ? 1 : 0).getValueType();
1004 EVT RVT = N->getValueType(0);
1005 EVT NVT = EVT();
1006 SDLoc dl(N);
1007
1008 // If the input is not legal, eg: i1 -> fp, then it needs to be promoted to
1009 // a larger type, eg: i8 -> fp. Even if it is legal, no libcall may exactly
1010 // match. Look for an appropriate libcall.
1011 RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
1012 for (unsigned t = MVT::FIRST_INTEGER_VALUETYPE;
1013 t <= MVT::LAST_INTEGER_VALUETYPE && LC == RTLIB::UNKNOWN_LIBCALL; ++t) {
1014 NVT = (MVT::SimpleValueType)t;
1015 // The source needs to big enough to hold the operand.
1016 if (NVT.bitsGE(SVT))
1017 LC = Signed ? RTLIB::getSINTTOFP(NVT, RVT):RTLIB::getUINTTOFP (NVT, RVT);
1018 }
1019 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!");
1020
1021 EVT NRVT = TLI.getTypeToTransformTo(*DAG.getContext(), RVT);
1022 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
1023 if (LCImpl == RTLIB::Unsupported)
1024 return SoftenFloatRes_NoLibcall(N, NRVT);
1025
1026 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1027 // Sign/zero extend the argument if the libcall takes a larger type.
1028 SDValue Op = DAG.getNode(Signed ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, dl,
1029 NVT, N->getOperand(IsStrict ? 1 : 0));
1030 TargetLowering::MakeLibCallOptions CallOptions;
1031 CallOptions.setIsSigned(Signed);
1032 CallOptions.setTypeListBeforeSoften(SVT, RVT);
1033 std::pair<SDValue, SDValue> Tmp =
1034 TLI.makeLibCall(DAG, LCImpl, NRVT, Op, CallOptions, dl, Chain);
1035
1036 if (IsStrict)
1037 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1038 return Tmp.first;
1039}
1040
1041SDValue DAGTypeLegalizer::SoftenFloatRes_VECREDUCE(SDNode *N) {
1042 // Expand and soften recursively.
1043 ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduce(N, DAG));
1044 return SDValue();
1045}
1046
1047SDValue DAGTypeLegalizer::SoftenFloatRes_VECREDUCE_SEQ(SDNode *N) {
1048 ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduceSeq(N, DAG));
1049 return SDValue();
1050}
1051
1052//===----------------------------------------------------------------------===//
1053// Convert Float Operand to Integer
1054//===----------------------------------------------------------------------===//
1055
1056bool DAGTypeLegalizer::SoftenFloatOperand(SDNode *N, unsigned OpNo) {
1057 LLVM_DEBUG(dbgs() << "Soften float operand " << OpNo << ": "; N->dump(&DAG));
1058 SDValue Res = SDValue();
1059
1060 switch (N->getOpcode()) {
1061 default:
1062#ifndef NDEBUG
1063 dbgs() << "SoftenFloatOperand Op #" << OpNo << ": ";
1064 N->dump(&DAG); dbgs() << "\n";
1065#endif
1066 report_fatal_error("Do not know how to soften this operator's operand!");
1067
1068 case ISD::BITCAST: Res = SoftenFloatOp_BITCAST(N); break;
1069 case ISD::BR_CC: Res = SoftenFloatOp_BR_CC(N); break;
1071 case ISD::FP_TO_FP16: // Same as FP_ROUND for softening purposes
1072 case ISD::FP_TO_BF16:
1075 case ISD::FP_ROUND: Res = SoftenFloatOp_FP_ROUND(N); break;
1078 case ISD::FP_TO_SINT:
1079 case ISD::FP_TO_UINT: Res = SoftenFloatOp_FP_TO_XINT(N); break;
1082 Res = SoftenFloatOp_FP_TO_XINT_SAT(N); break;
1083 case ISD::STRICT_LROUND:
1084 case ISD::LROUND: Res = SoftenFloatOp_LROUND(N); break;
1086 case ISD::LLROUND: Res = SoftenFloatOp_LLROUND(N); break;
1087 case ISD::STRICT_LRINT:
1088 case ISD::LRINT: Res = SoftenFloatOp_LRINT(N); break;
1089 case ISD::STRICT_LLRINT:
1090 case ISD::LLRINT: Res = SoftenFloatOp_LLRINT(N); break;
1091 case ISD::SELECT_CC: Res = SoftenFloatOp_SELECT_CC(N); break;
1092 case ISD::STRICT_FSETCC:
1094 case ISD::SETCC: Res = SoftenFloatOp_SETCC(N); break;
1095 case ISD::STORE: Res = SoftenFloatOp_STORE(N, OpNo); break;
1096 case ISD::ATOMIC_STORE:
1097 Res = SoftenFloatOp_ATOMIC_STORE(N, OpNo);
1098 break;
1099 case ISD::FCOPYSIGN: Res = SoftenFloatOp_FCOPYSIGN(N); break;
1100 case ISD::FAKE_USE:
1101 Res = SoftenFloatOp_FAKE_USE(N);
1102 break;
1103 case ISD::STACKMAP:
1104 Res = SoftenFloatOp_STACKMAP(N, OpNo);
1105 break;
1106 case ISD::PATCHPOINT:
1107 Res = SoftenFloatOp_PATCHPOINT(N, OpNo);
1108 break;
1109 }
1110
1111 // If the result is null, the sub-method took care of registering results etc.
1112 if (!Res.getNode()) return false;
1113
1114 // If the result is N, the sub-method updated N in place. Tell the legalizer
1115 // core about this to re-analyze.
1116 if (Res.getNode() == N)
1117 return true;
1118
1119 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
1120 "Invalid operand softening");
1121
1122 ReplaceValueWith(SDValue(N, 0), Res);
1123 return false;
1124}
1125
1126SDValue DAGTypeLegalizer::SoftenFloatOp_BITCAST(SDNode *N) {
1127 SDValue Op0 = GetSoftenedFloat(N->getOperand(0));
1128
1129 return DAG.getNode(ISD::BITCAST, SDLoc(N), N->getValueType(0), Op0);
1130}
1131
1132SDValue DAGTypeLegalizer::SoftenFloatOp_FP_ROUND(SDNode *N) {
1133 // We actually deal with the partially-softened FP_TO_FP16 node too, which
1134 // returns an i16 so doesn't meet the constraints necessary for FP_ROUND.
1135 assert(N->getOpcode() == ISD::FP_ROUND || N->getOpcode() == ISD::FP_TO_FP16 ||
1136 N->getOpcode() == ISD::STRICT_FP_TO_FP16 ||
1137 N->getOpcode() == ISD::FP_TO_BF16 ||
1138 N->getOpcode() == ISD::STRICT_FP_TO_BF16 ||
1139 N->getOpcode() == ISD::STRICT_FP_ROUND);
1140
1141 bool IsStrict = N->isStrictFPOpcode();
1142 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
1143 EVT SVT = Op.getValueType();
1144 EVT RVT = N->getValueType(0);
1145 EVT FloatRVT = RVT;
1146 if (N->getOpcode() == ISD::FP_TO_FP16 ||
1147 N->getOpcode() == ISD::STRICT_FP_TO_FP16)
1148 FloatRVT = MVT::f16;
1149 else if (N->getOpcode() == ISD::FP_TO_BF16 ||
1150 N->getOpcode() == ISD::STRICT_FP_TO_BF16)
1151 FloatRVT = MVT::bf16;
1152
1153 RTLIB::Libcall LC = RTLIB::getFPROUND(SVT, FloatRVT);
1154 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_ROUND libcall");
1155
1156 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1157 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
1158 if (LCImpl == RTLIB::Unsupported) {
1159 DAG.getContext()->emitError(Twine("no libcall available for ") +
1160 N->getOperationName(&DAG));
1161 SDValue Poison = DAG.getPOISON(RVT);
1162 if (IsStrict) {
1163 ReplaceValueWith(SDValue(N, 1), Chain);
1164 ReplaceValueWith(SDValue(N, 0), Poison);
1165 return SDValue();
1166 }
1167 return Poison;
1168 }
1169 Op = GetSoftenedFloat(Op);
1170 TargetLowering::MakeLibCallOptions CallOptions;
1171 CallOptions.setTypeListBeforeSoften(SVT, RVT);
1172 std::pair<SDValue, SDValue> Tmp =
1173 TLI.makeLibCall(DAG, LCImpl, RVT, Op, CallOptions, SDLoc(N), Chain);
1174 if (IsStrict) {
1175 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1176 ReplaceValueWith(SDValue(N, 0), Tmp.first);
1177 return SDValue();
1178 }
1179 return Tmp.first;
1180}
1181
1182SDValue DAGTypeLegalizer::SoftenFloatOp_BR_CC(SDNode *N) {
1183 SDValue NewLHS = N->getOperand(2), NewRHS = N->getOperand(3);
1184 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(1))->get();
1185
1186 EVT VT = NewLHS.getValueType();
1187 NewLHS = GetSoftenedFloat(NewLHS);
1188 NewRHS = GetSoftenedFloat(NewRHS);
1189 TLI.softenSetCCOperands(DAG, VT, NewLHS, NewRHS, CCCode, SDLoc(N),
1190 N->getOperand(2), N->getOperand(3));
1191
1192 // If softenSetCCOperands returned a scalar, we need to compare the result
1193 // against zero to select between true and false values.
1194 if (!NewRHS.getNode()) {
1195 NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
1196 CCCode = ISD::SETNE;
1197 }
1198
1199 // Update N to have the operands specified.
1200 return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0),
1201 DAG.getCondCode(CCCode), NewLHS, NewRHS,
1202 N->getOperand(4)),
1203 0);
1204}
1205
1206// Even if the result type is legal, no libcall may exactly match. (e.g. We
1207// don't have FP-i8 conversions) This helper method looks for an appropriate
1208// promoted libcall.
1209static RTLIB::Libcall findFPToIntLibcall(EVT SrcVT, EVT RetVT, EVT &Promoted,
1210 bool Signed) {
1211 RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
1212 for (unsigned IntVT = MVT::FIRST_INTEGER_VALUETYPE;
1213 IntVT <= MVT::LAST_INTEGER_VALUETYPE && LC == RTLIB::UNKNOWN_LIBCALL;
1214 ++IntVT) {
1215 Promoted = (MVT::SimpleValueType)IntVT;
1216 // The type needs to big enough to hold the result.
1217 if (Promoted.bitsGE(RetVT))
1218 LC = Signed ? RTLIB::getFPTOSINT(SrcVT, Promoted)
1219 : RTLIB::getFPTOUINT(SrcVT, Promoted);
1220 }
1221 return LC;
1222}
1223
1224SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_XINT(SDNode *N) {
1225 bool IsStrict = N->isStrictFPOpcode();
1226 bool Signed = N->getOpcode() == ISD::FP_TO_SINT ||
1227 N->getOpcode() == ISD::STRICT_FP_TO_SINT;
1228
1229 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
1230 EVT SVT = Op.getValueType();
1231 EVT RVT = N->getValueType(0);
1232 EVT NVT = EVT();
1233 SDLoc dl(N);
1234
1235 // If the result is not legal, eg: fp -> i1, then it needs to be promoted to
1236 // a larger type, eg: fp -> i32. Even if it is legal, no libcall may exactly
1237 // match, eg. we don't have fp -> i8 conversions.
1238 // Look for an appropriate libcall.
1239 RTLIB::Libcall LC = findFPToIntLibcall(SVT, RVT, NVT, Signed);
1240 assert(LC != RTLIB::UNKNOWN_LIBCALL && NVT.isSimple() &&
1241 "Unsupported FP_TO_XINT!");
1242
1243 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1244 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
1245 if (LCImpl == RTLIB::Unsupported) {
1246 DAG.getContext()->emitError(Twine("no libcall available for ") +
1247 N->getOperationName(&DAG));
1248 SDValue Poison = DAG.getPOISON(RVT);
1249 if (IsStrict) {
1250 ReplaceValueWith(SDValue(N, 1), Chain);
1251 ReplaceValueWith(SDValue(N, 0), Poison);
1252 return SDValue();
1253 }
1254 return Poison;
1255 }
1256
1257 Op = GetSoftenedFloat(Op);
1258 TargetLowering::MakeLibCallOptions CallOptions;
1259 CallOptions.setTypeListBeforeSoften(SVT, RVT);
1260 std::pair<SDValue, SDValue> Tmp =
1261 TLI.makeLibCall(DAG, LCImpl, NVT, Op, CallOptions, dl, Chain);
1262
1263 // Truncate the result if the libcall returns a larger type.
1264 SDValue Res = DAG.getNode(ISD::TRUNCATE, dl, RVT, Tmp.first);
1265
1266 if (!IsStrict)
1267 return Res;
1268
1269 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1270 ReplaceValueWith(SDValue(N, 0), Res);
1271 return SDValue();
1272}
1273
1274SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_XINT_SAT(SDNode *N) {
1275 SDValue Res = TLI.expandFP_TO_INT_SAT(N, DAG);
1276 return Res;
1277}
1278
1279SDValue DAGTypeLegalizer::SoftenFloatOp_SELECT_CC(SDNode *N) {
1280 SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
1281 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(4))->get();
1282
1283 EVT VT = NewLHS.getValueType();
1284 NewLHS = GetSoftenedFloat(NewLHS);
1285 NewRHS = GetSoftenedFloat(NewRHS);
1286 TLI.softenSetCCOperands(DAG, VT, NewLHS, NewRHS, CCCode, SDLoc(N),
1287 N->getOperand(0), N->getOperand(1));
1288
1289 // If softenSetCCOperands returned a scalar, we need to compare the result
1290 // against zero to select between true and false values.
1291 if (!NewRHS.getNode()) {
1292 NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
1293 CCCode = ISD::SETNE;
1294 }
1295
1296 // Update N to have the operands specified.
1297 return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
1298 N->getOperand(2), N->getOperand(3),
1299 DAG.getCondCode(CCCode)),
1300 0);
1301}
1302
1303SDValue DAGTypeLegalizer::SoftenFloatOp_SETCC(SDNode *N) {
1304 bool IsStrict = N->isStrictFPOpcode();
1305 SDValue Op0 = N->getOperand(IsStrict ? 1 : 0);
1306 SDValue Op1 = N->getOperand(IsStrict ? 2 : 1);
1307 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1308 ISD::CondCode CCCode =
1309 cast<CondCodeSDNode>(N->getOperand(IsStrict ? 3 : 2))->get();
1310
1311 EVT VT = Op0.getValueType();
1312 SDValue NewLHS = GetSoftenedFloat(Op0);
1313 SDValue NewRHS = GetSoftenedFloat(Op1);
1314 TLI.softenSetCCOperands(DAG, VT, NewLHS, NewRHS, CCCode, SDLoc(N), Op0, Op1,
1315 Chain, N->getOpcode() == ISD::STRICT_FSETCCS);
1316
1317 // Update N to have the operands specified.
1318 if (NewRHS.getNode()) {
1319 if (IsStrict)
1320 NewLHS = DAG.getNode(ISD::SETCC, SDLoc(N), N->getValueType(0), NewLHS,
1321 NewRHS, DAG.getCondCode(CCCode));
1322 else
1323 return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
1324 DAG.getCondCode(CCCode)), 0);
1325 }
1326
1327 // Otherwise, softenSetCCOperands returned a scalar, use it.
1328 assert((NewRHS.getNode() || NewLHS.getValueType() == N->getValueType(0)) &&
1329 "Unexpected setcc expansion!");
1330
1331 if (IsStrict) {
1332 ReplaceValueWith(SDValue(N, 0), NewLHS);
1333 ReplaceValueWith(SDValue(N, 1), Chain);
1334 return SDValue();
1335 }
1336 return NewLHS;
1337}
1338
1339SDValue DAGTypeLegalizer::SoftenFloatOp_STORE(SDNode *N, unsigned OpNo) {
1340 assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!");
1341 assert(OpNo == 1 && "Can only soften the stored value!");
1342 StoreSDNode *ST = cast<StoreSDNode>(N);
1343 SDValue Val = ST->getValue();
1344 SDLoc dl(N);
1345
1346 if (ST->isTruncatingStore())
1347 // Do an FP_ROUND followed by a non-truncating store.
1348 Val = BitConvertToInteger(
1349 DAG.getNode(ISD::FP_ROUND, dl, ST->getMemoryVT(), Val,
1350 DAG.getIntPtrConstant(0, dl, /*isTarget=*/true)));
1351 else
1352 Val = GetSoftenedFloat(Val);
1353
1354 // If softening widens the integer representation (e.g. x86_fp80 -> i96),
1355 // truncate the value before storing to preserve the original memory width.
1356 EVT MemVT =
1357 EVT::getIntegerVT(*DAG.getContext(), ST->getMemoryVT().getSizeInBits());
1358 return DAG.getTruncStore(ST->getChain(), dl, Val, ST->getBasePtr(), MemVT,
1359 ST->getMemOperand());
1360}
1361
1362SDValue DAGTypeLegalizer::SoftenFloatOp_ATOMIC_STORE(SDNode *N, unsigned OpNo) {
1363 assert(OpNo == 1 && "Can only soften the stored value!");
1364 AtomicSDNode *ST = cast<AtomicSDNode>(N);
1365 SDValue Val = ST->getVal();
1366 EVT VT = Val.getValueType();
1367 SDLoc dl(N);
1368
1369 assert(ST->getMemoryVT() == VT && "truncating atomic store not handled");
1370
1371 SDValue NewVal = GetSoftenedFloat(Val);
1372 return DAG.getAtomic(ISD::ATOMIC_STORE, dl, VT, ST->getChain(), NewVal,
1373 ST->getBasePtr(), ST->getMemOperand());
1374}
1375
1376SDValue DAGTypeLegalizer::SoftenFloatOp_FCOPYSIGN(SDNode *N) {
1377 SDValue LHS = N->getOperand(0);
1378 SDValue RHS = BitConvertToInteger(N->getOperand(1));
1379 SDLoc dl(N);
1380
1381 EVT LVT = LHS.getValueType();
1382 EVT ILVT = EVT::getIntegerVT(*DAG.getContext(), LVT.getSizeInBits());
1383 EVT RVT = RHS.getValueType();
1384
1385 unsigned LSize = LVT.getSizeInBits();
1386 unsigned RSize = RVT.getSizeInBits();
1387
1388 // Shift right or sign-extend it if the two operands have different types.
1389 int SizeDiff = RSize - LSize;
1390 if (SizeDiff > 0) {
1391 RHS =
1392 DAG.getNode(ISD::SRL, dl, RVT, RHS,
1393 DAG.getConstant(SizeDiff, dl,
1394 TLI.getShiftAmountTy(RHS.getValueType(),
1395 DAG.getDataLayout())));
1396 RHS = DAG.getNode(ISD::TRUNCATE, dl, ILVT, RHS);
1397 } else if (SizeDiff < 0) {
1398 RHS = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, RHS);
1399 RHS =
1400 DAG.getNode(ISD::SHL, dl, ILVT, RHS,
1401 DAG.getConstant(-SizeDiff, dl,
1402 TLI.getShiftAmountTy(RHS.getValueType(),
1403 DAG.getDataLayout())));
1404 }
1405
1406 RHS = DAG.getBitcast(LVT, RHS);
1407 return DAG.getNode(ISD::FCOPYSIGN, dl, LVT, LHS, RHS);
1408}
1409
1410SDValue DAGTypeLegalizer::SoftenFloatOp_Unary(SDNode *N, RTLIB::Libcall LC) {
1411 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
1412 bool IsStrict = N->isStrictFPOpcode();
1413 unsigned Offset = IsStrict ? 1 : 0;
1414 SDValue Op = GetSoftenedFloat(N->getOperand(0 + Offset));
1415 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1416 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
1417 if (LCImpl == RTLIB::Unsupported) {
1418 DAG.getContext()->emitError(Twine("no libcall available for ") +
1419 N->getOperationName(&DAG));
1420 SDValue Poison = DAG.getPOISON(N->getValueType(0));
1421 if (IsStrict) {
1422 ReplaceValueWith(SDValue(N, 1), Chain);
1423 ReplaceValueWith(SDValue(N, 0), Poison);
1424 return SDValue();
1425 }
1426 return Poison;
1427 }
1428 TargetLowering::MakeLibCallOptions CallOptions;
1429 EVT OpVT = N->getOperand(0 + Offset).getValueType();
1430 CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0));
1431 std::pair<SDValue, SDValue> Tmp =
1432 TLI.makeLibCall(DAG, LCImpl, NVT, Op, CallOptions, SDLoc(N), Chain);
1433 if (IsStrict) {
1434 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1435 ReplaceValueWith(SDValue(N, 0), Tmp.first);
1436 return SDValue();
1437 }
1438
1439 return Tmp.first;
1440}
1441
1442SDValue DAGTypeLegalizer::SoftenFloatOp_LROUND(SDNode *N) {
1443 EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1444 return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
1445 RTLIB::LROUND_F32,
1446 RTLIB::LROUND_F64,
1447 RTLIB::LROUND_F80,
1448 RTLIB::LROUND_F128,
1449 RTLIB::LROUND_PPCF128));
1450}
1451
1452SDValue DAGTypeLegalizer::SoftenFloatOp_LLROUND(SDNode *N) {
1453 EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1454 return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
1455 RTLIB::LLROUND_F32,
1456 RTLIB::LLROUND_F64,
1457 RTLIB::LLROUND_F80,
1458 RTLIB::LLROUND_F128,
1459 RTLIB::LLROUND_PPCF128));
1460}
1461
1462SDValue DAGTypeLegalizer::SoftenFloatOp_LRINT(SDNode *N) {
1463 EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1464 return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
1465 RTLIB::LRINT_F32,
1466 RTLIB::LRINT_F64,
1467 RTLIB::LRINT_F80,
1468 RTLIB::LRINT_F128,
1469 RTLIB::LRINT_PPCF128));
1470}
1471
1472SDValue DAGTypeLegalizer::SoftenFloatOp_LLRINT(SDNode *N) {
1473 EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1474 return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
1475 RTLIB::LLRINT_F32,
1476 RTLIB::LLRINT_F64,
1477 RTLIB::LLRINT_F80,
1478 RTLIB::LLRINT_F128,
1479 RTLIB::LLRINT_PPCF128));
1480}
1481
1482SDValue DAGTypeLegalizer::SoftenFloatOp_FAKE_USE(SDNode *N) {
1483 SDValue Op1 = BitConvertToInteger(N->getOperand(1));
1484 return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
1485 N->getOperand(0), Op1);
1486}
1487
1488SDValue DAGTypeLegalizer::SoftenFloatOp_STACKMAP(SDNode *N, unsigned OpNo) {
1489 assert(OpNo > 1); // Because the first two arguments are guaranteed legal.
1490 SmallVector<SDValue> NewOps(N->ops());
1491 NewOps[OpNo] = GetSoftenedFloat(NewOps[OpNo]);
1492 return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0);
1493}
1494
1495SDValue DAGTypeLegalizer::SoftenFloatOp_PATCHPOINT(SDNode *N, unsigned OpNo) {
1496 assert(OpNo >= 7);
1497 SmallVector<SDValue> NewOps(N->ops());
1498 NewOps[OpNo] = GetSoftenedFloat(NewOps[OpNo]);
1499 return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0);
1500}
1501
1502//===----------------------------------------------------------------------===//
1503// Float Result Expansion
1504//===----------------------------------------------------------------------===//
1505
1506/// ExpandFloatResult - This method is called when the specified result of the
1507/// specified node is found to need expansion. At this point, the node may also
1508/// have invalid operands or may have other results that need promotion, we just
1509/// know that (at least) one result needs expansion.
1510void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) {
1511 LLVM_DEBUG(dbgs() << "Expand float result: "; N->dump(&DAG));
1512 SDValue Lo, Hi;
1513 Lo = Hi = SDValue();
1514
1515 // See if the target wants to custom expand this node.
1516 if (CustomLowerNode(N, N->getValueType(ResNo), true))
1517 return;
1518
1519 switch (N->getOpcode()) {
1520 default:
1521#ifndef NDEBUG
1522 dbgs() << "ExpandFloatResult #" << ResNo << ": ";
1523 N->dump(&DAG); dbgs() << "\n";
1524#endif
1525 report_fatal_error("Do not know how to expand the result of this "
1526 "operator!");
1527 // clang-format off
1528 case ISD::POISON:
1529 case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
1530 case ISD::SELECT: SplitRes_Select(N, Lo, Hi); break;
1531 case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break;
1532
1533 case ISD::MERGE_VALUES: ExpandRes_MERGE_VALUES(N, ResNo, Lo, Hi); break;
1534 case ISD::BITCAST: ExpandRes_BITCAST(N, Lo, Hi); break;
1535 case ISD::BUILD_PAIR: ExpandRes_BUILD_PAIR(N, Lo, Hi); break;
1536 case ISD::EXTRACT_ELEMENT: ExpandRes_EXTRACT_ELEMENT(N, Lo, Hi); break;
1537 case ISD::EXTRACT_VECTOR_ELT: ExpandRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); break;
1538 case ISD::VAARG: ExpandRes_VAARG(N, Lo, Hi); break;
1539
1540 case ISD::ConstantFP: ExpandFloatRes_ConstantFP(N, Lo, Hi); break;
1541 case ISD::AssertNoFPClass: ExpandFloatRes_AssertNoFPClass(N, Lo, Hi); break;
1542 case ISD::FABS: ExpandFloatRes_FABS(N, Lo, Hi); break;
1544 case ISD::FMINNUM: ExpandFloatRes_FMINNUM(N, Lo, Hi); break;
1546 case ISD::FMAXNUM: ExpandFloatRes_FMAXNUM(N, Lo, Hi); break;
1547 case ISD::FMINIMUMNUM: ExpandFloatRes_FMINIMUMNUM(N, Lo, Hi); break;
1548 case ISD::FMAXIMUMNUM: ExpandFloatRes_FMAXIMUMNUM(N, Lo, Hi); break;
1549 case ISD::STRICT_FADD:
1550 case ISD::FADD: ExpandFloatRes_FADD(N, Lo, Hi); break;
1551 case ISD::STRICT_FACOS:
1552 case ISD::FACOS: ExpandFloatRes_FACOS(N, Lo, Hi); break;
1553 case ISD::STRICT_FASIN:
1554 case ISD::FASIN: ExpandFloatRes_FASIN(N, Lo, Hi); break;
1555 case ISD::STRICT_FATAN:
1556 case ISD::FATAN: ExpandFloatRes_FATAN(N, Lo, Hi); break;
1557 case ISD::STRICT_FATAN2:
1558 case ISD::FATAN2: ExpandFloatRes_FATAN2(N, Lo, Hi); break;
1559 case ISD::FCBRT: ExpandFloatRes_FCBRT(N, Lo, Hi); break;
1560 case ISD::STRICT_FCEIL:
1561 case ISD::FCEIL: ExpandFloatRes_FCEIL(N, Lo, Hi); break;
1562 case ISD::FCOPYSIGN: ExpandFloatRes_FCOPYSIGN(N, Lo, Hi); break;
1563 case ISD::STRICT_FCOS:
1564 case ISD::FCOS: ExpandFloatRes_FCOS(N, Lo, Hi); break;
1565 case ISD::STRICT_FCOSH:
1566 case ISD::FCOSH: ExpandFloatRes_FCOSH(N, Lo, Hi); break;
1567 case ISD::STRICT_FDIV:
1568 case ISD::FDIV: ExpandFloatRes_FDIV(N, Lo, Hi); break;
1569 case ISD::STRICT_FEXP:
1570 case ISD::FEXP: ExpandFloatRes_FEXP(N, Lo, Hi); break;
1571 case ISD::STRICT_FEXP2:
1572 case ISD::FEXP2: ExpandFloatRes_FEXP2(N, Lo, Hi); break;
1573 case ISD::FEXP10: ExpandFloatRes_FEXP10(N, Lo, Hi); break;
1574 case ISD::STRICT_FFLOOR:
1575 case ISD::FFLOOR: ExpandFloatRes_FFLOOR(N, Lo, Hi); break;
1576 case ISD::STRICT_FLOG:
1577 case ISD::FLOG: ExpandFloatRes_FLOG(N, Lo, Hi); break;
1578 case ISD::STRICT_FLOG2:
1579 case ISD::FLOG2: ExpandFloatRes_FLOG2(N, Lo, Hi); break;
1580 case ISD::STRICT_FLOG10:
1581 case ISD::FLOG10: ExpandFloatRes_FLOG10(N, Lo, Hi); break;
1582 case ISD::STRICT_FMA:
1583 case ISD::FMA: ExpandFloatRes_FMA(N, Lo, Hi); break;
1584 case ISD::STRICT_FMUL:
1585 case ISD::FMUL: ExpandFloatRes_FMUL(N, Lo, Hi); break;
1587 case ISD::FNEARBYINT: ExpandFloatRes_FNEARBYINT(N, Lo, Hi); break;
1588 case ISD::FNEG: ExpandFloatRes_FNEG(N, Lo, Hi); break;
1590 case ISD::FP_EXTEND: ExpandFloatRes_FP_EXTEND(N, Lo, Hi); break;
1591 case ISD::STRICT_FPOW:
1592 case ISD::FPOW: ExpandFloatRes_FPOW(N, Lo, Hi); break;
1593 case ISD::STRICT_FPOWI:
1594 case ISD::FPOWI: ExpandFloatRes_FPOWI(N, Lo, Hi); break;
1595 case ISD::FLDEXP:
1596 case ISD::STRICT_FLDEXP: ExpandFloatRes_FLDEXP(N, Lo, Hi); break;
1597 case ISD::FREEZE: ExpandFloatRes_FREEZE(N, Lo, Hi); break;
1598 case ISD::STRICT_FRINT:
1599 case ISD::FRINT: ExpandFloatRes_FRINT(N, Lo, Hi); break;
1600 case ISD::STRICT_FROUND:
1601 case ISD::FROUND: ExpandFloatRes_FROUND(N, Lo, Hi); break;
1603 case ISD::FROUNDEVEN: ExpandFloatRes_FROUNDEVEN(N, Lo, Hi); break;
1604 case ISD::STRICT_FSIN:
1605 case ISD::FSIN: ExpandFloatRes_FSIN(N, Lo, Hi); break;
1606 case ISD::STRICT_FSINH:
1607 case ISD::FSINH: ExpandFloatRes_FSINH(N, Lo, Hi); break;
1608 case ISD::STRICT_FSQRT:
1609 case ISD::FSQRT: ExpandFloatRes_FSQRT(N, Lo, Hi); break;
1610 case ISD::STRICT_FSUB:
1611 case ISD::FSUB: ExpandFloatRes_FSUB(N, Lo, Hi); break;
1612 case ISD::STRICT_FTAN:
1613 case ISD::FTAN: ExpandFloatRes_FTAN(N, Lo, Hi); break;
1614 case ISD::STRICT_FTANH:
1615 case ISD::FTANH: ExpandFloatRes_FTANH(N, Lo, Hi); break;
1616 case ISD::STRICT_FTRUNC:
1617 case ISD::FTRUNC: ExpandFloatRes_FTRUNC(N, Lo, Hi); break;
1618 case ISD::LOAD: ExpandFloatRes_LOAD(N, Lo, Hi); break;
1621 case ISD::SINT_TO_FP:
1622 case ISD::UINT_TO_FP: ExpandFloatRes_XINT_TO_FP(N, Lo, Hi); break;
1623 case ISD::STRICT_FREM:
1624 case ISD::FREM: ExpandFloatRes_FREM(N, Lo, Hi); break;
1625 case ISD::FMODF: ExpandFloatRes_FMODF(N); break;
1626 case ISD::FSINCOS: ExpandFloatRes_FSINCOS(N); break;
1627 case ISD::FSINCOSPI: ExpandFloatRes_FSINCOSPI(N); break;
1628 // clang-format on
1629 }
1630
1631 // If Lo/Hi is null, the sub-method took care of registering results etc.
1632 if (Lo.getNode())
1633 SetExpandedFloat(SDValue(N, ResNo), Lo, Hi);
1634}
1635
1636void DAGTypeLegalizer::ExpandFloatRes_ConstantFP(SDNode *N, SDValue &Lo,
1637 SDValue &Hi) {
1638 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
1639 assert(NVT.getSizeInBits() == 64 &&
1640 "Do not know how to expand this float constant!");
1641 APInt C = cast<ConstantFPSDNode>(N)->getValueAPF().bitcastToAPInt();
1642 SDLoc dl(N);
1643 const fltSemantics &Sem = NVT.getFltSemantics();
1644 Lo = DAG.getConstantFP(APFloat(Sem, C.extractBits(64, 64)), dl, NVT);
1645 Hi = DAG.getConstantFP(APFloat(Sem, C.extractBits(64, 0)), dl, NVT);
1646}
1647
1648void DAGTypeLegalizer::ExpandFloatRes_Unary(SDNode *N, RTLIB::Libcall LC,
1649 SDValue &Lo, SDValue &Hi) {
1650 bool IsStrict = N->isStrictFPOpcode();
1651 unsigned Offset = IsStrict ? 1 : 0;
1652 SDValue Op = N->getOperand(0 + Offset);
1653 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1654 TargetLowering::MakeLibCallOptions CallOptions;
1655 std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, N->getValueType(0),
1656 Op, CallOptions, SDLoc(N),
1657 Chain);
1658 if (IsStrict)
1659 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1660 GetPairElements(Tmp.first, Lo, Hi);
1661}
1662
1663void DAGTypeLegalizer::ExpandFloatRes_Binary(SDNode *N, RTLIB::Libcall LC,
1664 SDValue &Lo, SDValue &Hi) {
1665 bool IsStrict = N->isStrictFPOpcode();
1666 unsigned Offset = IsStrict ? 1 : 0;
1667 SDValue Ops[] = { N->getOperand(0 + Offset), N->getOperand(1 + Offset) };
1668 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1669 TargetLowering::MakeLibCallOptions CallOptions;
1670 std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, N->getValueType(0),
1671 Ops, CallOptions, SDLoc(N),
1672 Chain);
1673 if (IsStrict)
1674 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1675 GetPairElements(Tmp.first, Lo, Hi);
1676}
1677
1678void DAGTypeLegalizer::ExpandFloatRes_FMODF(SDNode *N) {
1679 ExpandFloatRes_UnaryWithTwoFPResults(N, RTLIB::getMODF(N->getValueType(0)),
1680 /*CallRetResNo=*/0);
1681}
1682
1683void DAGTypeLegalizer::ExpandFloatRes_FSINCOS(SDNode *N) {
1684 ExpandFloatRes_UnaryWithTwoFPResults(N, RTLIB::getSINCOS(N->getValueType(0)));
1685}
1686
1687void DAGTypeLegalizer::ExpandFloatRes_FSINCOSPI(SDNode *N) {
1688 ExpandFloatRes_UnaryWithTwoFPResults(N,
1689 RTLIB::getSINCOSPI(N->getValueType(0)));
1690}
1691
1692void DAGTypeLegalizer::ExpandFloatRes_UnaryWithTwoFPResults(
1693 SDNode *N, RTLIB::Libcall LC, std::optional<unsigned> CallRetResNo) {
1694 assert(!N->isStrictFPOpcode() && "strictfp not implemented");
1696 TLI.expandMultipleResultFPLibCall(DAG, LC, N, Results, CallRetResNo);
1697 for (auto [ResNo, Res] : enumerate(Results)) {
1698 SDValue Lo, Hi;
1699 GetPairElements(Res, Lo, Hi);
1700 SetExpandedFloat(SDValue(N, ResNo), Lo, Hi);
1701 }
1702}
1703
1704void DAGTypeLegalizer::ExpandFloatRes_FABS(SDNode *N, SDValue &Lo,
1705 SDValue &Hi) {
1706 assert(N->getValueType(0) == MVT::ppcf128 &&
1707 "Logic only correct for ppcf128!");
1708 SDLoc dl(N);
1709 SDValue Tmp;
1710 GetExpandedFloat(N->getOperand(0), Lo, Tmp);
1711 Hi = DAG.getNode(ISD::FABS, dl, Tmp.getValueType(), Tmp);
1712 // Lo = Hi==fabs(Hi) ? Lo : -Lo;
1713 Lo = DAG.getSelectCC(dl, Tmp, Hi, Lo,
1714 DAG.getNode(ISD::FNEG, dl, Lo.getValueType(), Lo),
1715 ISD::SETEQ);
1716}
1717
1718void DAGTypeLegalizer::ExpandFloatRes_FMINNUM(SDNode *N, SDValue &Lo,
1719 SDValue &Hi) {
1720 ExpandFloatRes_Binary(N, RTLIB::getFMIN(N->getValueType(0)), Lo, Hi);
1721}
1722
1723void DAGTypeLegalizer::ExpandFloatRes_FMAXNUM(SDNode *N, SDValue &Lo,
1724 SDValue &Hi) {
1725 ExpandFloatRes_Binary(N, RTLIB::getFMAX(N->getValueType(0)), Lo, Hi);
1726}
1727
1728void DAGTypeLegalizer::ExpandFloatRes_FMINIMUMNUM(SDNode *N, SDValue &Lo,
1729 SDValue &Hi) {
1730 ExpandFloatRes_Binary(N, RTLIB::getFMINIMUM_NUM(N->getValueType(0)), Lo, Hi);
1731}
1732
1733void DAGTypeLegalizer::ExpandFloatRes_FMAXIMUMNUM(SDNode *N, SDValue &Lo,
1734 SDValue &Hi) {
1735 ExpandFloatRes_Binary(N, RTLIB::getFMAXIMUM_NUM(N->getValueType(0)), Lo, Hi);
1736}
1737
1738void DAGTypeLegalizer::ExpandFloatRes_FADD(SDNode *N, SDValue &Lo,
1739 SDValue &Hi) {
1740 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
1741 RTLIB::ADD_F32, RTLIB::ADD_F64,
1742 RTLIB::ADD_F80, RTLIB::ADD_F128,
1743 RTLIB::ADD_PPCF128), Lo, Hi);
1744}
1745
1746void DAGTypeLegalizer::ExpandFloatRes_FACOS(SDNode *N, SDValue &Lo,
1747 SDValue &Hi) {
1748 ExpandFloatRes_Unary(N, RTLIB::getACOS(N->getValueType(0)), Lo, Hi);
1749}
1750
1751void DAGTypeLegalizer::ExpandFloatRes_FASIN(SDNode *N, SDValue &Lo,
1752 SDValue &Hi) {
1753 ExpandFloatRes_Unary(N, RTLIB::getASIN(N->getValueType(0)), Lo, Hi);
1754}
1755
1756void DAGTypeLegalizer::ExpandFloatRes_FATAN(SDNode *N, SDValue &Lo,
1757 SDValue &Hi) {
1758 ExpandFloatRes_Unary(N, RTLIB::getATAN(N->getValueType(0)), Lo, Hi);
1759}
1760
1761void DAGTypeLegalizer::ExpandFloatRes_FATAN2(SDNode *N, SDValue &Lo,
1762 SDValue &Hi) {
1763 ExpandFloatRes_Binary(N, RTLIB::getATAN2(N->getValueType(0)), Lo, Hi);
1764}
1765
1766void DAGTypeLegalizer::ExpandFloatRes_FCBRT(SDNode *N, SDValue &Lo,
1767 SDValue &Hi) {
1768 ExpandFloatRes_Unary(N, RTLIB::getCBRT(N->getValueType(0)), Lo, Hi);
1769}
1770
1771void DAGTypeLegalizer::ExpandFloatRes_FCEIL(SDNode *N,
1772 SDValue &Lo, SDValue &Hi) {
1773 ExpandFloatRes_Unary(N, RTLIB::getCEIL(N->getValueType(0)), Lo, Hi);
1774}
1775
1776void DAGTypeLegalizer::ExpandFloatRes_FCOPYSIGN(SDNode *N,
1777 SDValue &Lo, SDValue &Hi) {
1778 ExpandFloatRes_Binary(N, RTLIB::getCOPYSIGN(N->getValueType(0)), Lo, Hi);
1779}
1780
1781void DAGTypeLegalizer::ExpandFloatRes_FCOS(SDNode *N,
1782 SDValue &Lo, SDValue &Hi) {
1783 ExpandFloatRes_Unary(N, RTLIB::getCOS(N->getValueType(0)), Lo, Hi);
1784}
1785
1786void DAGTypeLegalizer::ExpandFloatRes_FCOSH(SDNode *N, SDValue &Lo,
1787 SDValue &Hi) {
1788 ExpandFloatRes_Unary(N, RTLIB::getCOSH(N->getValueType(0)), Lo, Hi);
1789}
1790
1791void DAGTypeLegalizer::ExpandFloatRes_FDIV(SDNode *N, SDValue &Lo,
1792 SDValue &Hi) {
1793 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
1794 RTLIB::DIV_F32,
1795 RTLIB::DIV_F64,
1796 RTLIB::DIV_F80,
1797 RTLIB::DIV_F128,
1798 RTLIB::DIV_PPCF128), Lo, Hi);
1799}
1800
1801void DAGTypeLegalizer::ExpandFloatRes_FEXP(SDNode *N,
1802 SDValue &Lo, SDValue &Hi) {
1803 ExpandFloatRes_Unary(N, RTLIB::getEXP(N->getValueType(0)), Lo, Hi);
1804}
1805
1806void DAGTypeLegalizer::ExpandFloatRes_FEXP2(SDNode *N,
1807 SDValue &Lo, SDValue &Hi) {
1808 ExpandFloatRes_Unary(N, RTLIB::getEXP2(N->getValueType(0)), Lo, Hi);
1809}
1810
1811void DAGTypeLegalizer::ExpandFloatRes_FEXP10(SDNode *N, SDValue &Lo,
1812 SDValue &Hi) {
1813 ExpandFloatRes_Unary(N, RTLIB::getEXP10(N->getValueType(0)), Lo, Hi);
1814}
1815
1816void DAGTypeLegalizer::ExpandFloatRes_FFLOOR(SDNode *N,
1817 SDValue &Lo, SDValue &Hi) {
1818 ExpandFloatRes_Unary(N, RTLIB::getFLOOR(N->getValueType(0)), Lo, Hi);
1819}
1820
1821void DAGTypeLegalizer::ExpandFloatRes_FLOG(SDNode *N,
1822 SDValue &Lo, SDValue &Hi) {
1823 ExpandFloatRes_Unary(N, RTLIB::getLOG(N->getValueType(0)), Lo, Hi);
1824}
1825
1826void DAGTypeLegalizer::ExpandFloatRes_FLOG2(SDNode *N,
1827 SDValue &Lo, SDValue &Hi) {
1828 ExpandFloatRes_Unary(N, RTLIB::getLOG2(N->getValueType(0)), Lo, Hi);
1829}
1830
1831void DAGTypeLegalizer::ExpandFloatRes_FLOG10(SDNode *N,
1832 SDValue &Lo, SDValue &Hi) {
1833 ExpandFloatRes_Unary(N, RTLIB::getLOG10(N->getValueType(0)), Lo, Hi);
1834}
1835
1836void DAGTypeLegalizer::ExpandFloatRes_FMA(SDNode *N, SDValue &Lo,
1837 SDValue &Hi) {
1838 bool IsStrict = N->isStrictFPOpcode();
1839 unsigned Offset = IsStrict ? 1 : 0;
1840 SDValue Ops[3] = { N->getOperand(0 + Offset), N->getOperand(1 + Offset),
1841 N->getOperand(2 + Offset) };
1842 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1843 TargetLowering::MakeLibCallOptions CallOptions;
1844 std::pair<SDValue, SDValue> Tmp =
1845 TLI.makeLibCall(DAG, RTLIB::getFMA(N->getValueType(0)),
1846 N->getValueType(0), Ops, CallOptions, SDLoc(N), Chain);
1847 if (IsStrict)
1848 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1849 GetPairElements(Tmp.first, Lo, Hi);
1850}
1851
1852void DAGTypeLegalizer::ExpandFloatRes_FMUL(SDNode *N, SDValue &Lo,
1853 SDValue &Hi) {
1854 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
1855 RTLIB::MUL_F32,
1856 RTLIB::MUL_F64,
1857 RTLIB::MUL_F80,
1858 RTLIB::MUL_F128,
1859 RTLIB::MUL_PPCF128), Lo, Hi);
1860}
1861
1862void DAGTypeLegalizer::ExpandFloatRes_FNEARBYINT(SDNode *N,
1863 SDValue &Lo, SDValue &Hi) {
1864 ExpandFloatRes_Unary(N, RTLIB::getNEARBYINT(N->getValueType(0)), Lo, Hi);
1865}
1866
1867void DAGTypeLegalizer::ExpandFloatRes_FNEG(SDNode *N, SDValue &Lo,
1868 SDValue &Hi) {
1869 SDLoc dl(N);
1870 GetExpandedFloat(N->getOperand(0), Lo, Hi);
1871 Lo = DAG.getNode(ISD::FNEG, dl, Lo.getValueType(), Lo);
1872 Hi = DAG.getNode(ISD::FNEG, dl, Hi.getValueType(), Hi);
1873}
1874
1875void DAGTypeLegalizer::ExpandFloatRes_AssertNoFPClass(SDNode *N, SDValue &Lo,
1876 SDValue &Hi) {
1877 // TODO: Handle ppcf128 by preserving AssertNoFPClass for one of the halves.
1878 SDLoc dl(N);
1879 GetExpandedFloat(N->getOperand(0), Lo, Hi);
1880}
1881
1882void DAGTypeLegalizer::ExpandFloatRes_FP_EXTEND(SDNode *N, SDValue &Lo,
1883 SDValue &Hi) {
1884 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
1885 SDLoc dl(N);
1886 bool IsStrict = N->isStrictFPOpcode();
1887
1888 SDValue Chain;
1889 if (IsStrict) {
1890 // If the expanded type is the same as the input type, just bypass the node.
1891 if (NVT == N->getOperand(1).getValueType()) {
1892 Hi = N->getOperand(1);
1893 Chain = N->getOperand(0);
1894 } else {
1895 // Other we need to extend.
1896 Hi = DAG.getNode(ISD::STRICT_FP_EXTEND, dl, { NVT, MVT::Other },
1897 { N->getOperand(0), N->getOperand(1) });
1898 Chain = Hi.getValue(1);
1899 }
1900 } else {
1901 Hi = DAG.getNode(ISD::FP_EXTEND, dl, NVT, N->getOperand(0));
1902 }
1903
1904 Lo = DAG.getConstantFP(APFloat::getZero(NVT.getFltSemantics()), dl, NVT);
1905
1906 if (IsStrict)
1907 ReplaceValueWith(SDValue(N, 1), Chain);
1908}
1909
1910void DAGTypeLegalizer::ExpandFloatRes_FPOW(SDNode *N,
1911 SDValue &Lo, SDValue &Hi) {
1912 ExpandFloatRes_Binary(N, RTLIB::getPOW(N->getValueType(0)), Lo, Hi);
1913}
1914
1915void DAGTypeLegalizer::ExpandFloatRes_FPOWI(SDNode *N,
1916 SDValue &Lo, SDValue &Hi) {
1917 ExpandFloatRes_Binary(N, RTLIB::getPOWI(N->getValueType(0)), Lo, Hi);
1918}
1919
1920void DAGTypeLegalizer::ExpandFloatRes_FLDEXP(SDNode *N, SDValue &Lo,
1921 SDValue &Hi) {
1922 ExpandFloatRes_Binary(N, RTLIB::getLDEXP(N->getValueType(0)), Lo, Hi);
1923}
1924
1925void DAGTypeLegalizer::ExpandFloatRes_FREEZE(SDNode *N,
1926 SDValue &Lo, SDValue &Hi) {
1927 assert(N->getValueType(0) == MVT::ppcf128 &&
1928 "Logic only correct for ppcf128!");
1929
1930 SDLoc dl(N);
1931 GetExpandedFloat(N->getOperand(0), Lo, Hi);
1932 Lo = DAG.getNode(ISD::FREEZE, dl, Lo.getValueType(), Lo);
1933 Hi = DAG.getNode(ISD::FREEZE, dl, Hi.getValueType(), Hi);
1934}
1935
1936void DAGTypeLegalizer::ExpandFloatRes_FREM(SDNode *N,
1937 SDValue &Lo, SDValue &Hi) {
1938 ExpandFloatRes_Binary(N, RTLIB::getREM(N->getValueType(0)), Lo, Hi);
1939}
1940
1941void DAGTypeLegalizer::ExpandFloatRes_FRINT(SDNode *N,
1942 SDValue &Lo, SDValue &Hi) {
1943 ExpandFloatRes_Unary(N, RTLIB::getRINT(N->getValueType(0)), Lo, Hi);
1944}
1945
1946void DAGTypeLegalizer::ExpandFloatRes_FROUND(SDNode *N,
1947 SDValue &Lo, SDValue &Hi) {
1948 ExpandFloatRes_Unary(N, RTLIB::getROUND(N->getValueType(0)), Lo, Hi);
1949}
1950
1951void DAGTypeLegalizer::ExpandFloatRes_FROUNDEVEN(SDNode *N,
1952 SDValue &Lo, SDValue &Hi) {
1953 ExpandFloatRes_Unary(N, RTLIB::getROUNDEVEN(N->getValueType(0)), Lo, Hi);
1954}
1955
1956void DAGTypeLegalizer::ExpandFloatRes_FSIN(SDNode *N,
1957 SDValue &Lo, SDValue &Hi) {
1958 ExpandFloatRes_Unary(N, RTLIB::getSIN(N->getValueType(0)), Lo, Hi);
1959}
1960
1961void DAGTypeLegalizer::ExpandFloatRes_FSINH(SDNode *N, SDValue &Lo,
1962 SDValue &Hi) {
1963 ExpandFloatRes_Unary(N, RTLIB::getSINH(N->getValueType(0)), Lo, Hi);
1964}
1965
1966void DAGTypeLegalizer::ExpandFloatRes_FSQRT(SDNode *N,
1967 SDValue &Lo, SDValue &Hi) {
1968 ExpandFloatRes_Unary(N, RTLIB::getSQRT(N->getValueType(0)), Lo, Hi);
1969}
1970
1971void DAGTypeLegalizer::ExpandFloatRes_FSUB(SDNode *N, SDValue &Lo,
1972 SDValue &Hi) {
1973 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
1974 RTLIB::SUB_F32,
1975 RTLIB::SUB_F64,
1976 RTLIB::SUB_F80,
1977 RTLIB::SUB_F128,
1978 RTLIB::SUB_PPCF128), Lo, Hi);
1979}
1980
1981void DAGTypeLegalizer::ExpandFloatRes_FTAN(SDNode *N, SDValue &Lo,
1982 SDValue &Hi) {
1983 ExpandFloatRes_Unary(N, RTLIB::getTAN(N->getValueType(0)), Lo, Hi);
1984}
1985
1986void DAGTypeLegalizer::ExpandFloatRes_FTANH(SDNode *N, SDValue &Lo,
1987 SDValue &Hi) {
1988 ExpandFloatRes_Unary(N, RTLIB::getTANH(N->getValueType(0)), Lo, Hi);
1989}
1990
1991void DAGTypeLegalizer::ExpandFloatRes_FTRUNC(SDNode *N,
1992 SDValue &Lo, SDValue &Hi) {
1993 ExpandFloatRes_Unary(N, RTLIB::getTRUNC(N->getValueType(0)), Lo, Hi);
1994}
1995
1996void DAGTypeLegalizer::ExpandFloatRes_LOAD(SDNode *N, SDValue &Lo,
1997 SDValue &Hi) {
1998 if (ISD::isNormalLoad(N)) {
1999 ExpandRes_NormalLoad(N, Lo, Hi);
2000 return;
2001 }
2002
2003 assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!");
2004 LoadSDNode *LD = cast<LoadSDNode>(N);
2005 SDValue Chain = LD->getChain();
2006 SDValue Ptr = LD->getBasePtr();
2007 SDLoc dl(N);
2008
2009 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0));
2010 assert(NVT.isByteSized() && "Expanded type not byte sized!");
2011 assert(LD->getMemoryVT().bitsLE(NVT) && "Float type not round?");
2012
2013 Hi = DAG.getExtLoad(LD->getExtensionType(), dl, NVT, Chain, Ptr,
2014 LD->getMemoryVT(), LD->getMemOperand());
2015
2016 // Remember the chain.
2017 Chain = Hi.getValue(1);
2018
2019 // The low part is zero.
2020 Lo = DAG.getConstantFP(APFloat::getZero(NVT.getFltSemantics()), dl, NVT);
2021
2022 // Modified the chain - switch anything that used the old chain to use the
2023 // new one.
2024 ReplaceValueWith(SDValue(LD, 1), Chain);
2025}
2026
2027void DAGTypeLegalizer::ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo,
2028 SDValue &Hi) {
2029 assert(N->getValueType(0) == MVT::ppcf128 && "Unsupported XINT_TO_FP!");
2030 EVT VT = N->getValueType(0);
2031 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
2032 bool Strict = N->isStrictFPOpcode();
2033 SDValue Src = N->getOperand(Strict ? 1 : 0);
2034 EVT SrcVT = Src.getValueType();
2035 bool isSigned = N->getOpcode() == ISD::SINT_TO_FP ||
2036 N->getOpcode() == ISD::STRICT_SINT_TO_FP;
2037 SDLoc dl(N);
2038 SDValue Chain = Strict ? N->getOperand(0) : DAG.getEntryNode();
2039
2040 // TODO: Any other flags to propagate?
2041 SDNodeFlags Flags;
2042 Flags.setNoFPExcept(N->getFlags().hasNoFPExcept());
2043
2044 // First do an SINT_TO_FP, whether the original was signed or unsigned.
2045 // When promoting partial word types to i32 we must honor the signedness,
2046 // though.
2047 if (SrcVT.bitsLE(MVT::i32)) {
2048 // The integer can be represented exactly in an f64.
2049 Lo = DAG.getConstantFP(APFloat::getZero(NVT.getFltSemantics()), dl, NVT);
2050 if (Strict) {
2051 Hi = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(NVT, MVT::Other),
2052 {Chain, Src}, Flags);
2053 Chain = Hi.getValue(1);
2054 } else
2055 Hi = DAG.getNode(N->getOpcode(), dl, NVT, Src);
2056 } else {
2057 RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
2058 if (SrcVT.bitsLE(MVT::i64)) {
2059 Src = DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, dl,
2060 MVT::i64, Src);
2061 LC = RTLIB::SINTTOFP_I64_PPCF128;
2062 } else if (SrcVT.bitsLE(MVT::i128)) {
2063 Src = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i128, Src);
2064 LC = RTLIB::SINTTOFP_I128_PPCF128;
2065 }
2066 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!");
2067
2068 TargetLowering::MakeLibCallOptions CallOptions;
2069 CallOptions.setIsSigned(true);
2070 std::pair<SDValue, SDValue> Tmp =
2071 TLI.makeLibCall(DAG, LC, VT, Src, CallOptions, dl, Chain);
2072 if (Strict)
2073 Chain = Tmp.second;
2074 GetPairElements(Tmp.first, Lo, Hi);
2075 }
2076
2077 // No need to complement for unsigned 32-bit integers
2078 if (isSigned || SrcVT.bitsLE(MVT::i32)) {
2079 if (Strict)
2080 ReplaceValueWith(SDValue(N, 1), Chain);
2081
2082 return;
2083 }
2084
2085 // Unsigned - fix up the SINT_TO_FP value just calculated.
2086 // FIXME: For unsigned i128 to ppc_fp128 conversion, we need to carefully
2087 // keep semantics correctness if the integer is not exactly representable
2088 // here. See ExpandLegalINT_TO_FP.
2089 Hi = DAG.getNode(ISD::BUILD_PAIR, dl, VT, Lo, Hi);
2090 SrcVT = Src.getValueType();
2091
2092 // x>=0 ? (ppcf128)(iN)x : (ppcf128)(iN)x + 2^N; N=32,64,128.
2093 static const uint64_t TwoE32[] = { 0x41f0000000000000LL, 0 };
2094 static const uint64_t TwoE64[] = { 0x43f0000000000000LL, 0 };
2095 static const uint64_t TwoE128[] = { 0x47f0000000000000LL, 0 };
2096 ArrayRef<uint64_t> Parts;
2097
2098 switch (SrcVT.getSimpleVT().SimpleTy) {
2099 default:
2100 llvm_unreachable("Unsupported UINT_TO_FP!");
2101 case MVT::i32:
2102 Parts = TwoE32;
2103 break;
2104 case MVT::i64:
2105 Parts = TwoE64;
2106 break;
2107 case MVT::i128:
2108 Parts = TwoE128;
2109 break;
2110 }
2111
2112 // TODO: Are there other fast-math-flags to propagate to this FADD?
2113 SDValue NewLo = DAG.getConstantFP(
2114 APFloat(APFloat::PPCDoubleDouble(), APInt(128, Parts)), dl, MVT::ppcf128);
2115 if (Strict) {
2116 Lo = DAG.getNode(ISD::STRICT_FADD, dl, DAG.getVTList(VT, MVT::Other),
2117 {Chain, Hi, NewLo}, Flags);
2118 Chain = Lo.getValue(1);
2119 ReplaceValueWith(SDValue(N, 1), Chain);
2120 } else
2121 Lo = DAG.getNode(ISD::FADD, dl, VT, Hi, NewLo);
2122 Lo = DAG.getSelectCC(dl, Src, DAG.getConstant(0, dl, SrcVT),
2123 Lo, Hi, ISD::SETLT);
2124 GetPairElements(Lo, Lo, Hi);
2125}
2126
2127
2128//===----------------------------------------------------------------------===//
2129// Float Operand Expansion
2130//===----------------------------------------------------------------------===//
2131
2132/// ExpandFloatOperand - This method is called when the specified operand of the
2133/// specified node is found to need expansion. At this point, all of the result
2134/// types of the node are known to be legal, but other operands of the node may
2135/// need promotion or expansion as well as the specified one.
2136bool DAGTypeLegalizer::ExpandFloatOperand(SDNode *N, unsigned OpNo) {
2137 LLVM_DEBUG(dbgs() << "Expand float operand: "; N->dump(&DAG));
2138 SDValue Res = SDValue();
2139
2140 // See if the target wants to custom expand this node.
2141 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
2142 return false;
2143
2144 switch (N->getOpcode()) {
2145 default:
2146#ifndef NDEBUG
2147 dbgs() << "ExpandFloatOperand Op #" << OpNo << ": ";
2148 N->dump(&DAG); dbgs() << "\n";
2149#endif
2150 report_fatal_error("Do not know how to expand this operator's operand!");
2151
2152 case ISD::BITCAST: Res = ExpandOp_BITCAST(N); break;
2153 case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break;
2154 case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break;
2155
2156 case ISD::BR_CC: Res = ExpandFloatOp_BR_CC(N); break;
2157 case ISD::FCOPYSIGN: Res = ExpandFloatOp_FCOPYSIGN(N); break;
2159 case ISD::FP_ROUND: Res = ExpandFloatOp_FP_ROUND(N); break;
2162 case ISD::FP_TO_SINT:
2163 case ISD::FP_TO_UINT: Res = ExpandFloatOp_FP_TO_XINT(N); break;
2164 case ISD::LROUND: Res = ExpandFloatOp_LROUND(N); break;
2165 case ISD::LLROUND: Res = ExpandFloatOp_LLROUND(N); break;
2166 case ISD::LRINT: Res = ExpandFloatOp_LRINT(N); break;
2167 case ISD::LLRINT: Res = ExpandFloatOp_LLRINT(N); break;
2168 case ISD::SELECT_CC: Res = ExpandFloatOp_SELECT_CC(N); break;
2169 case ISD::STRICT_FSETCC:
2171 case ISD::SETCC: Res = ExpandFloatOp_SETCC(N); break;
2172 case ISD::STORE: Res = ExpandFloatOp_STORE(cast<StoreSDNode>(N),
2173 OpNo); break;
2174 }
2175
2176 // If the result is null, the sub-method took care of registering results etc.
2177 if (!Res.getNode()) return false;
2178
2179 // If the result is N, the sub-method updated N in place. Tell the legalizer
2180 // core about this.
2181 if (Res.getNode() == N)
2182 return true;
2183
2184 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
2185 "Invalid operand expansion");
2186
2187 ReplaceValueWith(SDValue(N, 0), Res);
2188 return false;
2189}
2190
2191/// FloatExpandSetCCOperands - Expand the operands of a comparison. This code
2192/// is shared among BR_CC, SELECT_CC, and SETCC handlers.
2193void DAGTypeLegalizer::FloatExpandSetCCOperands(SDValue &NewLHS,
2194 SDValue &NewRHS,
2195 ISD::CondCode &CCCode,
2196 const SDLoc &dl, SDValue &Chain,
2197 bool IsSignaling) {
2198 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
2199 GetExpandedFloat(NewLHS, LHSLo, LHSHi);
2200 GetExpandedFloat(NewRHS, RHSLo, RHSHi);
2201
2202 assert(NewLHS.getValueType() == MVT::ppcf128 && "Unsupported setcc type!");
2203
2204 // FIXME: This generated code sucks. We want to generate
2205 // FCMPU crN, hi1, hi2
2206 // BNE crN, L:
2207 // FCMPU crN, lo1, lo2
2208 // The following can be improved, but not that much.
2209 SDValue Tmp1, Tmp2, Tmp3, OutputChain;
2210 Tmp1 = DAG.getSetCC(dl, getSetCCResultType(LHSHi.getValueType()), LHSHi,
2211 RHSHi, ISD::SETOEQ, Chain, IsSignaling);
2212 OutputChain = Tmp1->getNumValues() > 1 ? Tmp1.getValue(1) : SDValue();
2213 Tmp2 = DAG.getSetCC(dl, getSetCCResultType(LHSLo.getValueType()), LHSLo,
2214 RHSLo, CCCode, OutputChain, IsSignaling);
2215 OutputChain = Tmp2->getNumValues() > 1 ? Tmp2.getValue(1) : SDValue();
2216 Tmp3 = DAG.getNode(ISD::AND, dl, Tmp1.getValueType(), Tmp1, Tmp2);
2217 Tmp1 =
2218 DAG.getSetCC(dl, getSetCCResultType(LHSHi.getValueType()), LHSHi, RHSHi,
2219 ISD::SETUNE, OutputChain, IsSignaling);
2220 OutputChain = Tmp1->getNumValues() > 1 ? Tmp1.getValue(1) : SDValue();
2221 Tmp2 = DAG.getSetCC(dl, getSetCCResultType(LHSHi.getValueType()), LHSHi,
2222 RHSHi, CCCode, OutputChain, IsSignaling);
2223 OutputChain = Tmp2->getNumValues() > 1 ? Tmp2.getValue(1) : SDValue();
2224 Tmp1 = DAG.getNode(ISD::AND, dl, Tmp1.getValueType(), Tmp1, Tmp2);
2225 NewLHS = DAG.getNode(ISD::OR, dl, Tmp1.getValueType(), Tmp1, Tmp3);
2226 NewRHS = SDValue(); // LHS is the result, not a compare.
2227 Chain = OutputChain;
2228}
2229
2230SDValue DAGTypeLegalizer::ExpandFloatOp_BR_CC(SDNode *N) {
2231 SDValue NewLHS = N->getOperand(2), NewRHS = N->getOperand(3);
2232 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(1))->get();
2233 SDValue Chain;
2234 FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, SDLoc(N), Chain);
2235
2236 // If ExpandSetCCOperands returned a scalar, we need to compare the result
2237 // against zero to select between true and false values.
2238 if (!NewRHS.getNode()) {
2239 NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
2240 CCCode = ISD::SETNE;
2241 }
2242
2243 // Update N to have the operands specified.
2244 return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0),
2245 DAG.getCondCode(CCCode), NewLHS, NewRHS,
2246 N->getOperand(4)), 0);
2247}
2248
2249SDValue DAGTypeLegalizer::ExpandFloatOp_FCOPYSIGN(SDNode *N) {
2250 assert(N->getOperand(1).getValueType() == MVT::ppcf128 &&
2251 "Logic only correct for ppcf128!");
2252 SDValue Lo, Hi;
2253 GetExpandedFloat(N->getOperand(1), Lo, Hi);
2254 // The ppcf128 value is providing only the sign; take it from the
2255 // higher-order double (which must have the larger magnitude).
2256 return DAG.getNode(ISD::FCOPYSIGN, SDLoc(N),
2257 N->getValueType(0), N->getOperand(0), Hi);
2258}
2259
2260SDValue DAGTypeLegalizer::ExpandFloatOp_FP_ROUND(SDNode *N) {
2261 bool IsStrict = N->isStrictFPOpcode();
2262 assert(N->getOperand(IsStrict ? 1 : 0).getValueType() == MVT::ppcf128 &&
2263 "Logic only correct for ppcf128!");
2264 SDValue Lo, Hi;
2265 GetExpandedFloat(N->getOperand(IsStrict ? 1 : 0), Lo, Hi);
2266
2267 if (!IsStrict)
2268 // Round it the rest of the way (e.g. to f32) if needed.
2269 return DAG.getNode(ISD::FP_ROUND, SDLoc(N),
2270 N->getValueType(0), Hi, N->getOperand(1));
2271
2272 // Eliminate the node if the input float type is the same as the output float
2273 // type.
2274 if (Hi.getValueType() == N->getValueType(0)) {
2275 // Connect the output chain to the input chain, unlinking the node.
2276 ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
2277 ReplaceValueWith(SDValue(N, 0), Hi);
2278 return SDValue();
2279 }
2280
2281 SDValue Expansion = DAG.getNode(ISD::STRICT_FP_ROUND, SDLoc(N),
2282 {N->getValueType(0), MVT::Other},
2283 {N->getOperand(0), Hi, N->getOperand(2)});
2284 ReplaceValueWith(SDValue(N, 1), Expansion.getValue(1));
2285 ReplaceValueWith(SDValue(N, 0), Expansion);
2286 return SDValue();
2287}
2288
2289SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_XINT(SDNode *N) {
2290 EVT RVT = N->getValueType(0);
2291 SDLoc dl(N);
2292
2293 bool IsStrict = N->isStrictFPOpcode();
2294 bool Signed = N->getOpcode() == ISD::FP_TO_SINT ||
2295 N->getOpcode() == ISD::STRICT_FP_TO_SINT;
2296 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
2297 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
2298
2299 EVT NVT;
2300 RTLIB::Libcall LC = findFPToIntLibcall(Op.getValueType(), RVT, NVT, Signed);
2301 assert(LC != RTLIB::UNKNOWN_LIBCALL && NVT.isSimple() &&
2302 "Unsupported FP_TO_XINT!");
2303 TargetLowering::MakeLibCallOptions CallOptions;
2304 std::pair<SDValue, SDValue> Tmp =
2305 TLI.makeLibCall(DAG, LC, NVT, Op, CallOptions, dl, Chain);
2306 if (!IsStrict)
2307 return Tmp.first;
2308
2309 ReplaceValueWith(SDValue(N, 1), Tmp.second);
2310 ReplaceValueWith(SDValue(N, 0), Tmp.first);
2311 return SDValue();
2312}
2313
2314SDValue DAGTypeLegalizer::ExpandFloatOp_SELECT_CC(SDNode *N) {
2315 SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
2316 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(4))->get();
2317 SDValue Chain;
2318 FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, SDLoc(N), Chain);
2319
2320 // If ExpandSetCCOperands returned a scalar, we need to compare the result
2321 // against zero to select between true and false values.
2322 if (!NewRHS.getNode()) {
2323 NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
2324 CCCode = ISD::SETNE;
2325 }
2326
2327 // Update N to have the operands specified.
2328 return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
2329 N->getOperand(2), N->getOperand(3),
2330 DAG.getCondCode(CCCode)), 0);
2331}
2332
2333SDValue DAGTypeLegalizer::ExpandFloatOp_SETCC(SDNode *N) {
2334 bool IsStrict = N->isStrictFPOpcode();
2335 SDValue NewLHS = N->getOperand(IsStrict ? 1 : 0);
2336 SDValue NewRHS = N->getOperand(IsStrict ? 2 : 1);
2337 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
2338 ISD::CondCode CCCode =
2339 cast<CondCodeSDNode>(N->getOperand(IsStrict ? 3 : 2))->get();
2340 FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, SDLoc(N), Chain,
2341 N->getOpcode() == ISD::STRICT_FSETCCS);
2342
2343 // FloatExpandSetCCOperands always returned a scalar.
2344 assert(!NewRHS.getNode() && "Expect to return scalar");
2345 assert(NewLHS.getValueType() == N->getValueType(0) &&
2346 "Unexpected setcc expansion!");
2347 if (Chain) {
2348 ReplaceValueWith(SDValue(N, 0), NewLHS);
2349 ReplaceValueWith(SDValue(N, 1), Chain);
2350 return SDValue();
2351 }
2352 return NewLHS;
2353}
2354
2355SDValue DAGTypeLegalizer::ExpandFloatOp_STORE(SDNode *N, unsigned OpNo) {
2356 if (ISD::isNormalStore(N))
2357 return ExpandOp_NormalStore(N, OpNo);
2358
2359 assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!");
2360 assert(OpNo == 1 && "Can only expand the stored value so far");
2361 StoreSDNode *ST = cast<StoreSDNode>(N);
2362
2363 SDValue Chain = ST->getChain();
2364 SDValue Ptr = ST->getBasePtr();
2365
2366 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(),
2367 ST->getValue().getValueType());
2368 assert(NVT.isByteSized() && "Expanded type not byte sized!");
2369 assert(ST->getMemoryVT().bitsLE(NVT) && "Float type not round?");
2370 (void)NVT;
2371
2372 SDValue Lo, Hi;
2373 GetExpandedOp(ST->getValue(), Lo, Hi);
2374
2375 return DAG.getTruncStore(Chain, SDLoc(N), Hi, Ptr,
2376 ST->getMemoryVT(), ST->getMemOperand());
2377}
2378
2379SDValue DAGTypeLegalizer::ExpandFloatOp_XRINT_XROUND(SDNode *N,
2380 RTLIB::Libcall LC) {
2381 EVT RVT = N->getValueType(0);
2382 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
2383 if (LCImpl == RTLIB::Unsupported) {
2384 DAG.getContext()->emitError(Twine("no libcall available for ") +
2385 N->getOperationName(&DAG));
2386 return DAG.getPOISON(RVT);
2387 }
2388
2389 TargetLowering::MakeLibCallOptions CallOptions;
2390 return TLI
2391 .makeLibCall(DAG, LCImpl, RVT, N->getOperand(0), CallOptions, SDLoc(N))
2392 .first;
2393}
2394
2395SDValue DAGTypeLegalizer::ExpandFloatOp_LROUND(SDNode *N) {
2396 EVT RetVT = N->getOperand(0).getValueType();
2397 return ExpandFloatOp_XRINT_XROUND(
2398 N, GetFPLibCall(RetVT, RTLIB::LROUND_F32, RTLIB::LROUND_F64,
2399 RTLIB::LROUND_F80, RTLIB::LROUND_F128,
2400 RTLIB::LROUND_PPCF128));
2401}
2402
2403SDValue DAGTypeLegalizer::ExpandFloatOp_LLROUND(SDNode *N) {
2404 EVT RetVT = N->getOperand(0).getValueType();
2405 return ExpandFloatOp_XRINT_XROUND(
2406 N, GetFPLibCall(RetVT, RTLIB::LLROUND_F32, RTLIB::LLROUND_F64,
2407 RTLIB::LLROUND_F80, RTLIB::LLROUND_F128,
2408 RTLIB::LLROUND_PPCF128));
2409}
2410
2411SDValue DAGTypeLegalizer::ExpandFloatOp_LRINT(SDNode *N) {
2412 EVT RetVT = N->getOperand(0).getValueType();
2413 return ExpandFloatOp_XRINT_XROUND(
2414 N,
2415 GetFPLibCall(RetVT, RTLIB::LRINT_F32, RTLIB::LRINT_F64, RTLIB::LRINT_F80,
2416 RTLIB::LRINT_F128, RTLIB::LRINT_PPCF128));
2417}
2418
2419SDValue DAGTypeLegalizer::ExpandFloatOp_LLRINT(SDNode *N) {
2420 EVT RetVT = N->getOperand(0).getValueType();
2421 return ExpandFloatOp_XRINT_XROUND(
2422 N, GetFPLibCall(RetVT, RTLIB::LLRINT_F32, RTLIB::LLRINT_F64,
2423 RTLIB::LLRINT_F80, RTLIB::LLRINT_F128,
2424 RTLIB::LLRINT_PPCF128));
2425}
2426
2427//===----------------------------------------------------------------------===//
2428// Float Operand Promotion
2429//===----------------------------------------------------------------------===//
2430//
2431
2433 if (OpVT == MVT::f16)
2434 return ISD::FP16_TO_FP;
2435 if (RetVT == MVT::f16)
2436 return ISD::FP_TO_FP16;
2437 if (OpVT == MVT::bf16)
2438 return ISD::BF16_TO_FP;
2439 if (RetVT == MVT::bf16)
2440 return ISD::FP_TO_BF16;
2441 report_fatal_error("Attempt at an invalid promotion-related conversion");
2442}
2443
2445 if (OpVT == MVT::f16)
2447 if (RetVT == MVT::f16)
2449 if (OpVT == MVT::bf16)
2451 if (RetVT == MVT::bf16)
2453 report_fatal_error("Attempt at an invalid promotion-related conversion");
2454}
2455
2456SDValue DAGTypeLegalizer::BitcastToInt_ATOMIC_SWAP(SDNode *N) {
2457 AtomicSDNode *AM = cast<AtomicSDNode>(N);
2458 SDLoc SL(N);
2459
2460 SDValue CastVal = BitConvertToInteger(AM->getVal());
2461 EVT CastVT = CastVal.getValueType();
2462
2463 SDValue NewAtomic
2464 = DAG.getAtomic(ISD::ATOMIC_SWAP, SL, CastVT,
2465 DAG.getVTList(CastVT, MVT::Other),
2466 { AM->getChain(), AM->getBasePtr(), CastVal },
2467 AM->getMemOperand());
2468
2469 SDValue Result = NewAtomic;
2470
2471 // Legalize the chain result by replacing uses of the old value chain with the
2472 // new one
2473 ReplaceValueWith(SDValue(N, 1), NewAtomic.getValue(1));
2474
2475 return Result;
2476}
2477
2478//===----------------------------------------------------------------------===//
2479// Half Result Soft Promotion
2480//===----------------------------------------------------------------------===//
2481
2482void DAGTypeLegalizer::SoftPromoteHalfResult(SDNode *N, unsigned ResNo) {
2483 LLVM_DEBUG(dbgs() << "Soft promote half result " << ResNo << ": ";
2484 N->dump(&DAG));
2485 SDValue R = SDValue();
2486
2487 // See if the target wants to custom expand this node.
2488 if (CustomLowerNode(N, N->getValueType(ResNo), true)) {
2489 LLVM_DEBUG(dbgs() << "Node has been custom expanded, done\n");
2490 return;
2491 }
2492
2493 switch (N->getOpcode()) {
2494 default:
2495#ifndef NDEBUG
2496 dbgs() << "SoftPromoteHalfResult #" << ResNo << ": ";
2497 N->dump(&DAG); dbgs() << "\n";
2498#endif
2499 report_fatal_error("Do not know how to soft promote this operator's "
2500 "result!");
2501
2502 case ISD::ARITH_FENCE:
2503 R = SoftPromoteHalfRes_ARITH_FENCE(N); break;
2504 case ISD::BITCAST: R = SoftPromoteHalfRes_BITCAST(N); break;
2505 case ISD::ConstantFP: R = SoftPromoteHalfRes_ConstantFP(N); break;
2507 R = SoftPromoteHalfRes_EXTRACT_VECTOR_ELT(N); break;
2508 case ISD::FCOPYSIGN: R = SoftPromoteHalfRes_FCOPYSIGN(N); break;
2510 case ISD::FP_ROUND: R = SoftPromoteHalfRes_FP_ROUND(N); break;
2511
2512 // Unary FP Operations
2513 case ISD::FACOS:
2514 case ISD::FASIN:
2515 case ISD::FATAN:
2516 case ISD::FCBRT:
2517 case ISD::FCEIL:
2518 case ISD::FCOS:
2519 case ISD::FCOSH:
2520 case ISD::FEXP:
2521 case ISD::FEXP2:
2522 case ISD::FEXP10:
2523 case ISD::FFLOOR:
2524 case ISD::FLOG:
2525 case ISD::FLOG2:
2526 case ISD::FLOG10:
2527 case ISD::FNEARBYINT:
2528 case ISD::FREEZE:
2529 case ISD::FRINT:
2530 case ISD::FROUND:
2531 case ISD::FROUNDEVEN:
2532 case ISD::FSIN:
2533 case ISD::FSINH:
2534 case ISD::FSQRT:
2535 case ISD::FTRUNC:
2536 case ISD::FTAN:
2537 case ISD::FTANH:
2538 case ISD::FCANONICALIZE: R = SoftPromoteHalfRes_UnaryOp(N); break;
2539 case ISD::FABS:
2540 R = SoftPromoteHalfRes_FABS(N);
2541 break;
2542 case ISD::FNEG:
2543 R = SoftPromoteHalfRes_FNEG(N);
2544 break;
2546 R = SoftPromoteHalfRes_AssertNoFPClass(N);
2547 break;
2548
2549 // Binary FP Operations
2550 case ISD::FADD:
2551 case ISD::FDIV:
2552 case ISD::FMAXIMUM:
2553 case ISD::FMINIMUM:
2554 case ISD::FMAXIMUMNUM:
2555 case ISD::FMINIMUMNUM:
2556 case ISD::FMAXNUM:
2557 case ISD::FMINNUM:
2558 case ISD::FMUL:
2559 case ISD::FPOW:
2560 case ISD::FATAN2:
2561 case ISD::FREM:
2562 case ISD::FSUB: R = SoftPromoteHalfRes_BinOp(N); break;
2563
2564 case ISD::FMA: // FMA is same as FMAD
2565 case ISD::FMAD: R = SoftPromoteHalfRes_FMAD(N); break;
2566
2567 case ISD::FPOWI:
2568 case ISD::FLDEXP: R = SoftPromoteHalfRes_ExpOp(N); break;
2569
2570 case ISD::FFREXP: R = SoftPromoteHalfRes_FFREXP(N); break;
2571
2572 case ISD::FMODF:
2573 case ISD::FSINCOS:
2574 case ISD::FSINCOSPI:
2575 R = SoftPromoteHalfRes_UnaryWithTwoFPResults(N);
2576 break;
2577
2578 case ISD::LOAD: R = SoftPromoteHalfRes_LOAD(N); break;
2579 case ISD::ATOMIC_LOAD:
2580 R = SoftPromoteHalfRes_ATOMIC_LOAD(N);
2581 break;
2582 case ISD::SELECT: R = SoftPromoteHalfRes_SELECT(N); break;
2583 case ISD::SELECT_CC: R = SoftPromoteHalfRes_SELECT_CC(N); break;
2586 case ISD::SINT_TO_FP:
2587 case ISD::UINT_TO_FP: R = SoftPromoteHalfRes_XINT_TO_FP(N); break;
2589 R = SoftPromoteHalfRes_CONVERT_FROM_ARBITRARY_FP(N);
2590 break;
2591 case ISD::POISON:
2592 case ISD::UNDEF: R = SoftPromoteHalfRes_UNDEF(N); break;
2593 case ISD::ATOMIC_SWAP: R = BitcastToInt_ATOMIC_SWAP(N); break;
2602 R = SoftPromoteHalfRes_VECREDUCE(N);
2603 break;
2606 R = SoftPromoteHalfRes_VECREDUCE_SEQ(N);
2607 break;
2608 }
2609
2610 if (R.getNode())
2611 SetSoftPromotedHalf(SDValue(N, ResNo), R);
2612}
2613
2614SDValue DAGTypeLegalizer::SoftPromoteHalfRes_ARITH_FENCE(SDNode *N) {
2615 return DAG.getNode(ISD::ARITH_FENCE, SDLoc(N), MVT::i16,
2616 BitConvertToInteger(N->getOperand(0)));
2617}
2618
2619SDValue DAGTypeLegalizer::SoftPromoteHalfRes_BITCAST(SDNode *N) {
2620 return BitConvertToInteger(N->getOperand(0));
2621}
2622
2623SDValue DAGTypeLegalizer::SoftPromoteHalfRes_ConstantFP(SDNode *N) {
2624 ConstantFPSDNode *CN = cast<ConstantFPSDNode>(N);
2625
2626 // Get the (bit-cast) APInt of the APFloat and build an integer constant
2627 return DAG.getConstant(CN->getValueAPF().bitcastToAPInt(), SDLoc(CN),
2628 MVT::i16);
2629}
2630
2631SDValue DAGTypeLegalizer::SoftPromoteHalfRes_EXTRACT_VECTOR_ELT(SDNode *N) {
2632 SDValue NewOp = BitConvertVectorToIntegerVector(N->getOperand(0));
2633 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
2634 NewOp.getValueType().getVectorElementType(), NewOp,
2635 N->getOperand(1));
2636}
2637
2638SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FCOPYSIGN(SDNode *N) {
2639 SDValue LHS = GetSoftPromotedHalf(N->getOperand(0));
2640 SDValue RHS = BitConvertToInteger(N->getOperand(1));
2641 SDLoc dl(N);
2642
2643 EVT LVT = LHS.getValueType();
2644 EVT RVT = RHS.getValueType();
2645
2646 unsigned LSize = LVT.getSizeInBits();
2647 unsigned RSize = RVT.getSizeInBits();
2648
2649 // First get the sign bit of second operand.
2650 SDValue SignBit = DAG.getNode(
2651 ISD::SHL, dl, RVT, DAG.getConstant(1, dl, RVT),
2652 DAG.getConstant(RSize - 1, dl,
2653 TLI.getShiftAmountTy(RVT, DAG.getDataLayout())));
2654 SignBit = DAG.getNode(ISD::AND, dl, RVT, RHS, SignBit);
2655
2656 // Shift right or sign-extend it if the two operands have different types.
2657 int SizeDiff = RVT.getSizeInBits() - LVT.getSizeInBits();
2658 if (SizeDiff > 0) {
2659 SignBit =
2660 DAG.getNode(ISD::SRL, dl, RVT, SignBit,
2661 DAG.getConstant(SizeDiff, dl,
2662 TLI.getShiftAmountTy(SignBit.getValueType(),
2663 DAG.getDataLayout())));
2664 SignBit = DAG.getNode(ISD::TRUNCATE, dl, LVT, SignBit);
2665 } else if (SizeDiff < 0) {
2666 SignBit = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, SignBit);
2667 SignBit =
2668 DAG.getNode(ISD::SHL, dl, LVT, SignBit,
2669 DAG.getConstant(-SizeDiff, dl,
2670 TLI.getShiftAmountTy(SignBit.getValueType(),
2671 DAG.getDataLayout())));
2672 }
2673
2674 // Clear the sign bit of the first operand.
2675 SDValue Mask = DAG.getNode(
2676 ISD::SHL, dl, LVT, DAG.getConstant(1, dl, LVT),
2677 DAG.getConstant(LSize - 1, dl,
2678 TLI.getShiftAmountTy(LVT, DAG.getDataLayout())));
2679 Mask = DAG.getNode(ISD::SUB, dl, LVT, Mask, DAG.getConstant(1, dl, LVT));
2680 LHS = DAG.getNode(ISD::AND, dl, LVT, LHS, Mask);
2681
2682 // Or the value with the sign bit.
2683 return DAG.getNode(ISD::OR, dl, LVT, LHS, SignBit);
2684}
2685
2686SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FMAD(SDNode *N) {
2687 EVT OVT = N->getValueType(0);
2688 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2689 SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
2690 SDValue Op1 = GetSoftPromotedHalf(N->getOperand(1));
2691 SDValue Op2 = GetSoftPromotedHalf(N->getOperand(2));
2692 SDNodeFlags Flags = N->getFlags();
2693 SDLoc dl(N);
2694
2695 // Promote to the larger FP type.
2696 auto PromotionOpcode = GetPromotionOpcode(OVT, NVT);
2697 Op0 = DAG.getNode(PromotionOpcode, dl, NVT, Op0);
2698 Op1 = DAG.getNode(PromotionOpcode, dl, NVT, Op1);
2699 Op2 = DAG.getNode(PromotionOpcode, dl, NVT, Op2);
2700
2701 SDValue Res;
2702 if (OVT == MVT::f16) {
2703 // If f16 fma is not natively supported, the value must be promoted to an
2704 // f64 (and not to f32!) to prevent double rounding issues.
2705 SDValue A64 = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Op0, Flags);
2706 SDValue B64 = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Op1, Flags);
2707 SDValue C64 = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Op2, Flags);
2708
2709 // Prefer a wide FMA node if available; otherwise expand to mul+add.
2710 SDValue WideRes;
2711 if (TLI.isFMAFasterThanFMulAndFAdd(DAG.getMachineFunction(), MVT::f64)) {
2712 WideRes = DAG.getNode(ISD::FMA, dl, MVT::f64, A64, B64, C64, Flags);
2713 } else {
2714 SDValue Mul = DAG.getNode(ISD::FMUL, dl, MVT::f64, A64, B64, Flags);
2715 WideRes = DAG.getNode(ISD::FADD, dl, MVT::f64, Mul, C64, Flags);
2716 }
2717
2718 return DAG.getNode(GetPromotionOpcode(MVT::f64, OVT), dl, MVT::i16,
2719 WideRes);
2720 }
2721
2722 Res = DAG.getNode(N->getOpcode(), dl, NVT, Op0, Op1, Op2, Flags);
2723 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
2724}
2725
2726SDValue DAGTypeLegalizer::SoftPromoteHalfRes_ExpOp(SDNode *N) {
2727 EVT OVT = N->getValueType(0);
2728 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2729 SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
2730 SDValue Op1 = N->getOperand(1);
2731 SDLoc dl(N);
2732
2733 // Promote to the larger FP type.
2734 Op0 = DAG.getNode(GetPromotionOpcode(OVT, NVT), dl, NVT, Op0);
2735
2736 SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, Op0, Op1);
2737
2738 // Convert back to FP16 as an integer.
2739 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
2740}
2741
2742SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FFREXP(SDNode *N) {
2743 EVT OVT = N->getValueType(0);
2744 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2745 SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
2746 SDLoc dl(N);
2747
2748 // Promote to the larger FP type.
2749 Op = DAG.getNode(GetPromotionOpcode(OVT, NVT), dl, NVT, Op);
2750
2751 SDValue Res = DAG.getNode(N->getOpcode(), dl,
2752 DAG.getVTList(NVT, N->getValueType(1)), Op);
2753
2754 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
2755
2756 // Convert back to FP16 as an integer.
2757 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
2758}
2759
2760SDValue DAGTypeLegalizer::SoftPromoteHalfRes_UnaryWithTwoFPResults(SDNode *N) {
2761 EVT OVT = N->getValueType(0);
2762 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2763 SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
2764 SDLoc dl(N);
2765
2766 // Promote to the larger FP type.
2767 Op = DAG.getNode(GetPromotionOpcode(OVT, NVT), dl, NVT, Op);
2768 SDValue Res = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(NVT, NVT), Op);
2769
2770 // Convert back to FP16 as an integer.
2771 ISD::NodeType Truncate = GetPromotionOpcode(NVT, OVT);
2772 for (unsigned ResNum = 0, NumValues = N->getNumValues(); ResNum < NumValues;
2773 ++ResNum) {
2774 SDValue Trunc = DAG.getNode(Truncate, dl, MVT::i16, Res.getValue(ResNum));
2775 SetSoftPromotedHalf(SDValue(N, ResNum), Trunc);
2776 }
2777
2778 return SDValue();
2779}
2780
2781SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FP_ROUND(SDNode *N) {
2782 EVT RVT = N->getValueType(0);
2783 bool IsStrict = N->isStrictFPOpcode();
2784 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
2785 EVT SVT = Op.getValueType();
2786
2787 // If the input type needs to be softened, do that now so that call lowering
2788 // will see the f16 type.
2789 if (getTypeAction(SVT) == TargetLowering::TypeSoftenFloat) {
2790 RTLIB::Libcall LC = RTLIB::getFPROUND(SVT, RVT);
2791 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_ROUND libcall");
2792
2793 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
2794 Op = GetSoftenedFloat(Op);
2795 TargetLowering::MakeLibCallOptions CallOptions;
2796 CallOptions.setTypeListBeforeSoften(SVT, RVT);
2797 std::pair<SDValue, SDValue> Tmp =
2798 TLI.makeLibCall(DAG, LC, RVT, Op, CallOptions, SDLoc(N), Chain);
2799 if (IsStrict)
2800 ReplaceValueWith(SDValue(N, 1), Tmp.second);
2801 return DAG.getNode(ISD::BITCAST, SDLoc(N), MVT::i16, Tmp.first);
2802 }
2803
2804 if (IsStrict) {
2805 SDValue Res = DAG.getNode(GetPromotionOpcodeStrict(SVT, RVT), SDLoc(N),
2806 {MVT::i16, MVT::Other}, {N->getOperand(0), Op});
2807 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
2808 return Res;
2809 }
2810
2811 return DAG.getNode(GetPromotionOpcode(SVT, RVT), SDLoc(N), MVT::i16,
2812 N->getOperand(0));
2813}
2814
2815SDValue DAGTypeLegalizer::SoftPromoteHalfRes_LOAD(SDNode *N) {
2816 LoadSDNode *L = cast<LoadSDNode>(N);
2817
2818 // Load the value as an integer value with the same number of bits.
2819 assert(L->getExtensionType() == ISD::NON_EXTLOAD && "Unexpected extension!");
2820 SDValue NewL =
2821 DAG.getLoad(L->getAddressingMode(), L->getExtensionType(), MVT::i16,
2822 SDLoc(N), L->getChain(), L->getBasePtr(), L->getOffset(),
2823 L->getPointerInfo(), MVT::i16, L->getBaseAlign(),
2824 L->getMemOperand()->getFlags(), L->getAAInfo());
2825 // Legalize the chain result by replacing uses of the old value chain with the
2826 // new one
2827 ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
2828 return NewL;
2829}
2830
2831SDValue DAGTypeLegalizer::SoftPromoteHalfRes_ATOMIC_LOAD(SDNode *N) {
2832 AtomicSDNode *AM = cast<AtomicSDNode>(N);
2833
2834 // Load the value as an integer value with the same number of bits.
2835 SDValue NewL = DAG.getAtomic(
2836 ISD::ATOMIC_LOAD, SDLoc(N), MVT::i16, DAG.getVTList(MVT::i16, MVT::Other),
2837 {AM->getChain(), AM->getBasePtr()}, AM->getMemOperand());
2838
2839 // Legalize the chain result by replacing uses of the old value chain with the
2840 // new one
2841 ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
2842 return NewL;
2843}
2844
2845SDValue DAGTypeLegalizer::SoftPromoteHalfRes_SELECT(SDNode *N) {
2846 SDValue Op1 = GetSoftPromotedHalf(N->getOperand(1));
2847 SDValue Op2 = GetSoftPromotedHalf(N->getOperand(2));
2848 return DAG.getSelect(SDLoc(N), Op1.getValueType(), N->getOperand(0), Op1, Op2,
2849 N->getFlags());
2850}
2851
2852SDValue DAGTypeLegalizer::SoftPromoteHalfRes_SELECT_CC(SDNode *N) {
2853 SDValue Op2 = GetSoftPromotedHalf(N->getOperand(2));
2854 SDValue Op3 = GetSoftPromotedHalf(N->getOperand(3));
2855 return DAG.getNode(ISD::SELECT_CC, SDLoc(N), Op2.getValueType(),
2856 N->getOperand(0), N->getOperand(1), Op2, Op3,
2857 N->getOperand(4));
2858}
2859
2860SDValue DAGTypeLegalizer::SoftPromoteHalfRes_XINT_TO_FP(SDNode *N) {
2861 EVT OVT = N->getValueType(0);
2862 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2863 SDLoc dl(N);
2864
2865 if (N->isStrictFPOpcode()) {
2866 SDValue Op = DAG.getNode(N->getOpcode(), dl, {NVT, MVT::Other},
2867 {N->getOperand(0), N->getOperand(1)});
2868 Op = DAG.getNode(GetPromotionOpcodeStrict(NVT, OVT), dl,
2869 {MVT::i16, MVT::Other}, {Op.getValue(1), Op});
2870 ReplaceValueWith(SDValue(N, 1), Op.getValue(1));
2871 return Op;
2872 }
2873
2874 SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, N->getOperand(0));
2875
2876 // Round the value to the softened type.
2877 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
2878}
2879
2880SDValue
2881DAGTypeLegalizer::SoftPromoteHalfRes_CONVERT_FROM_ARBITRARY_FP(SDNode *N) {
2882 EVT OVT = N->getValueType(0);
2883 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2884 SDLoc dl(N);
2885
2887 N->getOperand(0), N->getOperand(1));
2888
2889 // Round the value to the softened type.
2890 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
2891}
2892
2893SDValue DAGTypeLegalizer::SoftPromoteHalfRes_UNDEF(SDNode *N) {
2894 return DAG.getUNDEF(MVT::i16);
2895}
2896
2897SDValue DAGTypeLegalizer::SoftPromoteHalfRes_UnaryOp(SDNode *N) {
2898 EVT OVT = N->getValueType(0);
2899 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2900 SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
2901 SDLoc dl(N);
2902
2903 // Promote to the larger FP type.
2904 Op = DAG.getNode(GetPromotionOpcode(OVT, NVT), dl, NVT, Op);
2905
2906 SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, Op);
2907
2908 // Convert back to FP16 as an integer.
2909 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
2910}
2911
2912SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FABS(SDNode *N) {
2913 SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
2914 SDLoc dl(N);
2915
2916 // Clear the sign bit.
2917 return DAG.getNode(ISD::AND, dl, MVT::i16, Op,
2918 DAG.getConstant(0x7fff, dl, MVT::i16));
2919}
2920
2921SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FNEG(SDNode *N) {
2922 SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
2923 SDLoc dl(N);
2924
2925 // Invert the sign bit.
2926 return DAG.getNode(ISD::XOR, dl, MVT::i16, Op,
2927 DAG.getConstant(0x8000, dl, MVT::i16));
2928}
2929
2930SDValue DAGTypeLegalizer::SoftPromoteHalfRes_AssertNoFPClass(SDNode *N) {
2931 return GetSoftPromotedHalf(N->getOperand(0));
2932}
2933
2934SDValue DAGTypeLegalizer::SoftPromoteHalfRes_BinOp(SDNode *N) {
2935 EVT OVT = N->getValueType(0);
2936 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2937 SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
2938 SDValue Op1 = GetSoftPromotedHalf(N->getOperand(1));
2939 SDLoc dl(N);
2940
2941 // Promote to the larger FP type.
2942 auto PromotionOpcode = GetPromotionOpcode(OVT, NVT);
2943 Op0 = DAG.getNode(PromotionOpcode, dl, NVT, Op0);
2944 Op1 = DAG.getNode(PromotionOpcode, dl, NVT, Op1);
2945
2946 SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, Op0, Op1);
2947
2948 // Convert back to FP16 as an integer.
2949 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
2950}
2951
2952SDValue DAGTypeLegalizer::SoftPromoteHalfRes_VECREDUCE(SDNode *N) {
2953 // Expand and soften recursively.
2954 ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduce(N, DAG));
2955 return SDValue();
2956}
2957
2958SDValue DAGTypeLegalizer::SoftPromoteHalfRes_VECREDUCE_SEQ(SDNode *N) {
2959 // Expand and soften.
2960 ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduceSeq(N, DAG));
2961 return SDValue();
2962}
2963
2964//===----------------------------------------------------------------------===//
2965// Half Operand Soft Promotion
2966//===----------------------------------------------------------------------===//
2967
2968bool DAGTypeLegalizer::SoftPromoteHalfOperand(SDNode *N, unsigned OpNo) {
2969 LLVM_DEBUG(dbgs() << "Soft promote half operand " << OpNo << ": ";
2970 N->dump(&DAG));
2971 SDValue Res = SDValue();
2972
2973 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false)) {
2974 LLVM_DEBUG(dbgs() << "Node has been custom lowered, done\n");
2975 return false;
2976 }
2977
2978 // Nodes that use a promotion-requiring floating point operand, but doesn't
2979 // produce a soft promotion-requiring floating point result, need to be
2980 // legalized to use the soft promoted float operand. Nodes that produce at
2981 // least one soft promotion-requiring floating point result have their
2982 // operands legalized as a part of PromoteFloatResult.
2983 switch (N->getOpcode()) {
2984 default:
2985 #ifndef NDEBUG
2986 dbgs() << "SoftPromoteHalfOperand Op #" << OpNo << ": ";
2987 N->dump(&DAG); dbgs() << "\n";
2988 #endif
2989 report_fatal_error("Do not know how to soft promote this operator's "
2990 "operand!");
2991
2992 case ISD::BITCAST: Res = SoftPromoteHalfOp_BITCAST(N); break;
2993 case ISD::BUILD_VECTOR:
2994 Res = SoftPromoteHalfOp_BUILD_VECTOR(N);
2995 break;
2996 case ISD::FAKE_USE:
2997 Res = SoftPromoteHalfOp_FAKE_USE(N, OpNo);
2998 break;
2999 case ISD::FCOPYSIGN:
3000 Res = SoftPromoteHalfOp_FCOPYSIGN(N, OpNo);
3001 break;
3002 case ISD::FP_TO_SINT:
3003 case ISD::FP_TO_UINT:
3006 case ISD::LLRINT:
3007 case ISD::LLROUND:
3008 case ISD::LRINT:
3009 case ISD::LROUND:
3010 case ISD::STRICT_LLRINT:
3012 case ISD::STRICT_LRINT:
3013 case ISD::STRICT_LROUND:
3014 Res = SoftPromoteHalfOp_Op0WithStrict(N);
3015 break;
3018 Res = SoftPromoteHalfOp_FP_TO_XINT_SAT(N); break;
3020 Res = SoftPromoteHalfOp_CONVERT_TO_ARBITRARY_FP(N);
3021 break;
3023 case ISD::FP_EXTEND: Res = SoftPromoteHalfOp_FP_EXTEND(N); break;
3024 case ISD::SELECT_CC: Res = SoftPromoteHalfOp_SELECT_CC(N, OpNo); break;
3025 case ISD::BR_CC:
3026 Res = SoftPromoteHalfOp_BR_CC(N);
3027 break;
3028 case ISD::SETCC: Res = SoftPromoteHalfOp_SETCC(N); break;
3029 case ISD::STORE: Res = SoftPromoteHalfOp_STORE(N, OpNo); break;
3030 case ISD::ATOMIC_STORE:
3031 Res = SoftPromoteHalfOp_ATOMIC_STORE(N, OpNo);
3032 break;
3033 case ISD::STACKMAP:
3034 Res = SoftPromoteHalfOp_STACKMAP(N, OpNo);
3035 break;
3036 case ISD::PATCHPOINT:
3037 Res = SoftPromoteHalfOp_PATCHPOINT(N, OpNo);
3038 break;
3039 }
3040
3041 if (!Res.getNode())
3042 return false;
3043
3044 assert(Res.getNode() != N && "Expected a new node!");
3045
3046 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
3047 "Invalid operand expansion");
3048
3049 ReplaceValueWith(SDValue(N, 0), Res);
3050 return false;
3051}
3052
3053SDValue DAGTypeLegalizer::SoftPromoteHalfOp_BITCAST(SDNode *N) {
3054 SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
3055
3056 return DAG.getNode(ISD::BITCAST, SDLoc(N), N->getValueType(0), Op0);
3057}
3058
3059SDValue DAGTypeLegalizer::SoftPromoteHalfOp_BUILD_VECTOR(SDNode *N) {
3060 SDLoc dl(N);
3061 EVT VT = N->getValueType(0);
3062
3063 SmallVector<SDValue, 8> Ops(N->getNumOperands());
3064 for (unsigned I = 0, E = N->getNumOperands(); I != E; ++I)
3065 Ops[I] = GetSoftPromotedHalf(N->getOperand(I));
3066
3067 EVT IVT = VT.changeVectorElementTypeToInteger();
3068 SDValue Res = DAG.getBuildVector(IVT, dl, Ops);
3069 return DAG.getBitcast(VT, Res);
3070}
3071
3072SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FAKE_USE(SDNode *N, unsigned OpNo) {
3073 assert(OpNo == 1 && "Only Operand 1 must need promotion here");
3074 SDValue Op = GetSoftPromotedHalf(N->getOperand(OpNo));
3075 return DAG.getNode(N->getOpcode(), SDLoc(N), MVT::Other, N->getOperand(0),
3076 Op);
3077}
3078
3079SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FCOPYSIGN(SDNode *N,
3080 unsigned OpNo) {
3081 assert(OpNo == 1 && "Only Operand 1 must need promotion here");
3082 SDValue Op1 = N->getOperand(1);
3083 EVT RVT = Op1.getValueType();
3084 SDLoc dl(N);
3085
3086 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op1.getValueType());
3087
3088 Op1 = GetSoftPromotedHalf(Op1);
3089 Op1 = DAG.getNode(GetPromotionOpcode(RVT, NVT), dl, NVT, Op1);
3090
3091 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0), N->getOperand(0),
3092 Op1);
3093}
3094
3095SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_EXTEND(SDNode *N) {
3096 EVT RVT = N->getValueType(0);
3097 bool IsStrict = N->isStrictFPOpcode();
3098 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
3099 EVT SVT = Op.getValueType();
3100 Op = GetSoftPromotedHalf(N->getOperand(IsStrict ? 1 : 0));
3101
3102 if (IsStrict) {
3103 SDValue Res = DAG.getNode(GetPromotionOpcodeStrict(SVT, RVT), SDLoc(N),
3104 {RVT, MVT::Other}, {N->getOperand(0), Op});
3105 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
3106 ReplaceValueWith(SDValue(N, 0), Res);
3107 return SDValue();
3108 }
3109
3110 return DAG.getNode(GetPromotionOpcode(SVT, RVT), SDLoc(N), RVT, Op);
3111}
3112
3113SDValue DAGTypeLegalizer::SoftPromoteHalfOp_Op0WithStrict(SDNode *N) {
3114 EVT RVT = N->getValueType(0);
3115 bool IsStrict = N->isStrictFPOpcode();
3116 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
3117 EVT SVT = Op.getValueType();
3118 SDLoc dl(N);
3119
3120 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), SVT);
3121 Op = GetSoftPromotedHalf(Op);
3122
3123 if (IsStrict) {
3124 Op = DAG.getNode(GetPromotionOpcodeStrict(SVT, RVT), dl, {NVT, MVT::Other},
3125 {N->getOperand(0), Op});
3126 Op = DAG.getNode(N->getOpcode(), dl, {RVT, MVT::Other},
3127 {Op.getValue(1), Op});
3128 ReplaceValueWith(SDValue(N, 1), Op.getValue(1));
3129 ReplaceValueWith(SDValue(N, 0), Op);
3130 return SDValue();
3131 }
3132
3133 SDValue Res = DAG.getNode(GetPromotionOpcode(SVT, RVT), dl, NVT, Op);
3134 return DAG.getNode(N->getOpcode(), dl, RVT, Res);
3135}
3136
3137SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_TO_XINT_SAT(SDNode *N) {
3138 EVT RVT = N->getValueType(0);
3139 SDValue Op = N->getOperand(0);
3140 EVT SVT = Op.getValueType();
3141 SDLoc dl(N);
3142
3143 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType());
3144
3145 Op = GetSoftPromotedHalf(Op);
3146
3147 SDValue Res = DAG.getNode(GetPromotionOpcode(SVT, RVT), dl, NVT, Op);
3148
3149 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0), Res,
3150 N->getOperand(1));
3151}
3152
3153// TODO: CONVERT_TO_ARBITRARY_FP also needs SoftenFloatOperand and
3154// ExpandFloatOperand handlers for targets with software float or ppcf128
3155// source types. Same gap exists for CONVERT_FROM_ARBITRARY_FP.
3156SDValue DAGTypeLegalizer::SoftPromoteHalfOp_CONVERT_TO_ARBITRARY_FP(SDNode *N) {
3157 EVT RVT = N->getValueType(0);
3158 SDValue Op = N->getOperand(0);
3159 EVT SVT = Op.getValueType();
3160 SDLoc dl(N);
3161
3162 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType());
3163 Op = GetSoftPromotedHalf(Op);
3164 SDValue Res = DAG.getNode(GetPromotionOpcode(SVT, RVT), dl, NVT, Op);
3165
3166 return DAG.getNode(ISD::CONVERT_TO_ARBITRARY_FP, dl, N->getValueType(0), Res,
3167 N->getOperand(1), N->getOperand(2), N->getOperand(3));
3168}
3169
3170SDValue DAGTypeLegalizer::SoftPromoteHalfOp_BR_CC(SDNode *N) {
3171 // ISD::BR_CC node: chain(0), condcode(1), LHS(2), RHS(3), dest(4)
3172 // The comparison operands (LHS, RHS) are soft-promoted halfs.
3173 SDValue Op0 = N->getOperand(2);
3174 SDValue Op1 = N->getOperand(3);
3175 SDLoc dl(N);
3176
3177 EVT SVT = Op0.getValueType();
3178 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), SVT);
3179
3180 // Get the soft-promoted i16 values
3181 Op0 = GetSoftPromotedHalf(Op0);
3182 Op1 = GetSoftPromotedHalf(Op1);
3183
3184 // Promote both comparison operands to the larger FP type.
3185 unsigned PromotionOpcode = GetPromotionOpcode(SVT, NVT);
3186 Op0 = DAG.getNode(PromotionOpcode, dl, NVT, Op0);
3187 Op1 = DAG.getNode(PromotionOpcode, dl, NVT, Op1);
3188
3189 // Create a new BR_CC node with promoted operands
3190 return DAG.getNode(ISD::BR_CC, dl, MVT::Other, N->getOperand(0),
3191 N->getOperand(1), Op0, Op1, N->getOperand(4));
3192}
3193
3194SDValue DAGTypeLegalizer::SoftPromoteHalfOp_SELECT_CC(SDNode *N,
3195 unsigned OpNo) {
3196 assert(OpNo == 0 && "Can only soften the comparison values");
3197 SDValue Op0 = N->getOperand(0);
3198 SDValue Op1 = N->getOperand(1);
3199 SDLoc dl(N);
3200
3201 EVT SVT = Op0.getValueType();
3202 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), SVT);
3203
3204 Op0 = GetSoftPromotedHalf(Op0);
3205 Op1 = GetSoftPromotedHalf(Op1);
3206
3207 // Promote to the larger FP type.
3208 auto PromotionOpcode = GetPromotionOpcode(SVT, NVT);
3209 Op0 = DAG.getNode(PromotionOpcode, dl, NVT, Op0);
3210 Op1 = DAG.getNode(PromotionOpcode, dl, NVT, Op1);
3211
3212 return DAG.getNode(ISD::SELECT_CC, SDLoc(N), N->getValueType(0), Op0, Op1,
3213 N->getOperand(2), N->getOperand(3), N->getOperand(4));
3214}
3215
3216SDValue DAGTypeLegalizer::SoftPromoteHalfOp_SETCC(SDNode *N) {
3217 SDValue Op0 = N->getOperand(0);
3218 SDValue Op1 = N->getOperand(1);
3219 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(2))->get();
3220 SDLoc dl(N);
3221
3222 EVT SVT = Op0.getValueType();
3223 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op0.getValueType());
3224
3225 Op0 = GetSoftPromotedHalf(Op0);
3226 Op1 = GetSoftPromotedHalf(Op1);
3227
3228 // Promote to the larger FP type.
3229 auto PromotionOpcode = GetPromotionOpcode(SVT, NVT);
3230 Op0 = DAG.getNode(PromotionOpcode, dl, NVT, Op0);
3231 Op1 = DAG.getNode(PromotionOpcode, dl, NVT, Op1);
3232
3233 return DAG.getSetCC(SDLoc(N), N->getValueType(0), Op0, Op1, CCCode);
3234}
3235
3236SDValue DAGTypeLegalizer::SoftPromoteHalfOp_STORE(SDNode *N, unsigned OpNo) {
3237 assert(OpNo == 1 && "Can only soften the stored value!");
3238 StoreSDNode *ST = cast<StoreSDNode>(N);
3239 SDValue Val = ST->getValue();
3240 SDLoc dl(N);
3241
3242 assert(!ST->isTruncatingStore() && "Unexpected truncating store.");
3243 SDValue Promoted = GetSoftPromotedHalf(Val);
3244 return DAG.getStore(ST->getChain(), dl, Promoted, ST->getBasePtr(),
3245 ST->getMemOperand());
3246}
3247
3248SDValue DAGTypeLegalizer::SoftPromoteHalfOp_ATOMIC_STORE(SDNode *N,
3249 unsigned OpNo) {
3250 assert(OpNo == 1 && "Can only soften the stored value!");
3251 AtomicSDNode *ST = cast<AtomicSDNode>(N);
3252 SDValue Val = ST->getVal();
3253 SDLoc dl(N);
3254
3255 SDValue Promoted = GetSoftPromotedHalf(Val);
3256 return DAG.getAtomic(ISD::ATOMIC_STORE, dl, Promoted.getValueType(),
3257 ST->getChain(), Promoted, ST->getBasePtr(),
3258 ST->getMemOperand());
3259}
3260
3261SDValue DAGTypeLegalizer::SoftPromoteHalfOp_STACKMAP(SDNode *N, unsigned OpNo) {
3262 assert(OpNo > 1); // Because the first two arguments are guaranteed legal.
3263 SmallVector<SDValue> NewOps(N->ops());
3264 SDValue Op = N->getOperand(OpNo);
3265 NewOps[OpNo] = GetSoftPromotedHalf(Op);
3267 DAG.getNode(N->getOpcode(), SDLoc(N), N->getVTList(), NewOps);
3268
3269 for (unsigned ResNum = 0; ResNum < N->getNumValues(); ResNum++)
3270 ReplaceValueWith(SDValue(N, ResNum), NewNode.getValue(ResNum));
3271
3272 return SDValue(); // Signal that we replaced the node ourselves.
3273}
3274
3275SDValue DAGTypeLegalizer::SoftPromoteHalfOp_PATCHPOINT(SDNode *N,
3276 unsigned OpNo) {
3277 assert(OpNo >= 7);
3278 SmallVector<SDValue> NewOps(N->ops());
3279 SDValue Op = N->getOperand(OpNo);
3280 NewOps[OpNo] = GetSoftPromotedHalf(Op);
3282 DAG.getNode(N->getOpcode(), SDLoc(N), N->getVTList(), NewOps);
3283
3284 for (unsigned ResNum = 0; ResNum < N->getNumValues(); ResNum++)
3285 ReplaceValueWith(SDValue(N, ResNum), NewNode.getValue(ResNum));
3286
3287 return SDValue(); // Signal that we replaced the node ourselves.
3288}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
DXIL Intrinsic Expansion
static bool isSigned(unsigned Opcode)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static RTLIB::Libcall findFPToIntLibcall(EVT SrcVT, EVT RetVT, EVT &Promoted, bool Signed)
static RTLIB::Libcall GetFPLibCall(EVT VT, RTLIB::Libcall Call_F32, RTLIB::Libcall Call_F64, RTLIB::Libcall Call_F80, RTLIB::Libcall Call_F128, RTLIB::Libcall Call_PPCF128)
GetFPLibCall - Return the right libcall for the given floating point type.
static ISD::NodeType GetPromotionOpcode(EVT OpVT, EVT RetVT)
static ISD::NodeType GetPromotionOpcodeStrict(EVT OpVT, EVT RetVT)
#define I(x, y, z)
Definition MD5.cpp:57
static Type * getValueType(Value *V, bool LookThroughCmp=false)
Returns the "element type" of the given value/instruction V.
#define LLVM_DEBUG(...)
Definition Debug.h:119
Value * RHS
Value * LHS
static const fltSemantics & PPCDoubleDouble()
Definition APFloat.h:307
APInt bitcastToAPInt() const
Definition APFloat.h:1475
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Definition APFloat.h:1183
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
Definition APInt.h:231
void clearBit(unsigned BitPosition)
Set a given bit to 0.
Definition APInt.h:1427
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
Definition APInt.h:226
const uint64_t * getRawData() const
This function returns a pointer to the internal storage of the APInt.
Definition APInt.h:572
const SDValue & getVal() const
const APFloat & getValueAPF() const
@ NewNode
This is a new node, not before seen, that was created in the process of legalizing some other node.
SimpleValueType SimpleTy
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOInvariant
The memory access always returns the same value (or traps).
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
bool isStrictFPOpcode()
Test if this node is a strict floating point pseudo-op.
SDNodeFlags getFlags() const
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
void push_back(const T &Elt)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
Definition ISDOpcodes.h:41
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:829
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
Definition ISDOpcodes.h:261
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
Definition ISDOpcodes.h:513
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:236
@ VECREDUCE_SEQ_FADD
Generic reduction nodes.
@ VECREDUCE_FMINIMUMNUM
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ FMAD
FMAD - Perform a * b + c, while getting the same result as the separately rounded operations.
Definition ISDOpcodes.h:524
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:863
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:520
@ FMODF
FMODF - Decomposes the operand into integral and fractional parts, each having the same type and sign...
@ FATAN2
FATAN2 - atan2, inspired by libm.
@ FSINCOSPI
FSINCOSPI - Compute both the sine and cosine times pi more accurately than FSINCOS(pi*x),...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:890
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:417
@ VECREDUCE_FMAXIMUM
FMINIMUM/FMAXIMUM nodes propatate NaNs and signed zeroes using the llvm.minimum and llvm....
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ FAKE_USE
FAKE_USE represents a use of the operand but does not do anything.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
Definition ISDOpcodes.h:254
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
Definition ISDOpcodes.h:438
@ CONVERT_FROM_ARBITRARY_FP
CONVERT_FROM_ARBITRARY_FP - This operator converts from an arbitrary floating-point represented as an...
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:854
@ STRICT_UINT_TO_FP
Definition ISDOpcodes.h:487
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ VECREDUCE_FMAXIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM nodes do not propagate NaNs and order signed zeroes using the llvm....
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition ISDOpcodes.h:543
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:806
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:233
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
Definition ISDOpcodes.h:247
@ ARITH_FENCE
ARITH_FENCE - This corresponds to a arithmetic fence intrinsic.
@ STRICT_FP_TO_FP16
@ STRICT_FP16_TO_FP
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:771
@ AssertNoFPClass
AssertNoFPClass - These nodes record if a register contains a float value that is known to be not som...
Definition ISDOpcodes.h:78
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:578
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:860
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:821
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ PATCHPOINT
The llvm.experimental.patchpoint.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:988
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
Definition ISDOpcodes.h:486
@ STRICT_BF16_TO_FP
@ STRICT_FROUNDEVEN
Definition ISDOpcodes.h:466
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ STRICT_FP_TO_UINT
Definition ISDOpcodes.h:480
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
Definition ISDOpcodes.h:502
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:479
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:936
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:507
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
@ STRICT_FP_TO_BF16
@ STRICT_FADD
Constrained versions of the binary floating point operators.
Definition ISDOpcodes.h:427
@ STACKMAP
The llvm.experimental.stackmap intrinsic.
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
Definition ISDOpcodes.h:241
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:969
@ STRICT_FNEARBYINT
Definition ISDOpcodes.h:458
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
Definition ISDOpcodes.h:955
@ VECREDUCE_FMINIMUM
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:866
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ VECREDUCE_SEQ_FMUL
@ CONVERT_TO_ARBITRARY_FP
CONVERT_TO_ARBITRARY_FP - Converts a native FP value to an arbitrary floating-point format,...
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:536
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:558
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isUNINDEXEDLoad(const SDNode *N)
Returns true if the specified node is an unindexed load.
bool isUNINDEXEDStore(const SDNode *N)
Returns true if the specified node is an unindexed store.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
void * PointerTy
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ Mul
Product of integers.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
#define N
Extended Value Type.
Definition ValueTypes.h:35
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
Definition ValueTypes.h:90
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition ValueTypes.h:145
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
bool isByteSized() const
Return true if the bit size is a multiple of 8.
Definition ValueTypes.h:266
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:339
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
Definition ValueTypes.h:61
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
Definition ValueTypes.h:315
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
Definition ValueTypes.h:331
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
void setNoFPExcept(bool b)
MakeLibCallOptions & setTypeListBeforeSoften(ArrayRef< EVT > OpsVT, EVT RetVT)
MakeLibCallOptions & setIsSigned(bool Value=true)