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