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