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 CallOptions.setIsSigned();
698 std::pair<SDValue, SDValue> Tmp =
699 TLI.makeLibCall(DAG, LCImpl, NVT, Ops, CallOptions, SDLoc(N), Chain);
700 if (IsStrict)
701 ReplaceValueWith(SDValue(N, 1), Tmp.second);
702 return Tmp.first;
703}
704
705SDValue DAGTypeLegalizer::SoftenFloatRes_FFREXP(SDNode *N) {
706 assert(!N->isStrictFPOpcode() && "strictfp not implemented for frexp");
707 EVT VT0 = N->getValueType(0);
708 EVT VT1 = N->getValueType(1);
709 RTLIB::Libcall LC = RTLIB::getFREXP(VT0);
710 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
711 EVT NVT0 = TLI.getTypeToTransformTo(*DAG.getContext(), VT0);
712 SDLoc DL(N);
713
714 if (LCImpl == RTLIB::Unsupported) {
715 DAG.getContext()->emitError(Twine("no libcall available for ") +
716 N->getOperationName(&DAG));
717 SDValue PoisonExp = DAG.getPOISON(VT1);
718 ReplaceValueWith(SDValue(N, 1), PoisonExp);
719 return DAG.getMergeValues({DAG.getPOISON(NVT0), PoisonExp}, DL);
720 }
721
722 if (DAG.getLibInfo().getIntSize() != VT1.getSizeInBits()) {
723 // If the exponent does not match with sizeof(int) a libcall would use the
724 // wrong type for the argument.
725 // TODO: Should be able to handle mismatches.
726 DAG.getContext()->emitError("ffrexp exponent does not match sizeof(int)");
727 SDValue PoisonExp = DAG.getPOISON(VT1);
728 ReplaceValueWith(SDValue(N, 1), PoisonExp);
729 return DAG.getMergeValues({DAG.getPOISON(NVT0), PoisonExp}, DL);
730 }
731
732 SDValue StackSlot = DAG.CreateStackTemporary(VT1);
733
734 auto PointerTy = PointerType::getUnqual(*DAG.getContext());
735 TargetLowering::MakeLibCallOptions CallOptions;
736 SDValue Ops[2] = {GetSoftenedFloat(N->getOperand(0)), StackSlot};
737 EVT OpsVT[2] = {VT0, StackSlot.getValueType()};
738 Type *CallOpsTypeOverrides[2] = {nullptr, PointerTy};
739
740 // TODO: setTypeListBeforeSoften can't properly express multiple return types,
741 // but we only really need to handle the 0th one for softening anyway.
742 CallOptions.setTypeListBeforeSoften({OpsVT}, VT0)
743 .setOpsTypeOverrides(CallOpsTypeOverrides);
744
745 auto [ReturnVal, Chain] = TLI.makeLibCall(DAG, LCImpl, NVT0, Ops, CallOptions,
746 DL, /*Chain=*/SDValue());
747 int FrameIdx = cast<FrameIndexSDNode>(StackSlot)->getIndex();
748 auto PtrInfo =
749 MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FrameIdx);
750
751 SDValue LoadExp = DAG.getLoad(VT1, DL, Chain, StackSlot, PtrInfo);
752
753 ReplaceValueWith(SDValue(N, 1), LoadExp);
754 return ReturnVal;
755}
756
757bool DAGTypeLegalizer::SoftenFloatRes_UnaryWithTwoFPResults(
758 SDNode *N, RTLIB::Libcall LC, std::optional<unsigned> CallRetResNo) {
759 assert(!N->isStrictFPOpcode() && "strictfp not implemented");
760 EVT VT = N->getValueType(0);
761
762 assert(VT == N->getValueType(1) &&
763 "expected both return values to have the same type");
764
765 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
766 if (LCImpl == RTLIB::Unsupported)
767 return false;
768
769 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
770
771 SDLoc DL(N);
772
773 SmallVector<SDValue, 3> Ops = {GetSoftenedFloat(N->getOperand(0))};
774 SmallVector<EVT, 3> OpsVT = {VT};
775
776 std::array<SDValue, 2> StackSlots;
777 SmallVector<Type *, 3> CallOpsTypeOverrides = {nullptr};
778 auto PointerTy = PointerType::getUnqual(*DAG.getContext());
779 for (unsigned ResNum = 0; ResNum < N->getNumValues(); ++ResNum) {
780 if (ResNum == CallRetResNo)
781 continue;
782 SDValue StackSlot = DAG.CreateStackTemporary(NVT);
783 Ops.push_back(StackSlot);
784 OpsVT.push_back(StackSlot.getValueType());
785 StackSlots[ResNum] = StackSlot;
786 CallOpsTypeOverrides.push_back(PointerTy);
787 }
788
789 TargetLowering::MakeLibCallOptions CallOptions;
790 // TODO: setTypeListBeforeSoften can't properly express multiple return types,
791 // but since both returns have the same type it should be okay.
792 CallOptions.setTypeListBeforeSoften({OpsVT}, VT)
793 .setOpsTypeOverrides(CallOpsTypeOverrides);
794
795 auto [ReturnVal, Chain] =
796 TLI.makeLibCall(DAG, LCImpl, NVT, Ops, CallOptions, DL,
797 /*Chain=*/SDValue());
798
799 auto CreateStackLoad = [&, Chain = Chain](SDValue StackSlot) {
800 int FrameIdx = cast<FrameIndexSDNode>(StackSlot)->getIndex();
801 auto PtrInfo =
802 MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FrameIdx);
803 return DAG.getLoad(NVT, DL, Chain, StackSlot, PtrInfo);
804 };
805
806 for (auto [ResNum, SlackSlot] : enumerate(StackSlots)) {
807 if (CallRetResNo == ResNum) {
808 SetSoftenedFloat(SDValue(N, ResNum), ReturnVal);
809 continue;
810 }
811 SetSoftenedFloat(SDValue(N, ResNum), CreateStackLoad(SlackSlot));
812 }
813
814 return true;
815}
816
817SDValue DAGTypeLegalizer::SoftenFloatRes_FSINCOS(SDNode *N) {
818 EVT VT = N->getValueType(0);
819 if (SoftenFloatRes_UnaryWithTwoFPResults(N, RTLIB::getSINCOS(VT)))
820 return SDValue();
821
822 // Fall back on softening the separate sin and cos calls if available.
823 RTLIB::Libcall SinLC = RTLIB::getSIN(VT);
824 RTLIB::Libcall CosLC = RTLIB::getCOS(VT);
825
826 SDValue SoftSin, SoftCos;
827 if (DAG.getLibcalls().getLibcallImpl(SinLC) == RTLIB::Unsupported ||
828 DAG.getLibcalls().getLibcallImpl(CosLC) == RTLIB::Unsupported) {
829 DAG.getContext()->emitError("do not know how to soften fsincos");
830
831 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
832 SoftSin = SoftCos = DAG.getPOISON(NVT);
833 } else {
834 SoftSin = SoftenFloatRes_Unary(N, SinLC);
835 SoftCos = SoftenFloatRes_Unary(N, CosLC);
836 }
837
838 SetSoftenedFloat(SDValue(N, 0), SoftSin);
839 SetSoftenedFloat(SDValue(N, 1), SoftCos);
840 return SDValue();
841}
842
843SDValue DAGTypeLegalizer::SoftenFloatRes_FMODF(SDNode *N) {
844 EVT VT = N->getValueType(0);
845 if (SoftenFloatRes_UnaryWithTwoFPResults(N, RTLIB::getMODF(VT),
846 /*CallRetResNo=*/0))
847 return SDValue();
848
849 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
850 DAG.getContext()->emitError("do not know how to soften fmodf");
851 SDValue Poison = DAG.getPOISON(NVT);
852 SetSoftenedFloat(SDValue(N, 0), Poison);
853 SetSoftenedFloat(SDValue(N, 1), Poison);
854 return SDValue();
855}
856
857SDValue DAGTypeLegalizer::SoftenFloatRes_FREM(SDNode *N) {
858 return SoftenFloatRes_Binary(N, RTLIB::getREM(N->getValueType(0)));
859}
860
861SDValue DAGTypeLegalizer::SoftenFloatRes_FRINT(SDNode *N) {
862 return SoftenFloatRes_Unary(N, RTLIB::getRINT(N->getValueType(0)));
863}
864
865SDValue DAGTypeLegalizer::SoftenFloatRes_FROUND(SDNode *N) {
866 return SoftenFloatRes_Unary(N, RTLIB::getROUND(N->getValueType(0)));
867}
868
869SDValue DAGTypeLegalizer::SoftenFloatRes_FROUNDEVEN(SDNode *N) {
870 return SoftenFloatRes_Unary(N, RTLIB::getROUNDEVEN(N->getValueType(0)));
871}
872
873SDValue DAGTypeLegalizer::SoftenFloatRes_FSIN(SDNode *N) {
874 return SoftenFloatRes_Unary(N, RTLIB::getSIN(N->getValueType(0)));
875}
876
877SDValue DAGTypeLegalizer::SoftenFloatRes_FSINH(SDNode *N) {
878 return SoftenFloatRes_Unary(N, RTLIB::getSINH(N->getValueType(0)));
879}
880
881SDValue DAGTypeLegalizer::SoftenFloatRes_FSQRT(SDNode *N) {
882 return SoftenFloatRes_Unary(N, RTLIB::getSQRT(N->getValueType(0)));
883}
884
885SDValue DAGTypeLegalizer::SoftenFloatRes_FSUB(SDNode *N) {
886 return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
887 RTLIB::SUB_F32,
888 RTLIB::SUB_F64,
889 RTLIB::SUB_F80,
890 RTLIB::SUB_F128,
891 RTLIB::SUB_PPCF128));
892}
893
894SDValue DAGTypeLegalizer::SoftenFloatRes_FTAN(SDNode *N) {
895 return SoftenFloatRes_Unary(N, RTLIB::getTAN(N->getValueType(0)));
896}
897
898SDValue DAGTypeLegalizer::SoftenFloatRes_FTANH(SDNode *N) {
899 return SoftenFloatRes_Unary(N, RTLIB::getTANH(N->getValueType(0)));
900}
901
902SDValue DAGTypeLegalizer::SoftenFloatRes_FTRUNC(SDNode *N) {
903 return SoftenFloatRes_Unary(N, RTLIB::getTRUNC(N->getValueType(0)));
904}
905
906SDValue DAGTypeLegalizer::SoftenFloatRes_LOAD(SDNode *N) {
907 LoadSDNode *L = cast<LoadSDNode>(N);
908 EVT VT = N->getValueType(0);
909 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
910 SDLoc dl(N);
911
912 auto MMOFlags =
913 L->getMemOperand()->getFlags() &
915 SDValue NewL;
916 if (L->getExtensionType() == ISD::NON_EXTLOAD) {
917 // If softening widens the integer representation (e.g. x86_fp80 -> i96),
918 // load the original memory width and extend to the softened type.
919 EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
920 NewL = DAG.getLoad(L->getAddressingMode(), ISD::EXTLOAD, NVT, dl,
921 L->getChain(), L->getBasePtr(), L->getOffset(),
922 L->getPointerInfo(), MemVT, L->getBaseAlign(), MMOFlags,
923 L->getAAInfo());
924 // Legalized the chain result - switch anything that used the old chain to
925 // use the new one.
926 ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
927 return NewL;
928 }
929
930 // Do a non-extending load followed by FP_EXTEND.
931 NewL = DAG.getLoad(L->getAddressingMode(), ISD::NON_EXTLOAD, L->getMemoryVT(),
932 dl, L->getChain(), L->getBasePtr(), L->getOffset(),
933 L->getPointerInfo(), L->getMemoryVT(), L->getBaseAlign(),
934 MMOFlags, L->getAAInfo());
935 // Legalized the chain result - switch anything that used the old chain to
936 // use the new one.
937 ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
938 auto ExtendNode = DAG.getNode(ISD::FP_EXTEND, dl, VT, NewL);
939 return BitConvertToInteger(ExtendNode);
940}
941
942SDValue DAGTypeLegalizer::SoftenFloatRes_ATOMIC_LOAD(SDNode *N) {
943 AtomicSDNode *L = cast<AtomicSDNode>(N);
944 EVT VT = N->getValueType(0);
945 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
946 SDLoc dl(N);
947
948 if (L->getExtensionType() == ISD::NON_EXTLOAD) {
949 SDValue NewL =
950 DAG.getAtomic(ISD::ATOMIC_LOAD, dl, NVT, DAG.getVTList(NVT, MVT::Other),
951 {L->getChain(), L->getBasePtr()}, L->getMemOperand());
952
953 // Legalized the chain result - switch anything that used the old chain to
954 // use the new one.
955 ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
956 return NewL;
957 }
958
959 report_fatal_error("softening fp extending atomic load not handled");
960}
961
962SDValue DAGTypeLegalizer::SoftenFloatRes_SELECT(SDNode *N) {
963 SDValue LHS = GetSoftenedFloat(N->getOperand(1));
964 SDValue RHS = GetSoftenedFloat(N->getOperand(2));
965 return DAG.getSelect(SDLoc(N),
966 LHS.getValueType(), N->getOperand(0), LHS, RHS);
967}
968
969SDValue DAGTypeLegalizer::SoftenFloatRes_SELECT_CC(SDNode *N) {
970 SDValue LHS = GetSoftenedFloat(N->getOperand(2));
971 SDValue RHS = GetSoftenedFloat(N->getOperand(3));
972 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
973 LHS.getValueType(), N->getOperand(0),
974 N->getOperand(1), LHS, RHS, N->getOperand(4));
975}
976
977SDValue DAGTypeLegalizer::SoftenFloatRes_UNDEF(SDNode *N) {
978 return DAG.getUNDEF(TLI.getTypeToTransformTo(*DAG.getContext(),
979 N->getValueType(0)));
980}
981
982SDValue DAGTypeLegalizer::SoftenFloatRes_VAARG(SDNode *N) {
983 SDValue Chain = N->getOperand(0); // Get the chain.
984 SDValue Ptr = N->getOperand(1); // Get the pointer.
985 EVT VT = N->getValueType(0);
986 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
987 SDLoc dl(N);
988
989 SDValue NewVAARG;
990 NewVAARG = DAG.getVAArg(NVT, dl, Chain, Ptr, N->getOperand(2),
991 N->getConstantOperandVal(3));
992
993 // Legalized the chain result - switch anything that used the old chain to
994 // use the new one.
995 if (N != NewVAARG.getValue(1).getNode())
996 ReplaceValueWith(SDValue(N, 1), NewVAARG.getValue(1));
997 return NewVAARG;
998}
999
1000SDValue DAGTypeLegalizer::SoftenFloatRes_XINT_TO_FP(SDNode *N) {
1001 bool IsStrict = N->isStrictFPOpcode();
1002 bool Signed = N->getOpcode() == ISD::SINT_TO_FP ||
1003 N->getOpcode() == ISD::STRICT_SINT_TO_FP;
1004 EVT SVT = N->getOperand(IsStrict ? 1 : 0).getValueType();
1005 EVT RVT = N->getValueType(0);
1006 EVT NVT = EVT();
1007 SDLoc dl(N);
1008
1009 // If the input is not legal, eg: i1 -> fp, then it needs to be promoted to
1010 // a larger type, eg: i8 -> fp. Even if it is legal, no libcall may exactly
1011 // match. Look for an appropriate libcall.
1012 RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
1013 for (unsigned t = MVT::FIRST_INTEGER_VALUETYPE;
1014 t <= MVT::LAST_INTEGER_VALUETYPE && LC == RTLIB::UNKNOWN_LIBCALL; ++t) {
1015 NVT = (MVT::SimpleValueType)t;
1016 // The source needs to big enough to hold the operand.
1017 if (NVT.bitsGE(SVT))
1018 LC = Signed ? RTLIB::getSINTTOFP(NVT, RVT):RTLIB::getUINTTOFP (NVT, RVT);
1019 }
1020 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!");
1021
1022 EVT NRVT = TLI.getTypeToTransformTo(*DAG.getContext(), RVT);
1023 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
1024 if (LCImpl == RTLIB::Unsupported)
1025 return SoftenFloatRes_NoLibcall(N, NRVT);
1026
1027 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1028 // Sign/zero extend the argument if the libcall takes a larger type.
1029 SDValue Op = DAG.getNode(Signed ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, dl,
1030 NVT, N->getOperand(IsStrict ? 1 : 0));
1031 TargetLowering::MakeLibCallOptions CallOptions;
1032 CallOptions.setIsSigned(Signed);
1033 CallOptions.setTypeListBeforeSoften(SVT, RVT);
1034 std::pair<SDValue, SDValue> Tmp =
1035 TLI.makeLibCall(DAG, LCImpl, NRVT, Op, CallOptions, dl, Chain);
1036
1037 if (IsStrict)
1038 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1039 return Tmp.first;
1040}
1041
1042SDValue DAGTypeLegalizer::SoftenFloatRes_VECREDUCE(SDNode *N) {
1043 // Expand and soften recursively.
1044 ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduce(N, DAG));
1045 return SDValue();
1046}
1047
1048SDValue DAGTypeLegalizer::SoftenFloatRes_VECREDUCE_SEQ(SDNode *N) {
1049 ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduceSeq(N, DAG));
1050 return SDValue();
1051}
1052
1053//===----------------------------------------------------------------------===//
1054// Convert Float Operand to Integer
1055//===----------------------------------------------------------------------===//
1056
1057bool DAGTypeLegalizer::SoftenFloatOperand(SDNode *N, unsigned OpNo) {
1058 LLVM_DEBUG(dbgs() << "Soften float operand " << OpNo << ": "; N->dump(&DAG));
1059 SDValue Res = SDValue();
1060
1061 switch (N->getOpcode()) {
1062 default:
1063#ifndef NDEBUG
1064 dbgs() << "SoftenFloatOperand Op #" << OpNo << ": ";
1065 N->dump(&DAG); dbgs() << "\n";
1066#endif
1067 report_fatal_error("Do not know how to soften this operator's operand!");
1068
1069 case ISD::BITCAST: Res = SoftenFloatOp_BITCAST(N); break;
1070 case ISD::BR_CC: Res = SoftenFloatOp_BR_CC(N); break;
1072 case ISD::FP_TO_FP16: // Same as FP_ROUND for softening purposes
1073 case ISD::FP_TO_BF16:
1076 case ISD::FP_ROUND: Res = SoftenFloatOp_FP_ROUND(N); break;
1079 case ISD::FP_TO_SINT:
1080 case ISD::FP_TO_UINT: Res = SoftenFloatOp_FP_TO_XINT(N); break;
1083 Res = SoftenFloatOp_FP_TO_XINT_SAT(N); break;
1084 case ISD::STRICT_LROUND:
1085 case ISD::LROUND: Res = SoftenFloatOp_LROUND(N); break;
1087 case ISD::LLROUND: Res = SoftenFloatOp_LLROUND(N); break;
1088 case ISD::STRICT_LRINT:
1089 case ISD::LRINT: Res = SoftenFloatOp_LRINT(N); break;
1090 case ISD::STRICT_LLRINT:
1091 case ISD::LLRINT: Res = SoftenFloatOp_LLRINT(N); break;
1092 case ISD::SELECT_CC: Res = SoftenFloatOp_SELECT_CC(N); break;
1093 case ISD::STRICT_FSETCC:
1095 case ISD::SETCC: Res = SoftenFloatOp_SETCC(N); break;
1096 case ISD::STORE: Res = SoftenFloatOp_STORE(N, OpNo); break;
1097 case ISD::ATOMIC_STORE:
1098 Res = SoftenFloatOp_ATOMIC_STORE(N, OpNo);
1099 break;
1100 case ISD::FCOPYSIGN: Res = SoftenFloatOp_FCOPYSIGN(N); break;
1101 case ISD::FAKE_USE:
1102 Res = SoftenFloatOp_FAKE_USE(N);
1103 break;
1104 case ISD::STACKMAP:
1105 Res = SoftenFloatOp_STACKMAP(N, OpNo);
1106 break;
1107 case ISD::PATCHPOINT:
1108 Res = SoftenFloatOp_PATCHPOINT(N, OpNo);
1109 break;
1110 }
1111
1112 // If the result is null, the sub-method took care of registering results etc.
1113 if (!Res.getNode()) return false;
1114
1115 // If the result is N, the sub-method updated N in place. Tell the legalizer
1116 // core about this to re-analyze.
1117 if (Res.getNode() == N)
1118 return true;
1119
1120 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
1121 "Invalid operand softening");
1122
1123 ReplaceValueWith(SDValue(N, 0), Res);
1124 return false;
1125}
1126
1127SDValue DAGTypeLegalizer::SoftenFloatOp_BITCAST(SDNode *N) {
1128 SDValue Op0 = GetSoftenedFloat(N->getOperand(0));
1129
1130 return DAG.getNode(ISD::BITCAST, SDLoc(N), N->getValueType(0), Op0);
1131}
1132
1133SDValue DAGTypeLegalizer::SoftenFloatOp_FP_ROUND(SDNode *N) {
1134 // We actually deal with the partially-softened FP_TO_FP16 node too, which
1135 // returns an i16 so doesn't meet the constraints necessary for FP_ROUND.
1136 assert(N->getOpcode() == ISD::FP_ROUND || N->getOpcode() == ISD::FP_TO_FP16 ||
1137 N->getOpcode() == ISD::STRICT_FP_TO_FP16 ||
1138 N->getOpcode() == ISD::FP_TO_BF16 ||
1139 N->getOpcode() == ISD::STRICT_FP_TO_BF16 ||
1140 N->getOpcode() == ISD::STRICT_FP_ROUND);
1141
1142 bool IsStrict = N->isStrictFPOpcode();
1143 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
1144 EVT SVT = Op.getValueType();
1145 EVT RVT = N->getValueType(0);
1146 EVT FloatRVT = RVT;
1147 if (N->getOpcode() == ISD::FP_TO_FP16 ||
1148 N->getOpcode() == ISD::STRICT_FP_TO_FP16)
1149 FloatRVT = MVT::f16;
1150 else if (N->getOpcode() == ISD::FP_TO_BF16 ||
1151 N->getOpcode() == ISD::STRICT_FP_TO_BF16)
1152 FloatRVT = MVT::bf16;
1153
1154 RTLIB::Libcall LC = RTLIB::getFPROUND(SVT, FloatRVT);
1155 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_ROUND libcall");
1156
1157 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1158 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
1159 if (LCImpl == RTLIB::Unsupported) {
1160 DAG.getContext()->emitError(Twine("no libcall available for ") +
1161 N->getOperationName(&DAG));
1162 SDValue Poison = DAG.getPOISON(RVT);
1163 if (IsStrict) {
1164 ReplaceValueWith(SDValue(N, 1), Chain);
1165 ReplaceValueWith(SDValue(N, 0), Poison);
1166 return SDValue();
1167 }
1168 return Poison;
1169 }
1170 Op = GetSoftenedFloat(Op);
1171 TargetLowering::MakeLibCallOptions CallOptions;
1172 CallOptions.setTypeListBeforeSoften(SVT, RVT);
1173 std::pair<SDValue, SDValue> Tmp =
1174 TLI.makeLibCall(DAG, LCImpl, RVT, Op, CallOptions, SDLoc(N), Chain);
1175 if (IsStrict) {
1176 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1177 ReplaceValueWith(SDValue(N, 0), Tmp.first);
1178 return SDValue();
1179 }
1180 return Tmp.first;
1181}
1182
1183SDValue DAGTypeLegalizer::SoftenFloatOp_BR_CC(SDNode *N) {
1184 SDValue NewLHS = N->getOperand(2), NewRHS = N->getOperand(3);
1185 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(1))->get();
1186
1187 EVT VT = NewLHS.getValueType();
1188 NewLHS = GetSoftenedFloat(NewLHS);
1189 NewRHS = GetSoftenedFloat(NewRHS);
1190 TLI.softenSetCCOperands(DAG, VT, NewLHS, NewRHS, CCCode, SDLoc(N),
1191 N->getOperand(2), N->getOperand(3));
1192
1193 // If softenSetCCOperands returned a scalar, we need to compare the result
1194 // against zero to select between true and false values.
1195 if (!NewRHS.getNode()) {
1196 NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
1197 CCCode = ISD::SETNE;
1198 }
1199
1200 // Update N to have the operands specified.
1201 return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0),
1202 DAG.getCondCode(CCCode), NewLHS, NewRHS,
1203 N->getOperand(4)),
1204 0);
1205}
1206
1207// Even if the result type is legal, no libcall may exactly match. (e.g. We
1208// don't have FP-i8 conversions) This helper method looks for an appropriate
1209// promoted libcall.
1210static RTLIB::Libcall findFPToIntLibcall(EVT SrcVT, EVT RetVT, EVT &Promoted,
1211 bool Signed) {
1212 RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
1213 for (unsigned IntVT = MVT::FIRST_INTEGER_VALUETYPE;
1214 IntVT <= MVT::LAST_INTEGER_VALUETYPE && LC == RTLIB::UNKNOWN_LIBCALL;
1215 ++IntVT) {
1216 Promoted = (MVT::SimpleValueType)IntVT;
1217 // The type needs to big enough to hold the result.
1218 if (Promoted.bitsGE(RetVT))
1219 LC = Signed ? RTLIB::getFPTOSINT(SrcVT, Promoted)
1220 : RTLIB::getFPTOUINT(SrcVT, Promoted);
1221 }
1222 return LC;
1223}
1224
1225SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_XINT(SDNode *N) {
1226 bool IsStrict = N->isStrictFPOpcode();
1227 bool Signed = N->getOpcode() == ISD::FP_TO_SINT ||
1228 N->getOpcode() == ISD::STRICT_FP_TO_SINT;
1229
1230 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
1231 EVT SVT = Op.getValueType();
1232 EVT RVT = N->getValueType(0);
1233 EVT NVT = EVT();
1234 SDLoc dl(N);
1235
1236 // If the result is not legal, eg: fp -> i1, then it needs to be promoted to
1237 // a larger type, eg: fp -> i32. Even if it is legal, no libcall may exactly
1238 // match, eg. we don't have fp -> i8 conversions.
1239 // Look for an appropriate libcall.
1240 RTLIB::Libcall LC = findFPToIntLibcall(SVT, RVT, NVT, Signed);
1241 assert(LC != RTLIB::UNKNOWN_LIBCALL && NVT.isSimple() &&
1242 "Unsupported FP_TO_XINT!");
1243
1244 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1245 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
1246 if (LCImpl == RTLIB::Unsupported) {
1247 DAG.getContext()->emitError(Twine("no libcall available for ") +
1248 N->getOperationName(&DAG));
1249 SDValue Poison = DAG.getPOISON(RVT);
1250 if (IsStrict) {
1251 ReplaceValueWith(SDValue(N, 1), Chain);
1252 ReplaceValueWith(SDValue(N, 0), Poison);
1253 return SDValue();
1254 }
1255 return Poison;
1256 }
1257
1258 Op = GetSoftenedFloat(Op);
1259 TargetLowering::MakeLibCallOptions CallOptions;
1260 CallOptions.setTypeListBeforeSoften(SVT, RVT);
1261 std::pair<SDValue, SDValue> Tmp =
1262 TLI.makeLibCall(DAG, LCImpl, NVT, Op, CallOptions, dl, Chain);
1263
1264 // Truncate the result if the libcall returns a larger type.
1265 SDValue Res = DAG.getNode(ISD::TRUNCATE, dl, RVT, Tmp.first);
1266
1267 if (!IsStrict)
1268 return Res;
1269
1270 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1271 ReplaceValueWith(SDValue(N, 0), Res);
1272 return SDValue();
1273}
1274
1275SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_XINT_SAT(SDNode *N) {
1276 SDValue Res = TLI.expandFP_TO_INT_SAT(N, DAG);
1277 return Res;
1278}
1279
1280SDValue DAGTypeLegalizer::SoftenFloatOp_SELECT_CC(SDNode *N) {
1281 SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
1282 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(4))->get();
1283
1284 EVT VT = NewLHS.getValueType();
1285 NewLHS = GetSoftenedFloat(NewLHS);
1286 NewRHS = GetSoftenedFloat(NewRHS);
1287 TLI.softenSetCCOperands(DAG, VT, NewLHS, NewRHS, CCCode, SDLoc(N),
1288 N->getOperand(0), N->getOperand(1));
1289
1290 // If softenSetCCOperands returned a scalar, we need to compare the result
1291 // against zero to select between true and false values.
1292 if (!NewRHS.getNode()) {
1293 NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
1294 CCCode = ISD::SETNE;
1295 }
1296
1297 // Update N to have the operands specified.
1298 return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
1299 N->getOperand(2), N->getOperand(3),
1300 DAG.getCondCode(CCCode)),
1301 0);
1302}
1303
1304SDValue DAGTypeLegalizer::SoftenFloatOp_SETCC(SDNode *N) {
1305 bool IsStrict = N->isStrictFPOpcode();
1306 SDValue Op0 = N->getOperand(IsStrict ? 1 : 0);
1307 SDValue Op1 = N->getOperand(IsStrict ? 2 : 1);
1308 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1309 ISD::CondCode CCCode =
1310 cast<CondCodeSDNode>(N->getOperand(IsStrict ? 3 : 2))->get();
1311
1312 EVT VT = Op0.getValueType();
1313 SDValue NewLHS = GetSoftenedFloat(Op0);
1314 SDValue NewRHS = GetSoftenedFloat(Op1);
1315 TLI.softenSetCCOperands(DAG, VT, NewLHS, NewRHS, CCCode, SDLoc(N), Op0, Op1,
1316 Chain, N->getOpcode() == ISD::STRICT_FSETCCS);
1317
1318 // Update N to have the operands specified.
1319 if (NewRHS.getNode()) {
1320 if (IsStrict)
1321 NewLHS = DAG.getNode(ISD::SETCC, SDLoc(N), N->getValueType(0), NewLHS,
1322 NewRHS, DAG.getCondCode(CCCode));
1323 else
1324 return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
1325 DAG.getCondCode(CCCode)), 0);
1326 }
1327
1328 // Otherwise, softenSetCCOperands returned a scalar, use it.
1329 assert((NewRHS.getNode() || NewLHS.getValueType() == N->getValueType(0)) &&
1330 "Unexpected setcc expansion!");
1331
1332 if (IsStrict) {
1333 ReplaceValueWith(SDValue(N, 0), NewLHS);
1334 ReplaceValueWith(SDValue(N, 1), Chain);
1335 return SDValue();
1336 }
1337 return NewLHS;
1338}
1339
1340SDValue DAGTypeLegalizer::SoftenFloatOp_STORE(SDNode *N, unsigned OpNo) {
1341 assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!");
1342 assert(OpNo == 1 && "Can only soften the stored value!");
1343 StoreSDNode *ST = cast<StoreSDNode>(N);
1344 SDValue Val = ST->getValue();
1345 SDLoc dl(N);
1346
1347 if (ST->isTruncatingStore())
1348 // Do an FP_ROUND followed by a non-truncating store.
1349 Val = BitConvertToInteger(
1350 DAG.getNode(ISD::FP_ROUND, dl, ST->getMemoryVT(), Val,
1351 DAG.getIntPtrConstant(0, dl, /*isTarget=*/true)));
1352 else
1353 Val = GetSoftenedFloat(Val);
1354
1355 // If softening widens the integer representation (e.g. x86_fp80 -> i96),
1356 // truncate the value before storing to preserve the original memory width.
1357 EVT MemVT =
1358 EVT::getIntegerVT(*DAG.getContext(), ST->getMemoryVT().getSizeInBits());
1359 return DAG.getTruncStore(ST->getChain(), dl, Val, ST->getBasePtr(), MemVT,
1360 ST->getMemOperand());
1361}
1362
1363SDValue DAGTypeLegalizer::SoftenFloatOp_ATOMIC_STORE(SDNode *N, unsigned OpNo) {
1364 assert(OpNo == 1 && "Can only soften the stored value!");
1365 AtomicSDNode *ST = cast<AtomicSDNode>(N);
1366 SDValue Val = ST->getVal();
1367 EVT VT = Val.getValueType();
1368 SDLoc dl(N);
1369
1370 assert(ST->getMemoryVT() == VT && "truncating atomic store not handled");
1371
1372 SDValue NewVal = GetSoftenedFloat(Val);
1373 return DAG.getAtomic(ISD::ATOMIC_STORE, dl, VT, ST->getChain(), NewVal,
1374 ST->getBasePtr(), ST->getMemOperand());
1375}
1376
1377SDValue DAGTypeLegalizer::SoftenFloatOp_FCOPYSIGN(SDNode *N) {
1378 SDValue LHS = N->getOperand(0);
1379 SDValue RHS = BitConvertToInteger(N->getOperand(1));
1380 SDLoc dl(N);
1381
1382 EVT LVT = LHS.getValueType();
1383 EVT ILVT = EVT::getIntegerVT(*DAG.getContext(), LVT.getSizeInBits());
1384 EVT RVT = RHS.getValueType();
1385
1386 unsigned LSize = LVT.getSizeInBits();
1387 unsigned RSize = RVT.getSizeInBits();
1388
1389 // Shift right or sign-extend it if the two operands have different types.
1390 int SizeDiff = RSize - LSize;
1391 if (SizeDiff > 0) {
1392 RHS =
1393 DAG.getNode(ISD::SRL, dl, RVT, RHS,
1394 DAG.getConstant(SizeDiff, dl,
1395 TLI.getShiftAmountTy(RHS.getValueType(),
1396 DAG.getDataLayout())));
1397 RHS = DAG.getNode(ISD::TRUNCATE, dl, ILVT, RHS);
1398 } else if (SizeDiff < 0) {
1399 RHS = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, RHS);
1400 RHS =
1401 DAG.getNode(ISD::SHL, dl, ILVT, RHS,
1402 DAG.getConstant(-SizeDiff, dl,
1403 TLI.getShiftAmountTy(RHS.getValueType(),
1404 DAG.getDataLayout())));
1405 }
1406
1407 RHS = DAG.getBitcast(LVT, RHS);
1408 return DAG.getNode(ISD::FCOPYSIGN, dl, LVT, LHS, RHS);
1409}
1410
1411SDValue DAGTypeLegalizer::SoftenFloatOp_Unary(SDNode *N, RTLIB::Libcall LC) {
1412 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
1413 bool IsStrict = N->isStrictFPOpcode();
1414 unsigned Offset = IsStrict ? 1 : 0;
1415 SDValue Op = GetSoftenedFloat(N->getOperand(0 + Offset));
1416 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1417 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
1418 if (LCImpl == RTLIB::Unsupported) {
1419 DAG.getContext()->emitError(Twine("no libcall available for ") +
1420 N->getOperationName(&DAG));
1421 SDValue Poison = DAG.getPOISON(N->getValueType(0));
1422 if (IsStrict) {
1423 ReplaceValueWith(SDValue(N, 1), Chain);
1424 ReplaceValueWith(SDValue(N, 0), Poison);
1425 return SDValue();
1426 }
1427 return Poison;
1428 }
1429 TargetLowering::MakeLibCallOptions CallOptions;
1430 EVT OpVT = N->getOperand(0 + Offset).getValueType();
1431 CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0));
1432 std::pair<SDValue, SDValue> Tmp =
1433 TLI.makeLibCall(DAG, LCImpl, NVT, Op, CallOptions, SDLoc(N), Chain);
1434 if (IsStrict) {
1435 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1436 ReplaceValueWith(SDValue(N, 0), Tmp.first);
1437 return SDValue();
1438 }
1439
1440 return Tmp.first;
1441}
1442
1443SDValue DAGTypeLegalizer::SoftenFloatOp_LROUND(SDNode *N) {
1444 EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1445 return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
1446 RTLIB::LROUND_F32,
1447 RTLIB::LROUND_F64,
1448 RTLIB::LROUND_F80,
1449 RTLIB::LROUND_F128,
1450 RTLIB::LROUND_PPCF128));
1451}
1452
1453SDValue DAGTypeLegalizer::SoftenFloatOp_LLROUND(SDNode *N) {
1454 EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1455 return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
1456 RTLIB::LLROUND_F32,
1457 RTLIB::LLROUND_F64,
1458 RTLIB::LLROUND_F80,
1459 RTLIB::LLROUND_F128,
1460 RTLIB::LLROUND_PPCF128));
1461}
1462
1463SDValue DAGTypeLegalizer::SoftenFloatOp_LRINT(SDNode *N) {
1464 EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1465 return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
1466 RTLIB::LRINT_F32,
1467 RTLIB::LRINT_F64,
1468 RTLIB::LRINT_F80,
1469 RTLIB::LRINT_F128,
1470 RTLIB::LRINT_PPCF128));
1471}
1472
1473SDValue DAGTypeLegalizer::SoftenFloatOp_LLRINT(SDNode *N) {
1474 EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1475 return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
1476 RTLIB::LLRINT_F32,
1477 RTLIB::LLRINT_F64,
1478 RTLIB::LLRINT_F80,
1479 RTLIB::LLRINT_F128,
1480 RTLIB::LLRINT_PPCF128));
1481}
1482
1483SDValue DAGTypeLegalizer::SoftenFloatOp_FAKE_USE(SDNode *N) {
1484 SDValue Op1 = BitConvertToInteger(N->getOperand(1));
1485 return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
1486 N->getOperand(0), Op1);
1487}
1488
1489SDValue DAGTypeLegalizer::SoftenFloatOp_STACKMAP(SDNode *N, unsigned OpNo) {
1490 assert(OpNo > 1); // Because the first two arguments are guaranteed legal.
1491 SmallVector<SDValue> NewOps(N->ops());
1492 NewOps[OpNo] = GetSoftenedFloat(NewOps[OpNo]);
1493 return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0);
1494}
1495
1496SDValue DAGTypeLegalizer::SoftenFloatOp_PATCHPOINT(SDNode *N, unsigned OpNo) {
1497 assert(OpNo >= 7);
1498 SmallVector<SDValue> NewOps(N->ops());
1499 NewOps[OpNo] = GetSoftenedFloat(NewOps[OpNo]);
1500 return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0);
1501}
1502
1503//===----------------------------------------------------------------------===//
1504// Float Result Expansion
1505//===----------------------------------------------------------------------===//
1506
1507/// ExpandFloatResult - This method is called when the specified result of the
1508/// specified node is found to need expansion. At this point, the node may also
1509/// have invalid operands or may have other results that need promotion, we just
1510/// know that (at least) one result needs expansion.
1511void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) {
1512 LLVM_DEBUG(dbgs() << "Expand float result: "; N->dump(&DAG));
1513 SDValue Lo, Hi;
1514 Lo = Hi = SDValue();
1515
1516 // See if the target wants to custom expand this node.
1517 if (CustomLowerNode(N, N->getValueType(ResNo), true))
1518 return;
1519
1520 switch (N->getOpcode()) {
1521 default:
1522#ifndef NDEBUG
1523 dbgs() << "ExpandFloatResult #" << ResNo << ": ";
1524 N->dump(&DAG); dbgs() << "\n";
1525#endif
1526 report_fatal_error("Do not know how to expand the result of this "
1527 "operator!");
1528 // clang-format off
1529 case ISD::POISON:
1530 case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
1531 case ISD::SELECT: SplitRes_Select(N, Lo, Hi); break;
1532 case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break;
1533
1534 case ISD::MERGE_VALUES: ExpandRes_MERGE_VALUES(N, ResNo, Lo, Hi); break;
1535 case ISD::BITCAST: ExpandRes_BITCAST(N, Lo, Hi); break;
1536 case ISD::BUILD_PAIR: ExpandRes_BUILD_PAIR(N, Lo, Hi); break;
1537 case ISD::EXTRACT_ELEMENT: ExpandRes_EXTRACT_ELEMENT(N, Lo, Hi); break;
1538 case ISD::EXTRACT_VECTOR_ELT: ExpandRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); break;
1539 case ISD::VAARG: ExpandRes_VAARG(N, Lo, Hi); break;
1540
1541 case ISD::ConstantFP: ExpandFloatRes_ConstantFP(N, Lo, Hi); break;
1542 case ISD::AssertNoFPClass: ExpandFloatRes_AssertNoFPClass(N, Lo, Hi); break;
1543 case ISD::FABS: ExpandFloatRes_FABS(N, Lo, Hi); break;
1545 case ISD::FMINNUM: ExpandFloatRes_FMINNUM(N, Lo, Hi); break;
1547 case ISD::FMAXNUM: ExpandFloatRes_FMAXNUM(N, Lo, Hi); break;
1548 case ISD::FMINIMUMNUM: ExpandFloatRes_FMINIMUMNUM(N, Lo, Hi); break;
1549 case ISD::FMAXIMUMNUM: ExpandFloatRes_FMAXIMUMNUM(N, Lo, Hi); break;
1550 case ISD::STRICT_FADD:
1551 case ISD::FADD: ExpandFloatRes_FADD(N, Lo, Hi); break;
1552 case ISD::STRICT_FACOS:
1553 case ISD::FACOS: ExpandFloatRes_FACOS(N, Lo, Hi); break;
1554 case ISD::STRICT_FASIN:
1555 case ISD::FASIN: ExpandFloatRes_FASIN(N, Lo, Hi); break;
1556 case ISD::STRICT_FATAN:
1557 case ISD::FATAN: ExpandFloatRes_FATAN(N, Lo, Hi); break;
1558 case ISD::STRICT_FATAN2:
1559 case ISD::FATAN2: ExpandFloatRes_FATAN2(N, Lo, Hi); break;
1560 case ISD::FCBRT: ExpandFloatRes_FCBRT(N, Lo, Hi); break;
1561 case ISD::STRICT_FCEIL:
1562 case ISD::FCEIL: ExpandFloatRes_FCEIL(N, Lo, Hi); break;
1563 case ISD::FCOPYSIGN: ExpandFloatRes_FCOPYSIGN(N, Lo, Hi); break;
1564 case ISD::STRICT_FCOS:
1565 case ISD::FCOS: ExpandFloatRes_FCOS(N, Lo, Hi); break;
1566 case ISD::STRICT_FCOSH:
1567 case ISD::FCOSH: ExpandFloatRes_FCOSH(N, Lo, Hi); break;
1568 case ISD::STRICT_FDIV:
1569 case ISD::FDIV: ExpandFloatRes_FDIV(N, Lo, Hi); break;
1570 case ISD::STRICT_FEXP:
1571 case ISD::FEXP: ExpandFloatRes_FEXP(N, Lo, Hi); break;
1572 case ISD::STRICT_FEXP2:
1573 case ISD::FEXP2: ExpandFloatRes_FEXP2(N, Lo, Hi); break;
1574 case ISD::FEXP10: ExpandFloatRes_FEXP10(N, Lo, Hi); break;
1575 case ISD::STRICT_FFLOOR:
1576 case ISD::FFLOOR: ExpandFloatRes_FFLOOR(N, Lo, Hi); break;
1577 case ISD::STRICT_FLOG:
1578 case ISD::FLOG: ExpandFloatRes_FLOG(N, Lo, Hi); break;
1579 case ISD::STRICT_FLOG2:
1580 case ISD::FLOG2: ExpandFloatRes_FLOG2(N, Lo, Hi); break;
1581 case ISD::STRICT_FLOG10:
1582 case ISD::FLOG10: ExpandFloatRes_FLOG10(N, Lo, Hi); break;
1583 case ISD::STRICT_FMA:
1584 case ISD::FMA: ExpandFloatRes_FMA(N, Lo, Hi); break;
1585 case ISD::STRICT_FMUL:
1586 case ISD::FMUL: ExpandFloatRes_FMUL(N, Lo, Hi); break;
1588 case ISD::FNEARBYINT: ExpandFloatRes_FNEARBYINT(N, Lo, Hi); break;
1589 case ISD::FNEG: ExpandFloatRes_FNEG(N, Lo, Hi); break;
1591 case ISD::FP_EXTEND: ExpandFloatRes_FP_EXTEND(N, Lo, Hi); break;
1592 case ISD::STRICT_FPOW:
1593 case ISD::FPOW: ExpandFloatRes_FPOW(N, Lo, Hi); break;
1594 case ISD::STRICT_FPOWI:
1595 case ISD::FPOWI: ExpandFloatRes_FPOWI(N, Lo, Hi); break;
1596 case ISD::FLDEXP:
1597 case ISD::STRICT_FLDEXP: ExpandFloatRes_FLDEXP(N, Lo, Hi); break;
1598 case ISD::FREEZE: ExpandFloatRes_FREEZE(N, Lo, Hi); break;
1599 case ISD::STRICT_FRINT:
1600 case ISD::FRINT: ExpandFloatRes_FRINT(N, Lo, Hi); break;
1601 case ISD::STRICT_FROUND:
1602 case ISD::FROUND: ExpandFloatRes_FROUND(N, Lo, Hi); break;
1604 case ISD::FROUNDEVEN: ExpandFloatRes_FROUNDEVEN(N, Lo, Hi); break;
1605 case ISD::STRICT_FSIN:
1606 case ISD::FSIN: ExpandFloatRes_FSIN(N, Lo, Hi); break;
1607 case ISD::STRICT_FSINH:
1608 case ISD::FSINH: ExpandFloatRes_FSINH(N, Lo, Hi); break;
1609 case ISD::STRICT_FSQRT:
1610 case ISD::FSQRT: ExpandFloatRes_FSQRT(N, Lo, Hi); break;
1611 case ISD::STRICT_FSUB:
1612 case ISD::FSUB: ExpandFloatRes_FSUB(N, Lo, Hi); break;
1613 case ISD::STRICT_FTAN:
1614 case ISD::FTAN: ExpandFloatRes_FTAN(N, Lo, Hi); break;
1615 case ISD::STRICT_FTANH:
1616 case ISD::FTANH: ExpandFloatRes_FTANH(N, Lo, Hi); break;
1617 case ISD::STRICT_FTRUNC:
1618 case ISD::FTRUNC: ExpandFloatRes_FTRUNC(N, Lo, Hi); break;
1619 case ISD::LOAD: ExpandFloatRes_LOAD(N, Lo, Hi); break;
1622 case ISD::SINT_TO_FP:
1623 case ISD::UINT_TO_FP: ExpandFloatRes_XINT_TO_FP(N, Lo, Hi); break;
1624 case ISD::STRICT_FREM:
1625 case ISD::FREM: ExpandFloatRes_FREM(N, Lo, Hi); break;
1626 case ISD::FMODF: ExpandFloatRes_FMODF(N); break;
1627 case ISD::FSINCOS: ExpandFloatRes_FSINCOS(N); break;
1628 case ISD::FSINCOSPI: ExpandFloatRes_FSINCOSPI(N); break;
1629 // clang-format on
1630 }
1631
1632 // If Lo/Hi is null, the sub-method took care of registering results etc.
1633 if (Lo.getNode())
1634 SetExpandedFloat(SDValue(N, ResNo), Lo, Hi);
1635}
1636
1637void DAGTypeLegalizer::ExpandFloatRes_ConstantFP(SDNode *N, SDValue &Lo,
1638 SDValue &Hi) {
1639 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
1640 assert(NVT.getSizeInBits() == 64 &&
1641 "Do not know how to expand this float constant!");
1642 APInt C = cast<ConstantFPSDNode>(N)->getValueAPF().bitcastToAPInt();
1643 SDLoc dl(N);
1644 const fltSemantics &Sem = NVT.getFltSemantics();
1645 Lo = DAG.getConstantFP(APFloat(Sem, C.extractBits(64, 64)), dl, NVT);
1646 Hi = DAG.getConstantFP(APFloat(Sem, C.extractBits(64, 0)), dl, NVT);
1647}
1648
1649void DAGTypeLegalizer::ExpandFloatRes_Unary(SDNode *N, RTLIB::Libcall LC,
1650 SDValue &Lo, SDValue &Hi) {
1651 bool IsStrict = N->isStrictFPOpcode();
1652 unsigned Offset = IsStrict ? 1 : 0;
1653 SDValue Op = N->getOperand(0 + Offset);
1654 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1655 TargetLowering::MakeLibCallOptions CallOptions;
1656 std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, N->getValueType(0),
1657 Op, CallOptions, SDLoc(N),
1658 Chain);
1659 if (IsStrict)
1660 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1661 GetPairElements(Tmp.first, Lo, Hi);
1662}
1663
1664void DAGTypeLegalizer::ExpandFloatRes_Binary(SDNode *N, RTLIB::Libcall LC,
1665 SDValue &Lo, SDValue &Hi) {
1666 bool IsStrict = N->isStrictFPOpcode();
1667 unsigned Offset = IsStrict ? 1 : 0;
1668 SDValue Ops[] = { N->getOperand(0 + Offset), N->getOperand(1 + Offset) };
1669 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1670 TargetLowering::MakeLibCallOptions CallOptions;
1671 std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, N->getValueType(0),
1672 Ops, CallOptions, SDLoc(N),
1673 Chain);
1674 if (IsStrict)
1675 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1676 GetPairElements(Tmp.first, Lo, Hi);
1677}
1678
1679void DAGTypeLegalizer::ExpandFloatRes_FMODF(SDNode *N) {
1680 ExpandFloatRes_UnaryWithTwoFPResults(N, RTLIB::getMODF(N->getValueType(0)),
1681 /*CallRetResNo=*/0);
1682}
1683
1684void DAGTypeLegalizer::ExpandFloatRes_FSINCOS(SDNode *N) {
1685 ExpandFloatRes_UnaryWithTwoFPResults(N, RTLIB::getSINCOS(N->getValueType(0)));
1686}
1687
1688void DAGTypeLegalizer::ExpandFloatRes_FSINCOSPI(SDNode *N) {
1689 ExpandFloatRes_UnaryWithTwoFPResults(N,
1690 RTLIB::getSINCOSPI(N->getValueType(0)));
1691}
1692
1693void DAGTypeLegalizer::ExpandFloatRes_UnaryWithTwoFPResults(
1694 SDNode *N, RTLIB::Libcall LC, std::optional<unsigned> CallRetResNo) {
1695 assert(!N->isStrictFPOpcode() && "strictfp not implemented");
1697 TLI.expandMultipleResultFPLibCall(DAG, LC, N, Results, CallRetResNo);
1698 for (auto [ResNo, Res] : enumerate(Results)) {
1699 SDValue Lo, Hi;
1700 GetPairElements(Res, Lo, Hi);
1701 SetExpandedFloat(SDValue(N, ResNo), Lo, Hi);
1702 }
1703}
1704
1705void DAGTypeLegalizer::ExpandFloatRes_FABS(SDNode *N, SDValue &Lo,
1706 SDValue &Hi) {
1707 assert(N->getValueType(0) == MVT::ppcf128 &&
1708 "Logic only correct for ppcf128!");
1709 SDLoc dl(N);
1710 SDValue Tmp;
1711 GetExpandedFloat(N->getOperand(0), Lo, Tmp);
1712 Hi = DAG.getNode(ISD::FABS, dl, Tmp.getValueType(), Tmp);
1713 // Lo = Hi==fabs(Hi) ? Lo : -Lo;
1714 Lo = DAG.getSelectCC(dl, Tmp, Hi, Lo,
1715 DAG.getNode(ISD::FNEG, dl, Lo.getValueType(), Lo),
1716 ISD::SETEQ);
1717}
1718
1719void DAGTypeLegalizer::ExpandFloatRes_FMINNUM(SDNode *N, SDValue &Lo,
1720 SDValue &Hi) {
1721 ExpandFloatRes_Binary(N, RTLIB::getFMIN(N->getValueType(0)), Lo, Hi);
1722}
1723
1724void DAGTypeLegalizer::ExpandFloatRes_FMAXNUM(SDNode *N, SDValue &Lo,
1725 SDValue &Hi) {
1726 ExpandFloatRes_Binary(N, RTLIB::getFMAX(N->getValueType(0)), Lo, Hi);
1727}
1728
1729void DAGTypeLegalizer::ExpandFloatRes_FMINIMUMNUM(SDNode *N, SDValue &Lo,
1730 SDValue &Hi) {
1731 ExpandFloatRes_Binary(N, RTLIB::getFMINIMUM_NUM(N->getValueType(0)), Lo, Hi);
1732}
1733
1734void DAGTypeLegalizer::ExpandFloatRes_FMAXIMUMNUM(SDNode *N, SDValue &Lo,
1735 SDValue &Hi) {
1736 ExpandFloatRes_Binary(N, RTLIB::getFMAXIMUM_NUM(N->getValueType(0)), Lo, Hi);
1737}
1738
1739void DAGTypeLegalizer::ExpandFloatRes_FADD(SDNode *N, SDValue &Lo,
1740 SDValue &Hi) {
1741 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
1742 RTLIB::ADD_F32, RTLIB::ADD_F64,
1743 RTLIB::ADD_F80, RTLIB::ADD_F128,
1744 RTLIB::ADD_PPCF128), Lo, Hi);
1745}
1746
1747void DAGTypeLegalizer::ExpandFloatRes_FACOS(SDNode *N, SDValue &Lo,
1748 SDValue &Hi) {
1749 ExpandFloatRes_Unary(N, RTLIB::getACOS(N->getValueType(0)), Lo, Hi);
1750}
1751
1752void DAGTypeLegalizer::ExpandFloatRes_FASIN(SDNode *N, SDValue &Lo,
1753 SDValue &Hi) {
1754 ExpandFloatRes_Unary(N, RTLIB::getASIN(N->getValueType(0)), Lo, Hi);
1755}
1756
1757void DAGTypeLegalizer::ExpandFloatRes_FATAN(SDNode *N, SDValue &Lo,
1758 SDValue &Hi) {
1759 ExpandFloatRes_Unary(N, RTLIB::getATAN(N->getValueType(0)), Lo, Hi);
1760}
1761
1762void DAGTypeLegalizer::ExpandFloatRes_FATAN2(SDNode *N, SDValue &Lo,
1763 SDValue &Hi) {
1764 ExpandFloatRes_Binary(N, RTLIB::getATAN2(N->getValueType(0)), Lo, Hi);
1765}
1766
1767void DAGTypeLegalizer::ExpandFloatRes_FCBRT(SDNode *N, SDValue &Lo,
1768 SDValue &Hi) {
1769 ExpandFloatRes_Unary(N, RTLIB::getCBRT(N->getValueType(0)), Lo, Hi);
1770}
1771
1772void DAGTypeLegalizer::ExpandFloatRes_FCEIL(SDNode *N,
1773 SDValue &Lo, SDValue &Hi) {
1774 ExpandFloatRes_Unary(N, RTLIB::getCEIL(N->getValueType(0)), Lo, Hi);
1775}
1776
1777void DAGTypeLegalizer::ExpandFloatRes_FCOPYSIGN(SDNode *N,
1778 SDValue &Lo, SDValue &Hi) {
1779 ExpandFloatRes_Binary(N, RTLIB::getCOPYSIGN(N->getValueType(0)), Lo, Hi);
1780}
1781
1782void DAGTypeLegalizer::ExpandFloatRes_FCOS(SDNode *N,
1783 SDValue &Lo, SDValue &Hi) {
1784 ExpandFloatRes_Unary(N, RTLIB::getCOS(N->getValueType(0)), Lo, Hi);
1785}
1786
1787void DAGTypeLegalizer::ExpandFloatRes_FCOSH(SDNode *N, SDValue &Lo,
1788 SDValue &Hi) {
1789 ExpandFloatRes_Unary(N, RTLIB::getCOSH(N->getValueType(0)), Lo, Hi);
1790}
1791
1792void DAGTypeLegalizer::ExpandFloatRes_FDIV(SDNode *N, SDValue &Lo,
1793 SDValue &Hi) {
1794 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
1795 RTLIB::DIV_F32,
1796 RTLIB::DIV_F64,
1797 RTLIB::DIV_F80,
1798 RTLIB::DIV_F128,
1799 RTLIB::DIV_PPCF128), Lo, Hi);
1800}
1801
1802void DAGTypeLegalizer::ExpandFloatRes_FEXP(SDNode *N,
1803 SDValue &Lo, SDValue &Hi) {
1804 ExpandFloatRes_Unary(N, RTLIB::getEXP(N->getValueType(0)), Lo, Hi);
1805}
1806
1807void DAGTypeLegalizer::ExpandFloatRes_FEXP2(SDNode *N,
1808 SDValue &Lo, SDValue &Hi) {
1809 ExpandFloatRes_Unary(N, RTLIB::getEXP2(N->getValueType(0)), Lo, Hi);
1810}
1811
1812void DAGTypeLegalizer::ExpandFloatRes_FEXP10(SDNode *N, SDValue &Lo,
1813 SDValue &Hi) {
1814 ExpandFloatRes_Unary(N, RTLIB::getEXP10(N->getValueType(0)), Lo, Hi);
1815}
1816
1817void DAGTypeLegalizer::ExpandFloatRes_FFLOOR(SDNode *N,
1818 SDValue &Lo, SDValue &Hi) {
1819 ExpandFloatRes_Unary(N, RTLIB::getFLOOR(N->getValueType(0)), Lo, Hi);
1820}
1821
1822void DAGTypeLegalizer::ExpandFloatRes_FLOG(SDNode *N,
1823 SDValue &Lo, SDValue &Hi) {
1824 ExpandFloatRes_Unary(N, RTLIB::getLOG(N->getValueType(0)), Lo, Hi);
1825}
1826
1827void DAGTypeLegalizer::ExpandFloatRes_FLOG2(SDNode *N,
1828 SDValue &Lo, SDValue &Hi) {
1829 ExpandFloatRes_Unary(N, RTLIB::getLOG2(N->getValueType(0)), Lo, Hi);
1830}
1831
1832void DAGTypeLegalizer::ExpandFloatRes_FLOG10(SDNode *N,
1833 SDValue &Lo, SDValue &Hi) {
1834 ExpandFloatRes_Unary(N, RTLIB::getLOG10(N->getValueType(0)), Lo, Hi);
1835}
1836
1837void DAGTypeLegalizer::ExpandFloatRes_FMA(SDNode *N, SDValue &Lo,
1838 SDValue &Hi) {
1839 bool IsStrict = N->isStrictFPOpcode();
1840 unsigned Offset = IsStrict ? 1 : 0;
1841 SDValue Ops[3] = { N->getOperand(0 + Offset), N->getOperand(1 + Offset),
1842 N->getOperand(2 + Offset) };
1843 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1844 TargetLowering::MakeLibCallOptions CallOptions;
1845 std::pair<SDValue, SDValue> Tmp =
1846 TLI.makeLibCall(DAG, RTLIB::getFMA(N->getValueType(0)),
1847 N->getValueType(0), Ops, CallOptions, SDLoc(N), Chain);
1848 if (IsStrict)
1849 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1850 GetPairElements(Tmp.first, Lo, Hi);
1851}
1852
1853void DAGTypeLegalizer::ExpandFloatRes_FMUL(SDNode *N, SDValue &Lo,
1854 SDValue &Hi) {
1855 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
1856 RTLIB::MUL_F32,
1857 RTLIB::MUL_F64,
1858 RTLIB::MUL_F80,
1859 RTLIB::MUL_F128,
1860 RTLIB::MUL_PPCF128), Lo, Hi);
1861}
1862
1863void DAGTypeLegalizer::ExpandFloatRes_FNEARBYINT(SDNode *N,
1864 SDValue &Lo, SDValue &Hi) {
1865 ExpandFloatRes_Unary(N, RTLIB::getNEARBYINT(N->getValueType(0)), Lo, Hi);
1866}
1867
1868void DAGTypeLegalizer::ExpandFloatRes_FNEG(SDNode *N, SDValue &Lo,
1869 SDValue &Hi) {
1870 SDLoc dl(N);
1871 GetExpandedFloat(N->getOperand(0), Lo, Hi);
1872 Lo = DAG.getNode(ISD::FNEG, dl, Lo.getValueType(), Lo);
1873 Hi = DAG.getNode(ISD::FNEG, dl, Hi.getValueType(), Hi);
1874}
1875
1876void DAGTypeLegalizer::ExpandFloatRes_AssertNoFPClass(SDNode *N, SDValue &Lo,
1877 SDValue &Hi) {
1878 // TODO: Handle ppcf128 by preserving AssertNoFPClass for one of the halves.
1879 SDLoc dl(N);
1880 GetExpandedFloat(N->getOperand(0), Lo, Hi);
1881}
1882
1883void DAGTypeLegalizer::ExpandFloatRes_FP_EXTEND(SDNode *N, SDValue &Lo,
1884 SDValue &Hi) {
1885 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
1886 SDLoc dl(N);
1887 bool IsStrict = N->isStrictFPOpcode();
1888
1889 SDValue Chain;
1890 if (IsStrict) {
1891 // If the expanded type is the same as the input type, just bypass the node.
1892 if (NVT == N->getOperand(1).getValueType()) {
1893 Hi = N->getOperand(1);
1894 Chain = N->getOperand(0);
1895 } else {
1896 // Other we need to extend.
1897 Hi = DAG.getNode(ISD::STRICT_FP_EXTEND, dl, { NVT, MVT::Other },
1898 { N->getOperand(0), N->getOperand(1) });
1899 Chain = Hi.getValue(1);
1900 }
1901 } else {
1902 Hi = DAG.getNode(ISD::FP_EXTEND, dl, NVT, N->getOperand(0));
1903 }
1904
1905 Lo = DAG.getConstantFP(APFloat::getZero(NVT.getFltSemantics()), dl, NVT);
1906
1907 if (IsStrict)
1908 ReplaceValueWith(SDValue(N, 1), Chain);
1909}
1910
1911void DAGTypeLegalizer::ExpandFloatRes_FPOW(SDNode *N,
1912 SDValue &Lo, SDValue &Hi) {
1913 ExpandFloatRes_Binary(N, RTLIB::getPOW(N->getValueType(0)), Lo, Hi);
1914}
1915
1916void DAGTypeLegalizer::ExpandFloatRes_FPOWI(SDNode *N,
1917 SDValue &Lo, SDValue &Hi) {
1918 ExpandFloatRes_Binary(N, RTLIB::getPOWI(N->getValueType(0)), Lo, Hi);
1919}
1920
1921void DAGTypeLegalizer::ExpandFloatRes_FLDEXP(SDNode *N, SDValue &Lo,
1922 SDValue &Hi) {
1923 ExpandFloatRes_Binary(N, RTLIB::getLDEXP(N->getValueType(0)), Lo, Hi);
1924}
1925
1926void DAGTypeLegalizer::ExpandFloatRes_FREEZE(SDNode *N,
1927 SDValue &Lo, SDValue &Hi) {
1928 assert(N->getValueType(0) == MVT::ppcf128 &&
1929 "Logic only correct for ppcf128!");
1930
1931 SDLoc dl(N);
1932 GetExpandedFloat(N->getOperand(0), Lo, Hi);
1933 Lo = DAG.getNode(ISD::FREEZE, dl, Lo.getValueType(), Lo);
1934 Hi = DAG.getNode(ISD::FREEZE, dl, Hi.getValueType(), Hi);
1935}
1936
1937void DAGTypeLegalizer::ExpandFloatRes_FREM(SDNode *N,
1938 SDValue &Lo, SDValue &Hi) {
1939 ExpandFloatRes_Binary(N, RTLIB::getREM(N->getValueType(0)), Lo, Hi);
1940}
1941
1942void DAGTypeLegalizer::ExpandFloatRes_FRINT(SDNode *N,
1943 SDValue &Lo, SDValue &Hi) {
1944 ExpandFloatRes_Unary(N, RTLIB::getRINT(N->getValueType(0)), Lo, Hi);
1945}
1946
1947void DAGTypeLegalizer::ExpandFloatRes_FROUND(SDNode *N,
1948 SDValue &Lo, SDValue &Hi) {
1949 ExpandFloatRes_Unary(N, RTLIB::getROUND(N->getValueType(0)), Lo, Hi);
1950}
1951
1952void DAGTypeLegalizer::ExpandFloatRes_FROUNDEVEN(SDNode *N,
1953 SDValue &Lo, SDValue &Hi) {
1954 ExpandFloatRes_Unary(N, RTLIB::getROUNDEVEN(N->getValueType(0)), Lo, Hi);
1955}
1956
1957void DAGTypeLegalizer::ExpandFloatRes_FSIN(SDNode *N,
1958 SDValue &Lo, SDValue &Hi) {
1959 ExpandFloatRes_Unary(N, RTLIB::getSIN(N->getValueType(0)), Lo, Hi);
1960}
1961
1962void DAGTypeLegalizer::ExpandFloatRes_FSINH(SDNode *N, SDValue &Lo,
1963 SDValue &Hi) {
1964 ExpandFloatRes_Unary(N, RTLIB::getSINH(N->getValueType(0)), Lo, Hi);
1965}
1966
1967void DAGTypeLegalizer::ExpandFloatRes_FSQRT(SDNode *N,
1968 SDValue &Lo, SDValue &Hi) {
1969 ExpandFloatRes_Unary(N, RTLIB::getSQRT(N->getValueType(0)), Lo, Hi);
1970}
1971
1972void DAGTypeLegalizer::ExpandFloatRes_FSUB(SDNode *N, SDValue &Lo,
1973 SDValue &Hi) {
1974 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
1975 RTLIB::SUB_F32,
1976 RTLIB::SUB_F64,
1977 RTLIB::SUB_F80,
1978 RTLIB::SUB_F128,
1979 RTLIB::SUB_PPCF128), Lo, Hi);
1980}
1981
1982void DAGTypeLegalizer::ExpandFloatRes_FTAN(SDNode *N, SDValue &Lo,
1983 SDValue &Hi) {
1984 ExpandFloatRes_Unary(N, RTLIB::getTAN(N->getValueType(0)), Lo, Hi);
1985}
1986
1987void DAGTypeLegalizer::ExpandFloatRes_FTANH(SDNode *N, SDValue &Lo,
1988 SDValue &Hi) {
1989 ExpandFloatRes_Unary(N, RTLIB::getTANH(N->getValueType(0)), Lo, Hi);
1990}
1991
1992void DAGTypeLegalizer::ExpandFloatRes_FTRUNC(SDNode *N,
1993 SDValue &Lo, SDValue &Hi) {
1994 ExpandFloatRes_Unary(N, RTLIB::getTRUNC(N->getValueType(0)), Lo, Hi);
1995}
1996
1997void DAGTypeLegalizer::ExpandFloatRes_LOAD(SDNode *N, SDValue &Lo,
1998 SDValue &Hi) {
1999 if (ISD::isNormalLoad(N)) {
2000 ExpandRes_NormalLoad(N, Lo, Hi);
2001 return;
2002 }
2003
2004 assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!");
2005 LoadSDNode *LD = cast<LoadSDNode>(N);
2006 SDValue Chain = LD->getChain();
2007 SDValue Ptr = LD->getBasePtr();
2008 SDLoc dl(N);
2009
2010 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0));
2011 assert(NVT.isByteSized() && "Expanded type not byte sized!");
2012 assert(LD->getMemoryVT().bitsLE(NVT) && "Float type not round?");
2013
2014 Hi = DAG.getExtLoad(LD->getExtensionType(), dl, NVT, Chain, Ptr,
2015 LD->getMemoryVT(), LD->getMemOperand());
2016
2017 // Remember the chain.
2018 Chain = Hi.getValue(1);
2019
2020 // The low part is zero.
2021 Lo = DAG.getConstantFP(APFloat::getZero(NVT.getFltSemantics()), dl, NVT);
2022
2023 // Modified the chain - switch anything that used the old chain to use the
2024 // new one.
2025 ReplaceValueWith(SDValue(LD, 1), Chain);
2026}
2027
2028void DAGTypeLegalizer::ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo,
2029 SDValue &Hi) {
2030 assert(N->getValueType(0) == MVT::ppcf128 && "Unsupported XINT_TO_FP!");
2031 EVT VT = N->getValueType(0);
2032 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
2033 bool Strict = N->isStrictFPOpcode();
2034 SDValue Src = N->getOperand(Strict ? 1 : 0);
2035 EVT SrcVT = Src.getValueType();
2036 bool isSigned = N->getOpcode() == ISD::SINT_TO_FP ||
2037 N->getOpcode() == ISD::STRICT_SINT_TO_FP;
2038 SDLoc dl(N);
2039 SDValue Chain = Strict ? N->getOperand(0) : DAG.getEntryNode();
2040
2041 // TODO: Any other flags to propagate?
2042 SDNodeFlags Flags;
2043 Flags.setNoFPExcept(N->getFlags().hasNoFPExcept());
2044
2045 // First do an SINT_TO_FP, whether the original was signed or unsigned.
2046 // When promoting partial word types to i32 we must honor the signedness,
2047 // though.
2048 if (SrcVT.bitsLE(MVT::i32)) {
2049 // The integer can be represented exactly in an f64.
2050 Lo = DAG.getConstantFP(APFloat::getZero(NVT.getFltSemantics()), dl, NVT);
2051 if (Strict) {
2052 Hi = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(NVT, MVT::Other),
2053 {Chain, Src}, Flags);
2054 Chain = Hi.getValue(1);
2055 } else
2056 Hi = DAG.getNode(N->getOpcode(), dl, NVT, Src);
2057 } else {
2058 RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
2059 if (SrcVT.bitsLE(MVT::i64)) {
2060 Src = DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, dl,
2061 MVT::i64, Src);
2062 LC = RTLIB::SINTTOFP_I64_PPCF128;
2063 } else if (SrcVT.bitsLE(MVT::i128)) {
2064 Src = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i128, Src);
2065 LC = RTLIB::SINTTOFP_I128_PPCF128;
2066 }
2067 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!");
2068
2069 TargetLowering::MakeLibCallOptions CallOptions;
2070 CallOptions.setIsSigned(true);
2071 std::pair<SDValue, SDValue> Tmp =
2072 TLI.makeLibCall(DAG, LC, VT, Src, CallOptions, dl, Chain);
2073 if (Strict)
2074 Chain = Tmp.second;
2075 GetPairElements(Tmp.first, Lo, Hi);
2076 }
2077
2078 // No need to complement for unsigned 32-bit integers
2079 if (isSigned || SrcVT.bitsLE(MVT::i32)) {
2080 if (Strict)
2081 ReplaceValueWith(SDValue(N, 1), Chain);
2082
2083 return;
2084 }
2085
2086 // Unsigned - fix up the SINT_TO_FP value just calculated.
2087 // FIXME: For unsigned i128 to ppc_fp128 conversion, we need to carefully
2088 // keep semantics correctness if the integer is not exactly representable
2089 // here. See ExpandLegalINT_TO_FP.
2090 Hi = DAG.getNode(ISD::BUILD_PAIR, dl, VT, Lo, Hi);
2091 SrcVT = Src.getValueType();
2092
2093 // x>=0 ? (ppcf128)(iN)x : (ppcf128)(iN)x + 2^N; N=32,64,128.
2094 static const uint64_t TwoE32[] = { 0x41f0000000000000LL, 0 };
2095 static const uint64_t TwoE64[] = { 0x43f0000000000000LL, 0 };
2096 static const uint64_t TwoE128[] = { 0x47f0000000000000LL, 0 };
2097 ArrayRef<uint64_t> Parts;
2098
2099 switch (SrcVT.getSimpleVT().SimpleTy) {
2100 default:
2101 llvm_unreachable("Unsupported UINT_TO_FP!");
2102 case MVT::i32:
2103 Parts = TwoE32;
2104 break;
2105 case MVT::i64:
2106 Parts = TwoE64;
2107 break;
2108 case MVT::i128:
2109 Parts = TwoE128;
2110 break;
2111 }
2112
2113 // TODO: Are there other fast-math-flags to propagate to this FADD?
2114 SDValue NewLo = DAG.getConstantFP(
2115 APFloat(APFloat::PPCDoubleDouble(), APInt(128, Parts)), dl, MVT::ppcf128);
2116 if (Strict) {
2117 Lo = DAG.getNode(ISD::STRICT_FADD, dl, DAG.getVTList(VT, MVT::Other),
2118 {Chain, Hi, NewLo}, Flags);
2119 Chain = Lo.getValue(1);
2120 ReplaceValueWith(SDValue(N, 1), Chain);
2121 } else
2122 Lo = DAG.getNode(ISD::FADD, dl, VT, Hi, NewLo);
2123 Lo = DAG.getSelectCC(dl, Src, DAG.getConstant(0, dl, SrcVT),
2124 Lo, Hi, ISD::SETLT);
2125 GetPairElements(Lo, Lo, Hi);
2126}
2127
2128
2129//===----------------------------------------------------------------------===//
2130// Float Operand Expansion
2131//===----------------------------------------------------------------------===//
2132
2133/// ExpandFloatOperand - This method is called when the specified operand of the
2134/// specified node is found to need expansion. At this point, all of the result
2135/// types of the node are known to be legal, but other operands of the node may
2136/// need promotion or expansion as well as the specified one.
2137bool DAGTypeLegalizer::ExpandFloatOperand(SDNode *N, unsigned OpNo) {
2138 LLVM_DEBUG(dbgs() << "Expand float operand: "; N->dump(&DAG));
2139 SDValue Res = SDValue();
2140
2141 // See if the target wants to custom expand this node.
2142 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
2143 return false;
2144
2145 switch (N->getOpcode()) {
2146 default:
2147#ifndef NDEBUG
2148 dbgs() << "ExpandFloatOperand Op #" << OpNo << ": ";
2149 N->dump(&DAG); dbgs() << "\n";
2150#endif
2151 report_fatal_error("Do not know how to expand this operator's operand!");
2152
2153 case ISD::BITCAST: Res = ExpandOp_BITCAST(N); break;
2154 case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break;
2155 case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break;
2156
2157 case ISD::BR_CC: Res = ExpandFloatOp_BR_CC(N); break;
2158 case ISD::FCOPYSIGN: Res = ExpandFloatOp_FCOPYSIGN(N); break;
2160 case ISD::FP_ROUND: Res = ExpandFloatOp_FP_ROUND(N); break;
2163 case ISD::FP_TO_SINT:
2164 case ISD::FP_TO_UINT: Res = ExpandFloatOp_FP_TO_XINT(N); break;
2165 case ISD::LROUND: Res = ExpandFloatOp_LROUND(N); break;
2166 case ISD::LLROUND: Res = ExpandFloatOp_LLROUND(N); break;
2167 case ISD::LRINT: Res = ExpandFloatOp_LRINT(N); break;
2168 case ISD::LLRINT: Res = ExpandFloatOp_LLRINT(N); break;
2169 case ISD::SELECT_CC: Res = ExpandFloatOp_SELECT_CC(N); break;
2170 case ISD::STRICT_FSETCC:
2172 case ISD::SETCC: Res = ExpandFloatOp_SETCC(N); break;
2173 case ISD::STORE: Res = ExpandFloatOp_STORE(cast<StoreSDNode>(N),
2174 OpNo); break;
2175 }
2176
2177 // If the result is null, the sub-method took care of registering results etc.
2178 if (!Res.getNode()) return false;
2179
2180 // If the result is N, the sub-method updated N in place. Tell the legalizer
2181 // core about this.
2182 if (Res.getNode() == N)
2183 return true;
2184
2185 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
2186 "Invalid operand expansion");
2187
2188 ReplaceValueWith(SDValue(N, 0), Res);
2189 return false;
2190}
2191
2192/// FloatExpandSetCCOperands - Expand the operands of a comparison. This code
2193/// is shared among BR_CC, SELECT_CC, and SETCC handlers.
2194void DAGTypeLegalizer::FloatExpandSetCCOperands(SDValue &NewLHS,
2195 SDValue &NewRHS,
2196 ISD::CondCode &CCCode,
2197 const SDLoc &dl, SDValue &Chain,
2198 bool IsSignaling) {
2199 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
2200 GetExpandedFloat(NewLHS, LHSLo, LHSHi);
2201 GetExpandedFloat(NewRHS, RHSLo, RHSHi);
2202
2203 assert(NewLHS.getValueType() == MVT::ppcf128 && "Unsupported setcc type!");
2204
2205 // FIXME: This generated code sucks. We want to generate
2206 // FCMPU crN, hi1, hi2
2207 // BNE crN, L:
2208 // FCMPU crN, lo1, lo2
2209 // The following can be improved, but not that much.
2210 SDValue Tmp1, Tmp2, Tmp3, OutputChain;
2211 Tmp1 = DAG.getSetCC(dl, getSetCCResultType(LHSHi.getValueType()), LHSHi,
2212 RHSHi, ISD::SETOEQ, Chain, IsSignaling);
2213 OutputChain = Tmp1->getNumValues() > 1 ? Tmp1.getValue(1) : SDValue();
2214 Tmp2 = DAG.getSetCC(dl, getSetCCResultType(LHSLo.getValueType()), LHSLo,
2215 RHSLo, CCCode, OutputChain, IsSignaling);
2216 OutputChain = Tmp2->getNumValues() > 1 ? Tmp2.getValue(1) : SDValue();
2217 Tmp3 = DAG.getNode(ISD::AND, dl, Tmp1.getValueType(), Tmp1, Tmp2);
2218 Tmp1 =
2219 DAG.getSetCC(dl, getSetCCResultType(LHSHi.getValueType()), LHSHi, RHSHi,
2220 ISD::SETUNE, OutputChain, IsSignaling);
2221 OutputChain = Tmp1->getNumValues() > 1 ? Tmp1.getValue(1) : SDValue();
2222 Tmp2 = DAG.getSetCC(dl, getSetCCResultType(LHSHi.getValueType()), LHSHi,
2223 RHSHi, CCCode, OutputChain, IsSignaling);
2224 OutputChain = Tmp2->getNumValues() > 1 ? Tmp2.getValue(1) : SDValue();
2225 Tmp1 = DAG.getNode(ISD::AND, dl, Tmp1.getValueType(), Tmp1, Tmp2);
2226 NewLHS = DAG.getNode(ISD::OR, dl, Tmp1.getValueType(), Tmp1, Tmp3);
2227 NewRHS = SDValue(); // LHS is the result, not a compare.
2228 Chain = OutputChain;
2229}
2230
2231SDValue DAGTypeLegalizer::ExpandFloatOp_BR_CC(SDNode *N) {
2232 SDValue NewLHS = N->getOperand(2), NewRHS = N->getOperand(3);
2233 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(1))->get();
2234 SDValue Chain;
2235 FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, SDLoc(N), Chain);
2236
2237 // If ExpandSetCCOperands returned a scalar, we need to compare the result
2238 // against zero to select between true and false values.
2239 if (!NewRHS.getNode()) {
2240 NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
2241 CCCode = ISD::SETNE;
2242 }
2243
2244 // Update N to have the operands specified.
2245 return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0),
2246 DAG.getCondCode(CCCode), NewLHS, NewRHS,
2247 N->getOperand(4)), 0);
2248}
2249
2250SDValue DAGTypeLegalizer::ExpandFloatOp_FCOPYSIGN(SDNode *N) {
2251 assert(N->getOperand(1).getValueType() == MVT::ppcf128 &&
2252 "Logic only correct for ppcf128!");
2253 SDValue Lo, Hi;
2254 GetExpandedFloat(N->getOperand(1), Lo, Hi);
2255 // The ppcf128 value is providing only the sign; take it from the
2256 // higher-order double (which must have the larger magnitude).
2257 return DAG.getNode(ISD::FCOPYSIGN, SDLoc(N),
2258 N->getValueType(0), N->getOperand(0), Hi);
2259}
2260
2261SDValue DAGTypeLegalizer::ExpandFloatOp_FP_ROUND(SDNode *N) {
2262 bool IsStrict = N->isStrictFPOpcode();
2263 assert(N->getOperand(IsStrict ? 1 : 0).getValueType() == MVT::ppcf128 &&
2264 "Logic only correct for ppcf128!");
2265 SDValue Lo, Hi;
2266 GetExpandedFloat(N->getOperand(IsStrict ? 1 : 0), Lo, Hi);
2267
2268 if (!IsStrict)
2269 // Round it the rest of the way (e.g. to f32) if needed.
2270 return DAG.getNode(ISD::FP_ROUND, SDLoc(N),
2271 N->getValueType(0), Hi, N->getOperand(1));
2272
2273 // Eliminate the node if the input float type is the same as the output float
2274 // type.
2275 if (Hi.getValueType() == N->getValueType(0)) {
2276 // Connect the output chain to the input chain, unlinking the node.
2277 ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
2278 ReplaceValueWith(SDValue(N, 0), Hi);
2279 return SDValue();
2280 }
2281
2282 SDValue Expansion = DAG.getNode(ISD::STRICT_FP_ROUND, SDLoc(N),
2283 {N->getValueType(0), MVT::Other},
2284 {N->getOperand(0), Hi, N->getOperand(2)});
2285 ReplaceValueWith(SDValue(N, 1), Expansion.getValue(1));
2286 ReplaceValueWith(SDValue(N, 0), Expansion);
2287 return SDValue();
2288}
2289
2290SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_XINT(SDNode *N) {
2291 EVT RVT = N->getValueType(0);
2292 SDLoc dl(N);
2293
2294 bool IsStrict = N->isStrictFPOpcode();
2295 bool Signed = N->getOpcode() == ISD::FP_TO_SINT ||
2296 N->getOpcode() == ISD::STRICT_FP_TO_SINT;
2297 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
2298 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
2299
2300 EVT NVT;
2301 RTLIB::Libcall LC = findFPToIntLibcall(Op.getValueType(), RVT, NVT, Signed);
2302 assert(LC != RTLIB::UNKNOWN_LIBCALL && NVT.isSimple() &&
2303 "Unsupported FP_TO_XINT!");
2304 TargetLowering::MakeLibCallOptions CallOptions;
2305 std::pair<SDValue, SDValue> Tmp =
2306 TLI.makeLibCall(DAG, LC, NVT, Op, CallOptions, dl, Chain);
2307 if (!IsStrict)
2308 return Tmp.first;
2309
2310 ReplaceValueWith(SDValue(N, 1), Tmp.second);
2311 ReplaceValueWith(SDValue(N, 0), Tmp.first);
2312 return SDValue();
2313}
2314
2315SDValue DAGTypeLegalizer::ExpandFloatOp_SELECT_CC(SDNode *N) {
2316 SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
2317 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(4))->get();
2318 SDValue Chain;
2319 FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, SDLoc(N), Chain);
2320
2321 // If ExpandSetCCOperands returned a scalar, we need to compare the result
2322 // against zero to select between true and false values.
2323 if (!NewRHS.getNode()) {
2324 NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
2325 CCCode = ISD::SETNE;
2326 }
2327
2328 // Update N to have the operands specified.
2329 return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
2330 N->getOperand(2), N->getOperand(3),
2331 DAG.getCondCode(CCCode)), 0);
2332}
2333
2334SDValue DAGTypeLegalizer::ExpandFloatOp_SETCC(SDNode *N) {
2335 bool IsStrict = N->isStrictFPOpcode();
2336 SDValue NewLHS = N->getOperand(IsStrict ? 1 : 0);
2337 SDValue NewRHS = N->getOperand(IsStrict ? 2 : 1);
2338 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
2339 ISD::CondCode CCCode =
2340 cast<CondCodeSDNode>(N->getOperand(IsStrict ? 3 : 2))->get();
2341 FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, SDLoc(N), Chain,
2342 N->getOpcode() == ISD::STRICT_FSETCCS);
2343
2344 // FloatExpandSetCCOperands always returned a scalar.
2345 assert(!NewRHS.getNode() && "Expect to return scalar");
2346 assert(NewLHS.getValueType() == N->getValueType(0) &&
2347 "Unexpected setcc expansion!");
2348 if (Chain) {
2349 ReplaceValueWith(SDValue(N, 0), NewLHS);
2350 ReplaceValueWith(SDValue(N, 1), Chain);
2351 return SDValue();
2352 }
2353 return NewLHS;
2354}
2355
2356SDValue DAGTypeLegalizer::ExpandFloatOp_STORE(SDNode *N, unsigned OpNo) {
2357 if (ISD::isNormalStore(N))
2358 return ExpandOp_NormalStore(N, OpNo);
2359
2360 assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!");
2361 assert(OpNo == 1 && "Can only expand the stored value so far");
2362 StoreSDNode *ST = cast<StoreSDNode>(N);
2363
2364 SDValue Chain = ST->getChain();
2365 SDValue Ptr = ST->getBasePtr();
2366
2367 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(),
2368 ST->getValue().getValueType());
2369 assert(NVT.isByteSized() && "Expanded type not byte sized!");
2370 assert(ST->getMemoryVT().bitsLE(NVT) && "Float type not round?");
2371 (void)NVT;
2372
2373 SDValue Lo, Hi;
2374 GetExpandedOp(ST->getValue(), Lo, Hi);
2375
2376 return DAG.getTruncStore(Chain, SDLoc(N), Hi, Ptr,
2377 ST->getMemoryVT(), ST->getMemOperand());
2378}
2379
2380SDValue DAGTypeLegalizer::ExpandFloatOp_XRINT_XROUND(SDNode *N,
2381 RTLIB::Libcall LC) {
2382 EVT RVT = N->getValueType(0);
2383 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
2384 if (LCImpl == RTLIB::Unsupported) {
2385 DAG.getContext()->emitError(Twine("no libcall available for ") +
2386 N->getOperationName(&DAG));
2387 return DAG.getPOISON(RVT);
2388 }
2389
2390 TargetLowering::MakeLibCallOptions CallOptions;
2391 return TLI
2392 .makeLibCall(DAG, LCImpl, RVT, N->getOperand(0), CallOptions, SDLoc(N))
2393 .first;
2394}
2395
2396SDValue DAGTypeLegalizer::ExpandFloatOp_LROUND(SDNode *N) {
2397 EVT RetVT = N->getOperand(0).getValueType();
2398 return ExpandFloatOp_XRINT_XROUND(
2399 N, GetFPLibCall(RetVT, RTLIB::LROUND_F32, RTLIB::LROUND_F64,
2400 RTLIB::LROUND_F80, RTLIB::LROUND_F128,
2401 RTLIB::LROUND_PPCF128));
2402}
2403
2404SDValue DAGTypeLegalizer::ExpandFloatOp_LLROUND(SDNode *N) {
2405 EVT RetVT = N->getOperand(0).getValueType();
2406 return ExpandFloatOp_XRINT_XROUND(
2407 N, GetFPLibCall(RetVT, RTLIB::LLROUND_F32, RTLIB::LLROUND_F64,
2408 RTLIB::LLROUND_F80, RTLIB::LLROUND_F128,
2409 RTLIB::LLROUND_PPCF128));
2410}
2411
2412SDValue DAGTypeLegalizer::ExpandFloatOp_LRINT(SDNode *N) {
2413 EVT RetVT = N->getOperand(0).getValueType();
2414 return ExpandFloatOp_XRINT_XROUND(
2415 N,
2416 GetFPLibCall(RetVT, RTLIB::LRINT_F32, RTLIB::LRINT_F64, RTLIB::LRINT_F80,
2417 RTLIB::LRINT_F128, RTLIB::LRINT_PPCF128));
2418}
2419
2420SDValue DAGTypeLegalizer::ExpandFloatOp_LLRINT(SDNode *N) {
2421 EVT RetVT = N->getOperand(0).getValueType();
2422 return ExpandFloatOp_XRINT_XROUND(
2423 N, GetFPLibCall(RetVT, RTLIB::LLRINT_F32, RTLIB::LLRINT_F64,
2424 RTLIB::LLRINT_F80, RTLIB::LLRINT_F128,
2425 RTLIB::LLRINT_PPCF128));
2426}
2427
2428//===----------------------------------------------------------------------===//
2429// Float Operand Promotion
2430//===----------------------------------------------------------------------===//
2431//
2432
2434 if (OpVT == MVT::f16)
2435 return ISD::FP16_TO_FP;
2436 if (RetVT == MVT::f16)
2437 return ISD::FP_TO_FP16;
2438 if (OpVT == MVT::bf16)
2439 return ISD::BF16_TO_FP;
2440 if (RetVT == MVT::bf16)
2441 return ISD::FP_TO_BF16;
2442 report_fatal_error("Attempt at an invalid promotion-related conversion");
2443}
2444
2446 if (OpVT == MVT::f16)
2448 if (RetVT == MVT::f16)
2450 if (OpVT == MVT::bf16)
2452 if (RetVT == MVT::bf16)
2454 report_fatal_error("Attempt at an invalid promotion-related conversion");
2455}
2456
2457SDValue DAGTypeLegalizer::BitcastToInt_ATOMIC_SWAP(SDNode *N) {
2458 AtomicSDNode *AM = cast<AtomicSDNode>(N);
2459 SDLoc SL(N);
2460
2461 SDValue CastVal = BitConvertToInteger(AM->getVal());
2462 EVT CastVT = CastVal.getValueType();
2463
2464 SDValue NewAtomic
2465 = DAG.getAtomic(ISD::ATOMIC_SWAP, SL, CastVT,
2466 DAG.getVTList(CastVT, MVT::Other),
2467 { AM->getChain(), AM->getBasePtr(), CastVal },
2468 AM->getMemOperand());
2469
2470 SDValue Result = NewAtomic;
2471
2472 // Legalize the chain result by replacing uses of the old value chain with the
2473 // new one
2474 ReplaceValueWith(SDValue(N, 1), NewAtomic.getValue(1));
2475
2476 return Result;
2477}
2478
2479//===----------------------------------------------------------------------===//
2480// Half Result Soft Promotion
2481//===----------------------------------------------------------------------===//
2482
2483void DAGTypeLegalizer::SoftPromoteHalfResult(SDNode *N, unsigned ResNo) {
2484 LLVM_DEBUG(dbgs() << "Soft promote half result " << ResNo << ": ";
2485 N->dump(&DAG));
2486 SDValue R = SDValue();
2487
2488 // See if the target wants to custom expand this node.
2489 if (CustomLowerNode(N, N->getValueType(ResNo), true)) {
2490 LLVM_DEBUG(dbgs() << "Node has been custom expanded, done\n");
2491 return;
2492 }
2493
2494 switch (N->getOpcode()) {
2495 default:
2496#ifndef NDEBUG
2497 dbgs() << "SoftPromoteHalfResult #" << ResNo << ": ";
2498 N->dump(&DAG); dbgs() << "\n";
2499#endif
2500 report_fatal_error("Do not know how to soft promote this operator's "
2501 "result!");
2502
2503 case ISD::ARITH_FENCE:
2504 R = SoftPromoteHalfRes_ARITH_FENCE(N); break;
2505 case ISD::BITCAST: R = SoftPromoteHalfRes_BITCAST(N); break;
2506 case ISD::ConstantFP: R = SoftPromoteHalfRes_ConstantFP(N); break;
2508 R = SoftPromoteHalfRes_EXTRACT_VECTOR_ELT(N); break;
2509 case ISD::FCOPYSIGN: R = SoftPromoteHalfRes_FCOPYSIGN(N); break;
2511 case ISD::FP_ROUND: R = SoftPromoteHalfRes_FP_ROUND(N); break;
2512
2513 // Unary FP Operations
2514 case ISD::FACOS:
2515 case ISD::FASIN:
2516 case ISD::FATAN:
2517 case ISD::FCBRT:
2518 case ISD::FCEIL:
2519 case ISD::FCOS:
2520 case ISD::FCOSH:
2521 case ISD::FEXP:
2522 case ISD::FEXP2:
2523 case ISD::FEXP10:
2524 case ISD::FFLOOR:
2525 case ISD::FLOG:
2526 case ISD::FLOG2:
2527 case ISD::FLOG10:
2528 case ISD::FNEARBYINT:
2529 case ISD::FREEZE:
2530 case ISD::FRINT:
2531 case ISD::FROUND:
2532 case ISD::FROUNDEVEN:
2533 case ISD::FSIN:
2534 case ISD::FSINH:
2535 case ISD::FSQRT:
2536 case ISD::FTRUNC:
2537 case ISD::FTAN:
2538 case ISD::FTANH:
2539 case ISD::FCANONICALIZE: R = SoftPromoteHalfRes_UnaryOp(N); break;
2540 case ISD::FABS:
2541 R = SoftPromoteHalfRes_FABS(N);
2542 break;
2543 case ISD::FNEG:
2544 R = SoftPromoteHalfRes_FNEG(N);
2545 break;
2547 R = SoftPromoteHalfRes_AssertNoFPClass(N);
2548 break;
2549
2550 // Binary FP Operations
2551 case ISD::FADD:
2552 case ISD::FDIV:
2553 case ISD::FMAXIMUM:
2554 case ISD::FMINIMUM:
2555 case ISD::FMAXIMUMNUM:
2556 case ISD::FMINIMUMNUM:
2557 case ISD::FMAXNUM:
2558 case ISD::FMINNUM:
2559 case ISD::FMUL:
2560 case ISD::FPOW:
2561 case ISD::FATAN2:
2562 case ISD::FREM:
2563 case ISD::FSUB: R = SoftPromoteHalfRes_BinOp(N); break;
2564
2565 case ISD::FMA: // FMA is same as FMAD
2566 case ISD::FMAD: R = SoftPromoteHalfRes_FMAD(N); break;
2567
2568 case ISD::FPOWI:
2569 case ISD::FLDEXP: R = SoftPromoteHalfRes_ExpOp(N); break;
2570
2571 case ISD::FFREXP: R = SoftPromoteHalfRes_FFREXP(N); break;
2572
2573 case ISD::FMODF:
2574 case ISD::FSINCOS:
2575 case ISD::FSINCOSPI:
2576 R = SoftPromoteHalfRes_UnaryWithTwoFPResults(N);
2577 break;
2578
2579 case ISD::LOAD: R = SoftPromoteHalfRes_LOAD(N); break;
2580 case ISD::ATOMIC_LOAD:
2581 R = SoftPromoteHalfRes_ATOMIC_LOAD(N);
2582 break;
2583 case ISD::SELECT: R = SoftPromoteHalfRes_SELECT(N); break;
2584 case ISD::SELECT_CC: R = SoftPromoteHalfRes_SELECT_CC(N); break;
2587 case ISD::SINT_TO_FP:
2588 case ISD::UINT_TO_FP: R = SoftPromoteHalfRes_XINT_TO_FP(N); break;
2590 R = SoftPromoteHalfRes_CONVERT_FROM_ARBITRARY_FP(N);
2591 break;
2592 case ISD::POISON:
2593 case ISD::UNDEF: R = SoftPromoteHalfRes_UNDEF(N); break;
2594 case ISD::ATOMIC_SWAP: R = BitcastToInt_ATOMIC_SWAP(N); break;
2603 R = SoftPromoteHalfRes_VECREDUCE(N);
2604 break;
2607 R = SoftPromoteHalfRes_VECREDUCE_SEQ(N);
2608 break;
2609 }
2610
2611 if (R.getNode())
2612 SetSoftPromotedHalf(SDValue(N, ResNo), R);
2613}
2614
2615SDValue DAGTypeLegalizer::SoftPromoteHalfRes_ARITH_FENCE(SDNode *N) {
2616 return DAG.getNode(ISD::ARITH_FENCE, SDLoc(N), MVT::i16,
2617 BitConvertToInteger(N->getOperand(0)));
2618}
2619
2620SDValue DAGTypeLegalizer::SoftPromoteHalfRes_BITCAST(SDNode *N) {
2621 return BitConvertToInteger(N->getOperand(0));
2622}
2623
2624SDValue DAGTypeLegalizer::SoftPromoteHalfRes_ConstantFP(SDNode *N) {
2625 ConstantFPSDNode *CN = cast<ConstantFPSDNode>(N);
2626
2627 // Get the (bit-cast) APInt of the APFloat and build an integer constant
2628 return DAG.getConstant(CN->getValueAPF().bitcastToAPInt(), SDLoc(CN),
2629 MVT::i16);
2630}
2631
2632SDValue DAGTypeLegalizer::SoftPromoteHalfRes_EXTRACT_VECTOR_ELT(SDNode *N) {
2633 SDValue NewOp = BitConvertVectorToIntegerVector(N->getOperand(0));
2634 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
2635 NewOp.getValueType().getVectorElementType(), NewOp,
2636 N->getOperand(1));
2637}
2638
2639SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FCOPYSIGN(SDNode *N) {
2640 SDValue LHS = GetSoftPromotedHalf(N->getOperand(0));
2641 SDValue RHS = BitConvertToInteger(N->getOperand(1));
2642 SDLoc dl(N);
2643
2644 EVT LVT = LHS.getValueType();
2645 EVT RVT = RHS.getValueType();
2646
2647 unsigned LSize = LVT.getSizeInBits();
2648 unsigned RSize = RVT.getSizeInBits();
2649
2650 // First get the sign bit of second operand.
2651 SDValue SignBit = DAG.getNode(
2652 ISD::SHL, dl, RVT, DAG.getConstant(1, dl, RVT),
2653 DAG.getConstant(RSize - 1, dl,
2654 TLI.getShiftAmountTy(RVT, DAG.getDataLayout())));
2655 SignBit = DAG.getNode(ISD::AND, dl, RVT, RHS, SignBit);
2656
2657 // Shift right or sign-extend it if the two operands have different types.
2658 int SizeDiff = RVT.getSizeInBits() - LVT.getSizeInBits();
2659 if (SizeDiff > 0) {
2660 SignBit =
2661 DAG.getNode(ISD::SRL, dl, RVT, SignBit,
2662 DAG.getConstant(SizeDiff, dl,
2663 TLI.getShiftAmountTy(SignBit.getValueType(),
2664 DAG.getDataLayout())));
2665 SignBit = DAG.getNode(ISD::TRUNCATE, dl, LVT, SignBit);
2666 } else if (SizeDiff < 0) {
2667 SignBit = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, SignBit);
2668 SignBit =
2669 DAG.getNode(ISD::SHL, dl, LVT, SignBit,
2670 DAG.getConstant(-SizeDiff, dl,
2671 TLI.getShiftAmountTy(SignBit.getValueType(),
2672 DAG.getDataLayout())));
2673 }
2674
2675 // Clear the sign bit of the first operand.
2676 SDValue Mask = DAG.getNode(
2677 ISD::SHL, dl, LVT, DAG.getConstant(1, dl, LVT),
2678 DAG.getConstant(LSize - 1, dl,
2679 TLI.getShiftAmountTy(LVT, DAG.getDataLayout())));
2680 Mask = DAG.getNode(ISD::SUB, dl, LVT, Mask, DAG.getConstant(1, dl, LVT));
2681 LHS = DAG.getNode(ISD::AND, dl, LVT, LHS, Mask);
2682
2683 // Or the value with the sign bit.
2684 return DAG.getNode(ISD::OR, dl, LVT, LHS, SignBit);
2685}
2686
2687SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FMAD(SDNode *N) {
2688 EVT OVT = N->getValueType(0);
2689 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2690 SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
2691 SDValue Op1 = GetSoftPromotedHalf(N->getOperand(1));
2692 SDValue Op2 = GetSoftPromotedHalf(N->getOperand(2));
2693 SDNodeFlags Flags = N->getFlags();
2694 SDLoc dl(N);
2695
2696 // Promote to the larger FP type.
2697 auto PromotionOpcode = GetPromotionOpcode(OVT, NVT);
2698 Op0 = DAG.getNode(PromotionOpcode, dl, NVT, Op0);
2699 Op1 = DAG.getNode(PromotionOpcode, dl, NVT, Op1);
2700 Op2 = DAG.getNode(PromotionOpcode, dl, NVT, Op2);
2701
2702 SDValue Res;
2703 if (OVT == MVT::f16) {
2704 // If f16 fma is not natively supported, the value must be promoted to an
2705 // f64 (and not to f32!) to prevent double rounding issues.
2706 SDValue A64 = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Op0, Flags);
2707 SDValue B64 = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Op1, Flags);
2708 SDValue C64 = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Op2, Flags);
2709
2710 // Prefer a wide FMA node if available; otherwise expand to mul+add.
2711 SDValue WideRes;
2712 if (TLI.isFMAFasterThanFMulAndFAdd(DAG.getMachineFunction(), MVT::f64)) {
2713 WideRes = DAG.getNode(ISD::FMA, dl, MVT::f64, A64, B64, C64, Flags);
2714 } else {
2715 SDValue Mul = DAG.getNode(ISD::FMUL, dl, MVT::f64, A64, B64, Flags);
2716 WideRes = DAG.getNode(ISD::FADD, dl, MVT::f64, Mul, C64, Flags);
2717 }
2718
2719 return DAG.getNode(GetPromotionOpcode(MVT::f64, OVT), dl, MVT::i16,
2720 WideRes);
2721 }
2722
2723 Res = DAG.getNode(N->getOpcode(), dl, NVT, Op0, Op1, Op2, Flags);
2724 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
2725}
2726
2727SDValue DAGTypeLegalizer::SoftPromoteHalfRes_ExpOp(SDNode *N) {
2728 EVT OVT = N->getValueType(0);
2729 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2730 SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
2731 SDValue Op1 = N->getOperand(1);
2732 SDLoc dl(N);
2733
2734 // Promote to the larger FP type.
2735 Op0 = DAG.getNode(GetPromotionOpcode(OVT, NVT), dl, NVT, Op0);
2736
2737 SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, Op0, Op1);
2738
2739 // Convert back to FP16 as an integer.
2740 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
2741}
2742
2743SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FFREXP(SDNode *N) {
2744 EVT OVT = N->getValueType(0);
2745 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2746 SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
2747 SDLoc dl(N);
2748
2749 // Promote to the larger FP type.
2750 Op = DAG.getNode(GetPromotionOpcode(OVT, NVT), dl, NVT, Op);
2751
2752 SDValue Res = DAG.getNode(N->getOpcode(), dl,
2753 DAG.getVTList(NVT, N->getValueType(1)), Op);
2754
2755 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
2756
2757 // Convert back to FP16 as an integer.
2758 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
2759}
2760
2761SDValue DAGTypeLegalizer::SoftPromoteHalfRes_UnaryWithTwoFPResults(SDNode *N) {
2762 EVT OVT = N->getValueType(0);
2763 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2764 SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
2765 SDLoc dl(N);
2766
2767 // Promote to the larger FP type.
2768 Op = DAG.getNode(GetPromotionOpcode(OVT, NVT), dl, NVT, Op);
2769 SDValue Res = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(NVT, NVT), Op);
2770
2771 // Convert back to FP16 as an integer.
2772 ISD::NodeType Truncate = GetPromotionOpcode(NVT, OVT);
2773 for (unsigned ResNum = 0, NumValues = N->getNumValues(); ResNum < NumValues;
2774 ++ResNum) {
2775 SDValue Trunc = DAG.getNode(Truncate, dl, MVT::i16, Res.getValue(ResNum));
2776 SetSoftPromotedHalf(SDValue(N, ResNum), Trunc);
2777 }
2778
2779 return SDValue();
2780}
2781
2782SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FP_ROUND(SDNode *N) {
2783 EVT RVT = N->getValueType(0);
2784 bool IsStrict = N->isStrictFPOpcode();
2785 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
2786 EVT SVT = Op.getValueType();
2787
2788 // If the input type needs to be softened, do that now so that call lowering
2789 // will see the f16 type.
2790 if (getTypeAction(SVT) == TargetLowering::TypeSoftenFloat) {
2791 RTLIB::Libcall LC = RTLIB::getFPROUND(SVT, RVT);
2792 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_ROUND libcall");
2793
2794 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
2795 Op = GetSoftenedFloat(Op);
2796 TargetLowering::MakeLibCallOptions CallOptions;
2797 CallOptions.setTypeListBeforeSoften(SVT, RVT);
2798 std::pair<SDValue, SDValue> Tmp =
2799 TLI.makeLibCall(DAG, LC, RVT, Op, CallOptions, SDLoc(N), Chain);
2800 if (IsStrict)
2801 ReplaceValueWith(SDValue(N, 1), Tmp.second);
2802 return DAG.getNode(ISD::BITCAST, SDLoc(N), MVT::i16, Tmp.first);
2803 }
2804
2805 if (IsStrict) {
2806 SDValue Res = DAG.getNode(GetPromotionOpcodeStrict(SVT, RVT), SDLoc(N),
2807 {MVT::i16, MVT::Other}, {N->getOperand(0), Op});
2808 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
2809 return Res;
2810 }
2811
2812 return DAG.getNode(GetPromotionOpcode(SVT, RVT), SDLoc(N), MVT::i16,
2813 N->getOperand(0));
2814}
2815
2816SDValue DAGTypeLegalizer::SoftPromoteHalfRes_LOAD(SDNode *N) {
2817 LoadSDNode *L = cast<LoadSDNode>(N);
2818
2819 // Load the value as an integer value with the same number of bits.
2820 assert(L->getExtensionType() == ISD::NON_EXTLOAD && "Unexpected extension!");
2821 SDValue NewL =
2822 DAG.getLoad(L->getAddressingMode(), L->getExtensionType(), MVT::i16,
2823 SDLoc(N), L->getChain(), L->getBasePtr(), L->getOffset(),
2824 L->getPointerInfo(), MVT::i16, L->getBaseAlign(),
2825 L->getMemOperand()->getFlags(), L->getAAInfo());
2826 // Legalize the chain result by replacing uses of the old value chain with the
2827 // new one
2828 ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
2829 return NewL;
2830}
2831
2832SDValue DAGTypeLegalizer::SoftPromoteHalfRes_ATOMIC_LOAD(SDNode *N) {
2833 AtomicSDNode *AM = cast<AtomicSDNode>(N);
2834
2835 // Load the value as an integer value with the same number of bits.
2836 SDValue NewL = DAG.getAtomic(
2837 ISD::ATOMIC_LOAD, SDLoc(N), MVT::i16, DAG.getVTList(MVT::i16, MVT::Other),
2838 {AM->getChain(), AM->getBasePtr()}, AM->getMemOperand());
2839
2840 // Legalize the chain result by replacing uses of the old value chain with the
2841 // new one
2842 ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
2843 return NewL;
2844}
2845
2846SDValue DAGTypeLegalizer::SoftPromoteHalfRes_SELECT(SDNode *N) {
2847 SDValue Op1 = GetSoftPromotedHalf(N->getOperand(1));
2848 SDValue Op2 = GetSoftPromotedHalf(N->getOperand(2));
2849 return DAG.getSelect(SDLoc(N), Op1.getValueType(), N->getOperand(0), Op1, Op2,
2850 N->getFlags());
2851}
2852
2853SDValue DAGTypeLegalizer::SoftPromoteHalfRes_SELECT_CC(SDNode *N) {
2854 SDValue Op2 = GetSoftPromotedHalf(N->getOperand(2));
2855 SDValue Op3 = GetSoftPromotedHalf(N->getOperand(3));
2856 return DAG.getNode(ISD::SELECT_CC, SDLoc(N), Op2.getValueType(),
2857 N->getOperand(0), N->getOperand(1), Op2, Op3,
2858 N->getOperand(4));
2859}
2860
2861SDValue DAGTypeLegalizer::SoftPromoteHalfRes_XINT_TO_FP(SDNode *N) {
2862 EVT OVT = N->getValueType(0);
2863 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2864 SDLoc dl(N);
2865
2866 if (N->isStrictFPOpcode()) {
2867 SDValue Op = DAG.getNode(N->getOpcode(), dl, {NVT, MVT::Other},
2868 {N->getOperand(0), N->getOperand(1)});
2869 Op = DAG.getNode(GetPromotionOpcodeStrict(NVT, OVT), dl,
2870 {MVT::i16, MVT::Other}, {Op.getValue(1), Op});
2871 ReplaceValueWith(SDValue(N, 1), Op.getValue(1));
2872 return Op;
2873 }
2874
2875 SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, N->getOperand(0));
2876
2877 // Round the value to the softened type.
2878 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
2879}
2880
2881SDValue
2882DAGTypeLegalizer::SoftPromoteHalfRes_CONVERT_FROM_ARBITRARY_FP(SDNode *N) {
2883 EVT OVT = N->getValueType(0);
2884 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2885 SDLoc dl(N);
2886
2888 N->getOperand(0), N->getOperand(1));
2889
2890 // Round the value to the softened type.
2891 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
2892}
2893
2894SDValue DAGTypeLegalizer::SoftPromoteHalfRes_UNDEF(SDNode *N) {
2895 return DAG.getUNDEF(MVT::i16);
2896}
2897
2898SDValue DAGTypeLegalizer::SoftPromoteHalfRes_UnaryOp(SDNode *N) {
2899 EVT OVT = N->getValueType(0);
2900 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2901 SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
2902 SDLoc dl(N);
2903
2904 // Promote to the larger FP type.
2905 Op = DAG.getNode(GetPromotionOpcode(OVT, NVT), dl, NVT, Op);
2906
2907 SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, Op);
2908
2909 // Convert back to FP16 as an integer.
2910 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
2911}
2912
2913SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FABS(SDNode *N) {
2914 SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
2915 SDLoc dl(N);
2916
2917 // Clear the sign bit.
2918 return DAG.getNode(ISD::AND, dl, MVT::i16, Op,
2919 DAG.getConstant(0x7fff, dl, MVT::i16));
2920}
2921
2922SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FNEG(SDNode *N) {
2923 SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
2924 SDLoc dl(N);
2925
2926 // Invert the sign bit.
2927 return DAG.getNode(ISD::XOR, dl, MVT::i16, Op,
2928 DAG.getConstant(0x8000, dl, MVT::i16));
2929}
2930
2931SDValue DAGTypeLegalizer::SoftPromoteHalfRes_AssertNoFPClass(SDNode *N) {
2932 return GetSoftPromotedHalf(N->getOperand(0));
2933}
2934
2935SDValue DAGTypeLegalizer::SoftPromoteHalfRes_BinOp(SDNode *N) {
2936 EVT OVT = N->getValueType(0);
2937 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2938 SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
2939 SDValue Op1 = GetSoftPromotedHalf(N->getOperand(1));
2940 SDLoc dl(N);
2941
2942 // Promote to the larger FP type.
2943 auto PromotionOpcode = GetPromotionOpcode(OVT, NVT);
2944 Op0 = DAG.getNode(PromotionOpcode, dl, NVT, Op0);
2945 Op1 = DAG.getNode(PromotionOpcode, dl, NVT, Op1);
2946
2947 SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, Op0, Op1);
2948
2949 // Convert back to FP16 as an integer.
2950 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
2951}
2952
2953SDValue DAGTypeLegalizer::SoftPromoteHalfRes_VECREDUCE(SDNode *N) {
2954 // Expand and soften recursively.
2955 ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduce(N, DAG));
2956 return SDValue();
2957}
2958
2959SDValue DAGTypeLegalizer::SoftPromoteHalfRes_VECREDUCE_SEQ(SDNode *N) {
2960 // Expand and soften.
2961 ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduceSeq(N, DAG));
2962 return SDValue();
2963}
2964
2965//===----------------------------------------------------------------------===//
2966// Half Operand Soft Promotion
2967//===----------------------------------------------------------------------===//
2968
2969bool DAGTypeLegalizer::SoftPromoteHalfOperand(SDNode *N, unsigned OpNo) {
2970 LLVM_DEBUG(dbgs() << "Soft promote half operand " << OpNo << ": ";
2971 N->dump(&DAG));
2972 SDValue Res = SDValue();
2973
2974 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false)) {
2975 LLVM_DEBUG(dbgs() << "Node has been custom lowered, done\n");
2976 return false;
2977 }
2978
2979 // Nodes that use a promotion-requiring floating point operand, but doesn't
2980 // produce a soft promotion-requiring floating point result, need to be
2981 // legalized to use the soft promoted float operand. Nodes that produce at
2982 // least one soft promotion-requiring floating point result have their
2983 // operands legalized as a part of PromoteFloatResult.
2984 switch (N->getOpcode()) {
2985 default:
2986 #ifndef NDEBUG
2987 dbgs() << "SoftPromoteHalfOperand Op #" << OpNo << ": ";
2988 N->dump(&DAG); dbgs() << "\n";
2989 #endif
2990 report_fatal_error("Do not know how to soft promote this operator's "
2991 "operand!");
2992
2993 case ISD::BITCAST: Res = SoftPromoteHalfOp_BITCAST(N); break;
2994 case ISD::BUILD_VECTOR:
2995 Res = SoftPromoteHalfOp_BUILD_VECTOR(N);
2996 break;
2997 case ISD::FAKE_USE:
2998 Res = SoftPromoteHalfOp_FAKE_USE(N, OpNo);
2999 break;
3000 case ISD::FCOPYSIGN:
3001 Res = SoftPromoteHalfOp_FCOPYSIGN(N, OpNo);
3002 break;
3003 case ISD::FP_TO_SINT:
3004 case ISD::FP_TO_UINT:
3007 case ISD::LLRINT:
3008 case ISD::LLROUND:
3009 case ISD::LRINT:
3010 case ISD::LROUND:
3011 case ISD::STRICT_LLRINT:
3013 case ISD::STRICT_LRINT:
3014 case ISD::STRICT_LROUND:
3015 Res = SoftPromoteHalfOp_Op0WithStrict(N);
3016 break;
3019 Res = SoftPromoteHalfOp_FP_TO_XINT_SAT(N); break;
3021 Res = SoftPromoteHalfOp_CONVERT_TO_ARBITRARY_FP(N);
3022 break;
3024 case ISD::FP_EXTEND: Res = SoftPromoteHalfOp_FP_EXTEND(N); break;
3025 case ISD::SELECT_CC: Res = SoftPromoteHalfOp_SELECT_CC(N, OpNo); break;
3026 case ISD::BR_CC:
3027 Res = SoftPromoteHalfOp_BR_CC(N);
3028 break;
3029 case ISD::SETCC: Res = SoftPromoteHalfOp_SETCC(N); break;
3030 case ISD::STORE: Res = SoftPromoteHalfOp_STORE(N, OpNo); break;
3031 case ISD::ATOMIC_STORE:
3032 Res = SoftPromoteHalfOp_ATOMIC_STORE(N, OpNo);
3033 break;
3034 case ISD::STACKMAP:
3035 Res = SoftPromoteHalfOp_STACKMAP(N, OpNo);
3036 break;
3037 case ISD::PATCHPOINT:
3038 Res = SoftPromoteHalfOp_PATCHPOINT(N, OpNo);
3039 break;
3040 }
3041
3042 if (!Res.getNode())
3043 return false;
3044
3045 assert(Res.getNode() != N && "Expected a new node!");
3046
3047 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
3048 "Invalid operand expansion");
3049
3050 ReplaceValueWith(SDValue(N, 0), Res);
3051 return false;
3052}
3053
3054SDValue DAGTypeLegalizer::SoftPromoteHalfOp_BITCAST(SDNode *N) {
3055 SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
3056
3057 return DAG.getNode(ISD::BITCAST, SDLoc(N), N->getValueType(0), Op0);
3058}
3059
3060SDValue DAGTypeLegalizer::SoftPromoteHalfOp_BUILD_VECTOR(SDNode *N) {
3061 SDLoc dl(N);
3062 EVT VT = N->getValueType(0);
3063
3064 SmallVector<SDValue, 8> Ops(N->getNumOperands());
3065 for (unsigned I = 0, E = N->getNumOperands(); I != E; ++I)
3066 Ops[I] = GetSoftPromotedHalf(N->getOperand(I));
3067
3068 EVT IVT = VT.changeVectorElementTypeToInteger();
3069 SDValue Res = DAG.getBuildVector(IVT, dl, Ops);
3070 return DAG.getBitcast(VT, Res);
3071}
3072
3073SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FAKE_USE(SDNode *N, unsigned OpNo) {
3074 assert(OpNo == 1 && "Only Operand 1 must need promotion here");
3075 SDValue Op = GetSoftPromotedHalf(N->getOperand(OpNo));
3076 return DAG.getNode(N->getOpcode(), SDLoc(N), MVT::Other, N->getOperand(0),
3077 Op);
3078}
3079
3080SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FCOPYSIGN(SDNode *N,
3081 unsigned OpNo) {
3082 assert(OpNo == 1 && "Only Operand 1 must need promotion here");
3083 SDValue Op1 = N->getOperand(1);
3084 EVT RVT = Op1.getValueType();
3085 SDLoc dl(N);
3086
3087 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op1.getValueType());
3088
3089 Op1 = GetSoftPromotedHalf(Op1);
3090 Op1 = DAG.getNode(GetPromotionOpcode(RVT, NVT), dl, NVT, Op1);
3091
3092 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0), N->getOperand(0),
3093 Op1);
3094}
3095
3096SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_EXTEND(SDNode *N) {
3097 EVT RVT = N->getValueType(0);
3098 bool IsStrict = N->isStrictFPOpcode();
3099 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
3100 EVT SVT = Op.getValueType();
3101 Op = GetSoftPromotedHalf(N->getOperand(IsStrict ? 1 : 0));
3102
3103 if (IsStrict) {
3104 SDValue Res = DAG.getNode(GetPromotionOpcodeStrict(SVT, RVT), SDLoc(N),
3105 {RVT, MVT::Other}, {N->getOperand(0), Op});
3106 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
3107 ReplaceValueWith(SDValue(N, 0), Res);
3108 return SDValue();
3109 }
3110
3111 return DAG.getNode(GetPromotionOpcode(SVT, RVT), SDLoc(N), RVT, Op);
3112}
3113
3114SDValue DAGTypeLegalizer::SoftPromoteHalfOp_Op0WithStrict(SDNode *N) {
3115 EVT RVT = N->getValueType(0);
3116 bool IsStrict = N->isStrictFPOpcode();
3117 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
3118 EVT SVT = Op.getValueType();
3119 SDLoc dl(N);
3120
3121 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), SVT);
3122 Op = GetSoftPromotedHalf(Op);
3123
3124 if (IsStrict) {
3125 Op = DAG.getNode(GetPromotionOpcodeStrict(SVT, RVT), dl, {NVT, MVT::Other},
3126 {N->getOperand(0), Op});
3127 Op = DAG.getNode(N->getOpcode(), dl, {RVT, MVT::Other},
3128 {Op.getValue(1), Op});
3129 ReplaceValueWith(SDValue(N, 1), Op.getValue(1));
3130 ReplaceValueWith(SDValue(N, 0), Op);
3131 return SDValue();
3132 }
3133
3134 SDValue Res = DAG.getNode(GetPromotionOpcode(SVT, RVT), dl, NVT, Op);
3135 return DAG.getNode(N->getOpcode(), dl, RVT, Res);
3136}
3137
3138SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_TO_XINT_SAT(SDNode *N) {
3139 EVT RVT = N->getValueType(0);
3140 SDValue Op = N->getOperand(0);
3141 EVT SVT = Op.getValueType();
3142 SDLoc dl(N);
3143
3144 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType());
3145
3146 Op = GetSoftPromotedHalf(Op);
3147
3148 SDValue Res = DAG.getNode(GetPromotionOpcode(SVT, RVT), dl, NVT, Op);
3149
3150 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0), Res,
3151 N->getOperand(1));
3152}
3153
3154// TODO: CONVERT_TO_ARBITRARY_FP also needs SoftenFloatOperand and
3155// ExpandFloatOperand handlers for targets with software float or ppcf128
3156// source types. Same gap exists for CONVERT_FROM_ARBITRARY_FP.
3157SDValue DAGTypeLegalizer::SoftPromoteHalfOp_CONVERT_TO_ARBITRARY_FP(SDNode *N) {
3158 EVT RVT = N->getValueType(0);
3159 SDValue Op = N->getOperand(0);
3160 EVT SVT = Op.getValueType();
3161 SDLoc dl(N);
3162
3163 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType());
3164 Op = GetSoftPromotedHalf(Op);
3165 SDValue Res = DAG.getNode(GetPromotionOpcode(SVT, RVT), dl, NVT, Op);
3166
3167 return DAG.getNode(ISD::CONVERT_TO_ARBITRARY_FP, dl, N->getValueType(0), Res,
3168 N->getOperand(1), N->getOperand(2), N->getOperand(3));
3169}
3170
3171SDValue DAGTypeLegalizer::SoftPromoteHalfOp_BR_CC(SDNode *N) {
3172 // ISD::BR_CC node: chain(0), condcode(1), LHS(2), RHS(3), dest(4)
3173 // The comparison operands (LHS, RHS) are soft-promoted halfs.
3174 SDValue Op0 = N->getOperand(2);
3175 SDValue Op1 = N->getOperand(3);
3176 SDLoc dl(N);
3177
3178 EVT SVT = Op0.getValueType();
3179 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), SVT);
3180
3181 // Get the soft-promoted i16 values
3182 Op0 = GetSoftPromotedHalf(Op0);
3183 Op1 = GetSoftPromotedHalf(Op1);
3184
3185 // Promote both comparison operands to the larger FP type.
3186 unsigned PromotionOpcode = GetPromotionOpcode(SVT, NVT);
3187 Op0 = DAG.getNode(PromotionOpcode, dl, NVT, Op0);
3188 Op1 = DAG.getNode(PromotionOpcode, dl, NVT, Op1);
3189
3190 // Create a new BR_CC node with promoted operands
3191 return DAG.getNode(ISD::BR_CC, dl, MVT::Other, N->getOperand(0),
3192 N->getOperand(1), Op0, Op1, N->getOperand(4));
3193}
3194
3195SDValue DAGTypeLegalizer::SoftPromoteHalfOp_SELECT_CC(SDNode *N,
3196 unsigned OpNo) {
3197 assert(OpNo == 0 && "Can only soften the comparison values");
3198 SDValue Op0 = N->getOperand(0);
3199 SDValue Op1 = N->getOperand(1);
3200 SDLoc dl(N);
3201
3202 EVT SVT = Op0.getValueType();
3203 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), SVT);
3204
3205 Op0 = GetSoftPromotedHalf(Op0);
3206 Op1 = GetSoftPromotedHalf(Op1);
3207
3208 // Promote to the larger FP type.
3209 auto PromotionOpcode = GetPromotionOpcode(SVT, NVT);
3210 Op0 = DAG.getNode(PromotionOpcode, dl, NVT, Op0);
3211 Op1 = DAG.getNode(PromotionOpcode, dl, NVT, Op1);
3212
3213 return DAG.getNode(ISD::SELECT_CC, SDLoc(N), N->getValueType(0), Op0, Op1,
3214 N->getOperand(2), N->getOperand(3), N->getOperand(4));
3215}
3216
3217SDValue DAGTypeLegalizer::SoftPromoteHalfOp_SETCC(SDNode *N) {
3218 SDValue Op0 = N->getOperand(0);
3219 SDValue Op1 = N->getOperand(1);
3220 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(2))->get();
3221 SDLoc dl(N);
3222
3223 EVT SVT = Op0.getValueType();
3224 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op0.getValueType());
3225
3226 Op0 = GetSoftPromotedHalf(Op0);
3227 Op1 = GetSoftPromotedHalf(Op1);
3228
3229 // Promote to the larger FP type.
3230 auto PromotionOpcode = GetPromotionOpcode(SVT, NVT);
3231 Op0 = DAG.getNode(PromotionOpcode, dl, NVT, Op0);
3232 Op1 = DAG.getNode(PromotionOpcode, dl, NVT, Op1);
3233
3234 return DAG.getSetCC(SDLoc(N), N->getValueType(0), Op0, Op1, CCCode);
3235}
3236
3237SDValue DAGTypeLegalizer::SoftPromoteHalfOp_STORE(SDNode *N, unsigned OpNo) {
3238 assert(OpNo == 1 && "Can only soften the stored value!");
3239 StoreSDNode *ST = cast<StoreSDNode>(N);
3240 SDValue Val = ST->getValue();
3241 SDLoc dl(N);
3242
3243 assert(!ST->isTruncatingStore() && "Unexpected truncating store.");
3244 SDValue Promoted = GetSoftPromotedHalf(Val);
3245 return DAG.getStore(ST->getChain(), dl, Promoted, ST->getBasePtr(),
3246 ST->getMemOperand());
3247}
3248
3249SDValue DAGTypeLegalizer::SoftPromoteHalfOp_ATOMIC_STORE(SDNode *N,
3250 unsigned OpNo) {
3251 assert(OpNo == 1 && "Can only soften the stored value!");
3252 AtomicSDNode *ST = cast<AtomicSDNode>(N);
3253 SDValue Val = ST->getVal();
3254 SDLoc dl(N);
3255
3256 SDValue Promoted = GetSoftPromotedHalf(Val);
3257 return DAG.getAtomic(ISD::ATOMIC_STORE, dl, Promoted.getValueType(),
3258 ST->getChain(), Promoted, ST->getBasePtr(),
3259 ST->getMemOperand());
3260}
3261
3262SDValue DAGTypeLegalizer::SoftPromoteHalfOp_STACKMAP(SDNode *N, unsigned OpNo) {
3263 assert(OpNo > 1); // Because the first two arguments are guaranteed legal.
3264 SmallVector<SDValue> NewOps(N->ops());
3265 SDValue Op = N->getOperand(OpNo);
3266 NewOps[OpNo] = GetSoftPromotedHalf(Op);
3268 DAG.getNode(N->getOpcode(), SDLoc(N), N->getVTList(), NewOps);
3269
3270 for (unsigned ResNum = 0; ResNum < N->getNumValues(); ResNum++)
3271 ReplaceValueWith(SDValue(N, ResNum), NewNode.getValue(ResNum));
3272
3273 return SDValue(); // Signal that we replaced the node ourselves.
3274}
3275
3276SDValue DAGTypeLegalizer::SoftPromoteHalfOp_PATCHPOINT(SDNode *N,
3277 unsigned OpNo) {
3278 assert(OpNo >= 7);
3279 SmallVector<SDValue> NewOps(N->ops());
3280 SDValue Op = N->getOperand(OpNo);
3281 NewOps[OpNo] = GetSoftPromotedHalf(Op);
3283 DAG.getNode(N->getOpcode(), SDLoc(N), N->getVTList(), NewOps);
3284
3285 for (unsigned ResNum = 0; ResNum < N->getNumValues(); ResNum++)
3286 ReplaceValueWith(SDValue(N, ResNum), NewNode.getValue(ResNum));
3287
3288 return SDValue(); // Signal that we replaced the node ourselves.
3289}
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
#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.
Type * getValueType(Value *V, bool ReVec, bool LookThroughCmp)
Returns the "element type" of the given value/instruction V.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
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)