LLVM 22.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 if (getTypeAction(Op.getValueType()) == TargetLowering::TypePromoteFloat) {
638 Op = GetPromotedFloat(Op);
639 // If the promotion did the FP_EXTEND to the destination type for us,
640 // there's nothing left to do here.
641 if (Op.getValueType() == N->getValueType(0)) {
642 if (IsStrict)
643 ReplaceValueWith(SDValue(N, 1), Chain);
644 return BitConvertToInteger(Op);
645 }
646 }
647
648 // There's only a libcall for f16 -> f32 and shifting is only valid for bf16
649 // -> f32, so proceed in two stages. Also, it's entirely possible for both
650 // f16 and f32 to be legal, so use the fully hard-float FP_EXTEND rather
651 // than FP16_TO_FP.
652 if ((Op.getValueType() == MVT::f16 || Op.getValueType() == MVT::bf16) &&
653 N->getValueType(0) != MVT::f32) {
654 if (IsStrict) {
655 Op = DAG.getNode(ISD::STRICT_FP_EXTEND, SDLoc(N),
656 { MVT::f32, MVT::Other }, { Chain, Op });
657 Chain = Op.getValue(1);
658 } else {
659 Op = DAG.getNode(ISD::FP_EXTEND, SDLoc(N), MVT::f32, Op);
660 }
661 }
662
663 if (Op.getValueType() == MVT::bf16) {
664 // FIXME: Need ReplaceValueWith on chain in strict case
665 return SoftenFloatRes_BF16_TO_FP(N);
666 }
667
668 RTLIB::Libcall LC = RTLIB::getFPEXT(Op.getValueType(), N->getValueType(0));
669 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_EXTEND!");
670 TargetLowering::MakeLibCallOptions CallOptions;
671 EVT OpVT = N->getOperand(IsStrict ? 1 : 0).getValueType();
672 CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0));
673 std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, NVT, Op,
674 CallOptions, SDLoc(N),
675 Chain);
676 if (IsStrict)
677 ReplaceValueWith(SDValue(N, 1), Tmp.second);
678 return Tmp.first;
679}
680
681// FIXME: Should we just use 'normal' FP_EXTEND / FP_TRUNC instead of special
682// nodes?
683SDValue DAGTypeLegalizer::SoftenFloatRes_FP16_TO_FP(SDNode *N) {
684 EVT MidVT = TLI.getTypeToTransformTo(*DAG.getContext(), MVT::f32);
685 SDValue Op = N->getOperand(0);
686 TargetLowering::MakeLibCallOptions CallOptions;
687 EVT OpsVT[1] = { N->getOperand(0).getValueType() };
688 CallOptions.setTypeListBeforeSoften(OpsVT, N->getValueType(0));
689 SDValue Res32 = TLI.makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MidVT, Op,
690 CallOptions, SDLoc(N)).first;
691 if (N->getValueType(0) == MVT::f32)
692 return Res32;
693
694 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
695 RTLIB::Libcall LC = RTLIB::getFPEXT(MVT::f32, N->getValueType(0));
696 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_EXTEND!");
697 return TLI.makeLibCall(DAG, LC, NVT, Res32, CallOptions, SDLoc(N)).first;
698}
699
700// FIXME: Should we just use 'normal' FP_EXTEND / FP_TRUNC instead of special
701// nodes?
702SDValue DAGTypeLegalizer::SoftenFloatRes_BF16_TO_FP(SDNode *N) {
703 assert(N->getValueType(0) == MVT::f32 &&
704 "Can only soften BF16_TO_FP with f32 result");
705 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), MVT::f32);
706 SDValue Op = N->getOperand(0);
707 SDLoc DL(N);
708 Op = DAG.getNode(ISD::ANY_EXTEND, DL, NVT,
709 DAG.getNode(ISD::BITCAST, DL, MVT::i16, Op));
710 SDValue Res = DAG.getNode(ISD::SHL, DL, NVT, Op,
711 DAG.getShiftAmountConstant(16, NVT, DL));
712 return Res;
713}
714
715SDValue DAGTypeLegalizer::SoftenFloatRes_FP_ROUND(SDNode *N) {
716 bool IsStrict = N->isStrictFPOpcode();
717 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
718 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
719 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
720 RTLIB::Libcall LC = RTLIB::getFPROUND(Op.getValueType(), N->getValueType(0));
721 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_ROUND!");
722 TargetLowering::MakeLibCallOptions CallOptions;
723 EVT OpVT = N->getOperand(IsStrict ? 1 : 0).getValueType();
724 CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0));
725 std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, NVT, Op,
726 CallOptions, SDLoc(N),
727 Chain);
728 if (IsStrict)
729 ReplaceValueWith(SDValue(N, 1), Tmp.second);
730 return Tmp.first;
731}
732
733SDValue DAGTypeLegalizer::SoftenFloatRes_FPOW(SDNode *N) {
734 return SoftenFloatRes_Binary(N, RTLIB::getPOW(N->getValueType(0)));
735}
736
737SDValue DAGTypeLegalizer::SoftenFloatRes_ExpOp(SDNode *N) {
738 bool IsStrict = N->isStrictFPOpcode();
739 unsigned Offset = IsStrict ? 1 : 0;
740 bool IsPowI =
741 N->getOpcode() == ISD::FPOWI || N->getOpcode() == ISD::STRICT_FPOWI;
742 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
743
744 RTLIB::Libcall LC = IsPowI ? RTLIB::getPOWI(N->getValueType(0))
745 : RTLIB::getLDEXP(N->getValueType(0));
746 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fpowi.");
747 if (TLI.getLibcallImpl(LC) == RTLIB::Unsupported) {
748 // Some targets don't have a powi libcall; use pow instead.
749 // FIXME: Implement this if some target needs it.
750 DAG.getContext()->emitError("do not know how to soften fpowi to fpow");
751 if (IsStrict)
752 ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
753 return DAG.getPOISON(NVT);
754 }
755
756 if (DAG.getLibInfo().getIntSize() !=
757 N->getOperand(1 + Offset).getValueType().getSizeInBits()) {
758 // If the exponent does not match with sizeof(int) a libcall to RTLIB::POWI
759 // would use the wrong type for the argument.
760 DAG.getContext()->emitError("powi exponent does not match sizeof(int)");
761 if (IsStrict)
762 ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
763 return DAG.getPOISON(NVT);
764 }
765
766 SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0 + Offset)),
767 N->getOperand(1 + Offset) };
768 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
769 TargetLowering::MakeLibCallOptions CallOptions;
770 EVT OpsVT[2] = { N->getOperand(0 + Offset).getValueType(),
771 N->getOperand(1 + Offset).getValueType() };
772 CallOptions.setTypeListBeforeSoften(OpsVT, N->getValueType(0));
773 std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, NVT, Ops,
774 CallOptions, SDLoc(N),
775 Chain);
776 if (IsStrict)
777 ReplaceValueWith(SDValue(N, 1), Tmp.second);
778 return Tmp.first;
779}
780
781SDValue DAGTypeLegalizer::SoftenFloatRes_FFREXP(SDNode *N) {
782 assert(!N->isStrictFPOpcode() && "strictfp not implemented for frexp");
783 EVT VT0 = N->getValueType(0);
784 EVT VT1 = N->getValueType(1);
785 RTLIB::Libcall LC = RTLIB::getFREXP(VT0);
786 EVT NVT0 = TLI.getTypeToTransformTo(*DAG.getContext(), VT0);
787 SDLoc DL(N);
788
789 if (DAG.getLibInfo().getIntSize() != VT1.getSizeInBits()) {
790 // If the exponent does not match with sizeof(int) a libcall would use the
791 // wrong type for the argument.
792 // TODO: Should be able to handle mismatches.
793 DAG.getContext()->emitError("ffrexp exponent does not match sizeof(int)");
794 SDValue PoisonExp = DAG.getPOISON(VT1);
795 ReplaceValueWith(SDValue(N, 1), PoisonExp);
796 return DAG.getMergeValues({DAG.getPOISON(NVT0), PoisonExp}, DL);
797 }
798
799 SDValue StackSlot = DAG.CreateStackTemporary(VT1);
800
801 auto PointerTy = PointerType::getUnqual(*DAG.getContext());
802 TargetLowering::MakeLibCallOptions CallOptions;
803 SDValue Ops[2] = {GetSoftenedFloat(N->getOperand(0)), StackSlot};
804 EVT OpsVT[2] = {VT0, StackSlot.getValueType()};
805 Type *CallOpsTypeOverrides[2] = {nullptr, PointerTy};
806
807 // TODO: setTypeListBeforeSoften can't properly express multiple return types,
808 // but we only really need to handle the 0th one for softening anyway.
809 CallOptions.setTypeListBeforeSoften({OpsVT}, VT0)
810 .setOpsTypeOverrides(CallOpsTypeOverrides);
811
812 auto [ReturnVal, Chain] = TLI.makeLibCall(DAG, LC, NVT0, Ops, CallOptions, DL,
813 /*Chain=*/SDValue());
814 int FrameIdx = cast<FrameIndexSDNode>(StackSlot)->getIndex();
815 auto PtrInfo =
816 MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FrameIdx);
817
818 SDValue LoadExp = DAG.getLoad(VT1, DL, Chain, StackSlot, PtrInfo);
819
820 ReplaceValueWith(SDValue(N, 1), LoadExp);
821 return ReturnVal;
822}
823
824bool DAGTypeLegalizer::SoftenFloatRes_UnaryWithTwoFPResults(
825 SDNode *N, RTLIB::Libcall LC, std::optional<unsigned> CallRetResNo) {
826 assert(!N->isStrictFPOpcode() && "strictfp not implemented");
827 EVT VT = N->getValueType(0);
828
829 assert(VT == N->getValueType(1) &&
830 "expected both return values to have the same type");
831
832 RTLIB::LibcallImpl LCImpl = TLI.getLibcallImpl(LC);
833 if (LCImpl == RTLIB::Unsupported)
834 return false;
835
836 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
837
838 SDLoc DL(N);
839
840 SmallVector<SDValue, 3> Ops = {GetSoftenedFloat(N->getOperand(0))};
841 SmallVector<EVT, 3> OpsVT = {VT};
842
843 std::array<SDValue, 2> StackSlots;
844 SmallVector<Type *, 3> CallOpsTypeOverrides = {nullptr};
845 auto PointerTy = PointerType::getUnqual(*DAG.getContext());
846 for (unsigned ResNum = 0; ResNum < N->getNumValues(); ++ResNum) {
847 if (ResNum == CallRetResNo)
848 continue;
849 SDValue StackSlot = DAG.CreateStackTemporary(NVT);
850 Ops.push_back(StackSlot);
851 OpsVT.push_back(StackSlot.getValueType());
852 StackSlots[ResNum] = StackSlot;
853 CallOpsTypeOverrides.push_back(PointerTy);
854 }
855
856 TargetLowering::MakeLibCallOptions CallOptions;
857 // TODO: setTypeListBeforeSoften can't properly express multiple return types,
858 // but since both returns have the same type it should be okay.
859 CallOptions.setTypeListBeforeSoften({OpsVT}, VT)
860 .setOpsTypeOverrides(CallOpsTypeOverrides);
861
862 auto [ReturnVal, Chain] =
863 TLI.makeLibCall(DAG, LCImpl, NVT, Ops, CallOptions, DL,
864 /*Chain=*/SDValue());
865
866 auto CreateStackLoad = [&, Chain = Chain](SDValue StackSlot) {
867 int FrameIdx = cast<FrameIndexSDNode>(StackSlot)->getIndex();
868 auto PtrInfo =
869 MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FrameIdx);
870 return DAG.getLoad(NVT, DL, Chain, StackSlot, PtrInfo);
871 };
872
873 for (auto [ResNum, SlackSlot] : enumerate(StackSlots)) {
874 if (CallRetResNo == ResNum) {
875 SetSoftenedFloat(SDValue(N, ResNum), ReturnVal);
876 continue;
877 }
878 SetSoftenedFloat(SDValue(N, ResNum), CreateStackLoad(SlackSlot));
879 }
880
881 return true;
882}
883
884SDValue DAGTypeLegalizer::SoftenFloatRes_FSINCOS(SDNode *N) {
885 EVT VT = N->getValueType(0);
886 if (SoftenFloatRes_UnaryWithTwoFPResults(N, RTLIB::getSINCOS(VT)))
887 return SDValue();
888
889 // Fall back on softening the separate sin and cos calls if available.
890 RTLIB::Libcall SinLC = RTLIB::getSIN(VT);
891 RTLIB::Libcall CosLC = RTLIB::getCOS(VT);
892
893 SDValue SoftSin, SoftCos;
894 if (TLI.getLibcallImpl(SinLC) == RTLIB::Unsupported ||
895 TLI.getLibcallImpl(CosLC) == RTLIB::Unsupported) {
896 DAG.getContext()->emitError("do not know how to soften fsincos");
897
898 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
899 SoftSin = SoftCos = DAG.getPOISON(NVT);
900 } else {
901 SoftSin = SoftenFloatRes_Unary(N, SinLC);
902 SoftCos = SoftenFloatRes_Unary(N, CosLC);
903 }
904
905 SetSoftenedFloat(SDValue(N, 0), SoftSin);
906 SetSoftenedFloat(SDValue(N, 1), SoftCos);
907 return SDValue();
908}
909
910SDValue DAGTypeLegalizer::SoftenFloatRes_FMODF(SDNode *N) {
911 EVT VT = N->getValueType(0);
912 if (SoftenFloatRes_UnaryWithTwoFPResults(N, RTLIB::getMODF(VT),
913 /*CallRetResNo=*/0))
914 return SDValue();
915
916 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
917 DAG.getContext()->emitError("do not know how to soften fmodf");
918 SDValue Poison = DAG.getPOISON(NVT);
919 SetSoftenedFloat(SDValue(N, 0), Poison);
920 SetSoftenedFloat(SDValue(N, 1), Poison);
921 return SDValue();
922}
923
924SDValue DAGTypeLegalizer::SoftenFloatRes_FREM(SDNode *N) {
925 return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
926 RTLIB::REM_F32,
927 RTLIB::REM_F64,
928 RTLIB::REM_F80,
929 RTLIB::REM_F128,
930 RTLIB::REM_PPCF128));
931}
932
933SDValue DAGTypeLegalizer::SoftenFloatRes_FRINT(SDNode *N) {
934 return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
935 RTLIB::RINT_F32,
936 RTLIB::RINT_F64,
937 RTLIB::RINT_F80,
938 RTLIB::RINT_F128,
939 RTLIB::RINT_PPCF128));
940}
941
942SDValue DAGTypeLegalizer::SoftenFloatRes_FROUND(SDNode *N) {
943 return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
944 RTLIB::ROUND_F32,
945 RTLIB::ROUND_F64,
946 RTLIB::ROUND_F80,
947 RTLIB::ROUND_F128,
948 RTLIB::ROUND_PPCF128));
949}
950
951SDValue DAGTypeLegalizer::SoftenFloatRes_FROUNDEVEN(SDNode *N) {
952 return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
953 RTLIB::ROUNDEVEN_F32,
954 RTLIB::ROUNDEVEN_F64,
955 RTLIB::ROUNDEVEN_F80,
956 RTLIB::ROUNDEVEN_F128,
957 RTLIB::ROUNDEVEN_PPCF128));
958}
959
960SDValue DAGTypeLegalizer::SoftenFloatRes_FSIN(SDNode *N) {
961 return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
962 RTLIB::SIN_F32,
963 RTLIB::SIN_F64,
964 RTLIB::SIN_F80,
965 RTLIB::SIN_F128,
966 RTLIB::SIN_PPCF128));
967}
968
969SDValue DAGTypeLegalizer::SoftenFloatRes_FSINH(SDNode *N) {
970 return SoftenFloatRes_Unary(
971 N, GetFPLibCall(N->getValueType(0), RTLIB::SINH_F32, RTLIB::SINH_F64,
972 RTLIB::SINH_F80, RTLIB::SINH_F128, RTLIB::SINH_PPCF128));
973}
974
975SDValue DAGTypeLegalizer::SoftenFloatRes_FSQRT(SDNode *N) {
976 return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
977 RTLIB::SQRT_F32,
978 RTLIB::SQRT_F64,
979 RTLIB::SQRT_F80,
980 RTLIB::SQRT_F128,
981 RTLIB::SQRT_PPCF128));
982}
983
984SDValue DAGTypeLegalizer::SoftenFloatRes_FSUB(SDNode *N) {
985 return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
986 RTLIB::SUB_F32,
987 RTLIB::SUB_F64,
988 RTLIB::SUB_F80,
989 RTLIB::SUB_F128,
990 RTLIB::SUB_PPCF128));
991}
992
993SDValue DAGTypeLegalizer::SoftenFloatRes_FTAN(SDNode *N) {
994 return SoftenFloatRes_Unary(
995 N, GetFPLibCall(N->getValueType(0), RTLIB::TAN_F32, RTLIB::TAN_F64,
996 RTLIB::TAN_F80, RTLIB::TAN_F128, RTLIB::TAN_PPCF128));
997}
998
999SDValue DAGTypeLegalizer::SoftenFloatRes_FTANH(SDNode *N) {
1000 return SoftenFloatRes_Unary(
1001 N, GetFPLibCall(N->getValueType(0), RTLIB::TANH_F32, RTLIB::TANH_F64,
1002 RTLIB::TANH_F80, RTLIB::TANH_F128, RTLIB::TANH_PPCF128));
1003}
1004
1005SDValue DAGTypeLegalizer::SoftenFloatRes_FTRUNC(SDNode *N) {
1006 return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
1007 RTLIB::TRUNC_F32,
1008 RTLIB::TRUNC_F64,
1009 RTLIB::TRUNC_F80,
1010 RTLIB::TRUNC_F128,
1011 RTLIB::TRUNC_PPCF128));
1012}
1013
1014SDValue DAGTypeLegalizer::SoftenFloatRes_LOAD(SDNode *N) {
1015 LoadSDNode *L = cast<LoadSDNode>(N);
1016 EVT VT = N->getValueType(0);
1017 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
1018 SDLoc dl(N);
1019
1020 auto MMOFlags =
1021 L->getMemOperand()->getFlags() &
1023 SDValue NewL;
1024 if (L->getExtensionType() == ISD::NON_EXTLOAD) {
1025 NewL = DAG.getLoad(L->getAddressingMode(), L->getExtensionType(), NVT, dl,
1026 L->getChain(), L->getBasePtr(), L->getOffset(),
1027 L->getPointerInfo(), NVT, L->getBaseAlign(), MMOFlags,
1028 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 return NewL;
1033 }
1034
1035 // Do a non-extending load followed by FP_EXTEND.
1036 NewL = DAG.getLoad(L->getAddressingMode(), ISD::NON_EXTLOAD, L->getMemoryVT(),
1037 dl, L->getChain(), L->getBasePtr(), L->getOffset(),
1038 L->getPointerInfo(), L->getMemoryVT(), L->getBaseAlign(),
1039 MMOFlags, L->getAAInfo());
1040 // Legalized the chain result - switch anything that used the old chain to
1041 // use the new one.
1042 ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
1043 auto ExtendNode = DAG.getNode(ISD::FP_EXTEND, dl, VT, NewL);
1044 return BitConvertToInteger(ExtendNode);
1045}
1046
1047SDValue DAGTypeLegalizer::SoftenFloatRes_ATOMIC_LOAD(SDNode *N) {
1048 AtomicSDNode *L = cast<AtomicSDNode>(N);
1049 EVT VT = N->getValueType(0);
1050 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
1051 SDLoc dl(N);
1052
1053 if (L->getExtensionType() == ISD::NON_EXTLOAD) {
1054 SDValue NewL =
1055 DAG.getAtomic(ISD::ATOMIC_LOAD, dl, NVT, DAG.getVTList(NVT, MVT::Other),
1056 {L->getChain(), L->getBasePtr()}, L->getMemOperand());
1057
1058 // Legalized the chain result - switch anything that used the old chain to
1059 // use the new one.
1060 ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
1061 return NewL;
1062 }
1063
1064 report_fatal_error("softening fp extending atomic load not handled");
1065}
1066
1067SDValue DAGTypeLegalizer::SoftenFloatRes_SELECT(SDNode *N) {
1068 SDValue LHS = GetSoftenedFloat(N->getOperand(1));
1069 SDValue RHS = GetSoftenedFloat(N->getOperand(2));
1070 return DAG.getSelect(SDLoc(N),
1071 LHS.getValueType(), N->getOperand(0), LHS, RHS);
1072}
1073
1074SDValue DAGTypeLegalizer::SoftenFloatRes_SELECT_CC(SDNode *N) {
1075 SDValue LHS = GetSoftenedFloat(N->getOperand(2));
1076 SDValue RHS = GetSoftenedFloat(N->getOperand(3));
1077 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
1078 LHS.getValueType(), N->getOperand(0),
1079 N->getOperand(1), LHS, RHS, N->getOperand(4));
1080}
1081
1082SDValue DAGTypeLegalizer::SoftenFloatRes_UNDEF(SDNode *N) {
1083 return DAG.getUNDEF(TLI.getTypeToTransformTo(*DAG.getContext(),
1084 N->getValueType(0)));
1085}
1086
1087SDValue DAGTypeLegalizer::SoftenFloatRes_VAARG(SDNode *N) {
1088 SDValue Chain = N->getOperand(0); // Get the chain.
1089 SDValue Ptr = N->getOperand(1); // Get the pointer.
1090 EVT VT = N->getValueType(0);
1091 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
1092 SDLoc dl(N);
1093
1094 SDValue NewVAARG;
1095 NewVAARG = DAG.getVAArg(NVT, dl, Chain, Ptr, N->getOperand(2),
1096 N->getConstantOperandVal(3));
1097
1098 // Legalized the chain result - switch anything that used the old chain to
1099 // use the new one.
1100 if (N != NewVAARG.getValue(1).getNode())
1101 ReplaceValueWith(SDValue(N, 1), NewVAARG.getValue(1));
1102 return NewVAARG;
1103}
1104
1105SDValue DAGTypeLegalizer::SoftenFloatRes_XINT_TO_FP(SDNode *N) {
1106 bool IsStrict = N->isStrictFPOpcode();
1107 bool Signed = N->getOpcode() == ISD::SINT_TO_FP ||
1108 N->getOpcode() == ISD::STRICT_SINT_TO_FP;
1109 EVT SVT = N->getOperand(IsStrict ? 1 : 0).getValueType();
1110 EVT RVT = N->getValueType(0);
1111 EVT NVT = EVT();
1112 SDLoc dl(N);
1113
1114 // If the input is not legal, eg: i1 -> fp, then it needs to be promoted to
1115 // a larger type, eg: i8 -> fp. Even if it is legal, no libcall may exactly
1116 // match. Look for an appropriate libcall.
1117 RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
1118 for (unsigned t = MVT::FIRST_INTEGER_VALUETYPE;
1119 t <= MVT::LAST_INTEGER_VALUETYPE && LC == RTLIB::UNKNOWN_LIBCALL; ++t) {
1120 NVT = (MVT::SimpleValueType)t;
1121 // The source needs to big enough to hold the operand.
1122 if (NVT.bitsGE(SVT))
1123 LC = Signed ? RTLIB::getSINTTOFP(NVT, RVT):RTLIB::getUINTTOFP (NVT, RVT);
1124 }
1125 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!");
1126
1127 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1128 // Sign/zero extend the argument if the libcall takes a larger type.
1129 SDValue Op = DAG.getNode(Signed ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, dl,
1130 NVT, N->getOperand(IsStrict ? 1 : 0));
1131 TargetLowering::MakeLibCallOptions CallOptions;
1132 CallOptions.setIsSigned(Signed);
1133 CallOptions.setTypeListBeforeSoften(SVT, RVT);
1134 std::pair<SDValue, SDValue> Tmp =
1135 TLI.makeLibCall(DAG, LC, TLI.getTypeToTransformTo(*DAG.getContext(), RVT),
1136 Op, CallOptions, dl, Chain);
1137
1138 if (IsStrict)
1139 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1140 return Tmp.first;
1141}
1142
1143SDValue DAGTypeLegalizer::SoftenFloatRes_VECREDUCE(SDNode *N) {
1144 // Expand and soften recursively.
1145 ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduce(N, DAG));
1146 return SDValue();
1147}
1148
1149SDValue DAGTypeLegalizer::SoftenFloatRes_VECREDUCE_SEQ(SDNode *N) {
1150 ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduceSeq(N, DAG));
1151 return SDValue();
1152}
1153
1154//===----------------------------------------------------------------------===//
1155// Convert Float Operand to Integer
1156//===----------------------------------------------------------------------===//
1157
1158bool DAGTypeLegalizer::SoftenFloatOperand(SDNode *N, unsigned OpNo) {
1159 LLVM_DEBUG(dbgs() << "Soften float operand " << OpNo << ": "; N->dump(&DAG));
1160 SDValue Res = SDValue();
1161
1162 switch (N->getOpcode()) {
1163 default:
1164#ifndef NDEBUG
1165 dbgs() << "SoftenFloatOperand Op #" << OpNo << ": ";
1166 N->dump(&DAG); dbgs() << "\n";
1167#endif
1168 report_fatal_error("Do not know how to soften this operator's operand!");
1169
1170 case ISD::BITCAST: Res = SoftenFloatOp_BITCAST(N); break;
1171 case ISD::BR_CC: Res = SoftenFloatOp_BR_CC(N); break;
1173 case ISD::FP_TO_FP16: // Same as FP_ROUND for softening purposes
1174 case ISD::FP_TO_BF16:
1177 case ISD::FP_ROUND: Res = SoftenFloatOp_FP_ROUND(N); break;
1180 case ISD::FP_TO_SINT:
1181 case ISD::FP_TO_UINT: Res = SoftenFloatOp_FP_TO_XINT(N); break;
1184 Res = SoftenFloatOp_FP_TO_XINT_SAT(N); break;
1185 case ISD::STRICT_LROUND:
1186 case ISD::LROUND: Res = SoftenFloatOp_LROUND(N); break;
1188 case ISD::LLROUND: Res = SoftenFloatOp_LLROUND(N); break;
1189 case ISD::STRICT_LRINT:
1190 case ISD::LRINT: Res = SoftenFloatOp_LRINT(N); break;
1191 case ISD::STRICT_LLRINT:
1192 case ISD::LLRINT: Res = SoftenFloatOp_LLRINT(N); break;
1193 case ISD::SELECT_CC: Res = SoftenFloatOp_SELECT_CC(N); break;
1194 case ISD::STRICT_FSETCC:
1196 case ISD::SETCC: Res = SoftenFloatOp_SETCC(N); break;
1197 case ISD::STORE: Res = SoftenFloatOp_STORE(N, OpNo); break;
1198 case ISD::ATOMIC_STORE:
1199 Res = SoftenFloatOp_ATOMIC_STORE(N, OpNo);
1200 break;
1201 case ISD::FCOPYSIGN: Res = SoftenFloatOp_FCOPYSIGN(N); break;
1202 case ISD::FAKE_USE:
1203 Res = SoftenFloatOp_FAKE_USE(N);
1204 break;
1205 case ISD::STACKMAP:
1206 Res = SoftenFloatOp_STACKMAP(N, OpNo);
1207 break;
1208 case ISD::PATCHPOINT:
1209 Res = SoftenFloatOp_PATCHPOINT(N, OpNo);
1210 break;
1211 }
1212
1213 // If the result is null, the sub-method took care of registering results etc.
1214 if (!Res.getNode()) return false;
1215
1216 // If the result is N, the sub-method updated N in place. Tell the legalizer
1217 // core about this to re-analyze.
1218 if (Res.getNode() == N)
1219 return true;
1220
1221 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
1222 "Invalid operand softening");
1223
1224 ReplaceValueWith(SDValue(N, 0), Res);
1225 return false;
1226}
1227
1228SDValue DAGTypeLegalizer::SoftenFloatOp_BITCAST(SDNode *N) {
1229 SDValue Op0 = GetSoftenedFloat(N->getOperand(0));
1230
1231 return DAG.getNode(ISD::BITCAST, SDLoc(N), N->getValueType(0), Op0);
1232}
1233
1234SDValue DAGTypeLegalizer::SoftenFloatOp_FP_ROUND(SDNode *N) {
1235 // We actually deal with the partially-softened FP_TO_FP16 node too, which
1236 // returns an i16 so doesn't meet the constraints necessary for FP_ROUND.
1237 assert(N->getOpcode() == ISD::FP_ROUND || N->getOpcode() == ISD::FP_TO_FP16 ||
1238 N->getOpcode() == ISD::STRICT_FP_TO_FP16 ||
1239 N->getOpcode() == ISD::FP_TO_BF16 ||
1240 N->getOpcode() == ISD::STRICT_FP_TO_BF16 ||
1241 N->getOpcode() == ISD::STRICT_FP_ROUND);
1242
1243 bool IsStrict = N->isStrictFPOpcode();
1244 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
1245 EVT SVT = Op.getValueType();
1246 EVT RVT = N->getValueType(0);
1247 EVT FloatRVT = RVT;
1248 if (N->getOpcode() == ISD::FP_TO_FP16 ||
1249 N->getOpcode() == ISD::STRICT_FP_TO_FP16)
1250 FloatRVT = MVT::f16;
1251 else if (N->getOpcode() == ISD::FP_TO_BF16 ||
1252 N->getOpcode() == ISD::STRICT_FP_TO_BF16)
1253 FloatRVT = MVT::bf16;
1254
1255 RTLIB::Libcall LC = RTLIB::getFPROUND(SVT, FloatRVT);
1256 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_ROUND libcall");
1257
1258 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1259 Op = GetSoftenedFloat(Op);
1260 TargetLowering::MakeLibCallOptions CallOptions;
1261 CallOptions.setTypeListBeforeSoften(SVT, RVT);
1262 std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, RVT, Op,
1263 CallOptions, SDLoc(N),
1264 Chain);
1265 if (IsStrict) {
1266 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1267 ReplaceValueWith(SDValue(N, 0), Tmp.first);
1268 return SDValue();
1269 }
1270 return Tmp.first;
1271}
1272
1273SDValue DAGTypeLegalizer::SoftenFloatOp_BR_CC(SDNode *N) {
1274 SDValue NewLHS = N->getOperand(2), NewRHS = N->getOperand(3);
1275 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(1))->get();
1276
1277 EVT VT = NewLHS.getValueType();
1278 NewLHS = GetSoftenedFloat(NewLHS);
1279 NewRHS = GetSoftenedFloat(NewRHS);
1280 TLI.softenSetCCOperands(DAG, VT, NewLHS, NewRHS, CCCode, SDLoc(N),
1281 N->getOperand(2), N->getOperand(3));
1282
1283 // If softenSetCCOperands returned a scalar, we need to compare the result
1284 // against zero to select between true and false values.
1285 if (!NewRHS.getNode()) {
1286 NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
1287 CCCode = ISD::SETNE;
1288 }
1289
1290 // Update N to have the operands specified.
1291 return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0),
1292 DAG.getCondCode(CCCode), NewLHS, NewRHS,
1293 N->getOperand(4)),
1294 0);
1295}
1296
1297// Even if the result type is legal, no libcall may exactly match. (e.g. We
1298// don't have FP-i8 conversions) This helper method looks for an appropriate
1299// promoted libcall.
1300static RTLIB::Libcall findFPToIntLibcall(EVT SrcVT, EVT RetVT, EVT &Promoted,
1301 bool Signed) {
1302 RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
1303 for (unsigned IntVT = MVT::FIRST_INTEGER_VALUETYPE;
1304 IntVT <= MVT::LAST_INTEGER_VALUETYPE && LC == RTLIB::UNKNOWN_LIBCALL;
1305 ++IntVT) {
1306 Promoted = (MVT::SimpleValueType)IntVT;
1307 // The type needs to big enough to hold the result.
1308 if (Promoted.bitsGE(RetVT))
1309 LC = Signed ? RTLIB::getFPTOSINT(SrcVT, Promoted)
1310 : RTLIB::getFPTOUINT(SrcVT, Promoted);
1311 }
1312 return LC;
1313}
1314
1315SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_XINT(SDNode *N) {
1316 bool IsStrict = N->isStrictFPOpcode();
1317 bool Signed = N->getOpcode() == ISD::FP_TO_SINT ||
1318 N->getOpcode() == ISD::STRICT_FP_TO_SINT;
1319
1320 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
1321 EVT SVT = Op.getValueType();
1322 EVT RVT = N->getValueType(0);
1323 EVT NVT = EVT();
1324 SDLoc dl(N);
1325
1326 // If the result is not legal, eg: fp -> i1, then it needs to be promoted to
1327 // a larger type, eg: fp -> i32. Even if it is legal, no libcall may exactly
1328 // match, eg. we don't have fp -> i8 conversions.
1329 // Look for an appropriate libcall.
1330 RTLIB::Libcall LC = findFPToIntLibcall(SVT, RVT, NVT, Signed);
1331 assert(LC != RTLIB::UNKNOWN_LIBCALL && NVT.isSimple() &&
1332 "Unsupported FP_TO_XINT!");
1333
1334 Op = GetSoftenedFloat(Op);
1335 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1336 TargetLowering::MakeLibCallOptions CallOptions;
1337 CallOptions.setTypeListBeforeSoften(SVT, RVT);
1338 std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, NVT, Op,
1339 CallOptions, dl, Chain);
1340
1341 // Truncate the result if the libcall returns a larger type.
1342 SDValue Res = DAG.getNode(ISD::TRUNCATE, dl, RVT, Tmp.first);
1343
1344 if (!IsStrict)
1345 return Res;
1346
1347 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1348 ReplaceValueWith(SDValue(N, 0), Res);
1349 return SDValue();
1350}
1351
1352SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_XINT_SAT(SDNode *N) {
1353 SDValue Res = TLI.expandFP_TO_INT_SAT(N, DAG);
1354 return Res;
1355}
1356
1357SDValue DAGTypeLegalizer::SoftenFloatOp_SELECT_CC(SDNode *N) {
1358 SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
1359 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(4))->get();
1360
1361 EVT VT = NewLHS.getValueType();
1362 NewLHS = GetSoftenedFloat(NewLHS);
1363 NewRHS = GetSoftenedFloat(NewRHS);
1364 TLI.softenSetCCOperands(DAG, VT, NewLHS, NewRHS, CCCode, SDLoc(N),
1365 N->getOperand(0), N->getOperand(1));
1366
1367 // If softenSetCCOperands returned a scalar, we need to compare the result
1368 // against zero to select between true and false values.
1369 if (!NewRHS.getNode()) {
1370 NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
1371 CCCode = ISD::SETNE;
1372 }
1373
1374 // Update N to have the operands specified.
1375 return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
1376 N->getOperand(2), N->getOperand(3),
1377 DAG.getCondCode(CCCode)),
1378 0);
1379}
1380
1381SDValue DAGTypeLegalizer::SoftenFloatOp_SETCC(SDNode *N) {
1382 bool IsStrict = N->isStrictFPOpcode();
1383 SDValue Op0 = N->getOperand(IsStrict ? 1 : 0);
1384 SDValue Op1 = N->getOperand(IsStrict ? 2 : 1);
1385 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1386 ISD::CondCode CCCode =
1387 cast<CondCodeSDNode>(N->getOperand(IsStrict ? 3 : 2))->get();
1388
1389 EVT VT = Op0.getValueType();
1390 SDValue NewLHS = GetSoftenedFloat(Op0);
1391 SDValue NewRHS = GetSoftenedFloat(Op1);
1392 TLI.softenSetCCOperands(DAG, VT, NewLHS, NewRHS, CCCode, SDLoc(N), Op0, Op1,
1393 Chain, N->getOpcode() == ISD::STRICT_FSETCCS);
1394
1395 // Update N to have the operands specified.
1396 if (NewRHS.getNode()) {
1397 if (IsStrict)
1398 NewLHS = DAG.getNode(ISD::SETCC, SDLoc(N), N->getValueType(0), NewLHS,
1399 NewRHS, DAG.getCondCode(CCCode));
1400 else
1401 return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
1402 DAG.getCondCode(CCCode)), 0);
1403 }
1404
1405 // Otherwise, softenSetCCOperands returned a scalar, use it.
1406 assert((NewRHS.getNode() || NewLHS.getValueType() == N->getValueType(0)) &&
1407 "Unexpected setcc expansion!");
1408
1409 if (IsStrict) {
1410 ReplaceValueWith(SDValue(N, 0), NewLHS);
1411 ReplaceValueWith(SDValue(N, 1), Chain);
1412 return SDValue();
1413 }
1414 return NewLHS;
1415}
1416
1417SDValue DAGTypeLegalizer::SoftenFloatOp_STORE(SDNode *N, unsigned OpNo) {
1418 assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!");
1419 assert(OpNo == 1 && "Can only soften the stored value!");
1420 StoreSDNode *ST = cast<StoreSDNode>(N);
1421 SDValue Val = ST->getValue();
1422 SDLoc dl(N);
1423
1424 if (ST->isTruncatingStore())
1425 // Do an FP_ROUND followed by a non-truncating store.
1426 Val = BitConvertToInteger(
1427 DAG.getNode(ISD::FP_ROUND, dl, ST->getMemoryVT(), Val,
1428 DAG.getIntPtrConstant(0, dl, /*isTarget=*/true)));
1429 else
1430 Val = GetSoftenedFloat(Val);
1431
1432 return DAG.getStore(ST->getChain(), dl, Val, ST->getBasePtr(),
1433 ST->getMemOperand());
1434}
1435
1436SDValue DAGTypeLegalizer::SoftenFloatOp_ATOMIC_STORE(SDNode *N, unsigned OpNo) {
1437 assert(OpNo == 1 && "Can only soften the stored value!");
1438 AtomicSDNode *ST = cast<AtomicSDNode>(N);
1439 SDValue Val = ST->getVal();
1440 EVT VT = Val.getValueType();
1441 SDLoc dl(N);
1442
1443 assert(ST->getMemoryVT() == VT && "truncating atomic store not handled");
1444
1445 SDValue NewVal = GetSoftenedFloat(Val);
1446 return DAG.getAtomic(ISD::ATOMIC_STORE, dl, VT, ST->getChain(), NewVal,
1447 ST->getBasePtr(), ST->getMemOperand());
1448}
1449
1450SDValue DAGTypeLegalizer::SoftenFloatOp_FCOPYSIGN(SDNode *N) {
1451 SDValue LHS = N->getOperand(0);
1452 SDValue RHS = BitConvertToInteger(N->getOperand(1));
1453 SDLoc dl(N);
1454
1455 EVT LVT = LHS.getValueType();
1456 EVT ILVT = EVT::getIntegerVT(*DAG.getContext(), LVT.getSizeInBits());
1457 EVT RVT = RHS.getValueType();
1458
1459 unsigned LSize = LVT.getSizeInBits();
1460 unsigned RSize = RVT.getSizeInBits();
1461
1462 // Shift right or sign-extend it if the two operands have different types.
1463 int SizeDiff = RSize - LSize;
1464 if (SizeDiff > 0) {
1465 RHS =
1466 DAG.getNode(ISD::SRL, dl, RVT, RHS,
1467 DAG.getConstant(SizeDiff, dl,
1468 TLI.getShiftAmountTy(RHS.getValueType(),
1469 DAG.getDataLayout())));
1470 RHS = DAG.getNode(ISD::TRUNCATE, dl, ILVT, RHS);
1471 } else if (SizeDiff < 0) {
1472 RHS = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, RHS);
1473 RHS =
1474 DAG.getNode(ISD::SHL, dl, ILVT, RHS,
1475 DAG.getConstant(-SizeDiff, dl,
1476 TLI.getShiftAmountTy(RHS.getValueType(),
1477 DAG.getDataLayout())));
1478 }
1479
1480 RHS = DAG.getBitcast(LVT, RHS);
1481 return DAG.getNode(ISD::FCOPYSIGN, dl, LVT, LHS, RHS);
1482}
1483
1484SDValue DAGTypeLegalizer::SoftenFloatOp_Unary(SDNode *N, RTLIB::Libcall LC) {
1485 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
1486 bool IsStrict = N->isStrictFPOpcode();
1487 unsigned Offset = IsStrict ? 1 : 0;
1488 SDValue Op = GetSoftenedFloat(N->getOperand(0 + Offset));
1489 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1490 TargetLowering::MakeLibCallOptions CallOptions;
1491 EVT OpVT = N->getOperand(0 + Offset).getValueType();
1492 CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0));
1493 std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, NVT, Op,
1494 CallOptions, SDLoc(N),
1495 Chain);
1496 if (IsStrict) {
1497 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1498 ReplaceValueWith(SDValue(N, 0), Tmp.first);
1499 return SDValue();
1500 }
1501
1502 return Tmp.first;
1503}
1504
1505SDValue DAGTypeLegalizer::SoftenFloatOp_LROUND(SDNode *N) {
1506 EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1507 return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
1508 RTLIB::LROUND_F32,
1509 RTLIB::LROUND_F64,
1510 RTLIB::LROUND_F80,
1511 RTLIB::LROUND_F128,
1512 RTLIB::LROUND_PPCF128));
1513}
1514
1515SDValue DAGTypeLegalizer::SoftenFloatOp_LLROUND(SDNode *N) {
1516 EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1517 return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
1518 RTLIB::LLROUND_F32,
1519 RTLIB::LLROUND_F64,
1520 RTLIB::LLROUND_F80,
1521 RTLIB::LLROUND_F128,
1522 RTLIB::LLROUND_PPCF128));
1523}
1524
1525SDValue DAGTypeLegalizer::SoftenFloatOp_LRINT(SDNode *N) {
1526 EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1527 return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
1528 RTLIB::LRINT_F32,
1529 RTLIB::LRINT_F64,
1530 RTLIB::LRINT_F80,
1531 RTLIB::LRINT_F128,
1532 RTLIB::LRINT_PPCF128));
1533}
1534
1535SDValue DAGTypeLegalizer::SoftenFloatOp_LLRINT(SDNode *N) {
1536 EVT OpVT = N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType();
1537 return SoftenFloatOp_Unary(N, GetFPLibCall(OpVT,
1538 RTLIB::LLRINT_F32,
1539 RTLIB::LLRINT_F64,
1540 RTLIB::LLRINT_F80,
1541 RTLIB::LLRINT_F128,
1542 RTLIB::LLRINT_PPCF128));
1543}
1544
1545SDValue DAGTypeLegalizer::SoftenFloatOp_FAKE_USE(SDNode *N) {
1546 SDValue Op1 = BitConvertToInteger(N->getOperand(1));
1547 return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
1548 N->getOperand(0), Op1);
1549}
1550
1551SDValue DAGTypeLegalizer::SoftenFloatOp_STACKMAP(SDNode *N, unsigned OpNo) {
1552 assert(OpNo > 1); // Because the first two arguments are guaranteed legal.
1553 SmallVector<SDValue> NewOps(N->ops());
1554 NewOps[OpNo] = GetSoftenedFloat(NewOps[OpNo]);
1555 return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0);
1556}
1557
1558SDValue DAGTypeLegalizer::SoftenFloatOp_PATCHPOINT(SDNode *N, unsigned OpNo) {
1559 assert(OpNo >= 7);
1560 SmallVector<SDValue> NewOps(N->ops());
1561 NewOps[OpNo] = GetSoftenedFloat(NewOps[OpNo]);
1562 return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0);
1563}
1564
1565//===----------------------------------------------------------------------===//
1566// Float Result Expansion
1567//===----------------------------------------------------------------------===//
1568
1569/// ExpandFloatResult - This method is called when the specified result of the
1570/// specified node is found to need expansion. At this point, the node may also
1571/// have invalid operands or may have other results that need promotion, we just
1572/// know that (at least) one result needs expansion.
1573void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) {
1574 LLVM_DEBUG(dbgs() << "Expand float result: "; N->dump(&DAG));
1575 SDValue Lo, Hi;
1576 Lo = Hi = SDValue();
1577
1578 // See if the target wants to custom expand this node.
1579 if (CustomLowerNode(N, N->getValueType(ResNo), true))
1580 return;
1581
1582 switch (N->getOpcode()) {
1583 default:
1584#ifndef NDEBUG
1585 dbgs() << "ExpandFloatResult #" << ResNo << ": ";
1586 N->dump(&DAG); dbgs() << "\n";
1587#endif
1588 report_fatal_error("Do not know how to expand the result of this "
1589 "operator!");
1590 // clang-format off
1591 case ISD::POISON:
1592 case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
1593 case ISD::SELECT: SplitRes_Select(N, Lo, Hi); break;
1594 case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break;
1595
1596 case ISD::MERGE_VALUES: ExpandRes_MERGE_VALUES(N, ResNo, Lo, Hi); break;
1597 case ISD::BITCAST: ExpandRes_BITCAST(N, Lo, Hi); break;
1598 case ISD::BUILD_PAIR: ExpandRes_BUILD_PAIR(N, Lo, Hi); break;
1599 case ISD::EXTRACT_ELEMENT: ExpandRes_EXTRACT_ELEMENT(N, Lo, Hi); break;
1600 case ISD::EXTRACT_VECTOR_ELT: ExpandRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); break;
1601 case ISD::VAARG: ExpandRes_VAARG(N, Lo, Hi); break;
1602
1603 case ISD::ConstantFP: ExpandFloatRes_ConstantFP(N, Lo, Hi); break;
1604 case ISD::AssertNoFPClass: ExpandFloatRes_AssertNoFPClass(N, Lo, Hi); break;
1605 case ISD::FABS: ExpandFloatRes_FABS(N, Lo, Hi); break;
1607 case ISD::FMINNUM: ExpandFloatRes_FMINNUM(N, Lo, Hi); break;
1609 case ISD::FMAXNUM: ExpandFloatRes_FMAXNUM(N, Lo, Hi); break;
1610 case ISD::FMINIMUMNUM: ExpandFloatRes_FMINIMUMNUM(N, Lo, Hi); break;
1611 case ISD::FMAXIMUMNUM: ExpandFloatRes_FMAXIMUMNUM(N, Lo, Hi); break;
1612 case ISD::STRICT_FADD:
1613 case ISD::FADD: ExpandFloatRes_FADD(N, Lo, Hi); break;
1614 case ISD::STRICT_FACOS:
1615 case ISD::FACOS: ExpandFloatRes_FACOS(N, Lo, Hi); break;
1616 case ISD::STRICT_FASIN:
1617 case ISD::FASIN: ExpandFloatRes_FASIN(N, Lo, Hi); break;
1618 case ISD::STRICT_FATAN:
1619 case ISD::FATAN: ExpandFloatRes_FATAN(N, Lo, Hi); break;
1620 case ISD::STRICT_FATAN2:
1621 case ISD::FATAN2: ExpandFloatRes_FATAN2(N, Lo, Hi); break;
1622 case ISD::FCBRT: ExpandFloatRes_FCBRT(N, Lo, Hi); break;
1623 case ISD::STRICT_FCEIL:
1624 case ISD::FCEIL: ExpandFloatRes_FCEIL(N, Lo, Hi); break;
1625 case ISD::FCOPYSIGN: ExpandFloatRes_FCOPYSIGN(N, Lo, Hi); break;
1626 case ISD::STRICT_FCOS:
1627 case ISD::FCOS: ExpandFloatRes_FCOS(N, Lo, Hi); break;
1628 case ISD::STRICT_FCOSH:
1629 case ISD::FCOSH: ExpandFloatRes_FCOSH(N, Lo, Hi); break;
1630 case ISD::STRICT_FDIV:
1631 case ISD::FDIV: ExpandFloatRes_FDIV(N, Lo, Hi); break;
1632 case ISD::STRICT_FEXP:
1633 case ISD::FEXP: ExpandFloatRes_FEXP(N, Lo, Hi); break;
1634 case ISD::STRICT_FEXP2:
1635 case ISD::FEXP2: ExpandFloatRes_FEXP2(N, Lo, Hi); break;
1636 case ISD::FEXP10: ExpandFloatRes_FEXP10(N, Lo, Hi); break;
1637 case ISD::STRICT_FFLOOR:
1638 case ISD::FFLOOR: ExpandFloatRes_FFLOOR(N, Lo, Hi); break;
1639 case ISD::STRICT_FLOG:
1640 case ISD::FLOG: ExpandFloatRes_FLOG(N, Lo, Hi); break;
1641 case ISD::STRICT_FLOG2:
1642 case ISD::FLOG2: ExpandFloatRes_FLOG2(N, Lo, Hi); break;
1643 case ISD::STRICT_FLOG10:
1644 case ISD::FLOG10: ExpandFloatRes_FLOG10(N, Lo, Hi); break;
1645 case ISD::STRICT_FMA:
1646 case ISD::FMA: ExpandFloatRes_FMA(N, Lo, Hi); break;
1647 case ISD::STRICT_FMUL:
1648 case ISD::FMUL: ExpandFloatRes_FMUL(N, Lo, Hi); break;
1650 case ISD::FNEARBYINT: ExpandFloatRes_FNEARBYINT(N, Lo, Hi); break;
1651 case ISD::FNEG: ExpandFloatRes_FNEG(N, Lo, Hi); break;
1653 case ISD::FP_EXTEND: ExpandFloatRes_FP_EXTEND(N, Lo, Hi); break;
1654 case ISD::STRICT_FPOW:
1655 case ISD::FPOW: ExpandFloatRes_FPOW(N, Lo, Hi); break;
1656 case ISD::STRICT_FPOWI:
1657 case ISD::FPOWI: ExpandFloatRes_FPOWI(N, Lo, Hi); break;
1658 case ISD::FLDEXP:
1659 case ISD::STRICT_FLDEXP: ExpandFloatRes_FLDEXP(N, Lo, Hi); break;
1660 case ISD::FREEZE: ExpandFloatRes_FREEZE(N, Lo, Hi); break;
1661 case ISD::STRICT_FRINT:
1662 case ISD::FRINT: ExpandFloatRes_FRINT(N, Lo, Hi); break;
1663 case ISD::STRICT_FROUND:
1664 case ISD::FROUND: ExpandFloatRes_FROUND(N, Lo, Hi); break;
1666 case ISD::FROUNDEVEN: ExpandFloatRes_FROUNDEVEN(N, Lo, Hi); break;
1667 case ISD::STRICT_FSIN:
1668 case ISD::FSIN: ExpandFloatRes_FSIN(N, Lo, Hi); break;
1669 case ISD::STRICT_FSINH:
1670 case ISD::FSINH: ExpandFloatRes_FSINH(N, Lo, Hi); break;
1671 case ISD::STRICT_FSQRT:
1672 case ISD::FSQRT: ExpandFloatRes_FSQRT(N, Lo, Hi); break;
1673 case ISD::STRICT_FSUB:
1674 case ISD::FSUB: ExpandFloatRes_FSUB(N, Lo, Hi); break;
1675 case ISD::STRICT_FTAN:
1676 case ISD::FTAN: ExpandFloatRes_FTAN(N, Lo, Hi); break;
1677 case ISD::STRICT_FTANH:
1678 case ISD::FTANH: ExpandFloatRes_FTANH(N, Lo, Hi); break;
1679 case ISD::STRICT_FTRUNC:
1680 case ISD::FTRUNC: ExpandFloatRes_FTRUNC(N, Lo, Hi); break;
1681 case ISD::LOAD: ExpandFloatRes_LOAD(N, Lo, Hi); break;
1684 case ISD::SINT_TO_FP:
1685 case ISD::UINT_TO_FP: ExpandFloatRes_XINT_TO_FP(N, Lo, Hi); break;
1686 case ISD::STRICT_FREM:
1687 case ISD::FREM: ExpandFloatRes_FREM(N, Lo, Hi); break;
1688 case ISD::FMODF: ExpandFloatRes_FMODF(N); break;
1689 case ISD::FSINCOS: ExpandFloatRes_FSINCOS(N); break;
1690 case ISD::FSINCOSPI: ExpandFloatRes_FSINCOSPI(N); break;
1691 // clang-format on
1692 }
1693
1694 // If Lo/Hi is null, the sub-method took care of registering results etc.
1695 if (Lo.getNode())
1696 SetExpandedFloat(SDValue(N, ResNo), Lo, Hi);
1697}
1698
1699void DAGTypeLegalizer::ExpandFloatRes_ConstantFP(SDNode *N, SDValue &Lo,
1700 SDValue &Hi) {
1701 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
1702 assert(NVT.getSizeInBits() == 64 &&
1703 "Do not know how to expand this float constant!");
1704 APInt C = cast<ConstantFPSDNode>(N)->getValueAPF().bitcastToAPInt();
1705 SDLoc dl(N);
1706 const fltSemantics &Sem = NVT.getFltSemantics();
1707 Lo = DAG.getConstantFP(APFloat(Sem, C.extractBits(64, 64)), dl, NVT);
1708 Hi = DAG.getConstantFP(APFloat(Sem, C.extractBits(64, 0)), dl, NVT);
1709}
1710
1711void DAGTypeLegalizer::ExpandFloatRes_Unary(SDNode *N, RTLIB::Libcall LC,
1712 SDValue &Lo, SDValue &Hi) {
1713 bool IsStrict = N->isStrictFPOpcode();
1714 unsigned Offset = IsStrict ? 1 : 0;
1715 SDValue Op = N->getOperand(0 + Offset);
1716 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1717 TargetLowering::MakeLibCallOptions CallOptions;
1718 std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, N->getValueType(0),
1719 Op, CallOptions, SDLoc(N),
1720 Chain);
1721 if (IsStrict)
1722 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1723 GetPairElements(Tmp.first, Lo, Hi);
1724}
1725
1726void DAGTypeLegalizer::ExpandFloatRes_Binary(SDNode *N, RTLIB::Libcall LC,
1727 SDValue &Lo, SDValue &Hi) {
1728 bool IsStrict = N->isStrictFPOpcode();
1729 unsigned Offset = IsStrict ? 1 : 0;
1730 SDValue Ops[] = { N->getOperand(0 + Offset), N->getOperand(1 + Offset) };
1731 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1732 TargetLowering::MakeLibCallOptions CallOptions;
1733 std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, LC, N->getValueType(0),
1734 Ops, CallOptions, SDLoc(N),
1735 Chain);
1736 if (IsStrict)
1737 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1738 GetPairElements(Tmp.first, Lo, Hi);
1739}
1740
1741void DAGTypeLegalizer::ExpandFloatRes_FMODF(SDNode *N) {
1742 ExpandFloatRes_UnaryWithTwoFPResults(N, RTLIB::getMODF(N->getValueType(0)),
1743 /*CallRetResNo=*/0);
1744}
1745
1746void DAGTypeLegalizer::ExpandFloatRes_FSINCOS(SDNode *N) {
1747 ExpandFloatRes_UnaryWithTwoFPResults(N, RTLIB::getSINCOS(N->getValueType(0)));
1748}
1749
1750void DAGTypeLegalizer::ExpandFloatRes_FSINCOSPI(SDNode *N) {
1751 ExpandFloatRes_UnaryWithTwoFPResults(N,
1752 RTLIB::getSINCOSPI(N->getValueType(0)));
1753}
1754
1755void DAGTypeLegalizer::ExpandFloatRes_UnaryWithTwoFPResults(
1756 SDNode *N, RTLIB::Libcall LC, std::optional<unsigned> CallRetResNo) {
1757 assert(!N->isStrictFPOpcode() && "strictfp not implemented");
1759 TLI.expandMultipleResultFPLibCall(DAG, LC, N, Results, CallRetResNo);
1760 for (auto [ResNo, Res] : enumerate(Results)) {
1761 SDValue Lo, Hi;
1762 GetPairElements(Res, Lo, Hi);
1763 SetExpandedFloat(SDValue(N, ResNo), Lo, Hi);
1764 }
1765}
1766
1767void DAGTypeLegalizer::ExpandFloatRes_FABS(SDNode *N, SDValue &Lo,
1768 SDValue &Hi) {
1769 assert(N->getValueType(0) == MVT::ppcf128 &&
1770 "Logic only correct for ppcf128!");
1771 SDLoc dl(N);
1772 SDValue Tmp;
1773 GetExpandedFloat(N->getOperand(0), Lo, Tmp);
1774 Hi = DAG.getNode(ISD::FABS, dl, Tmp.getValueType(), Tmp);
1775 // Lo = Hi==fabs(Hi) ? Lo : -Lo;
1776 Lo = DAG.getSelectCC(dl, Tmp, Hi, Lo,
1777 DAG.getNode(ISD::FNEG, dl, Lo.getValueType(), Lo),
1778 ISD::SETEQ);
1779}
1780
1781void DAGTypeLegalizer::ExpandFloatRes_FMINNUM(SDNode *N, SDValue &Lo,
1782 SDValue &Hi) {
1783 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
1784 RTLIB::FMIN_F32, RTLIB::FMIN_F64,
1785 RTLIB::FMIN_F80, RTLIB::FMIN_F128,
1786 RTLIB::FMIN_PPCF128), Lo, Hi);
1787}
1788
1789void DAGTypeLegalizer::ExpandFloatRes_FMAXNUM(SDNode *N, SDValue &Lo,
1790 SDValue &Hi) {
1791 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
1792 RTLIB::FMAX_F32, RTLIB::FMAX_F64,
1793 RTLIB::FMAX_F80, RTLIB::FMAX_F128,
1794 RTLIB::FMAX_PPCF128), Lo, Hi);
1795}
1796
1797void DAGTypeLegalizer::ExpandFloatRes_FMINIMUMNUM(SDNode *N, SDValue &Lo,
1798 SDValue &Hi) {
1799 ExpandFloatRes_Binary(
1800 N,
1801 GetFPLibCall(N->getValueType(0), RTLIB::FMINIMUM_NUM_F32,
1802 RTLIB::FMINIMUM_NUM_F64, RTLIB::FMINIMUM_NUM_F80,
1803 RTLIB::FMINIMUM_NUM_F128, RTLIB::FMINIMUM_NUM_PPCF128),
1804 Lo, Hi);
1805}
1806
1807void DAGTypeLegalizer::ExpandFloatRes_FMAXIMUMNUM(SDNode *N, SDValue &Lo,
1808 SDValue &Hi) {
1809 ExpandFloatRes_Binary(
1810 N,
1811 GetFPLibCall(N->getValueType(0), RTLIB::FMAXIMUM_NUM_F32,
1812 RTLIB::FMAXIMUM_NUM_F64, RTLIB::FMAXIMUM_NUM_F80,
1813 RTLIB::FMAXIMUM_NUM_F128, RTLIB::FMAXIMUM_NUM_PPCF128),
1814 Lo, Hi);
1815}
1816
1817void DAGTypeLegalizer::ExpandFloatRes_FADD(SDNode *N, SDValue &Lo,
1818 SDValue &Hi) {
1819 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
1820 RTLIB::ADD_F32, RTLIB::ADD_F64,
1821 RTLIB::ADD_F80, RTLIB::ADD_F128,
1822 RTLIB::ADD_PPCF128), Lo, Hi);
1823}
1824
1825void DAGTypeLegalizer::ExpandFloatRes_FACOS(SDNode *N, SDValue &Lo,
1826 SDValue &Hi) {
1827 ExpandFloatRes_Unary(N,
1828 GetFPLibCall(N->getValueType(0), RTLIB::ACOS_F32,
1829 RTLIB::ACOS_F64, RTLIB::ACOS_F80,
1830 RTLIB::ACOS_F128, RTLIB::ACOS_PPCF128),
1831 Lo, Hi);
1832}
1833
1834void DAGTypeLegalizer::ExpandFloatRes_FASIN(SDNode *N, SDValue &Lo,
1835 SDValue &Hi) {
1836 ExpandFloatRes_Unary(N,
1837 GetFPLibCall(N->getValueType(0), RTLIB::ASIN_F32,
1838 RTLIB::ASIN_F64, RTLIB::ASIN_F80,
1839 RTLIB::ASIN_F128, RTLIB::ASIN_PPCF128),
1840 Lo, Hi);
1841}
1842
1843void DAGTypeLegalizer::ExpandFloatRes_FATAN(SDNode *N, SDValue &Lo,
1844 SDValue &Hi) {
1845 ExpandFloatRes_Unary(N,
1846 GetFPLibCall(N->getValueType(0), RTLIB::ATAN_F32,
1847 RTLIB::ATAN_F64, RTLIB::ATAN_F80,
1848 RTLIB::ATAN_F128, RTLIB::ATAN_PPCF128),
1849 Lo, Hi);
1850}
1851
1852void DAGTypeLegalizer::ExpandFloatRes_FATAN2(SDNode *N, SDValue &Lo,
1853 SDValue &Hi) {
1854 ExpandFloatRes_Binary(N,
1855 GetFPLibCall(N->getValueType(0), RTLIB::ATAN2_F32,
1856 RTLIB::ATAN2_F64, RTLIB::ATAN2_F80,
1857 RTLIB::ATAN2_F128, RTLIB::ATAN2_PPCF128),
1858 Lo, Hi);
1859}
1860
1861void DAGTypeLegalizer::ExpandFloatRes_FCBRT(SDNode *N, SDValue &Lo,
1862 SDValue &Hi) {
1863 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), RTLIB::CBRT_F32,
1864 RTLIB::CBRT_F64, RTLIB::CBRT_F80,
1865 RTLIB::CBRT_F128,
1866 RTLIB::CBRT_PPCF128), Lo, Hi);
1867}
1868
1869void DAGTypeLegalizer::ExpandFloatRes_FCEIL(SDNode *N,
1870 SDValue &Lo, SDValue &Hi) {
1871 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
1872 RTLIB::CEIL_F32, RTLIB::CEIL_F64,
1873 RTLIB::CEIL_F80, RTLIB::CEIL_F128,
1874 RTLIB::CEIL_PPCF128), Lo, Hi);
1875}
1876
1877void DAGTypeLegalizer::ExpandFloatRes_FCOPYSIGN(SDNode *N,
1878 SDValue &Lo, SDValue &Hi) {
1879 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
1880 RTLIB::COPYSIGN_F32,
1881 RTLIB::COPYSIGN_F64,
1882 RTLIB::COPYSIGN_F80,
1883 RTLIB::COPYSIGN_F128,
1884 RTLIB::COPYSIGN_PPCF128), Lo, Hi);
1885}
1886
1887void DAGTypeLegalizer::ExpandFloatRes_FCOS(SDNode *N,
1888 SDValue &Lo, SDValue &Hi) {
1889 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
1890 RTLIB::COS_F32, RTLIB::COS_F64,
1891 RTLIB::COS_F80, RTLIB::COS_F128,
1892 RTLIB::COS_PPCF128), Lo, Hi);
1893}
1894
1895void DAGTypeLegalizer::ExpandFloatRes_FCOSH(SDNode *N, SDValue &Lo,
1896 SDValue &Hi) {
1897 ExpandFloatRes_Unary(N,
1898 GetFPLibCall(N->getValueType(0), RTLIB::COSH_F32,
1899 RTLIB::COSH_F64, RTLIB::COSH_F80,
1900 RTLIB::COSH_F128, RTLIB::COSH_PPCF128),
1901 Lo, Hi);
1902}
1903
1904void DAGTypeLegalizer::ExpandFloatRes_FDIV(SDNode *N, SDValue &Lo,
1905 SDValue &Hi) {
1906 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
1907 RTLIB::DIV_F32,
1908 RTLIB::DIV_F64,
1909 RTLIB::DIV_F80,
1910 RTLIB::DIV_F128,
1911 RTLIB::DIV_PPCF128), Lo, Hi);
1912}
1913
1914void DAGTypeLegalizer::ExpandFloatRes_FEXP(SDNode *N,
1915 SDValue &Lo, SDValue &Hi) {
1916 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
1917 RTLIB::EXP_F32, RTLIB::EXP_F64,
1918 RTLIB::EXP_F80, RTLIB::EXP_F128,
1919 RTLIB::EXP_PPCF128), Lo, Hi);
1920}
1921
1922void DAGTypeLegalizer::ExpandFloatRes_FEXP2(SDNode *N,
1923 SDValue &Lo, SDValue &Hi) {
1924 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
1925 RTLIB::EXP2_F32, RTLIB::EXP2_F64,
1926 RTLIB::EXP2_F80, RTLIB::EXP2_F128,
1927 RTLIB::EXP2_PPCF128), Lo, Hi);
1928}
1929
1930void DAGTypeLegalizer::ExpandFloatRes_FEXP10(SDNode *N, SDValue &Lo,
1931 SDValue &Hi) {
1932 ExpandFloatRes_Unary(N,
1933 GetFPLibCall(N->getValueType(0), RTLIB::EXP10_F32,
1934 RTLIB::EXP10_F64, RTLIB::EXP10_F80,
1935 RTLIB::EXP10_F128, RTLIB::EXP10_PPCF128),
1936 Lo, Hi);
1937}
1938
1939void DAGTypeLegalizer::ExpandFloatRes_FFLOOR(SDNode *N,
1940 SDValue &Lo, SDValue &Hi) {
1941 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
1942 RTLIB::FLOOR_F32, RTLIB::FLOOR_F64,
1943 RTLIB::FLOOR_F80, RTLIB::FLOOR_F128,
1944 RTLIB::FLOOR_PPCF128), Lo, Hi);
1945}
1946
1947void DAGTypeLegalizer::ExpandFloatRes_FLOG(SDNode *N,
1948 SDValue &Lo, SDValue &Hi) {
1949 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
1950 RTLIB::LOG_F32, RTLIB::LOG_F64,
1951 RTLIB::LOG_F80, RTLIB::LOG_F128,
1952 RTLIB::LOG_PPCF128), Lo, Hi);
1953}
1954
1955void DAGTypeLegalizer::ExpandFloatRes_FLOG2(SDNode *N,
1956 SDValue &Lo, SDValue &Hi) {
1957 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
1958 RTLIB::LOG2_F32, RTLIB::LOG2_F64,
1959 RTLIB::LOG2_F80, RTLIB::LOG2_F128,
1960 RTLIB::LOG2_PPCF128), Lo, Hi);
1961}
1962
1963void DAGTypeLegalizer::ExpandFloatRes_FLOG10(SDNode *N,
1964 SDValue &Lo, SDValue &Hi) {
1965 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
1966 RTLIB::LOG10_F32, RTLIB::LOG10_F64,
1967 RTLIB::LOG10_F80, RTLIB::LOG10_F128,
1968 RTLIB::LOG10_PPCF128), Lo, Hi);
1969}
1970
1971void DAGTypeLegalizer::ExpandFloatRes_FMA(SDNode *N, SDValue &Lo,
1972 SDValue &Hi) {
1973 bool IsStrict = N->isStrictFPOpcode();
1974 unsigned Offset = IsStrict ? 1 : 0;
1975 SDValue Ops[3] = { N->getOperand(0 + Offset), N->getOperand(1 + Offset),
1976 N->getOperand(2 + Offset) };
1977 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
1978 TargetLowering::MakeLibCallOptions CallOptions;
1979 std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(DAG, GetFPLibCall(N->getValueType(0),
1980 RTLIB::FMA_F32,
1981 RTLIB::FMA_F64,
1982 RTLIB::FMA_F80,
1983 RTLIB::FMA_F128,
1984 RTLIB::FMA_PPCF128),
1985 N->getValueType(0), Ops, CallOptions,
1986 SDLoc(N), Chain);
1987 if (IsStrict)
1988 ReplaceValueWith(SDValue(N, 1), Tmp.second);
1989 GetPairElements(Tmp.first, Lo, Hi);
1990}
1991
1992void DAGTypeLegalizer::ExpandFloatRes_FMUL(SDNode *N, SDValue &Lo,
1993 SDValue &Hi) {
1994 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
1995 RTLIB::MUL_F32,
1996 RTLIB::MUL_F64,
1997 RTLIB::MUL_F80,
1998 RTLIB::MUL_F128,
1999 RTLIB::MUL_PPCF128), Lo, Hi);
2000}
2001
2002void DAGTypeLegalizer::ExpandFloatRes_FNEARBYINT(SDNode *N,
2003 SDValue &Lo, SDValue &Hi) {
2004 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
2005 RTLIB::NEARBYINT_F32,
2006 RTLIB::NEARBYINT_F64,
2007 RTLIB::NEARBYINT_F80,
2008 RTLIB::NEARBYINT_F128,
2009 RTLIB::NEARBYINT_PPCF128), Lo, Hi);
2010}
2011
2012void DAGTypeLegalizer::ExpandFloatRes_FNEG(SDNode *N, SDValue &Lo,
2013 SDValue &Hi) {
2014 SDLoc dl(N);
2015 GetExpandedFloat(N->getOperand(0), Lo, Hi);
2016 Lo = DAG.getNode(ISD::FNEG, dl, Lo.getValueType(), Lo);
2017 Hi = DAG.getNode(ISD::FNEG, dl, Hi.getValueType(), Hi);
2018}
2019
2020void DAGTypeLegalizer::ExpandFloatRes_AssertNoFPClass(SDNode *N, SDValue &Lo,
2021 SDValue &Hi) {
2022 // TODO: Handle ppcf128 by preserving AssertNoFPClass for one of the halves.
2023 SDLoc dl(N);
2024 GetExpandedFloat(N->getOperand(0), Lo, Hi);
2025}
2026
2027void DAGTypeLegalizer::ExpandFloatRes_FP_EXTEND(SDNode *N, SDValue &Lo,
2028 SDValue &Hi) {
2029 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
2030 SDLoc dl(N);
2031 bool IsStrict = N->isStrictFPOpcode();
2032
2033 SDValue Chain;
2034 if (IsStrict) {
2035 // If the expanded type is the same as the input type, just bypass the node.
2036 if (NVT == N->getOperand(1).getValueType()) {
2037 Hi = N->getOperand(1);
2038 Chain = N->getOperand(0);
2039 } else {
2040 // Other we need to extend.
2041 Hi = DAG.getNode(ISD::STRICT_FP_EXTEND, dl, { NVT, MVT::Other },
2042 { N->getOperand(0), N->getOperand(1) });
2043 Chain = Hi.getValue(1);
2044 }
2045 } else {
2046 Hi = DAG.getNode(ISD::FP_EXTEND, dl, NVT, N->getOperand(0));
2047 }
2048
2049 Lo = DAG.getConstantFP(APFloat::getZero(NVT.getFltSemantics()), dl, NVT);
2050
2051 if (IsStrict)
2052 ReplaceValueWith(SDValue(N, 1), Chain);
2053}
2054
2055void DAGTypeLegalizer::ExpandFloatRes_FPOW(SDNode *N,
2056 SDValue &Lo, SDValue &Hi) {
2057 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
2058 RTLIB::POW_F32, RTLIB::POW_F64,
2059 RTLIB::POW_F80, RTLIB::POW_F128,
2060 RTLIB::POW_PPCF128), Lo, Hi);
2061}
2062
2063void DAGTypeLegalizer::ExpandFloatRes_FPOWI(SDNode *N,
2064 SDValue &Lo, SDValue &Hi) {
2065 ExpandFloatRes_Binary(N, RTLIB::getPOWI(N->getValueType(0)), Lo, Hi);
2066}
2067
2068void DAGTypeLegalizer::ExpandFloatRes_FLDEXP(SDNode *N, SDValue &Lo,
2069 SDValue &Hi) {
2070 ExpandFloatRes_Binary(N, RTLIB::getLDEXP(N->getValueType(0)), Lo, Hi);
2071}
2072
2073void DAGTypeLegalizer::ExpandFloatRes_FREEZE(SDNode *N,
2074 SDValue &Lo, SDValue &Hi) {
2075 assert(N->getValueType(0) == MVT::ppcf128 &&
2076 "Logic only correct for ppcf128!");
2077
2078 SDLoc dl(N);
2079 GetExpandedFloat(N->getOperand(0), Lo, Hi);
2080 Lo = DAG.getNode(ISD::FREEZE, dl, Lo.getValueType(), Lo);
2081 Hi = DAG.getNode(ISD::FREEZE, dl, Hi.getValueType(), Hi);
2082}
2083
2084void DAGTypeLegalizer::ExpandFloatRes_FREM(SDNode *N,
2085 SDValue &Lo, SDValue &Hi) {
2086 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
2087 RTLIB::REM_F32, RTLIB::REM_F64,
2088 RTLIB::REM_F80, RTLIB::REM_F128,
2089 RTLIB::REM_PPCF128), Lo, Hi);
2090}
2091
2092void DAGTypeLegalizer::ExpandFloatRes_FRINT(SDNode *N,
2093 SDValue &Lo, SDValue &Hi) {
2094 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
2095 RTLIB::RINT_F32, RTLIB::RINT_F64,
2096 RTLIB::RINT_F80, RTLIB::RINT_F128,
2097 RTLIB::RINT_PPCF128), Lo, Hi);
2098}
2099
2100void DAGTypeLegalizer::ExpandFloatRes_FROUND(SDNode *N,
2101 SDValue &Lo, SDValue &Hi) {
2102 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
2103 RTLIB::ROUND_F32,
2104 RTLIB::ROUND_F64,
2105 RTLIB::ROUND_F80,
2106 RTLIB::ROUND_F128,
2107 RTLIB::ROUND_PPCF128), Lo, Hi);
2108}
2109
2110void DAGTypeLegalizer::ExpandFloatRes_FROUNDEVEN(SDNode *N,
2111 SDValue &Lo, SDValue &Hi) {
2112 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
2113 RTLIB::ROUNDEVEN_F32,
2114 RTLIB::ROUNDEVEN_F64,
2115 RTLIB::ROUNDEVEN_F80,
2116 RTLIB::ROUNDEVEN_F128,
2117 RTLIB::ROUNDEVEN_PPCF128), Lo, Hi);
2118}
2119
2120void DAGTypeLegalizer::ExpandFloatRes_FSIN(SDNode *N,
2121 SDValue &Lo, SDValue &Hi) {
2122 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
2123 RTLIB::SIN_F32, RTLIB::SIN_F64,
2124 RTLIB::SIN_F80, RTLIB::SIN_F128,
2125 RTLIB::SIN_PPCF128), Lo, Hi);
2126}
2127
2128void DAGTypeLegalizer::ExpandFloatRes_FSINH(SDNode *N, SDValue &Lo,
2129 SDValue &Hi) {
2130 ExpandFloatRes_Unary(N,
2131 GetFPLibCall(N->getValueType(0), RTLIB::SINH_F32,
2132 RTLIB::SINH_F64, RTLIB::SINH_F80,
2133 RTLIB::SINH_F128, RTLIB::SINH_PPCF128),
2134 Lo, Hi);
2135}
2136
2137void DAGTypeLegalizer::ExpandFloatRes_FSQRT(SDNode *N,
2138 SDValue &Lo, SDValue &Hi) {
2139 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
2140 RTLIB::SQRT_F32, RTLIB::SQRT_F64,
2141 RTLIB::SQRT_F80, RTLIB::SQRT_F128,
2142 RTLIB::SQRT_PPCF128), Lo, Hi);
2143}
2144
2145void DAGTypeLegalizer::ExpandFloatRes_FSUB(SDNode *N, SDValue &Lo,
2146 SDValue &Hi) {
2147 ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
2148 RTLIB::SUB_F32,
2149 RTLIB::SUB_F64,
2150 RTLIB::SUB_F80,
2151 RTLIB::SUB_F128,
2152 RTLIB::SUB_PPCF128), Lo, Hi);
2153}
2154
2155void DAGTypeLegalizer::ExpandFloatRes_FTAN(SDNode *N, SDValue &Lo,
2156 SDValue &Hi) {
2157 ExpandFloatRes_Unary(N,
2158 GetFPLibCall(N->getValueType(0), RTLIB::TAN_F32,
2159 RTLIB::TAN_F64, RTLIB::TAN_F80,
2160 RTLIB::TAN_F128, RTLIB::TAN_PPCF128),
2161 Lo, Hi);
2162}
2163
2164void DAGTypeLegalizer::ExpandFloatRes_FTANH(SDNode *N, SDValue &Lo,
2165 SDValue &Hi) {
2166 ExpandFloatRes_Unary(N,
2167 GetFPLibCall(N->getValueType(0), RTLIB::TANH_F32,
2168 RTLIB::TANH_F64, RTLIB::TANH_F80,
2169 RTLIB::TANH_F128, RTLIB::TANH_PPCF128),
2170 Lo, Hi);
2171}
2172
2173void DAGTypeLegalizer::ExpandFloatRes_FTRUNC(SDNode *N,
2174 SDValue &Lo, SDValue &Hi) {
2175 ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0),
2176 RTLIB::TRUNC_F32, RTLIB::TRUNC_F64,
2177 RTLIB::TRUNC_F80, RTLIB::TRUNC_F128,
2178 RTLIB::TRUNC_PPCF128), Lo, Hi);
2179}
2180
2181void DAGTypeLegalizer::ExpandFloatRes_LOAD(SDNode *N, SDValue &Lo,
2182 SDValue &Hi) {
2183 if (ISD::isNormalLoad(N)) {
2184 ExpandRes_NormalLoad(N, Lo, Hi);
2185 return;
2186 }
2187
2188 assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!");
2189 LoadSDNode *LD = cast<LoadSDNode>(N);
2190 SDValue Chain = LD->getChain();
2191 SDValue Ptr = LD->getBasePtr();
2192 SDLoc dl(N);
2193
2194 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0));
2195 assert(NVT.isByteSized() && "Expanded type not byte sized!");
2196 assert(LD->getMemoryVT().bitsLE(NVT) && "Float type not round?");
2197
2198 Hi = DAG.getExtLoad(LD->getExtensionType(), dl, NVT, Chain, Ptr,
2199 LD->getMemoryVT(), LD->getMemOperand());
2200
2201 // Remember the chain.
2202 Chain = Hi.getValue(1);
2203
2204 // The low part is zero.
2205 Lo = DAG.getConstantFP(APFloat::getZero(NVT.getFltSemantics()), dl, NVT);
2206
2207 // Modified the chain - switch anything that used the old chain to use the
2208 // new one.
2209 ReplaceValueWith(SDValue(LD, 1), Chain);
2210}
2211
2212void DAGTypeLegalizer::ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo,
2213 SDValue &Hi) {
2214 assert(N->getValueType(0) == MVT::ppcf128 && "Unsupported XINT_TO_FP!");
2215 EVT VT = N->getValueType(0);
2216 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
2217 bool Strict = N->isStrictFPOpcode();
2218 SDValue Src = N->getOperand(Strict ? 1 : 0);
2219 EVT SrcVT = Src.getValueType();
2220 bool isSigned = N->getOpcode() == ISD::SINT_TO_FP ||
2221 N->getOpcode() == ISD::STRICT_SINT_TO_FP;
2222 SDLoc dl(N);
2223 SDValue Chain = Strict ? N->getOperand(0) : DAG.getEntryNode();
2224
2225 // TODO: Any other flags to propagate?
2226 SDNodeFlags Flags;
2227 Flags.setNoFPExcept(N->getFlags().hasNoFPExcept());
2228
2229 // First do an SINT_TO_FP, whether the original was signed or unsigned.
2230 // When promoting partial word types to i32 we must honor the signedness,
2231 // though.
2232 if (SrcVT.bitsLE(MVT::i32)) {
2233 // The integer can be represented exactly in an f64.
2234 Lo = DAG.getConstantFP(APFloat::getZero(NVT.getFltSemantics()), dl, NVT);
2235 if (Strict) {
2236 Hi = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(NVT, MVT::Other),
2237 {Chain, Src}, Flags);
2238 Chain = Hi.getValue(1);
2239 } else
2240 Hi = DAG.getNode(N->getOpcode(), dl, NVT, Src);
2241 } else {
2242 RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
2243 if (SrcVT.bitsLE(MVT::i64)) {
2244 Src = DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, dl,
2245 MVT::i64, Src);
2246 LC = RTLIB::SINTTOFP_I64_PPCF128;
2247 } else if (SrcVT.bitsLE(MVT::i128)) {
2248 Src = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i128, Src);
2249 LC = RTLIB::SINTTOFP_I128_PPCF128;
2250 }
2251 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!");
2252
2253 TargetLowering::MakeLibCallOptions CallOptions;
2254 CallOptions.setIsSigned(true);
2255 std::pair<SDValue, SDValue> Tmp =
2256 TLI.makeLibCall(DAG, LC, VT, Src, CallOptions, dl, Chain);
2257 if (Strict)
2258 Chain = Tmp.second;
2259 GetPairElements(Tmp.first, Lo, Hi);
2260 }
2261
2262 // No need to complement for unsigned 32-bit integers
2263 if (isSigned || SrcVT.bitsLE(MVT::i32)) {
2264 if (Strict)
2265 ReplaceValueWith(SDValue(N, 1), Chain);
2266
2267 return;
2268 }
2269
2270 // Unsigned - fix up the SINT_TO_FP value just calculated.
2271 // FIXME: For unsigned i128 to ppc_fp128 conversion, we need to carefully
2272 // keep semantics correctness if the integer is not exactly representable
2273 // here. See ExpandLegalINT_TO_FP.
2274 Hi = DAG.getNode(ISD::BUILD_PAIR, dl, VT, Lo, Hi);
2275 SrcVT = Src.getValueType();
2276
2277 // x>=0 ? (ppcf128)(iN)x : (ppcf128)(iN)x + 2^N; N=32,64,128.
2278 static const uint64_t TwoE32[] = { 0x41f0000000000000LL, 0 };
2279 static const uint64_t TwoE64[] = { 0x43f0000000000000LL, 0 };
2280 static const uint64_t TwoE128[] = { 0x47f0000000000000LL, 0 };
2281 ArrayRef<uint64_t> Parts;
2282
2283 switch (SrcVT.getSimpleVT().SimpleTy) {
2284 default:
2285 llvm_unreachable("Unsupported UINT_TO_FP!");
2286 case MVT::i32:
2287 Parts = TwoE32;
2288 break;
2289 case MVT::i64:
2290 Parts = TwoE64;
2291 break;
2292 case MVT::i128:
2293 Parts = TwoE128;
2294 break;
2295 }
2296
2297 // TODO: Are there other fast-math-flags to propagate to this FADD?
2298 SDValue NewLo = DAG.getConstantFP(
2299 APFloat(APFloat::PPCDoubleDouble(), APInt(128, Parts)), dl, MVT::ppcf128);
2300 if (Strict) {
2301 Lo = DAG.getNode(ISD::STRICT_FADD, dl, DAG.getVTList(VT, MVT::Other),
2302 {Chain, Hi, NewLo}, Flags);
2303 Chain = Lo.getValue(1);
2304 ReplaceValueWith(SDValue(N, 1), Chain);
2305 } else
2306 Lo = DAG.getNode(ISD::FADD, dl, VT, Hi, NewLo);
2307 Lo = DAG.getSelectCC(dl, Src, DAG.getConstant(0, dl, SrcVT),
2308 Lo, Hi, ISD::SETLT);
2309 GetPairElements(Lo, Lo, Hi);
2310}
2311
2312
2313//===----------------------------------------------------------------------===//
2314// Float Operand Expansion
2315//===----------------------------------------------------------------------===//
2316
2317/// ExpandFloatOperand - This method is called when the specified operand of the
2318/// specified node is found to need expansion. At this point, all of the result
2319/// types of the node are known to be legal, but other operands of the node may
2320/// need promotion or expansion as well as the specified one.
2321bool DAGTypeLegalizer::ExpandFloatOperand(SDNode *N, unsigned OpNo) {
2322 LLVM_DEBUG(dbgs() << "Expand float operand: "; N->dump(&DAG));
2323 SDValue Res = SDValue();
2324
2325 // See if the target wants to custom expand this node.
2326 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
2327 return false;
2328
2329 switch (N->getOpcode()) {
2330 default:
2331#ifndef NDEBUG
2332 dbgs() << "ExpandFloatOperand Op #" << OpNo << ": ";
2333 N->dump(&DAG); dbgs() << "\n";
2334#endif
2335 report_fatal_error("Do not know how to expand this operator's operand!");
2336
2337 case ISD::BITCAST: Res = ExpandOp_BITCAST(N); break;
2338 case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break;
2339 case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break;
2340
2341 case ISD::BR_CC: Res = ExpandFloatOp_BR_CC(N); break;
2342 case ISD::FCOPYSIGN: Res = ExpandFloatOp_FCOPYSIGN(N); break;
2344 case ISD::FP_ROUND: Res = ExpandFloatOp_FP_ROUND(N); break;
2347 case ISD::FP_TO_SINT:
2348 case ISD::FP_TO_UINT: Res = ExpandFloatOp_FP_TO_XINT(N); break;
2349 case ISD::LROUND: Res = ExpandFloatOp_LROUND(N); break;
2350 case ISD::LLROUND: Res = ExpandFloatOp_LLROUND(N); break;
2351 case ISD::LRINT: Res = ExpandFloatOp_LRINT(N); break;
2352 case ISD::LLRINT: Res = ExpandFloatOp_LLRINT(N); break;
2353 case ISD::SELECT_CC: Res = ExpandFloatOp_SELECT_CC(N); break;
2354 case ISD::STRICT_FSETCC:
2356 case ISD::SETCC: Res = ExpandFloatOp_SETCC(N); break;
2357 case ISD::STORE: Res = ExpandFloatOp_STORE(cast<StoreSDNode>(N),
2358 OpNo); break;
2359 }
2360
2361 // If the result is null, the sub-method took care of registering results etc.
2362 if (!Res.getNode()) return false;
2363
2364 // If the result is N, the sub-method updated N in place. Tell the legalizer
2365 // core about this.
2366 if (Res.getNode() == N)
2367 return true;
2368
2369 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
2370 "Invalid operand expansion");
2371
2372 ReplaceValueWith(SDValue(N, 0), Res);
2373 return false;
2374}
2375
2376/// FloatExpandSetCCOperands - Expand the operands of a comparison. This code
2377/// is shared among BR_CC, SELECT_CC, and SETCC handlers.
2378void DAGTypeLegalizer::FloatExpandSetCCOperands(SDValue &NewLHS,
2379 SDValue &NewRHS,
2380 ISD::CondCode &CCCode,
2381 const SDLoc &dl, SDValue &Chain,
2382 bool IsSignaling) {
2383 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
2384 GetExpandedFloat(NewLHS, LHSLo, LHSHi);
2385 GetExpandedFloat(NewRHS, RHSLo, RHSHi);
2386
2387 assert(NewLHS.getValueType() == MVT::ppcf128 && "Unsupported setcc type!");
2388
2389 // FIXME: This generated code sucks. We want to generate
2390 // FCMPU crN, hi1, hi2
2391 // BNE crN, L:
2392 // FCMPU crN, lo1, lo2
2393 // The following can be improved, but not that much.
2394 SDValue Tmp1, Tmp2, Tmp3, OutputChain;
2395 Tmp1 = DAG.getSetCC(dl, getSetCCResultType(LHSHi.getValueType()), LHSHi,
2396 RHSHi, ISD::SETOEQ, Chain, IsSignaling);
2397 OutputChain = Tmp1->getNumValues() > 1 ? Tmp1.getValue(1) : SDValue();
2398 Tmp2 = DAG.getSetCC(dl, getSetCCResultType(LHSLo.getValueType()), LHSLo,
2399 RHSLo, CCCode, OutputChain, IsSignaling);
2400 OutputChain = Tmp2->getNumValues() > 1 ? Tmp2.getValue(1) : SDValue();
2401 Tmp3 = DAG.getNode(ISD::AND, dl, Tmp1.getValueType(), Tmp1, Tmp2);
2402 Tmp1 =
2403 DAG.getSetCC(dl, getSetCCResultType(LHSHi.getValueType()), LHSHi, RHSHi,
2404 ISD::SETUNE, OutputChain, IsSignaling);
2405 OutputChain = Tmp1->getNumValues() > 1 ? Tmp1.getValue(1) : SDValue();
2406 Tmp2 = DAG.getSetCC(dl, getSetCCResultType(LHSHi.getValueType()), LHSHi,
2407 RHSHi, CCCode, OutputChain, IsSignaling);
2408 OutputChain = Tmp2->getNumValues() > 1 ? Tmp2.getValue(1) : SDValue();
2409 Tmp1 = DAG.getNode(ISD::AND, dl, Tmp1.getValueType(), Tmp1, Tmp2);
2410 NewLHS = DAG.getNode(ISD::OR, dl, Tmp1.getValueType(), Tmp1, Tmp3);
2411 NewRHS = SDValue(); // LHS is the result, not a compare.
2412 Chain = OutputChain;
2413}
2414
2415SDValue DAGTypeLegalizer::ExpandFloatOp_BR_CC(SDNode *N) {
2416 SDValue NewLHS = N->getOperand(2), NewRHS = N->getOperand(3);
2417 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(1))->get();
2418 SDValue Chain;
2419 FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, SDLoc(N), Chain);
2420
2421 // If ExpandSetCCOperands returned a scalar, we need to compare the result
2422 // against zero to select between true and false values.
2423 if (!NewRHS.getNode()) {
2424 NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
2425 CCCode = ISD::SETNE;
2426 }
2427
2428 // Update N to have the operands specified.
2429 return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0),
2430 DAG.getCondCode(CCCode), NewLHS, NewRHS,
2431 N->getOperand(4)), 0);
2432}
2433
2434SDValue DAGTypeLegalizer::ExpandFloatOp_FCOPYSIGN(SDNode *N) {
2435 assert(N->getOperand(1).getValueType() == MVT::ppcf128 &&
2436 "Logic only correct for ppcf128!");
2437 SDValue Lo, Hi;
2438 GetExpandedFloat(N->getOperand(1), Lo, Hi);
2439 // The ppcf128 value is providing only the sign; take it from the
2440 // higher-order double (which must have the larger magnitude).
2441 return DAG.getNode(ISD::FCOPYSIGN, SDLoc(N),
2442 N->getValueType(0), N->getOperand(0), Hi);
2443}
2444
2445SDValue DAGTypeLegalizer::ExpandFloatOp_FP_ROUND(SDNode *N) {
2446 bool IsStrict = N->isStrictFPOpcode();
2447 assert(N->getOperand(IsStrict ? 1 : 0).getValueType() == MVT::ppcf128 &&
2448 "Logic only correct for ppcf128!");
2449 SDValue Lo, Hi;
2450 GetExpandedFloat(N->getOperand(IsStrict ? 1 : 0), Lo, Hi);
2451
2452 if (!IsStrict)
2453 // Round it the rest of the way (e.g. to f32) if needed.
2454 return DAG.getNode(ISD::FP_ROUND, SDLoc(N),
2455 N->getValueType(0), Hi, N->getOperand(1));
2456
2457 // Eliminate the node if the input float type is the same as the output float
2458 // type.
2459 if (Hi.getValueType() == N->getValueType(0)) {
2460 // Connect the output chain to the input chain, unlinking the node.
2461 ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
2462 ReplaceValueWith(SDValue(N, 0), Hi);
2463 return SDValue();
2464 }
2465
2466 SDValue Expansion = DAG.getNode(ISD::STRICT_FP_ROUND, SDLoc(N),
2467 {N->getValueType(0), MVT::Other},
2468 {N->getOperand(0), Hi, N->getOperand(2)});
2469 ReplaceValueWith(SDValue(N, 1), Expansion.getValue(1));
2470 ReplaceValueWith(SDValue(N, 0), Expansion);
2471 return SDValue();
2472}
2473
2474SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_XINT(SDNode *N) {
2475 EVT RVT = N->getValueType(0);
2476 SDLoc dl(N);
2477
2478 bool IsStrict = N->isStrictFPOpcode();
2479 bool Signed = N->getOpcode() == ISD::FP_TO_SINT ||
2480 N->getOpcode() == ISD::STRICT_FP_TO_SINT;
2481 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
2482 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
2483
2484 EVT NVT;
2485 RTLIB::Libcall LC = findFPToIntLibcall(Op.getValueType(), RVT, NVT, Signed);
2486 assert(LC != RTLIB::UNKNOWN_LIBCALL && NVT.isSimple() &&
2487 "Unsupported FP_TO_XINT!");
2488 TargetLowering::MakeLibCallOptions CallOptions;
2489 std::pair<SDValue, SDValue> Tmp =
2490 TLI.makeLibCall(DAG, LC, NVT, Op, CallOptions, dl, Chain);
2491 if (!IsStrict)
2492 return Tmp.first;
2493
2494 ReplaceValueWith(SDValue(N, 1), Tmp.second);
2495 ReplaceValueWith(SDValue(N, 0), Tmp.first);
2496 return SDValue();
2497}
2498
2499SDValue DAGTypeLegalizer::ExpandFloatOp_SELECT_CC(SDNode *N) {
2500 SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
2501 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(4))->get();
2502 SDValue Chain;
2503 FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, SDLoc(N), Chain);
2504
2505 // If ExpandSetCCOperands returned a scalar, we need to compare the result
2506 // against zero to select between true and false values.
2507 if (!NewRHS.getNode()) {
2508 NewRHS = DAG.getConstant(0, SDLoc(N), NewLHS.getValueType());
2509 CCCode = ISD::SETNE;
2510 }
2511
2512 // Update N to have the operands specified.
2513 return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
2514 N->getOperand(2), N->getOperand(3),
2515 DAG.getCondCode(CCCode)), 0);
2516}
2517
2518SDValue DAGTypeLegalizer::ExpandFloatOp_SETCC(SDNode *N) {
2519 bool IsStrict = N->isStrictFPOpcode();
2520 SDValue NewLHS = N->getOperand(IsStrict ? 1 : 0);
2521 SDValue NewRHS = N->getOperand(IsStrict ? 2 : 1);
2522 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
2523 ISD::CondCode CCCode =
2524 cast<CondCodeSDNode>(N->getOperand(IsStrict ? 3 : 2))->get();
2525 FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, SDLoc(N), Chain,
2526 N->getOpcode() == ISD::STRICT_FSETCCS);
2527
2528 // FloatExpandSetCCOperands always returned a scalar.
2529 assert(!NewRHS.getNode() && "Expect to return scalar");
2530 assert(NewLHS.getValueType() == N->getValueType(0) &&
2531 "Unexpected setcc expansion!");
2532 if (Chain) {
2533 ReplaceValueWith(SDValue(N, 0), NewLHS);
2534 ReplaceValueWith(SDValue(N, 1), Chain);
2535 return SDValue();
2536 }
2537 return NewLHS;
2538}
2539
2540SDValue DAGTypeLegalizer::ExpandFloatOp_STORE(SDNode *N, unsigned OpNo) {
2541 if (ISD::isNormalStore(N))
2542 return ExpandOp_NormalStore(N, OpNo);
2543
2544 assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!");
2545 assert(OpNo == 1 && "Can only expand the stored value so far");
2546 StoreSDNode *ST = cast<StoreSDNode>(N);
2547
2548 SDValue Chain = ST->getChain();
2549 SDValue Ptr = ST->getBasePtr();
2550
2551 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(),
2552 ST->getValue().getValueType());
2553 assert(NVT.isByteSized() && "Expanded type not byte sized!");
2554 assert(ST->getMemoryVT().bitsLE(NVT) && "Float type not round?");
2555 (void)NVT;
2556
2557 SDValue Lo, Hi;
2558 GetExpandedOp(ST->getValue(), Lo, Hi);
2559
2560 return DAG.getTruncStore(Chain, SDLoc(N), Hi, Ptr,
2561 ST->getMemoryVT(), ST->getMemOperand());
2562}
2563
2564SDValue DAGTypeLegalizer::ExpandFloatOp_LROUND(SDNode *N) {
2565 EVT RVT = N->getValueType(0);
2566 EVT RetVT = N->getOperand(0).getValueType();
2567 TargetLowering::MakeLibCallOptions CallOptions;
2568 return TLI.makeLibCall(DAG, GetFPLibCall(RetVT,
2569 RTLIB::LROUND_F32,
2570 RTLIB::LROUND_F64,
2571 RTLIB::LROUND_F80,
2572 RTLIB::LROUND_F128,
2573 RTLIB::LROUND_PPCF128),
2574 RVT, N->getOperand(0), CallOptions, SDLoc(N)).first;
2575}
2576
2577SDValue DAGTypeLegalizer::ExpandFloatOp_LLROUND(SDNode *N) {
2578 EVT RVT = N->getValueType(0);
2579 EVT RetVT = N->getOperand(0).getValueType();
2580 TargetLowering::MakeLibCallOptions CallOptions;
2581 return TLI.makeLibCall(DAG, GetFPLibCall(RetVT,
2582 RTLIB::LLROUND_F32,
2583 RTLIB::LLROUND_F64,
2584 RTLIB::LLROUND_F80,
2585 RTLIB::LLROUND_F128,
2586 RTLIB::LLROUND_PPCF128),
2587 RVT, N->getOperand(0), CallOptions, SDLoc(N)).first;
2588}
2589
2590SDValue DAGTypeLegalizer::ExpandFloatOp_LRINT(SDNode *N) {
2591 EVT RVT = N->getValueType(0);
2592 EVT RetVT = N->getOperand(0).getValueType();
2593 TargetLowering::MakeLibCallOptions CallOptions;
2594 return TLI.makeLibCall(DAG, GetFPLibCall(RetVT,
2595 RTLIB::LRINT_F32,
2596 RTLIB::LRINT_F64,
2597 RTLIB::LRINT_F80,
2598 RTLIB::LRINT_F128,
2599 RTLIB::LRINT_PPCF128),
2600 RVT, N->getOperand(0), CallOptions, SDLoc(N)).first;
2601}
2602
2603SDValue DAGTypeLegalizer::ExpandFloatOp_LLRINT(SDNode *N) {
2604 EVT RVT = N->getValueType(0);
2605 EVT RetVT = N->getOperand(0).getValueType();
2606 TargetLowering::MakeLibCallOptions CallOptions;
2607 return TLI.makeLibCall(DAG, GetFPLibCall(RetVT,
2608 RTLIB::LLRINT_F32,
2609 RTLIB::LLRINT_F64,
2610 RTLIB::LLRINT_F80,
2611 RTLIB::LLRINT_F128,
2612 RTLIB::LLRINT_PPCF128),
2613 RVT, N->getOperand(0), CallOptions, SDLoc(N)).first;
2614}
2615
2616//===----------------------------------------------------------------------===//
2617// Float Operand Promotion
2618//===----------------------------------------------------------------------===//
2619//
2620
2622 if (OpVT == MVT::f16)
2623 return ISD::FP16_TO_FP;
2624 if (RetVT == MVT::f16)
2625 return ISD::FP_TO_FP16;
2626 if (OpVT == MVT::bf16)
2627 return ISD::BF16_TO_FP;
2628 if (RetVT == MVT::bf16)
2629 return ISD::FP_TO_BF16;
2630 report_fatal_error("Attempt at an invalid promotion-related conversion");
2631}
2632
2634 if (OpVT == MVT::f16)
2636 if (RetVT == MVT::f16)
2638 if (OpVT == MVT::bf16)
2640 if (RetVT == MVT::bf16)
2642 report_fatal_error("Attempt at an invalid promotion-related conversion");
2643}
2644
2645bool DAGTypeLegalizer::PromoteFloatOperand(SDNode *N, unsigned OpNo) {
2646 LLVM_DEBUG(dbgs() << "Promote float operand " << OpNo << ": "; N->dump(&DAG));
2647 SDValue R = SDValue();
2648
2649 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false)) {
2650 LLVM_DEBUG(dbgs() << "Node has been custom lowered, done\n");
2651 return false;
2652 }
2653
2654 // Nodes that use a promotion-requiring floating point operand, but doesn't
2655 // produce a promotion-requiring floating point result, need to be legalized
2656 // to use the promoted float operand. Nodes that produce at least one
2657 // promotion-requiring floating point result have their operands legalized as
2658 // a part of PromoteFloatResult.
2659 // clang-format off
2660 switch (N->getOpcode()) {
2661 default:
2662 #ifndef NDEBUG
2663 dbgs() << "PromoteFloatOperand Op #" << OpNo << ": ";
2664 N->dump(&DAG); dbgs() << "\n";
2665 #endif
2666 report_fatal_error("Do not know how to promote this operator's operand!");
2667
2668 case ISD::BITCAST: R = PromoteFloatOp_BITCAST(N, OpNo); break;
2669 case ISD::FAKE_USE:
2670 R = PromoteFloatOp_FAKE_USE(N, OpNo);
2671 break;
2672 case ISD::FCOPYSIGN: R = PromoteFloatOp_FCOPYSIGN(N, OpNo); break;
2673 case ISD::FP_TO_SINT:
2674 case ISD::FP_TO_UINT:
2675 case ISD::LROUND:
2676 case ISD::LLROUND:
2677 case ISD::LRINT:
2678 case ISD::LLRINT: R = PromoteFloatOp_UnaryOp(N, OpNo); break;
2679 case ISD::AssertNoFPClass: R = PromoteFloatOp_AssertNoFPClass(N, OpNo); break;
2682 R = PromoteFloatOp_FP_TO_XINT_SAT(N, OpNo); break;
2683 case ISD::FP_EXTEND: R = PromoteFloatOp_FP_EXTEND(N, OpNo); break;
2685 R = PromoteFloatOp_STRICT_FP_EXTEND(N, OpNo);
2686 break;
2687 case ISD::SELECT_CC: R = PromoteFloatOp_SELECT_CC(N, OpNo); break;
2688 case ISD::SETCC: R = PromoteFloatOp_SETCC(N, OpNo); break;
2689 case ISD::STORE: R = PromoteFloatOp_STORE(N, OpNo); break;
2690 case ISD::ATOMIC_STORE: R = PromoteFloatOp_ATOMIC_STORE(N, OpNo); break;
2691 }
2692 // clang-format on
2693
2694 if (R.getNode())
2695 ReplaceValueWith(SDValue(N, 0), R);
2696 return false;
2697}
2698
2699SDValue DAGTypeLegalizer::PromoteFloatOp_BITCAST(SDNode *N, unsigned OpNo) {
2700 SDValue Op = N->getOperand(0);
2701 EVT OpVT = Op->getValueType(0);
2702
2703 SDValue Promoted = GetPromotedFloat(N->getOperand(0));
2704 EVT PromotedVT = Promoted->getValueType(0);
2705
2706 // Convert the promoted float value to the desired IVT.
2707 EVT IVT = EVT::getIntegerVT(*DAG.getContext(), OpVT.getSizeInBits());
2708 SDValue Convert = DAG.getNode(GetPromotionOpcode(PromotedVT, OpVT), SDLoc(N),
2709 IVT, Promoted);
2710 // The final result type might not be an scalar so we need a bitcast. The
2711 // bitcast will be further legalized if needed.
2712 return DAG.getBitcast(N->getValueType(0), Convert);
2713}
2714
2715SDValue DAGTypeLegalizer::PromoteFloatOp_FAKE_USE(SDNode *N, unsigned OpNo) {
2716 assert(OpNo == 1 && "Only Operand 1 must need promotion here");
2717 SDValue Op = GetPromotedFloat(N->getOperand(OpNo));
2718 return DAG.getNode(N->getOpcode(), SDLoc(N), MVT::Other, N->getOperand(0),
2719 Op);
2720}
2721
2722// Promote Operand 1 of FCOPYSIGN. Operand 0 ought to be handled by
2723// PromoteFloatRes_FCOPYSIGN.
2724SDValue DAGTypeLegalizer::PromoteFloatOp_FCOPYSIGN(SDNode *N, unsigned OpNo) {
2725 assert (OpNo == 1 && "Only Operand 1 must need promotion here");
2726 SDValue Op1 = GetPromotedFloat(N->getOperand(1));
2727
2728 return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
2729 N->getOperand(0), Op1);
2730}
2731
2732// Convert the promoted float value to the desired integer type
2733SDValue DAGTypeLegalizer::PromoteFloatOp_UnaryOp(SDNode *N, unsigned OpNo) {
2734 SDValue Op = GetPromotedFloat(N->getOperand(0));
2735 return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), Op);
2736}
2737
2738// Convert the promoted float value to the desired integer type
2739SDValue DAGTypeLegalizer::PromoteFloatOp_AssertNoFPClass(SDNode *N,
2740 unsigned OpNo) {
2741 return GetPromotedFloat(N->getOperand(0));
2742}
2743
2744SDValue DAGTypeLegalizer::PromoteFloatOp_FP_TO_XINT_SAT(SDNode *N,
2745 unsigned OpNo) {
2746 SDValue Op = GetPromotedFloat(N->getOperand(0));
2747 return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), Op,
2748 N->getOperand(1));
2749}
2750
2751SDValue DAGTypeLegalizer::PromoteFloatOp_FP_EXTEND(SDNode *N, unsigned OpNo) {
2752 SDValue Op = GetPromotedFloat(N->getOperand(0));
2753 EVT VT = N->getValueType(0);
2754
2755 // Desired VT is same as promoted type. Use promoted float directly.
2756 if (VT == Op->getValueType(0))
2757 return Op;
2758
2759 // Else, extend the promoted float value to the desired VT.
2760 return DAG.getNode(ISD::FP_EXTEND, SDLoc(N), VT, Op);
2761}
2762
2763SDValue DAGTypeLegalizer::PromoteFloatOp_STRICT_FP_EXTEND(SDNode *N,
2764 unsigned OpNo) {
2765 assert(OpNo == 1 && "Promoting unpromotable operand");
2766
2767 SDValue Op = GetPromotedFloat(N->getOperand(1));
2768 EVT VT = N->getValueType(0);
2769
2770 // Desired VT is same as promoted type. Use promoted float directly.
2771 if (VT == Op->getValueType(0)) {
2772 ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
2773 return Op;
2774 }
2775
2776 // Else, extend the promoted float value to the desired VT.
2777 SDValue Res = DAG.getNode(ISD::STRICT_FP_EXTEND, SDLoc(N), N->getVTList(),
2778 N->getOperand(0), Op);
2779 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
2780 return Res;
2781}
2782
2783// Promote the float operands used for comparison. The true- and false-
2784// operands have the same type as the result and are promoted, if needed, by
2785// PromoteFloatRes_SELECT_CC
2786SDValue DAGTypeLegalizer::PromoteFloatOp_SELECT_CC(SDNode *N, unsigned OpNo) {
2787 SDValue LHS = GetPromotedFloat(N->getOperand(0));
2788 SDValue RHS = GetPromotedFloat(N->getOperand(1));
2789
2790 return DAG.getNode(ISD::SELECT_CC, SDLoc(N), N->getValueType(0),
2791 LHS, RHS, N->getOperand(2), N->getOperand(3),
2792 N->getOperand(4));
2793}
2794
2795// Construct a SETCC that compares the promoted values and sets the conditional
2796// code.
2797SDValue DAGTypeLegalizer::PromoteFloatOp_SETCC(SDNode *N, unsigned OpNo) {
2798 EVT VT = N->getValueType(0);
2799 SDValue Op0 = GetPromotedFloat(N->getOperand(0));
2800 SDValue Op1 = GetPromotedFloat(N->getOperand(1));
2801 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(2))->get();
2802
2803 return DAG.getSetCC(SDLoc(N), VT, Op0, Op1, CCCode);
2804
2805}
2806
2807// Lower the promoted Float down to the integer value of same size and construct
2808// a STORE of the integer value.
2809SDValue DAGTypeLegalizer::PromoteFloatOp_STORE(SDNode *N, unsigned OpNo) {
2810 StoreSDNode *ST = cast<StoreSDNode>(N);
2811 SDValue Val = ST->getValue();
2812 SDLoc DL(N);
2813
2814 SDValue Promoted = GetPromotedFloat(Val);
2815 EVT VT = ST->getOperand(1).getValueType();
2816 EVT IVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
2817
2818 SDValue NewVal;
2819 NewVal = DAG.getNode(GetPromotionOpcode(Promoted.getValueType(), VT), DL,
2820 IVT, Promoted);
2821
2822 return DAG.getStore(ST->getChain(), DL, NewVal, ST->getBasePtr(),
2823 ST->getMemOperand());
2824}
2825
2826SDValue DAGTypeLegalizer::PromoteFloatOp_ATOMIC_STORE(SDNode *N,
2827 unsigned OpNo) {
2828 AtomicSDNode *ST = cast<AtomicSDNode>(N);
2829 SDValue Val = ST->getVal();
2830 SDLoc DL(N);
2831
2832 SDValue Promoted = GetPromotedFloat(Val);
2833 EVT VT = ST->getOperand(1).getValueType();
2834 EVT IVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
2835
2836 SDValue NewVal = DAG.getNode(GetPromotionOpcode(Promoted.getValueType(), VT),
2837 DL, IVT, Promoted);
2838
2839 return DAG.getAtomic(ISD::ATOMIC_STORE, DL, IVT, ST->getChain(), NewVal,
2840 ST->getBasePtr(), ST->getMemOperand());
2841}
2842
2843//===----------------------------------------------------------------------===//
2844// Float Result Promotion
2845//===----------------------------------------------------------------------===//
2846
2847void DAGTypeLegalizer::PromoteFloatResult(SDNode *N, unsigned ResNo) {
2848 LLVM_DEBUG(dbgs() << "Promote float result " << ResNo << ": "; N->dump(&DAG));
2849 SDValue R = SDValue();
2850
2851 // See if the target wants to custom expand this node.
2852 if (CustomLowerNode(N, N->getValueType(ResNo), true)) {
2853 LLVM_DEBUG(dbgs() << "Node has been custom expanded, done\n");
2854 return;
2855 }
2856
2857 switch (N->getOpcode()) {
2858 // These opcodes cannot appear if promotion of FP16 is done in the backend
2859 // instead of Clang
2860 case ISD::FP16_TO_FP:
2861 case ISD::FP_TO_FP16:
2862 default:
2863#ifndef NDEBUG
2864 dbgs() << "PromoteFloatResult #" << ResNo << ": ";
2865 N->dump(&DAG); dbgs() << "\n";
2866#endif
2867 report_fatal_error("Do not know how to promote this operator's result!");
2868
2869 case ISD::BITCAST:
2870 R = PromoteFloatRes_BITCAST(N);
2871 break;
2872 case ISD::FREEZE:
2873 R = PromoteFloatRes_FREEZE(N);
2874 break;
2875 case ISD::ConstantFP: R = PromoteFloatRes_ConstantFP(N); break;
2877 R = PromoteFloatRes_EXTRACT_VECTOR_ELT(N); break;
2878 case ISD::FCOPYSIGN: R = PromoteFloatRes_FCOPYSIGN(N); break;
2879
2880 // Unary FP Operations
2881 case ISD::FABS:
2882 case ISD::FACOS:
2883 case ISD::FASIN:
2884 case ISD::FATAN:
2885 case ISD::FCBRT:
2886 case ISD::FCEIL:
2887 case ISD::FCOS:
2888 case ISD::FCOSH:
2889 case ISD::FEXP:
2890 case ISD::FEXP2:
2891 case ISD::FEXP10:
2892 case ISD::FFLOOR:
2893 case ISD::FLOG:
2894 case ISD::FLOG2:
2895 case ISD::FLOG10:
2896 case ISD::FNEARBYINT:
2897 case ISD::FNEG:
2898 case ISD::FRINT:
2899 case ISD::FROUND:
2900 case ISD::FROUNDEVEN:
2901 case ISD::FSIN:
2902 case ISD::FSINH:
2903 case ISD::FSQRT:
2904 case ISD::FTRUNC:
2905 case ISD::FTAN:
2906 case ISD::FTANH:
2907 case ISD::FCANONICALIZE: R = PromoteFloatRes_UnaryOp(N); break;
2909 R = PromoteFloatRes_AssertNoFPClass(N);
2910 break;
2911
2912 // Binary FP Operations
2913 case ISD::FADD:
2914 case ISD::FDIV:
2915 case ISD::FMAXIMUM:
2916 case ISD::FMINIMUM:
2917 case ISD::FMAXIMUMNUM:
2918 case ISD::FMINIMUMNUM:
2919 case ISD::FMAXNUM:
2920 case ISD::FMINNUM:
2921 case ISD::FMAXNUM_IEEE:
2922 case ISD::FMINNUM_IEEE:
2923 case ISD::FMUL:
2924 case ISD::FPOW:
2925 case ISD::FATAN2:
2926 case ISD::FREM:
2927 case ISD::FSUB: R = PromoteFloatRes_BinOp(N); break;
2928
2929 case ISD::FMA: // FMA is same as FMAD
2930 case ISD::FMAD: R = PromoteFloatRes_FMAD(N); break;
2931
2932 case ISD::FPOWI:
2933 case ISD::FLDEXP: R = PromoteFloatRes_ExpOp(N); break;
2934 case ISD::FFREXP: R = PromoteFloatRes_FFREXP(N); break;
2935
2936 case ISD::FMODF:
2937 case ISD::FSINCOS:
2938 case ISD::FSINCOSPI:
2939 R = PromoteFloatRes_UnaryWithTwoFPResults(N);
2940 break;
2941 case ISD::FP_ROUND: R = PromoteFloatRes_FP_ROUND(N); break;
2943 R = PromoteFloatRes_STRICT_FP_ROUND(N);
2944 break;
2945 case ISD::LOAD: R = PromoteFloatRes_LOAD(N); break;
2946 case ISD::ATOMIC_LOAD:
2947 R = PromoteFloatRes_ATOMIC_LOAD(N);
2948 break;
2949 case ISD::SELECT: R = PromoteFloatRes_SELECT(N); break;
2950 case ISD::SELECT_CC: R = PromoteFloatRes_SELECT_CC(N); break;
2951
2952 case ISD::SINT_TO_FP:
2953 case ISD::UINT_TO_FP: R = PromoteFloatRes_XINT_TO_FP(N); break;
2954 case ISD::POISON:
2955 case ISD::UNDEF: R = PromoteFloatRes_UNDEF(N); break;
2956 case ISD::ATOMIC_SWAP: R = BitcastToInt_ATOMIC_SWAP(N); break;
2963 R = PromoteFloatRes_VECREDUCE(N);
2964 break;
2967 R = PromoteFloatRes_VECREDUCE_SEQ(N);
2968 break;
2969 }
2970
2971 if (R.getNode())
2972 SetPromotedFloat(SDValue(N, ResNo), R);
2973}
2974
2975// Bitcast from i16 to f16: convert the i16 to a f32 value instead.
2976// At this point, it is not possible to determine if the bitcast value is
2977// eventually stored to memory or promoted to f32 or promoted to a floating
2978// point at a higher precision. Some of these cases are handled by FP_EXTEND,
2979// STORE promotion handlers.
2980SDValue DAGTypeLegalizer::PromoteFloatRes_BITCAST(SDNode *N) {
2981 EVT VT = N->getValueType(0);
2982 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
2983 // Input type isn't guaranteed to be a scalar int so bitcast if not. The
2984 // bitcast will be legalized further if necessary.
2985 EVT IVT = EVT::getIntegerVT(*DAG.getContext(),
2986 N->getOperand(0).getValueType().getSizeInBits());
2987 SDValue Cast = DAG.getBitcast(IVT, N->getOperand(0));
2988 return DAG.getNode(GetPromotionOpcode(VT, NVT), SDLoc(N), NVT, Cast);
2989}
2990
2991SDValue DAGTypeLegalizer::PromoteFloatRes_FREEZE(SDNode *N) {
2992 EVT VT = N->getValueType(0);
2993 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
2994 // Input type isn't guaranteed to be a scalar int so bitcast if not. The
2995 // bitcast will be legalized further if necessary.
2996 EVT IVT = EVT::getIntegerVT(*DAG.getContext(),
2997 N->getOperand(0).getValueType().getSizeInBits());
2998 SDValue Cast = DAG.getBitcast(IVT, N->getOperand(0));
2999 return DAG.getNode(GetPromotionOpcode(VT, NVT), SDLoc(N), NVT,
3000 DAG.getFreeze(Cast));
3001}
3002
3003SDValue DAGTypeLegalizer::PromoteFloatRes_ConstantFP(SDNode *N) {
3004 ConstantFPSDNode *CFPNode = cast<ConstantFPSDNode>(N);
3005 EVT VT = N->getValueType(0);
3006 SDLoc DL(N);
3007
3008 // Get the (bit-cast) APInt of the APFloat and build an integer constant
3009 EVT IVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
3010 SDValue C = DAG.getConstant(CFPNode->getValueAPF().bitcastToAPInt(), DL,
3011 IVT);
3012
3013 // Convert the Constant to the desired FP type
3014 // FIXME We might be able to do the conversion during compilation and get rid
3015 // of it from the object code
3016 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
3017 return DAG.getNode(GetPromotionOpcode(VT, NVT), DL, NVT, C);
3018}
3019
3020// If the Index operand is a constant, try to redirect the extract operation to
3021// the correct legalized vector. If not, bit-convert the input vector to
3022// equivalent integer vector. Extract the element as an (bit-cast) integer
3023// value and convert it to the promoted type.
3024SDValue DAGTypeLegalizer::PromoteFloatRes_EXTRACT_VECTOR_ELT(SDNode *N) {
3025 SDLoc DL(N);
3026
3027 // If the index is constant, try to extract the value from the legalized
3028 // vector type.
3029 if (isa<ConstantSDNode>(N->getOperand(1))) {
3030 SDValue Vec = N->getOperand(0);
3031 SDValue Idx = N->getOperand(1);
3032 EVT VecVT = Vec->getValueType(0);
3033 EVT EltVT = VecVT.getVectorElementType();
3034
3035 uint64_t IdxVal = Idx->getAsZExtVal();
3036
3037 switch (getTypeAction(VecVT)) {
3038 default: break;
3040 SDValue Res = GetScalarizedVector(N->getOperand(0));
3041 ReplaceValueWith(SDValue(N, 0), Res);
3042 return SDValue();
3043 }
3045 Vec = GetWidenedVector(Vec);
3046 SDValue Res = DAG.getNode(N->getOpcode(), DL, EltVT, Vec, Idx);
3047 ReplaceValueWith(SDValue(N, 0), Res);
3048 return SDValue();
3049 }
3051 SDValue Lo, Hi;
3052 GetSplitVector(Vec, Lo, Hi);
3053
3054 uint64_t LoElts = Lo.getValueType().getVectorNumElements();
3055 SDValue Res;
3056 if (IdxVal < LoElts)
3057 Res = DAG.getNode(N->getOpcode(), DL, EltVT, Lo, Idx);
3058 else
3059 Res = DAG.getNode(N->getOpcode(), DL, EltVT, Hi,
3060 DAG.getConstant(IdxVal - LoElts, DL,
3061 Idx.getValueType()));
3062 ReplaceValueWith(SDValue(N, 0), Res);
3063 return SDValue();
3064 }
3065
3066 }
3067 }
3068
3069 // Bit-convert the input vector to the equivalent integer vector
3070 SDValue NewOp = BitConvertVectorToIntegerVector(N->getOperand(0));
3071 EVT IVT = NewOp.getValueType().getVectorElementType();
3072
3073 // Extract the element as an (bit-cast) integer value
3074 SDValue NewVal = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, IVT,
3075 NewOp, N->getOperand(1));
3076
3077 // Convert the element to the desired FP type
3078 EVT VT = N->getValueType(0);
3079 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
3080 return DAG.getNode(GetPromotionOpcode(VT, NVT), SDLoc(N), NVT, NewVal);
3081}
3082
3083// FCOPYSIGN(X, Y) returns the value of X with the sign of Y. If the result
3084// needs promotion, so does the argument X. Note that Y, if needed, will be
3085// handled during operand promotion.
3086SDValue DAGTypeLegalizer::PromoteFloatRes_FCOPYSIGN(SDNode *N) {
3087 EVT VT = N->getValueType(0);
3088 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
3089 SDValue Op0 = GetPromotedFloat(N->getOperand(0));
3090
3091 SDValue Op1 = N->getOperand(1);
3092
3093 return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op0, Op1);
3094}
3095
3096// Unary operation where the result and the operand have PromoteFloat type
3097// action. Construct a new SDNode with the promoted float value of the old
3098// operand.
3099SDValue DAGTypeLegalizer::PromoteFloatRes_UnaryOp(SDNode *N) {
3100 EVT VT = N->getValueType(0);
3101 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
3102 SDValue Op = GetPromotedFloat(N->getOperand(0));
3103 return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op);
3104}
3105
3106// Unary operation with a more non-float operand where the result and the
3107// operand have PromoteFloat type action. Construct a new SDNode with the
3108// promoted float value of the old operand.
3109SDValue DAGTypeLegalizer::PromoteFloatRes_AssertNoFPClass(SDNode *N) {
3110 return GetPromotedFloat(N->getOperand(0));
3111}
3112
3113// Binary operations where the result and both operands have PromoteFloat type
3114// action. Construct a new SDNode with the promoted float values of the old
3115// operands.
3116SDValue DAGTypeLegalizer::PromoteFloatRes_BinOp(SDNode *N) {
3117 EVT VT = N->getValueType(0);
3118 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
3119 SDValue Op0 = GetPromotedFloat(N->getOperand(0));
3120 SDValue Op1 = GetPromotedFloat(N->getOperand(1));
3121 return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op0, Op1, N->getFlags());
3122}
3123
3124SDValue DAGTypeLegalizer::PromoteFloatRes_FMAD(SDNode *N) {
3125 EVT VT = N->getValueType(0);
3126 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
3127 SDValue Op0 = GetPromotedFloat(N->getOperand(0));
3128 SDValue Op1 = GetPromotedFloat(N->getOperand(1));
3129 SDValue Op2 = GetPromotedFloat(N->getOperand(2));
3130
3131 return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op0, Op1, Op2);
3132}
3133
3134// Promote the Float (first) operand and retain the Integer (second) operand
3135SDValue DAGTypeLegalizer::PromoteFloatRes_ExpOp(SDNode *N) {
3136 EVT VT = N->getValueType(0);
3137 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
3138 SDValue Op0 = GetPromotedFloat(N->getOperand(0));
3139 SDValue Op1 = N->getOperand(1);
3140
3141 return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op0, Op1);
3142}
3143
3144SDValue DAGTypeLegalizer::PromoteFloatRes_FFREXP(SDNode *N) {
3145 EVT VT = N->getValueType(0);
3146 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
3147 SDValue Op = GetPromotedFloat(N->getOperand(0));
3148 SDValue Res =
3149 DAG.getNode(N->getOpcode(), SDLoc(N), {NVT, N->getValueType(1)}, Op);
3150
3151 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
3152 return Res;
3153}
3154
3155SDValue DAGTypeLegalizer::PromoteFloatRes_UnaryWithTwoFPResults(SDNode *N) {
3156 EVT VT = N->getValueType(0);
3157 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
3158 SDValue Op = GetPromotedFloat(N->getOperand(0));
3159 SDValue Res = DAG.getNode(N->getOpcode(), SDLoc(N), {NVT, NVT}, Op);
3160
3161 for (unsigned ResNum = 0, NumValues = N->getNumValues(); ResNum < NumValues;
3162 ++ResNum) {
3163 SetPromotedFloat(SDValue(N, ResNum), Res.getValue(ResNum));
3164 }
3165
3166 return SDValue();
3167}
3168
3169// Explicit operation to reduce precision. Reduce the value to half precision
3170// and promote it back to the legal type.
3171SDValue DAGTypeLegalizer::PromoteFloatRes_FP_ROUND(SDNode *N) {
3172 SDLoc DL(N);
3173
3174 SDValue Op = N->getOperand(0);
3175 EVT VT = N->getValueType(0);
3176 EVT OpVT = Op->getValueType(0);
3177 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
3178 EVT IVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
3179
3180 // Round promoted float to desired precision
3181 SDValue Round = DAG.getNode(GetPromotionOpcode(OpVT, VT), DL, IVT, Op);
3182 // Promote it back to the legal output type
3183 return DAG.getNode(GetPromotionOpcode(VT, NVT), DL, NVT, Round);
3184}
3185
3186// Explicit operation to reduce precision. Reduce the value to half precision
3187// and promote it back to the legal type.
3188SDValue DAGTypeLegalizer::PromoteFloatRes_STRICT_FP_ROUND(SDNode *N) {
3189 SDLoc DL(N);
3190
3191 SDValue Chain = N->getOperand(0);
3192 SDValue Op = N->getOperand(1);
3193 EVT VT = N->getValueType(0);
3194 EVT OpVT = Op->getValueType(0);
3195 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
3196 EVT IVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
3197
3198 // Round promoted float to desired precision
3199 SDValue Round = DAG.getNode(GetPromotionOpcodeStrict(OpVT, VT), DL,
3200 DAG.getVTList(IVT, MVT::Other), Chain, Op);
3201 // Promote it back to the legal output type
3202 SDValue Res =
3203 DAG.getNode(GetPromotionOpcodeStrict(VT, NVT), DL,
3204 DAG.getVTList(NVT, MVT::Other), Round.getValue(1), Round);
3205 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
3206 return Res;
3207}
3208
3209SDValue DAGTypeLegalizer::PromoteFloatRes_LOAD(SDNode *N) {
3210 LoadSDNode *L = cast<LoadSDNode>(N);
3211 EVT VT = N->getValueType(0);
3212
3213 // Load the value as an integer value with the same number of bits.
3214 EVT IVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
3215 SDValue newL = DAG.getLoad(
3216 L->getAddressingMode(), L->getExtensionType(), IVT, SDLoc(N),
3217 L->getChain(), L->getBasePtr(), L->getOffset(), L->getPointerInfo(), IVT,
3218 L->getBaseAlign(), L->getMemOperand()->getFlags(), L->getAAInfo());
3219 // Legalize the chain result by replacing uses of the old value chain with the
3220 // new one
3221 ReplaceValueWith(SDValue(N, 1), newL.getValue(1));
3222
3223 // Convert the integer value to the desired FP type
3224 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
3225 return DAG.getNode(GetPromotionOpcode(VT, NVT), SDLoc(N), NVT, newL);
3226}
3227
3228SDValue DAGTypeLegalizer::PromoteFloatRes_ATOMIC_LOAD(SDNode *N) {
3229 AtomicSDNode *AM = cast<AtomicSDNode>(N);
3230 EVT VT = AM->getValueType(0);
3231
3232 // Load the value as an integer value with the same number of bits.
3233 EVT IVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
3234 SDValue newL = DAG.getAtomic(
3235 ISD::ATOMIC_LOAD, SDLoc(N), IVT, DAG.getVTList(IVT, MVT::Other),
3236 {AM->getChain(), AM->getBasePtr()}, AM->getMemOperand());
3237
3238 // Legalize the chain result by replacing uses of the old value chain with the
3239 // new one
3240 ReplaceValueWith(SDValue(N, 1), newL.getValue(1));
3241
3242 // Convert the integer value to the desired FP type
3243 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
3244 return DAG.getNode(GetPromotionOpcode(VT, IVT), SDLoc(N), NVT, newL);
3245}
3246
3247// Construct a new SELECT node with the promoted true- and false- values.
3248SDValue DAGTypeLegalizer::PromoteFloatRes_SELECT(SDNode *N) {
3249 SDValue TrueVal = GetPromotedFloat(N->getOperand(1));
3250 SDValue FalseVal = GetPromotedFloat(N->getOperand(2));
3251
3252 return DAG.getNode(ISD::SELECT, SDLoc(N), TrueVal->getValueType(0),
3253 N->getOperand(0), TrueVal, FalseVal);
3254}
3255
3256// Construct a new SELECT_CC node with the promoted true- and false- values.
3257// The operands used for comparison are promoted by PromoteFloatOp_SELECT_CC.
3258SDValue DAGTypeLegalizer::PromoteFloatRes_SELECT_CC(SDNode *N) {
3259 SDValue TrueVal = GetPromotedFloat(N->getOperand(2));
3260 SDValue FalseVal = GetPromotedFloat(N->getOperand(3));
3261
3262 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
3263 TrueVal.getNode()->getValueType(0), N->getOperand(0),
3264 N->getOperand(1), TrueVal, FalseVal, N->getOperand(4));
3265}
3266
3267// Construct a SDNode that transforms the SINT or UINT operand to the promoted
3268// float type.
3269SDValue DAGTypeLegalizer::PromoteFloatRes_XINT_TO_FP(SDNode *N) {
3270 SDLoc DL(N);
3271 EVT VT = N->getValueType(0);
3272 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
3273 SDValue NV = DAG.getNode(N->getOpcode(), DL, NVT, N->getOperand(0));
3274 // Round the value to the desired precision (that of the source type).
3275 return DAG.getNode(
3276 ISD::FP_EXTEND, DL, NVT,
3277 DAG.getNode(ISD::FP_ROUND, DL, VT, NV,
3278 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true)));
3279}
3280
3281SDValue DAGTypeLegalizer::PromoteFloatRes_UNDEF(SDNode *N) {
3282 return DAG.getUNDEF(TLI.getTypeToTransformTo(*DAG.getContext(),
3283 N->getValueType(0)));
3284}
3285
3286SDValue DAGTypeLegalizer::PromoteFloatRes_VECREDUCE(SDNode *N) {
3287 // Expand and promote recursively.
3288 // TODO: This is non-optimal, but dealing with the concurrently happening
3289 // vector-legalization is non-trivial. We could do something similar to
3290 // PromoteFloatRes_EXTRACT_VECTOR_ELT here.
3291 ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduce(N, DAG));
3292 return SDValue();
3293}
3294
3295SDValue DAGTypeLegalizer::PromoteFloatRes_VECREDUCE_SEQ(SDNode *N) {
3296 ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduceSeq(N, DAG));
3297 return SDValue();
3298}
3299
3300SDValue DAGTypeLegalizer::BitcastToInt_ATOMIC_SWAP(SDNode *N) {
3301 EVT VT = N->getValueType(0);
3302
3303 AtomicSDNode *AM = cast<AtomicSDNode>(N);
3304 SDLoc SL(N);
3305
3306 SDValue CastVal = BitConvertToInteger(AM->getVal());
3307 EVT CastVT = CastVal.getValueType();
3308
3309 SDValue NewAtomic
3310 = DAG.getAtomic(ISD::ATOMIC_SWAP, SL, CastVT,
3311 DAG.getVTList(CastVT, MVT::Other),
3312 { AM->getChain(), AM->getBasePtr(), CastVal },
3313 AM->getMemOperand());
3314
3315 SDValue Result = NewAtomic;
3316
3317 if (getTypeAction(VT) == TargetLowering::TypePromoteFloat) {
3318 EVT NFPVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
3319 Result = DAG.getNode(GetPromotionOpcode(VT, NFPVT), SL, NFPVT,
3320 NewAtomic);
3321 }
3322
3323 // Legalize the chain result by replacing uses of the old value chain with the
3324 // new one
3325 ReplaceValueWith(SDValue(N, 1), NewAtomic.getValue(1));
3326
3327 return Result;
3328
3329}
3330
3331//===----------------------------------------------------------------------===//
3332// Half Result Soft Promotion
3333//===----------------------------------------------------------------------===//
3334
3335void DAGTypeLegalizer::SoftPromoteHalfResult(SDNode *N, unsigned ResNo) {
3336 LLVM_DEBUG(dbgs() << "Soft promote half result " << ResNo << ": ";
3337 N->dump(&DAG));
3338 SDValue R = SDValue();
3339
3340 // See if the target wants to custom expand this node.
3341 if (CustomLowerNode(N, N->getValueType(ResNo), true)) {
3342 LLVM_DEBUG(dbgs() << "Node has been custom expanded, done\n");
3343 return;
3344 }
3345
3346 switch (N->getOpcode()) {
3347 default:
3348#ifndef NDEBUG
3349 dbgs() << "SoftPromoteHalfResult #" << ResNo << ": ";
3350 N->dump(&DAG); dbgs() << "\n";
3351#endif
3352 report_fatal_error("Do not know how to soft promote this operator's "
3353 "result!");
3354
3355 case ISD::ARITH_FENCE:
3356 R = SoftPromoteHalfRes_ARITH_FENCE(N); break;
3357 case ISD::BITCAST: R = SoftPromoteHalfRes_BITCAST(N); break;
3358 case ISD::ConstantFP: R = SoftPromoteHalfRes_ConstantFP(N); break;
3360 R = SoftPromoteHalfRes_EXTRACT_VECTOR_ELT(N); break;
3361 case ISD::FCOPYSIGN: R = SoftPromoteHalfRes_FCOPYSIGN(N); break;
3363 case ISD::FP_ROUND: R = SoftPromoteHalfRes_FP_ROUND(N); break;
3364
3365 // Unary FP Operations
3366 case ISD::FACOS:
3367 case ISD::FASIN:
3368 case ISD::FATAN:
3369 case ISD::FCBRT:
3370 case ISD::FCEIL:
3371 case ISD::FCOS:
3372 case ISD::FCOSH:
3373 case ISD::FEXP:
3374 case ISD::FEXP2:
3375 case ISD::FEXP10:
3376 case ISD::FFLOOR:
3377 case ISD::FLOG:
3378 case ISD::FLOG2:
3379 case ISD::FLOG10:
3380 case ISD::FNEARBYINT:
3381 case ISD::FREEZE:
3382 case ISD::FRINT:
3383 case ISD::FROUND:
3384 case ISD::FROUNDEVEN:
3385 case ISD::FSIN:
3386 case ISD::FSINH:
3387 case ISD::FSQRT:
3388 case ISD::FTRUNC:
3389 case ISD::FTAN:
3390 case ISD::FTANH:
3391 case ISD::FCANONICALIZE: R = SoftPromoteHalfRes_UnaryOp(N); break;
3392 case ISD::FABS:
3393 R = SoftPromoteHalfRes_FABS(N);
3394 break;
3395 case ISD::FNEG:
3396 R = SoftPromoteHalfRes_FNEG(N);
3397 break;
3399 R = SoftPromoteHalfRes_AssertNoFPClass(N);
3400 break;
3401
3402 // Binary FP Operations
3403 case ISD::FADD:
3404 case ISD::FDIV:
3405 case ISD::FMAXIMUM:
3406 case ISD::FMINIMUM:
3407 case ISD::FMAXIMUMNUM:
3408 case ISD::FMINIMUMNUM:
3409 case ISD::FMAXNUM:
3410 case ISD::FMINNUM:
3411 case ISD::FMUL:
3412 case ISD::FPOW:
3413 case ISD::FATAN2:
3414 case ISD::FREM:
3415 case ISD::FSUB: R = SoftPromoteHalfRes_BinOp(N); break;
3416
3417 case ISD::FMA: // FMA is same as FMAD
3418 case ISD::FMAD: R = SoftPromoteHalfRes_FMAD(N); break;
3419
3420 case ISD::FPOWI:
3421 case ISD::FLDEXP: R = SoftPromoteHalfRes_ExpOp(N); break;
3422
3423 case ISD::FFREXP: R = SoftPromoteHalfRes_FFREXP(N); break;
3424
3425 case ISD::FMODF:
3426 case ISD::FSINCOS:
3427 case ISD::FSINCOSPI:
3428 R = SoftPromoteHalfRes_UnaryWithTwoFPResults(N);
3429 break;
3430
3431 case ISD::LOAD: R = SoftPromoteHalfRes_LOAD(N); break;
3432 case ISD::ATOMIC_LOAD:
3433 R = SoftPromoteHalfRes_ATOMIC_LOAD(N);
3434 break;
3435 case ISD::SELECT: R = SoftPromoteHalfRes_SELECT(N); break;
3436 case ISD::SELECT_CC: R = SoftPromoteHalfRes_SELECT_CC(N); break;
3439 case ISD::SINT_TO_FP:
3440 case ISD::UINT_TO_FP: R = SoftPromoteHalfRes_XINT_TO_FP(N); break;
3441 case ISD::POISON:
3442 case ISD::UNDEF: R = SoftPromoteHalfRes_UNDEF(N); break;
3443 case ISD::ATOMIC_SWAP: R = BitcastToInt_ATOMIC_SWAP(N); break;
3450 R = SoftPromoteHalfRes_VECREDUCE(N);
3451 break;
3454 R = SoftPromoteHalfRes_VECREDUCE_SEQ(N);
3455 break;
3456 }
3457
3458 if (R.getNode())
3459 SetSoftPromotedHalf(SDValue(N, ResNo), R);
3460}
3461
3462SDValue DAGTypeLegalizer::SoftPromoteHalfRes_ARITH_FENCE(SDNode *N) {
3463 return DAG.getNode(ISD::ARITH_FENCE, SDLoc(N), MVT::i16,
3464 BitConvertToInteger(N->getOperand(0)));
3465}
3466
3467SDValue DAGTypeLegalizer::SoftPromoteHalfRes_BITCAST(SDNode *N) {
3468 return BitConvertToInteger(N->getOperand(0));
3469}
3470
3471SDValue DAGTypeLegalizer::SoftPromoteHalfRes_ConstantFP(SDNode *N) {
3472 ConstantFPSDNode *CN = cast<ConstantFPSDNode>(N);
3473
3474 // Get the (bit-cast) APInt of the APFloat and build an integer constant
3475 return DAG.getConstant(CN->getValueAPF().bitcastToAPInt(), SDLoc(CN),
3476 MVT::i16);
3477}
3478
3479SDValue DAGTypeLegalizer::SoftPromoteHalfRes_EXTRACT_VECTOR_ELT(SDNode *N) {
3480 SDValue NewOp = BitConvertVectorToIntegerVector(N->getOperand(0));
3481 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
3482 NewOp.getValueType().getVectorElementType(), NewOp,
3483 N->getOperand(1));
3484}
3485
3486SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FCOPYSIGN(SDNode *N) {
3487 SDValue LHS = GetSoftPromotedHalf(N->getOperand(0));
3488 SDValue RHS = BitConvertToInteger(N->getOperand(1));
3489 SDLoc dl(N);
3490
3491 EVT LVT = LHS.getValueType();
3492 EVT RVT = RHS.getValueType();
3493
3494 unsigned LSize = LVT.getSizeInBits();
3495 unsigned RSize = RVT.getSizeInBits();
3496
3497 // First get the sign bit of second operand.
3498 SDValue SignBit = DAG.getNode(
3499 ISD::SHL, dl, RVT, DAG.getConstant(1, dl, RVT),
3500 DAG.getConstant(RSize - 1, dl,
3501 TLI.getShiftAmountTy(RVT, DAG.getDataLayout())));
3502 SignBit = DAG.getNode(ISD::AND, dl, RVT, RHS, SignBit);
3503
3504 // Shift right or sign-extend it if the two operands have different types.
3505 int SizeDiff = RVT.getSizeInBits() - LVT.getSizeInBits();
3506 if (SizeDiff > 0) {
3507 SignBit =
3508 DAG.getNode(ISD::SRL, dl, RVT, SignBit,
3509 DAG.getConstant(SizeDiff, dl,
3510 TLI.getShiftAmountTy(SignBit.getValueType(),
3511 DAG.getDataLayout())));
3512 SignBit = DAG.getNode(ISD::TRUNCATE, dl, LVT, SignBit);
3513 } else if (SizeDiff < 0) {
3514 SignBit = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, SignBit);
3515 SignBit =
3516 DAG.getNode(ISD::SHL, dl, LVT, SignBit,
3517 DAG.getConstant(-SizeDiff, dl,
3518 TLI.getShiftAmountTy(SignBit.getValueType(),
3519 DAG.getDataLayout())));
3520 }
3521
3522 // Clear the sign bit of the first operand.
3523 SDValue Mask = DAG.getNode(
3524 ISD::SHL, dl, LVT, DAG.getConstant(1, dl, LVT),
3525 DAG.getConstant(LSize - 1, dl,
3526 TLI.getShiftAmountTy(LVT, DAG.getDataLayout())));
3527 Mask = DAG.getNode(ISD::SUB, dl, LVT, Mask, DAG.getConstant(1, dl, LVT));
3528 LHS = DAG.getNode(ISD::AND, dl, LVT, LHS, Mask);
3529
3530 // Or the value with the sign bit.
3531 return DAG.getNode(ISD::OR, dl, LVT, LHS, SignBit);
3532}
3533
3534SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FMAD(SDNode *N) {
3535 EVT OVT = N->getValueType(0);
3536 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
3537 SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
3538 SDValue Op1 = GetSoftPromotedHalf(N->getOperand(1));
3539 SDValue Op2 = GetSoftPromotedHalf(N->getOperand(2));
3540 SDNodeFlags Flags = N->getFlags();
3541 SDLoc dl(N);
3542
3543 // Promote to the larger FP type.
3544 auto PromotionOpcode = GetPromotionOpcode(OVT, NVT);
3545 Op0 = DAG.getNode(PromotionOpcode, dl, NVT, Op0);
3546 Op1 = DAG.getNode(PromotionOpcode, dl, NVT, Op1);
3547 Op2 = DAG.getNode(PromotionOpcode, dl, NVT, Op2);
3548
3549 SDValue Res;
3550 if (OVT == MVT::f16) {
3551 // If f16 fma is not natively supported, the value must be promoted to an
3552 // f64 (and not to f32!) to prevent double rounding issues.
3553 SDValue A64 = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Op0, Flags);
3554 SDValue B64 = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Op1, Flags);
3555 SDValue C64 = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Op2, Flags);
3556
3557 // Prefer a wide FMA node if available; otherwise expand to mul+add.
3558 SDValue WideRes;
3559 if (TLI.isFMAFasterThanFMulAndFAdd(DAG.getMachineFunction(), MVT::f64)) {
3560 WideRes = DAG.getNode(ISD::FMA, dl, MVT::f64, A64, B64, C64, Flags);
3561 } else {
3562 SDValue Mul = DAG.getNode(ISD::FMUL, dl, MVT::f64, A64, B64, Flags);
3563 WideRes = DAG.getNode(ISD::FADD, dl, MVT::f64, Mul, C64, Flags);
3564 }
3565
3566 return DAG.getNode(GetPromotionOpcode(MVT::f64, OVT), dl, MVT::i16,
3567 WideRes);
3568 }
3569
3570 Res = DAG.getNode(N->getOpcode(), dl, NVT, Op0, Op1, Op2, Flags);
3571 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
3572}
3573
3574SDValue DAGTypeLegalizer::SoftPromoteHalfRes_ExpOp(SDNode *N) {
3575 EVT OVT = N->getValueType(0);
3576 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
3577 SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
3578 SDValue Op1 = N->getOperand(1);
3579 SDLoc dl(N);
3580
3581 // Promote to the larger FP type.
3582 Op0 = DAG.getNode(GetPromotionOpcode(OVT, NVT), dl, NVT, Op0);
3583
3584 SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, Op0, Op1);
3585
3586 // Convert back to FP16 as an integer.
3587 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
3588}
3589
3590SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FFREXP(SDNode *N) {
3591 EVT OVT = N->getValueType(0);
3592 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
3593 SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
3594 SDLoc dl(N);
3595
3596 // Promote to the larger FP type.
3597 Op = DAG.getNode(GetPromotionOpcode(OVT, NVT), dl, NVT, Op);
3598
3599 SDValue Res = DAG.getNode(N->getOpcode(), dl,
3600 DAG.getVTList(NVT, N->getValueType(1)), Op);
3601
3602 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
3603
3604 // Convert back to FP16 as an integer.
3605 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
3606}
3607
3608SDValue DAGTypeLegalizer::SoftPromoteHalfRes_UnaryWithTwoFPResults(SDNode *N) {
3609 EVT OVT = N->getValueType(0);
3610 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
3611 SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
3612 SDLoc dl(N);
3613
3614 // Promote to the larger FP type.
3615 Op = DAG.getNode(GetPromotionOpcode(OVT, NVT), dl, NVT, Op);
3616 SDValue Res = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(NVT, NVT), Op);
3617
3618 // Convert back to FP16 as an integer.
3619 ISD::NodeType Truncate = GetPromotionOpcode(NVT, OVT);
3620 for (unsigned ResNum = 0, NumValues = N->getNumValues(); ResNum < NumValues;
3621 ++ResNum) {
3622 SDValue Trunc = DAG.getNode(Truncate, dl, MVT::i16, Res.getValue(ResNum));
3623 SetSoftPromotedHalf(SDValue(N, ResNum), Trunc);
3624 }
3625
3626 return SDValue();
3627}
3628
3629SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FP_ROUND(SDNode *N) {
3630 EVT RVT = N->getValueType(0);
3631 bool IsStrict = N->isStrictFPOpcode();
3632 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
3633 EVT SVT = Op.getValueType();
3634
3635 // If the input type needs to be softened, do that now so that call lowering
3636 // will see the f16 type.
3637 if (getTypeAction(SVT) == TargetLowering::TypeSoftenFloat) {
3638 RTLIB::Libcall LC = RTLIB::getFPROUND(SVT, RVT);
3639 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_ROUND libcall");
3640
3641 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
3642 Op = GetSoftenedFloat(Op);
3643 TargetLowering::MakeLibCallOptions CallOptions;
3644 CallOptions.setTypeListBeforeSoften(SVT, RVT);
3645 std::pair<SDValue, SDValue> Tmp =
3646 TLI.makeLibCall(DAG, LC, RVT, Op, CallOptions, SDLoc(N), Chain);
3647 if (IsStrict)
3648 ReplaceValueWith(SDValue(N, 1), Tmp.second);
3649 return DAG.getNode(ISD::BITCAST, SDLoc(N), MVT::i16, Tmp.first);
3650 }
3651
3652 if (IsStrict) {
3653 SDValue Res = DAG.getNode(GetPromotionOpcodeStrict(SVT, RVT), SDLoc(N),
3654 {MVT::i16, MVT::Other}, {N->getOperand(0), Op});
3655 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
3656 return Res;
3657 }
3658
3659 return DAG.getNode(GetPromotionOpcode(SVT, RVT), SDLoc(N), MVT::i16,
3660 N->getOperand(0));
3661}
3662
3663SDValue DAGTypeLegalizer::SoftPromoteHalfRes_LOAD(SDNode *N) {
3664 LoadSDNode *L = cast<LoadSDNode>(N);
3665
3666 // Load the value as an integer value with the same number of bits.
3667 assert(L->getExtensionType() == ISD::NON_EXTLOAD && "Unexpected extension!");
3668 SDValue NewL =
3669 DAG.getLoad(L->getAddressingMode(), L->getExtensionType(), MVT::i16,
3670 SDLoc(N), L->getChain(), L->getBasePtr(), L->getOffset(),
3671 L->getPointerInfo(), MVT::i16, L->getBaseAlign(),
3672 L->getMemOperand()->getFlags(), L->getAAInfo());
3673 // Legalize the chain result by replacing uses of the old value chain with the
3674 // new one
3675 ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
3676 return NewL;
3677}
3678
3679SDValue DAGTypeLegalizer::SoftPromoteHalfRes_ATOMIC_LOAD(SDNode *N) {
3680 AtomicSDNode *AM = cast<AtomicSDNode>(N);
3681
3682 // Load the value as an integer value with the same number of bits.
3683 SDValue NewL = DAG.getAtomic(
3684 ISD::ATOMIC_LOAD, SDLoc(N), MVT::i16, DAG.getVTList(MVT::i16, MVT::Other),
3685 {AM->getChain(), AM->getBasePtr()}, AM->getMemOperand());
3686
3687 // Legalize the chain result by replacing uses of the old value chain with the
3688 // new one
3689 ReplaceValueWith(SDValue(N, 1), NewL.getValue(1));
3690 return NewL;
3691}
3692
3693SDValue DAGTypeLegalizer::SoftPromoteHalfRes_SELECT(SDNode *N) {
3694 SDValue Op1 = GetSoftPromotedHalf(N->getOperand(1));
3695 SDValue Op2 = GetSoftPromotedHalf(N->getOperand(2));
3696 return DAG.getSelect(SDLoc(N), Op1.getValueType(), N->getOperand(0), Op1,
3697 Op2);
3698}
3699
3700SDValue DAGTypeLegalizer::SoftPromoteHalfRes_SELECT_CC(SDNode *N) {
3701 SDValue Op2 = GetSoftPromotedHalf(N->getOperand(2));
3702 SDValue Op3 = GetSoftPromotedHalf(N->getOperand(3));
3703 return DAG.getNode(ISD::SELECT_CC, SDLoc(N), Op2.getValueType(),
3704 N->getOperand(0), N->getOperand(1), Op2, Op3,
3705 N->getOperand(4));
3706}
3707
3708SDValue DAGTypeLegalizer::SoftPromoteHalfRes_XINT_TO_FP(SDNode *N) {
3709 EVT OVT = N->getValueType(0);
3710 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
3711 SDLoc dl(N);
3712
3713 if (N->isStrictFPOpcode()) {
3714 SDValue Op = DAG.getNode(N->getOpcode(), dl, {NVT, MVT::Other},
3715 {N->getOperand(0), N->getOperand(1)});
3716 Op = DAG.getNode(GetPromotionOpcodeStrict(NVT, OVT), dl,
3717 {MVT::i16, MVT::Other}, {Op.getValue(1), Op});
3718 ReplaceValueWith(SDValue(N, 1), Op.getValue(1));
3719 return Op;
3720 }
3721
3722 SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, N->getOperand(0));
3723
3724 // Round the value to the softened type.
3725 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
3726}
3727
3728SDValue DAGTypeLegalizer::SoftPromoteHalfRes_UNDEF(SDNode *N) {
3729 return DAG.getUNDEF(MVT::i16);
3730}
3731
3732SDValue DAGTypeLegalizer::SoftPromoteHalfRes_UnaryOp(SDNode *N) {
3733 EVT OVT = N->getValueType(0);
3734 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
3735 SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
3736 SDLoc dl(N);
3737
3738 // Promote to the larger FP type.
3739 Op = DAG.getNode(GetPromotionOpcode(OVT, NVT), dl, NVT, Op);
3740
3741 SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, Op);
3742
3743 // Convert back to FP16 as an integer.
3744 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
3745}
3746
3747SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FABS(SDNode *N) {
3748 SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
3749 SDLoc dl(N);
3750
3751 // Clear the sign bit.
3752 return DAG.getNode(ISD::AND, dl, MVT::i16, Op,
3753 DAG.getConstant(0x7fff, dl, MVT::i16));
3754}
3755
3756SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FNEG(SDNode *N) {
3757 SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
3758 SDLoc dl(N);
3759
3760 // Invert the sign bit.
3761 return DAG.getNode(ISD::XOR, dl, MVT::i16, Op,
3762 DAG.getConstant(0x8000, dl, MVT::i16));
3763}
3764
3765SDValue DAGTypeLegalizer::SoftPromoteHalfRes_AssertNoFPClass(SDNode *N) {
3766 return GetSoftPromotedHalf(N->getOperand(0));
3767}
3768
3769SDValue DAGTypeLegalizer::SoftPromoteHalfRes_BinOp(SDNode *N) {
3770 EVT OVT = N->getValueType(0);
3771 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
3772 SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
3773 SDValue Op1 = GetSoftPromotedHalf(N->getOperand(1));
3774 SDLoc dl(N);
3775
3776 // Promote to the larger FP type.
3777 auto PromotionOpcode = GetPromotionOpcode(OVT, NVT);
3778 Op0 = DAG.getNode(PromotionOpcode, dl, NVT, Op0);
3779 Op1 = DAG.getNode(PromotionOpcode, dl, NVT, Op1);
3780
3781 SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, Op0, Op1);
3782
3783 // Convert back to FP16 as an integer.
3784 return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
3785}
3786
3787SDValue DAGTypeLegalizer::SoftPromoteHalfRes_VECREDUCE(SDNode *N) {
3788 // Expand and soften recursively.
3789 ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduce(N, DAG));
3790 return SDValue();
3791}
3792
3793SDValue DAGTypeLegalizer::SoftPromoteHalfRes_VECREDUCE_SEQ(SDNode *N) {
3794 // Expand and soften.
3795 ReplaceValueWith(SDValue(N, 0), TLI.expandVecReduceSeq(N, DAG));
3796 return SDValue();
3797}
3798
3799//===----------------------------------------------------------------------===//
3800// Half Operand Soft Promotion
3801//===----------------------------------------------------------------------===//
3802
3803bool DAGTypeLegalizer::SoftPromoteHalfOperand(SDNode *N, unsigned OpNo) {
3804 LLVM_DEBUG(dbgs() << "Soft promote half operand " << OpNo << ": ";
3805 N->dump(&DAG));
3806 SDValue Res = SDValue();
3807
3808 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false)) {
3809 LLVM_DEBUG(dbgs() << "Node has been custom lowered, done\n");
3810 return false;
3811 }
3812
3813 // Nodes that use a promotion-requiring floating point operand, but doesn't
3814 // produce a soft promotion-requiring floating point result, need to be
3815 // legalized to use the soft promoted float operand. Nodes that produce at
3816 // least one soft promotion-requiring floating point result have their
3817 // operands legalized as a part of PromoteFloatResult.
3818 switch (N->getOpcode()) {
3819 default:
3820 #ifndef NDEBUG
3821 dbgs() << "SoftPromoteHalfOperand Op #" << OpNo << ": ";
3822 N->dump(&DAG); dbgs() << "\n";
3823 #endif
3824 report_fatal_error("Do not know how to soft promote this operator's "
3825 "operand!");
3826
3827 case ISD::BITCAST: Res = SoftPromoteHalfOp_BITCAST(N); break;
3828 case ISD::FAKE_USE:
3829 Res = SoftPromoteHalfOp_FAKE_USE(N, OpNo);
3830 break;
3831 case ISD::FCOPYSIGN: Res = SoftPromoteHalfOp_FCOPYSIGN(N, OpNo); break;
3834 case ISD::FP_TO_SINT:
3835 case ISD::FP_TO_UINT:
3836 case ISD::LRINT:
3837 case ISD::LLRINT:
3838 case ISD::LROUND:
3839 case ISD::LLROUND:
3840 Res = SoftPromoteHalfOp_Op0WithStrict(N);
3841 break;
3844 Res = SoftPromoteHalfOp_FP_TO_XINT_SAT(N); break;
3846 case ISD::FP_EXTEND: Res = SoftPromoteHalfOp_FP_EXTEND(N); break;
3847 case ISD::SELECT_CC: Res = SoftPromoteHalfOp_SELECT_CC(N, OpNo); break;
3848 case ISD::SETCC: Res = SoftPromoteHalfOp_SETCC(N); break;
3849 case ISD::STORE: Res = SoftPromoteHalfOp_STORE(N, OpNo); break;
3850 case ISD::ATOMIC_STORE:
3851 Res = SoftPromoteHalfOp_ATOMIC_STORE(N, OpNo);
3852 break;
3853 case ISD::STACKMAP:
3854 Res = SoftPromoteHalfOp_STACKMAP(N, OpNo);
3855 break;
3856 case ISD::PATCHPOINT:
3857 Res = SoftPromoteHalfOp_PATCHPOINT(N, OpNo);
3858 break;
3859 }
3860
3861 if (!Res.getNode())
3862 return false;
3863
3864 assert(Res.getNode() != N && "Expected a new node!");
3865
3866 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
3867 "Invalid operand expansion");
3868
3869 ReplaceValueWith(SDValue(N, 0), Res);
3870 return false;
3871}
3872
3873SDValue DAGTypeLegalizer::SoftPromoteHalfOp_BITCAST(SDNode *N) {
3874 SDValue Op0 = GetSoftPromotedHalf(N->getOperand(0));
3875
3876 return DAG.getNode(ISD::BITCAST, SDLoc(N), N->getValueType(0), Op0);
3877}
3878
3879SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FAKE_USE(SDNode *N, unsigned OpNo) {
3880 assert(OpNo == 1 && "Only Operand 1 must need promotion here");
3881 SDValue Op = GetSoftPromotedHalf(N->getOperand(OpNo));
3882 return DAG.getNode(N->getOpcode(), SDLoc(N), MVT::Other, N->getOperand(0),
3883 Op);
3884}
3885
3886SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FCOPYSIGN(SDNode *N,
3887 unsigned OpNo) {
3888 assert(OpNo == 1 && "Only Operand 1 must need promotion here");
3889 SDValue Op1 = N->getOperand(1);
3890 EVT RVT = Op1.getValueType();
3891 SDLoc dl(N);
3892
3893 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op1.getValueType());
3894
3895 Op1 = GetSoftPromotedHalf(Op1);
3896 Op1 = DAG.getNode(GetPromotionOpcode(RVT, NVT), dl, NVT, Op1);
3897
3898 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0), N->getOperand(0),
3899 Op1);
3900}
3901
3902SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_EXTEND(SDNode *N) {
3903 EVT RVT = N->getValueType(0);
3904 bool IsStrict = N->isStrictFPOpcode();
3905 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
3906 EVT SVT = Op.getValueType();
3907 Op = GetSoftPromotedHalf(N->getOperand(IsStrict ? 1 : 0));
3908
3909 if (IsStrict) {
3910 SDValue Res = DAG.getNode(GetPromotionOpcodeStrict(SVT, RVT), SDLoc(N),
3911 {RVT, MVT::Other}, {N->getOperand(0), Op});
3912 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
3913 ReplaceValueWith(SDValue(N, 0), Res);
3914 return SDValue();
3915 }
3916
3917 return DAG.getNode(GetPromotionOpcode(SVT, RVT), SDLoc(N), RVT, Op);
3918}
3919
3920SDValue DAGTypeLegalizer::SoftPromoteHalfOp_Op0WithStrict(SDNode *N) {
3921 EVT RVT = N->getValueType(0);
3922 bool IsStrict = N->isStrictFPOpcode();
3923 SDValue Op = N->getOperand(IsStrict ? 1 : 0);
3924 EVT SVT = Op.getValueType();
3925 SDLoc dl(N);
3926
3927 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), SVT);
3928 Op = GetSoftPromotedHalf(Op);
3929
3930 if (IsStrict) {
3931 Op = DAG.getNode(GetPromotionOpcodeStrict(SVT, RVT), dl, {NVT, MVT::Other},
3932 {N->getOperand(0), Op});
3933 Op = DAG.getNode(N->getOpcode(), dl, {RVT, MVT::Other},
3934 {Op.getValue(1), Op});
3935 ReplaceValueWith(SDValue(N, 1), Op.getValue(1));
3936 ReplaceValueWith(SDValue(N, 0), Op);
3937 return SDValue();
3938 }
3939
3940 SDValue Res = DAG.getNode(GetPromotionOpcode(SVT, RVT), dl, NVT, Op);
3941 return DAG.getNode(N->getOpcode(), dl, RVT, Res);
3942}
3943
3944SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_TO_XINT_SAT(SDNode *N) {
3945 EVT RVT = N->getValueType(0);
3946 SDValue Op = N->getOperand(0);
3947 EVT SVT = Op.getValueType();
3948 SDLoc dl(N);
3949
3950 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType());
3951
3952 Op = GetSoftPromotedHalf(Op);
3953
3954 SDValue Res = DAG.getNode(GetPromotionOpcode(SVT, RVT), dl, NVT, Op);
3955
3956 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0), Res,
3957 N->getOperand(1));
3958}
3959
3960SDValue DAGTypeLegalizer::SoftPromoteHalfOp_SELECT_CC(SDNode *N,
3961 unsigned OpNo) {
3962 assert(OpNo == 0 && "Can only soften the comparison values");
3963 SDValue Op0 = N->getOperand(0);
3964 SDValue Op1 = N->getOperand(1);
3965 SDLoc dl(N);
3966
3967 EVT SVT = Op0.getValueType();
3968 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), SVT);
3969
3970 Op0 = GetSoftPromotedHalf(Op0);
3971 Op1 = GetSoftPromotedHalf(Op1);
3972
3973 // Promote to the larger FP type.
3974 auto PromotionOpcode = GetPromotionOpcode(SVT, NVT);
3975 Op0 = DAG.getNode(PromotionOpcode, dl, NVT, Op0);
3976 Op1 = DAG.getNode(PromotionOpcode, dl, NVT, Op1);
3977
3978 return DAG.getNode(ISD::SELECT_CC, SDLoc(N), N->getValueType(0), Op0, Op1,
3979 N->getOperand(2), N->getOperand(3), N->getOperand(4));
3980}
3981
3982SDValue DAGTypeLegalizer::SoftPromoteHalfOp_SETCC(SDNode *N) {
3983 SDValue Op0 = N->getOperand(0);
3984 SDValue Op1 = N->getOperand(1);
3985 ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(2))->get();
3986 SDLoc dl(N);
3987
3988 EVT SVT = Op0.getValueType();
3989 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op0.getValueType());
3990
3991 Op0 = GetSoftPromotedHalf(Op0);
3992 Op1 = GetSoftPromotedHalf(Op1);
3993
3994 // Promote to the larger FP type.
3995 auto PromotionOpcode = GetPromotionOpcode(SVT, NVT);
3996 Op0 = DAG.getNode(PromotionOpcode, dl, NVT, Op0);
3997 Op1 = DAG.getNode(PromotionOpcode, dl, NVT, Op1);
3998
3999 return DAG.getSetCC(SDLoc(N), N->getValueType(0), Op0, Op1, CCCode);
4000}
4001
4002SDValue DAGTypeLegalizer::SoftPromoteHalfOp_STORE(SDNode *N, unsigned OpNo) {
4003 assert(OpNo == 1 && "Can only soften the stored value!");
4004 StoreSDNode *ST = cast<StoreSDNode>(N);
4005 SDValue Val = ST->getValue();
4006 SDLoc dl(N);
4007
4008 assert(!ST->isTruncatingStore() && "Unexpected truncating store.");
4009 SDValue Promoted = GetSoftPromotedHalf(Val);
4010 return DAG.getStore(ST->getChain(), dl, Promoted, ST->getBasePtr(),
4011 ST->getMemOperand());
4012}
4013
4014SDValue DAGTypeLegalizer::SoftPromoteHalfOp_ATOMIC_STORE(SDNode *N,
4015 unsigned OpNo) {
4016 assert(OpNo == 1 && "Can only soften the stored value!");
4017 AtomicSDNode *ST = cast<AtomicSDNode>(N);
4018 SDValue Val = ST->getVal();
4019 SDLoc dl(N);
4020
4021 SDValue Promoted = GetSoftPromotedHalf(Val);
4022 return DAG.getAtomic(ISD::ATOMIC_STORE, dl, Promoted.getValueType(),
4023 ST->getChain(), Promoted, ST->getBasePtr(),
4024 ST->getMemOperand());
4025}
4026
4027SDValue DAGTypeLegalizer::SoftPromoteHalfOp_STACKMAP(SDNode *N, unsigned OpNo) {
4028 assert(OpNo > 1); // Because the first two arguments are guaranteed legal.
4029 SmallVector<SDValue> NewOps(N->ops());
4030 SDValue Op = N->getOperand(OpNo);
4031 NewOps[OpNo] = GetSoftPromotedHalf(Op);
4033 DAG.getNode(N->getOpcode(), SDLoc(N), N->getVTList(), NewOps);
4034
4035 for (unsigned ResNum = 0; ResNum < N->getNumValues(); ResNum++)
4036 ReplaceValueWith(SDValue(N, ResNum), NewNode.getValue(ResNum));
4037
4038 return SDValue(); // Signal that we replaced the node ourselves.
4039}
4040
4041SDValue DAGTypeLegalizer::SoftPromoteHalfOp_PATCHPOINT(SDNode *N,
4042 unsigned OpNo) {
4043 assert(OpNo >= 7);
4044 SmallVector<SDValue> NewOps(N->ops());
4045 SDValue Op = N->getOperand(OpNo);
4046 NewOps[OpNo] = GetSoftPromotedHalf(Op);
4048 DAG.getNode(N->getOpcode(), SDLoc(N), N->getVTList(), NewOps);
4049
4050 for (unsigned ResNum = 0; ResNum < N->getNumValues(); ResNum++)
4051 ReplaceValueWith(SDValue(N, ResNum), NewNode.getValue(ResNum));
4052
4053 return SDValue(); // Signal that we replaced the node ourselves.
4054}
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:1335
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Definition APFloat.h:1061
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:1407
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
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
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:807
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
Definition ISDOpcodes.h:256
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
Definition ISDOpcodes.h:504
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:231
@ 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:515
@ 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:841
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:511
@ 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:868
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:410
@ 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...
Definition ISDOpcodes.h:991
@ 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:981
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
Definition ISDOpcodes.h:249
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
Definition ISDOpcodes.h:431
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:832
@ STRICT_UINT_TO_FP
Definition ISDOpcodes.h:478
@ 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:534
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:784
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:228
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
Definition ISDOpcodes.h:242
@ ARITH_FENCE
ARITH_FENCE - This corresponds to a arithmetic fence intrinsic.
@ STRICT_FP_TO_FP16
Definition ISDOpcodes.h:994
@ STRICT_FP16_TO_FP
Definition ISDOpcodes.h:993
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:762
@ AssertNoFPClass
AssertNoFPClass - These nodes record if a register contains a float value that is known to be not som...
Definition ISDOpcodes.h:78
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:569
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:838
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:799
@ 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:966
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
Definition ISDOpcodes.h:477
@ STRICT_BF16_TO_FP
@ STRICT_FROUNDEVEN
Definition ISDOpcodes.h:457
@ 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:471
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
Definition ISDOpcodes.h:493
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:470
@ 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:914
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:498
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:736
@ STRICT_FP_TO_BF16
@ STRICT_FADD
Constrained versions of the binary floating point operators.
Definition ISDOpcodes.h:420
@ 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:236
@ 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:947
@ STRICT_FNEARBYINT
Definition ISDOpcodes.h:451
@ 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:933
@ VECREDUCE_FMINIMUM
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:844
@ 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:527
@ 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:549
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.
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
@ 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:2503
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:167
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ 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)