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