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