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