LLVM 23.0.0git
AMDGPUISelLowering.cpp
Go to the documentation of this file.
1//===-- AMDGPUISelLowering.cpp - AMDGPU Common DAG lowering functions -----===//
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/// \file
10/// This is the parent TargetLowering class for hardware code gen
11/// targets.
12//
13//===----------------------------------------------------------------------===//
14
15#include "AMDGPUISelLowering.h"
16#include "AMDGPU.h"
17#include "AMDGPUInstrInfo.h"
19#include "AMDGPUMemoryUtils.h"
26#include "llvm/IR/IntrinsicsAMDGPU.h"
30
31using namespace llvm;
32
33#define GET_CALLING_CONV_IMPL
34#include "AMDGPUGenCallingConv.inc"
35
37 "amdgpu-bypass-slow-div",
38 cl::desc("Skip 64-bit divide for dynamic 32-bit values"),
39 cl::init(true));
40
41// Find a larger type to do a load / store of a vector with.
43 unsigned StoreSize = VT.getStoreSizeInBits();
44 if (StoreSize <= 32)
45 return EVT::getIntegerVT(Ctx, StoreSize);
46
47 if (StoreSize % 32 == 0)
48 return EVT::getVectorVT(Ctx, MVT::i32, StoreSize / 32);
49
50 return VT;
51}
52
56
58 // In order for this to be a signed 24-bit value, bit 23, must
59 // be a sign bit.
60 return DAG.ComputeMaxSignificantBits(Op);
61}
62
64 const TargetSubtargetInfo &STI,
65 const AMDGPUSubtarget &AMDGPUSTI)
66 : TargetLowering(TM, STI), Subtarget(&AMDGPUSTI) {
67 // Always lower memset, memcpy, and memmove intrinsics to load/store
68 // instructions, rather then generating calls to memset, mempcy or memmove.
72
73 // Enable ganging up loads and stores in the memcpy DAG lowering.
75
76 // Lower floating point store/load to integer store/load to reduce the number
77 // of patterns in tablegen.
79 AddPromotedToType(ISD::LOAD, MVT::f32, MVT::i32);
80
82 AddPromotedToType(ISD::LOAD, MVT::v2f32, MVT::v2i32);
83
85 AddPromotedToType(ISD::LOAD, MVT::v3f32, MVT::v3i32);
86
88 AddPromotedToType(ISD::LOAD, MVT::v4f32, MVT::v4i32);
89
91 AddPromotedToType(ISD::LOAD, MVT::v5f32, MVT::v5i32);
92
94 AddPromotedToType(ISD::LOAD, MVT::v6f32, MVT::v6i32);
95
97 AddPromotedToType(ISD::LOAD, MVT::v7f32, MVT::v7i32);
98
100 AddPromotedToType(ISD::LOAD, MVT::v8f32, MVT::v8i32);
101
103 AddPromotedToType(ISD::LOAD, MVT::v9f32, MVT::v9i32);
104
105 setOperationAction(ISD::LOAD, MVT::v10f32, Promote);
106 AddPromotedToType(ISD::LOAD, MVT::v10f32, MVT::v10i32);
107
108 setOperationAction(ISD::LOAD, MVT::v11f32, Promote);
109 AddPromotedToType(ISD::LOAD, MVT::v11f32, MVT::v11i32);
110
111 setOperationAction(ISD::LOAD, MVT::v12f32, Promote);
112 AddPromotedToType(ISD::LOAD, MVT::v12f32, MVT::v12i32);
113
114 setOperationAction(ISD::LOAD, MVT::v16f32, Promote);
115 AddPromotedToType(ISD::LOAD, MVT::v16f32, MVT::v16i32);
116
117 setOperationAction(ISD::LOAD, MVT::v32f32, Promote);
118 AddPromotedToType(ISD::LOAD, MVT::v32f32, MVT::v32i32);
119
121 AddPromotedToType(ISD::LOAD, MVT::i64, MVT::v2i32);
122
124 AddPromotedToType(ISD::LOAD, MVT::v2i64, MVT::v4i32);
125
127 AddPromotedToType(ISD::LOAD, MVT::f64, MVT::v2i32);
128
130 AddPromotedToType(ISD::LOAD, MVT::v2f64, MVT::v4i32);
131
133 AddPromotedToType(ISD::LOAD, MVT::v3i64, MVT::v6i32);
134
136 AddPromotedToType(ISD::LOAD, MVT::v4i64, MVT::v8i32);
137
139 AddPromotedToType(ISD::LOAD, MVT::v3f64, MVT::v6i32);
140
142 AddPromotedToType(ISD::LOAD, MVT::v4f64, MVT::v8i32);
143
145 AddPromotedToType(ISD::LOAD, MVT::v8i64, MVT::v16i32);
146
148 AddPromotedToType(ISD::LOAD, MVT::v8f64, MVT::v16i32);
149
150 setOperationAction(ISD::LOAD, MVT::v16i64, Promote);
151 AddPromotedToType(ISD::LOAD, MVT::v16i64, MVT::v32i32);
152
153 setOperationAction(ISD::LOAD, MVT::v16f64, Promote);
154 AddPromotedToType(ISD::LOAD, MVT::v16f64, MVT::v32i32);
155
157 AddPromotedToType(ISD::LOAD, MVT::i128, MVT::v4i32);
158
159 // TODO: Would be better to consume as directly legal
161 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::f32, MVT::i32);
162
164 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::f64, MVT::i64);
165
167 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::f16, MVT::i16);
168
170 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::bf16, MVT::i16);
171
173 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::v2f32, MVT::i64);
174
176 AddPromotedToType(ISD::ATOMIC_STORE, MVT::f32, MVT::i32);
177
179 AddPromotedToType(ISD::ATOMIC_STORE, MVT::f64, MVT::i64);
180
182 AddPromotedToType(ISD::ATOMIC_STORE, MVT::f16, MVT::i16);
183
185 AddPromotedToType(ISD::ATOMIC_STORE, MVT::bf16, MVT::i16);
186
188 AddPromotedToType(ISD::ATOMIC_STORE, MVT::v2f32, MVT::i64);
189
190 // There are no 64-bit extloads. These should be done as a 32-bit extload and
191 // an extension to 64-bit.
192 for (MVT VT : MVT::integer_valuetypes())
194 Expand);
195
196 for (MVT VT : MVT::integer_valuetypes()) {
197 if (VT == MVT::i64)
198 continue;
199
200 for (auto Op : {ISD::SEXTLOAD, ISD::ZEXTLOAD, ISD::EXTLOAD}) {
201 setLoadExtAction(Op, VT, MVT::i1, Promote);
202 setLoadExtAction(Op, VT, MVT::i8, Legal);
203 setLoadExtAction(Op, VT, MVT::i16, Legal);
204 setLoadExtAction(Op, VT, MVT::i32, Expand);
205 }
206 }
207
209 for (auto MemVT :
210 {MVT::v2i8, MVT::v4i8, MVT::v2i16, MVT::v3i16, MVT::v4i16})
212 Expand);
213
214 setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand);
215 setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::bf16, Expand);
216 setLoadExtAction(ISD::EXTLOAD, MVT::v2f32, MVT::v2f16, Expand);
217 setLoadExtAction(ISD::EXTLOAD, MVT::v2f32, MVT::v2bf16, Expand);
218 setLoadExtAction(ISD::EXTLOAD, MVT::v3f32, MVT::v3f16, Expand);
219 setLoadExtAction(ISD::EXTLOAD, MVT::v3f32, MVT::v3bf16, Expand);
220 setLoadExtAction(ISD::EXTLOAD, MVT::v4f32, MVT::v4f16, Expand);
221 setLoadExtAction(ISD::EXTLOAD, MVT::v4f32, MVT::v4bf16, Expand);
222 setLoadExtAction(ISD::EXTLOAD, MVT::v8f32, MVT::v8f16, Expand);
223 setLoadExtAction(ISD::EXTLOAD, MVT::v8f32, MVT::v8bf16, Expand);
224 setLoadExtAction(ISD::EXTLOAD, MVT::v16f32, MVT::v16f16, Expand);
225 setLoadExtAction(ISD::EXTLOAD, MVT::v16f32, MVT::v16bf16, Expand);
226 setLoadExtAction(ISD::EXTLOAD, MVT::v32f32, MVT::v32f16, Expand);
227 setLoadExtAction(ISD::EXTLOAD, MVT::v32f32, MVT::v32bf16, Expand);
228
229 setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);
230 setLoadExtAction(ISD::EXTLOAD, MVT::v2f64, MVT::v2f32, Expand);
231 setLoadExtAction(ISD::EXTLOAD, MVT::v3f64, MVT::v3f32, Expand);
232 setLoadExtAction(ISD::EXTLOAD, MVT::v4f64, MVT::v4f32, Expand);
233 setLoadExtAction(ISD::EXTLOAD, MVT::v8f64, MVT::v8f32, Expand);
234 setLoadExtAction(ISD::EXTLOAD, MVT::v16f64, MVT::v16f32, Expand);
235
236 setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand);
237 setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::bf16, Expand);
238 setLoadExtAction(ISD::EXTLOAD, MVT::v2f64, MVT::v2f16, Expand);
239 setLoadExtAction(ISD::EXTLOAD, MVT::v2f64, MVT::v2bf16, Expand);
240 setLoadExtAction(ISD::EXTLOAD, MVT::v3f64, MVT::v3f16, Expand);
241 setLoadExtAction(ISD::EXTLOAD, MVT::v3f64, MVT::v3bf16, Expand);
242 setLoadExtAction(ISD::EXTLOAD, MVT::v4f64, MVT::v4f16, Expand);
243 setLoadExtAction(ISD::EXTLOAD, MVT::v4f64, MVT::v4bf16, Expand);
244 setLoadExtAction(ISD::EXTLOAD, MVT::v8f64, MVT::v8f16, Expand);
245 setLoadExtAction(ISD::EXTLOAD, MVT::v8f64, MVT::v8bf16, Expand);
246 setLoadExtAction(ISD::EXTLOAD, MVT::v16f64, MVT::v16f16, Expand);
247 setLoadExtAction(ISD::EXTLOAD, MVT::v16f64, MVT::v16bf16, Expand);
248
250 AddPromotedToType(ISD::STORE, MVT::f32, MVT::i32);
251
253 AddPromotedToType(ISD::STORE, MVT::v2f32, MVT::v2i32);
254
256 AddPromotedToType(ISD::STORE, MVT::v3f32, MVT::v3i32);
257
259 AddPromotedToType(ISD::STORE, MVT::v4f32, MVT::v4i32);
260
262 AddPromotedToType(ISD::STORE, MVT::v5f32, MVT::v5i32);
263
265 AddPromotedToType(ISD::STORE, MVT::v6f32, MVT::v6i32);
266
268 AddPromotedToType(ISD::STORE, MVT::v7f32, MVT::v7i32);
269
271 AddPromotedToType(ISD::STORE, MVT::v8f32, MVT::v8i32);
272
274 AddPromotedToType(ISD::STORE, MVT::v9f32, MVT::v9i32);
275
277 AddPromotedToType(ISD::STORE, MVT::v10f32, MVT::v10i32);
278
280 AddPromotedToType(ISD::STORE, MVT::v11f32, MVT::v11i32);
281
283 AddPromotedToType(ISD::STORE, MVT::v12f32, MVT::v12i32);
284
286 AddPromotedToType(ISD::STORE, MVT::v16f32, MVT::v16i32);
287
289 AddPromotedToType(ISD::STORE, MVT::v32f32, MVT::v32i32);
290
292 AddPromotedToType(ISD::STORE, MVT::i64, MVT::v2i32);
293
295 AddPromotedToType(ISD::STORE, MVT::v2i64, MVT::v4i32);
296
298 AddPromotedToType(ISD::STORE, MVT::f64, MVT::v2i32);
299
301 AddPromotedToType(ISD::STORE, MVT::v2f64, MVT::v4i32);
302
304 AddPromotedToType(ISD::STORE, MVT::v3i64, MVT::v6i32);
305
307 AddPromotedToType(ISD::STORE, MVT::v3f64, MVT::v6i32);
308
310 AddPromotedToType(ISD::STORE, MVT::v4i64, MVT::v8i32);
311
313 AddPromotedToType(ISD::STORE, MVT::v4f64, MVT::v8i32);
314
316 AddPromotedToType(ISD::STORE, MVT::v8i64, MVT::v16i32);
317
319 AddPromotedToType(ISD::STORE, MVT::v8f64, MVT::v16i32);
320
322 AddPromotedToType(ISD::STORE, MVT::v16i64, MVT::v32i32);
323
325 AddPromotedToType(ISD::STORE, MVT::v16f64, MVT::v32i32);
326
328 AddPromotedToType(ISD::STORE, MVT::i128, MVT::v4i32);
329
330 setTruncStoreAction(MVT::i64, MVT::i1, Expand);
331 setTruncStoreAction(MVT::i64, MVT::i8, Expand);
332 setTruncStoreAction(MVT::i64, MVT::i16, Expand);
333 setTruncStoreAction(MVT::i64, MVT::i32, Expand);
334
335 setTruncStoreAction(MVT::v2i64, MVT::v2i1, Expand);
336 setTruncStoreAction(MVT::v2i64, MVT::v2i8, Expand);
337 setTruncStoreAction(MVT::v2i64, MVT::v2i16, Expand);
338 setTruncStoreAction(MVT::v2i64, MVT::v2i32, Expand);
339
340 setTruncStoreAction(MVT::f32, MVT::bf16, Expand);
341 setTruncStoreAction(MVT::f32, MVT::f16, Expand);
342 setTruncStoreAction(MVT::v2f32, MVT::v2bf16, Expand);
343 setTruncStoreAction(MVT::v2f32, MVT::v2f16, Expand);
344 setTruncStoreAction(MVT::v3f32, MVT::v3bf16, Expand);
345 setTruncStoreAction(MVT::v3f32, MVT::v3f16, Expand);
346 setTruncStoreAction(MVT::v4f32, MVT::v4bf16, Expand);
347 setTruncStoreAction(MVT::v4f32, MVT::v4f16, Expand);
348 setTruncStoreAction(MVT::v6f32, MVT::v6f16, Expand);
349 setTruncStoreAction(MVT::v8f32, MVT::v8bf16, Expand);
350 setTruncStoreAction(MVT::v8f32, MVT::v8f16, Expand);
351 setTruncStoreAction(MVT::v16f32, MVT::v16bf16, Expand);
352 setTruncStoreAction(MVT::v16f32, MVT::v16f16, Expand);
353 setTruncStoreAction(MVT::v32f32, MVT::v32bf16, Expand);
354 setTruncStoreAction(MVT::v32f32, MVT::v32f16, Expand);
355
356 setTruncStoreAction(MVT::f64, MVT::bf16, Expand);
357 setTruncStoreAction(MVT::f64, MVT::f16, Expand);
358 setTruncStoreAction(MVT::f64, MVT::f32, Expand);
359
360 setTruncStoreAction(MVT::v2f64, MVT::v2f32, Expand);
361 setTruncStoreAction(MVT::v2f64, MVT::v2bf16, Expand);
362 setTruncStoreAction(MVT::v2f64, MVT::v2f16, Expand);
363
364 setTruncStoreAction(MVT::v3i32, MVT::v3i8, Expand);
365
366 setTruncStoreAction(MVT::v3i64, MVT::v3i32, Expand);
367 setTruncStoreAction(MVT::v3i64, MVT::v3i16, Expand);
368 setTruncStoreAction(MVT::v3i64, MVT::v3i8, Expand);
369 setTruncStoreAction(MVT::v3i64, MVT::v3i1, Expand);
370 setTruncStoreAction(MVT::v3f64, MVT::v3f32, Expand);
371 setTruncStoreAction(MVT::v3f64, MVT::v3bf16, Expand);
372 setTruncStoreAction(MVT::v3f64, MVT::v3f16, Expand);
373
374 setTruncStoreAction(MVT::v4i64, MVT::v4i32, Expand);
375 setTruncStoreAction(MVT::v4i64, MVT::v4i16, Expand);
376 setTruncStoreAction(MVT::v4f64, MVT::v4f32, Expand);
377 setTruncStoreAction(MVT::v4f64, MVT::v4bf16, Expand);
378 setTruncStoreAction(MVT::v4f64, MVT::v4f16, Expand);
379
380 setTruncStoreAction(MVT::v5i32, MVT::v5i1, Expand);
381 setTruncStoreAction(MVT::v5i32, MVT::v5i8, Expand);
382 setTruncStoreAction(MVT::v5i32, MVT::v5i16, Expand);
383
384 setTruncStoreAction(MVT::v6i32, MVT::v6i1, Expand);
385 setTruncStoreAction(MVT::v6i32, MVT::v6i8, Expand);
386 setTruncStoreAction(MVT::v6i32, MVT::v6i16, Expand);
387
388 setTruncStoreAction(MVT::v7i32, MVT::v7i1, Expand);
389 setTruncStoreAction(MVT::v7i32, MVT::v7i8, Expand);
390 setTruncStoreAction(MVT::v7i32, MVT::v7i16, Expand);
391
392 setTruncStoreAction(MVT::v8f64, MVT::v8f32, Expand);
393 setTruncStoreAction(MVT::v8f64, MVT::v8bf16, Expand);
394 setTruncStoreAction(MVT::v8f64, MVT::v8f16, Expand);
395
396 setTruncStoreAction(MVT::v16f64, MVT::v16f32, Expand);
397 setTruncStoreAction(MVT::v16f64, MVT::v16bf16, Expand);
398 setTruncStoreAction(MVT::v16f64, MVT::v16f16, Expand);
399 setTruncStoreAction(MVT::v16i64, MVT::v16i16, Expand);
400 setTruncStoreAction(MVT::v16i64, MVT::v16i8, Expand);
401 setTruncStoreAction(MVT::v16i64, MVT::v16i8, Expand);
402 setTruncStoreAction(MVT::v16i64, MVT::v16i1, Expand);
403
404 setOperationAction(ISD::Constant, {MVT::i32, MVT::i64}, Legal);
405 setOperationAction(ISD::ConstantFP, {MVT::f32, MVT::f64}, Legal);
406
408
409 // For R600, this is totally unsupported, just custom lower to produce an
410 // error.
412
413 // Library functions. These default to Expand, but we have instructions
414 // for them.
417 {MVT::f16, MVT::f32}, Legal);
419
421 setOperationAction(ISD::FROUND, {MVT::f32, MVT::f64}, Custom);
423 {MVT::f16, MVT::f32, MVT::f64}, Expand);
424
427 Custom);
429
430 setOperationAction(ISD::FNEARBYINT, {MVT::f16, MVT::f32, MVT::f64}, Custom);
431
432 setOperationAction(ISD::FRINT, {MVT::f16, MVT::f32, MVT::f64}, Custom);
433
434 setOperationAction({ISD::LRINT, ISD::LLRINT}, {MVT::f16, MVT::f32, MVT::f64},
435 Expand);
436
437 setOperationAction(ISD::FREM, {MVT::f16, MVT::f32, MVT::f64}, Expand);
438 setOperationAction(ISD::IS_FPCLASS, {MVT::f32, MVT::f64}, Legal);
440
442 Custom);
443
444 setOperationAction(ISD::FCANONICALIZE, {MVT::f32, MVT::f64}, Legal);
445
446 // FIXME: These IS_FPCLASS vector fp types are marked custom so it reaches
447 // scalarization code. Can be removed when IS_FPCLASS expand isn't called by
448 // default unless marked custom/legal.
450 {MVT::v2f32, MVT::v3f32, MVT::v4f32, MVT::v5f32,
451 MVT::v6f32, MVT::v7f32, MVT::v8f32, MVT::v16f32,
452 MVT::v2f64, MVT::v3f64, MVT::v4f64, MVT::v8f64,
453 MVT::v16f64},
454 Custom);
455
456 // Expand to fneg + fadd.
458
460 {MVT::v3i32, MVT::v3f32, MVT::v4i32, MVT::v4f32,
461 MVT::v5i32, MVT::v5f32, MVT::v6i32, MVT::v6f32,
462 MVT::v7i32, MVT::v7f32, MVT::v8i32, MVT::v8f32,
463 MVT::v9i32, MVT::v9f32, MVT::v10i32, MVT::v10f32,
464 MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32},
465 Custom);
466
469 {MVT::v2f32, MVT::v2i32, MVT::v3f32, MVT::v3i32, MVT::v4f32,
470 MVT::v4i32, MVT::v5f32, MVT::v5i32, MVT::v6f32, MVT::v6i32,
471 MVT::v7f32, MVT::v7i32, MVT::v8f32, MVT::v8i32, MVT::v9f32,
472 MVT::v9i32, MVT::v10i32, MVT::v10f32, MVT::v11i32, MVT::v11f32,
473 MVT::v12i32, MVT::v12f32, MVT::v16i32, MVT::v32f32, MVT::v32i32,
474 MVT::v2f64, MVT::v2i64, MVT::v3f64, MVT::v3i64, MVT::v4f64,
475 MVT::v4i64, MVT::v8f64, MVT::v8i64, MVT::v16f64, MVT::v16i64},
476 Custom);
477
479 Expand);
480 setOperationAction(ISD::FP_TO_FP16, {MVT::f64, MVT::f32}, Custom);
481
482 const MVT ScalarIntVTs[] = { MVT::i32, MVT::i64 };
483 for (MVT VT : ScalarIntVTs) {
484 // These should use [SU]DIVREM, so set them to expand
486 Expand);
487
488 // GPU does not have divrem function for signed or unsigned.
490
491 // GPU does not have [S|U]MUL_LOHI functions as a single instruction.
493
495
497 Expand);
498 }
499
500 // The hardware supports 32-bit FSHR, but not FSHL.
502
503 setOperationAction({ISD::ROTL, ISD::ROTR}, {MVT::i32, MVT::i64}, Expand);
504
506
511 MVT::i64, Custom);
513
515 Legal);
516
519 MVT::i64, Custom);
520
521 for (auto VT : {MVT::i8, MVT::i16})
523
524 static const MVT::SimpleValueType VectorIntTypes[] = {
525 MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32, MVT::v6i32, MVT::v7i32,
526 MVT::v9i32, MVT::v10i32, MVT::v11i32, MVT::v12i32};
527
528 for (MVT VT : VectorIntTypes) {
529 // Expand the following operations for the current type by default.
530 // clang-format off
550 VT, Expand);
551 // clang-format on
552 }
553
554 static const MVT::SimpleValueType FloatVectorTypes[] = {
555 MVT::v2f32, MVT::v3f32, MVT::v4f32, MVT::v5f32, MVT::v6f32, MVT::v7f32,
556 MVT::v9f32, MVT::v10f32, MVT::v11f32, MVT::v12f32};
557
558 for (MVT VT : FloatVectorTypes) {
571 VT, Expand);
572 }
573
574 // This causes using an unrolled select operation rather than expansion with
575 // bit operations. This is in general better, but the alternative using BFI
576 // instructions may be better if the select sources are SGPRs.
578 AddPromotedToType(ISD::SELECT, MVT::v2f32, MVT::v2i32);
579
581 AddPromotedToType(ISD::SELECT, MVT::v3f32, MVT::v3i32);
582
584 AddPromotedToType(ISD::SELECT, MVT::v4f32, MVT::v4i32);
585
587 AddPromotedToType(ISD::SELECT, MVT::v5f32, MVT::v5i32);
588
590 AddPromotedToType(ISD::SELECT, MVT::v6f32, MVT::v6i32);
591
593 AddPromotedToType(ISD::SELECT, MVT::v7f32, MVT::v7i32);
594
596 AddPromotedToType(ISD::SELECT, MVT::v9f32, MVT::v9i32);
597
599 AddPromotedToType(ISD::SELECT, MVT::v10f32, MVT::v10i32);
600
602 AddPromotedToType(ISD::SELECT, MVT::v11f32, MVT::v11i32);
603
605 AddPromotedToType(ISD::SELECT, MVT::v12f32, MVT::v12i32);
606
608 setJumpIsExpensive(true);
609
612
614
615 // We want to find all load dependencies for long chains of stores to enable
616 // merging into very wide vectors. The problem is with vectors with > 4
617 // elements. MergeConsecutiveStores will attempt to merge these because x8/x16
618 // vectors are a legal type, even though we have to split the loads
619 // usually. When we can more precisely specify load legality per address
620 // space, we should be able to make FindBetterChain/MergeConsecutiveStores
621 // smarter so that they can figure out what to do in 2 iterations without all
622 // N > 4 stores on the same chain.
624
625 // memcpy/memmove/memset are expanded in the IR, so we shouldn't need to worry
626 // about these during lowering.
627 MaxStoresPerMemcpy = 0xffffffff;
628 MaxStoresPerMemmove = 0xffffffff;
629 MaxStoresPerMemset = 0xffffffff;
630
631 // The expansion for 64-bit division is enormous.
633 addBypassSlowDiv(64, 32);
634
645
649}
650
652 const auto Flags = Op.getNode()->getFlags();
653 if (Flags.hasNoSignedZeros())
654 return true;
655
656 return false;
657}
658
659//===----------------------------------------------------------------------===//
660// Target Information
661//===----------------------------------------------------------------------===//
662
664static bool fnegFoldsIntoOpcode(unsigned Opc) {
665 switch (Opc) {
666 case ISD::FADD:
667 case ISD::FSUB:
668 case ISD::FMUL:
669 case ISD::FMA:
670 case ISD::FMAD:
671 case ISD::FMINNUM:
672 case ISD::FMAXNUM:
675 case ISD::FMINIMUM:
676 case ISD::FMAXIMUM:
677 case ISD::FMINIMUMNUM:
678 case ISD::FMAXIMUMNUM:
679 case ISD::SELECT:
680 case ISD::FSIN:
681 case ISD::FTRUNC:
682 case ISD::FRINT:
683 case ISD::FNEARBYINT:
684 case ISD::FROUNDEVEN:
686 case AMDGPUISD::RCP:
687 case AMDGPUISD::RCP_LEGACY:
688 case AMDGPUISD::RCP_IFLAG:
689 case AMDGPUISD::SIN_HW:
690 case AMDGPUISD::FMUL_LEGACY:
691 case AMDGPUISD::FMIN_LEGACY:
692 case AMDGPUISD::FMAX_LEGACY:
693 case AMDGPUISD::FMED3:
694 // TODO: handle llvm.amdgcn.fma.legacy
695 return true;
696 case ISD::BITCAST:
697 llvm_unreachable("bitcast is special cased");
698 default:
699 return false;
700 }
701}
702
703static bool fnegFoldsIntoOp(const SDNode *N) {
704 unsigned Opc = N->getOpcode();
705 if (Opc == ISD::BITCAST) {
706 // TODO: Is there a benefit to checking the conditions performFNegCombine
707 // does? We don't for the other cases.
708 SDValue BCSrc = N->getOperand(0);
709 if (BCSrc.getOpcode() == ISD::BUILD_VECTOR) {
710 return BCSrc.getNumOperands() == 2 &&
711 BCSrc.getOperand(1).getValueSizeInBits() == 32;
712 }
713
714 return BCSrc.getOpcode() == ISD::SELECT && BCSrc.getValueType() == MVT::f32;
715 }
716
717 return fnegFoldsIntoOpcode(Opc);
718}
719
720/// \p returns true if the operation will definitely need to use a 64-bit
721/// encoding, and thus will use a VOP3 encoding regardless of the source
722/// modifiers.
724static bool opMustUseVOP3Encoding(const SDNode *N, MVT VT) {
725 return (N->getNumOperands() > 2 && N->getOpcode() != ISD::SELECT) ||
726 VT == MVT::f64;
727}
728
729/// Return true if v_cndmask_b32 will support fabs/fneg source modifiers for the
730/// type for ISD::SELECT.
732static bool selectSupportsSourceMods(const SDNode *N) {
733 // TODO: Only applies if select will be vector
734 return N->getValueType(0) == MVT::f32;
735}
736
737// Most FP instructions support source modifiers, but this could be refined
738// slightly.
740static bool hasSourceMods(const SDNode *N) {
741 if (isa<MemSDNode>(N))
742 return false;
743
744 switch (N->getOpcode()) {
745 case ISD::CopyToReg:
746 case ISD::FDIV:
747 case ISD::FREM:
748 case ISD::INLINEASM:
750 case AMDGPUISD::DIV_SCALE:
752
753 // TODO: Should really be looking at the users of the bitcast. These are
754 // problematic because bitcasts are used to legalize all stores to integer
755 // types.
756 case ISD::BITCAST:
757 return false;
759 switch (N->getConstantOperandVal(0)) {
760 case Intrinsic::amdgcn_interp_p1:
761 case Intrinsic::amdgcn_interp_p2:
762 case Intrinsic::amdgcn_interp_mov:
763 case Intrinsic::amdgcn_interp_p1_f16:
764 case Intrinsic::amdgcn_interp_p2_f16:
765 return false;
766 default:
767 return true;
768 }
769 }
770 case ISD::SELECT:
772 default:
773 return true;
774 }
775}
776
778 unsigned CostThreshold) {
779 // Some users (such as 3-operand FMA/MAD) must use a VOP3 encoding, and thus
780 // it is truly free to use a source modifier in all cases. If there are
781 // multiple users but for each one will necessitate using VOP3, there will be
782 // a code size increase. Try to avoid increasing code size unless we know it
783 // will save on the instruction count.
784 unsigned NumMayIncreaseSize = 0;
785 MVT VT = N->getValueType(0).getScalarType().getSimpleVT();
786
787 assert(!N->use_empty());
788
789 // XXX - Should this limit number of uses to check?
790 for (const SDNode *U : N->users()) {
791 if (!hasSourceMods(U))
792 return false;
793
794 if (!opMustUseVOP3Encoding(U, VT)) {
795 if (++NumMayIncreaseSize > CostThreshold)
796 return false;
797 }
798 }
799
800 return true;
801}
802
804 ISD::NodeType ExtendKind) const {
805 assert(!VT.isVector() && "only scalar expected");
806
807 // Round to the next multiple of 32-bits.
808 unsigned Size = VT.getSizeInBits();
809 if (Size <= 32)
810 return MVT::i32;
811 return EVT::getIntegerVT(Context, 32 * ((Size + 31) / 32));
812}
813
815 return 32;
816}
817
819 return true;
820}
821
822// The backend supports 32 and 64 bit floating point immediates.
823// FIXME: Why are we reporting vectors of FP immediates as legal?
825 bool ForCodeSize) const {
826 return isTypeLegal(VT.getScalarType());
827}
828
829// We don't want to shrink f64 / f32 constants.
831 EVT ScalarVT = VT.getScalarType();
832 return (ScalarVT != MVT::f32 && ScalarVT != MVT::f64);
833}
834
836 SDNode *N, ISD::LoadExtType ExtTy, EVT NewVT,
837 std::optional<unsigned> ByteOffset) const {
838 // TODO: This may be worth removing. Check regression tests for diffs.
839 if (!TargetLoweringBase::shouldReduceLoadWidth(N, ExtTy, NewVT, ByteOffset))
840 return false;
841
842 unsigned NewSize = NewVT.getStoreSizeInBits();
843
844 // If we are reducing to a 32-bit load or a smaller multi-dword load,
845 // this is always better.
846 if (NewSize >= 32)
847 return true;
848
849 EVT OldVT = N->getValueType(0);
850 unsigned OldSize = OldVT.getStoreSizeInBits();
851
853 unsigned AS = MN->getAddressSpace();
854 // Do not shrink an aligned scalar load to sub-dword.
855 // Scalar engine cannot do sub-dword loads.
856 // TODO: Update this for GFX12 which does have scalar sub-dword loads.
857 if (OldSize >= 32 && NewSize < 32 && MN->getAlign() >= Align(4) &&
861 MN->isInvariant())) &&
863 return false;
864
865 // Don't produce extloads from sub 32-bit types. SI doesn't have scalar
866 // extloads, so doing one requires using a buffer_load. In cases where we
867 // still couldn't use a scalar load, using the wider load shouldn't really
868 // hurt anything.
869
870 // If the old size already had to be an extload, there's no harm in continuing
871 // to reduce the width.
872 return (OldSize < 32);
873}
874
876 const SelectionDAG &DAG,
877 const MachineMemOperand &MMO) const {
878
879 assert(LoadTy.getSizeInBits() == CastTy.getSizeInBits());
880
881 if (LoadTy.getScalarType() == MVT::i32)
882 return false;
883
884 unsigned LScalarSize = LoadTy.getScalarSizeInBits();
885 unsigned CastScalarSize = CastTy.getScalarSizeInBits();
886
887 if ((LScalarSize >= CastScalarSize) && (CastScalarSize < 32))
888 return false;
889
890 unsigned Fast = 0;
892 CastTy, MMO, &Fast) &&
893 Fast;
894}
895
896// SI+ has instructions for cttz / ctlz for 32-bit values. This is probably also
897// profitable with the expansion for 64-bit since it's generally good to
898// speculate things.
900 return true;
901}
902
904 return true;
905}
906
908 switch (N->getOpcode()) {
909 case ISD::EntryToken:
910 case ISD::TokenFactor:
911 return true;
913 unsigned IntrID = N->getConstantOperandVal(0);
915 }
917 unsigned IntrID = N->getConstantOperandVal(1);
919 }
920 case ISD::LOAD:
921 if (cast<LoadSDNode>(N)->getMemOperand()->getAddrSpace() ==
923 return true;
924 return false;
925 case AMDGPUISD::SETCC: // ballot-style instruction
926 return true;
927 }
928 return false;
929}
930
932 SDValue Op, SelectionDAG &DAG, bool LegalOperations, bool ForCodeSize,
933 NegatibleCost &Cost, unsigned Depth) const {
934
935 switch (Op.getOpcode()) {
936 case ISD::FMA:
937 case ISD::FMAD: {
938 // Negating a fma is not free if it has users without source mods.
939 if (!allUsesHaveSourceMods(Op.getNode()))
940 return SDValue();
941 break;
942 }
943 case AMDGPUISD::RCP: {
944 SDValue Src = Op.getOperand(0);
945 EVT VT = Op.getValueType();
946 SDLoc SL(Op);
947
948 SDValue NegSrc = getNegatedExpression(Src, DAG, LegalOperations,
949 ForCodeSize, Cost, Depth + 1);
950 if (NegSrc)
951 return DAG.getNode(AMDGPUISD::RCP, SL, VT, NegSrc, Op->getFlags());
952 return SDValue();
953 }
954 default:
955 break;
956 }
957
958 return TargetLowering::getNegatedExpression(Op, DAG, LegalOperations,
959 ForCodeSize, Cost, Depth);
960}
961
962//===---------------------------------------------------------------------===//
963// Target Properties
964//===---------------------------------------------------------------------===//
965
968
969 // Packed operations do not have a fabs modifier.
970 // Report this based on the end legalized type.
971 return VT == MVT::f32 || VT == MVT::f64 || VT == MVT::f16 || VT == MVT::bf16;
972}
973
976 // Report this based on the end legalized type.
977 VT = VT.getScalarType();
978 return VT == MVT::f32 || VT == MVT::f64 || VT == MVT::f16 || VT == MVT::bf16;
979}
980
982 unsigned NumElem,
983 unsigned AS) const {
984 return true;
985}
986
988 // There are few operations which truly have vector input operands. Any vector
989 // operation is going to involve operations on each component, and a
990 // build_vector will be a copy per element, so it always makes sense to use a
991 // build_vector input in place of the extracted element to avoid a copy into a
992 // super register.
993 //
994 // We should probably only do this if all users are extracts only, but this
995 // should be the common case.
996 return true;
997}
998
1000 // Truncate is just accessing a subregister.
1001
1002 unsigned SrcSize = Source.getSizeInBits();
1003 unsigned DestSize = Dest.getSizeInBits();
1004
1005 return DestSize < SrcSize && DestSize % 32 == 0 ;
1006}
1007
1009 // Truncate is just accessing a subregister.
1010
1011 unsigned SrcSize = Source->getScalarSizeInBits();
1012 unsigned DestSize = Dest->getScalarSizeInBits();
1013
1014 if (DestSize== 16 && Subtarget->has16BitInsts())
1015 return SrcSize >= 32;
1016
1017 return DestSize < SrcSize && DestSize % 32 == 0;
1018}
1019
1021 unsigned SrcSize = Src->getScalarSizeInBits();
1022 unsigned DestSize = Dest->getScalarSizeInBits();
1023
1024 if (SrcSize == 16 && Subtarget->has16BitInsts())
1025 return DestSize >= 32;
1026
1027 return SrcSize == 32 && DestSize == 64;
1028}
1029
1031 // Any register load of a 64-bit value really requires 2 32-bit moves. For all
1032 // practical purposes, the extra mov 0 to load a 64-bit is free. As used,
1033 // this will enable reducing 64-bit operations the 32-bit, which is always
1034 // good.
1035
1036 if (Src == MVT::i16)
1037 return Dest == MVT::i32 ||Dest == MVT::i64 ;
1038
1039 return Src == MVT::i32 && Dest == MVT::i64;
1040}
1041
1043 EVT DestVT) const {
1044 switch (N->getOpcode()) {
1045 case ISD::ABS:
1046 case ISD::ADD:
1047 case ISD::SUB:
1048 case ISD::SHL:
1049 case ISD::SRL:
1050 case ISD::SRA:
1051 case ISD::AND:
1052 case ISD::OR:
1053 case ISD::XOR:
1054 case ISD::MUL:
1055 case ISD::SETCC:
1056 case ISD::SELECT:
1057 case ISD::SMIN:
1058 case ISD::SMAX:
1059 case ISD::UMIN:
1060 case ISD::UMAX:
1061 case ISD::USUBSAT:
1062 if (isTypeLegal(MVT::i16) &&
1063 (!DestVT.isVector() ||
1064 !isOperationLegal(ISD::ADD, MVT::v2i16))) { // Check if VOP3P
1065 // Don't narrow back down to i16 if promoted to i32 already.
1066 if (!N->isDivergent() && DestVT.isInteger() &&
1067 DestVT.getScalarSizeInBits() > 1 &&
1068 DestVT.getScalarSizeInBits() <= 16 &&
1069 SrcVT.getScalarSizeInBits() > 16) {
1070 return false;
1071 }
1072 }
1073 return true;
1074 default:
1075 break;
1076 }
1077
1078 // There aren't really 64-bit registers, but pairs of 32-bit ones and only a
1079 // limited number of native 64-bit operations. Shrinking an operation to fit
1080 // in a single 32-bit register should always be helpful. As currently used,
1081 // this is much less general than the name suggests, and is only used in
1082 // places trying to reduce the sizes of loads. Shrinking loads to < 32-bits is
1083 // not profitable, and may actually be harmful.
1084 if (isa<LoadSDNode>(N))
1085 return SrcVT.getSizeInBits() > 32 && DestVT.getSizeInBits() == 32;
1086
1087 return true;
1088}
1089
1091 const SDNode* N, CombineLevel Level) const {
1092 assert((N->getOpcode() == ISD::SHL || N->getOpcode() == ISD::SRA ||
1093 N->getOpcode() == ISD::SRL) &&
1094 "Expected shift op");
1095
1096 SDValue ShiftLHS = N->getOperand(0);
1097 if (!ShiftLHS->hasOneUse())
1098 return false;
1099
1100 if (ShiftLHS.getOpcode() == ISD::SIGN_EXTEND &&
1101 !ShiftLHS.getOperand(0)->hasOneUse())
1102 return false;
1103
1104 // Always commute pre-type legalization and right shifts.
1105 // We're looking for shl(or(x,y),z) patterns.
1107 N->getOpcode() != ISD::SHL || N->getOperand(0).getOpcode() != ISD::OR)
1108 return true;
1109
1110 // If only user is a i32 right-shift, then don't destroy a BFE pattern.
1111 if (N->getValueType(0) == MVT::i32 && N->hasOneUse() &&
1112 (N->user_begin()->getOpcode() == ISD::SRA ||
1113 N->user_begin()->getOpcode() == ISD::SRL))
1114 return false;
1115
1116 // Don't destroy or(shl(load_zext(),c), load_zext()) patterns.
1117 auto IsShiftAndLoad = [](SDValue LHS, SDValue RHS) {
1118 if (LHS.getOpcode() != ISD::SHL)
1119 return false;
1120 auto *RHSLd = dyn_cast<LoadSDNode>(RHS);
1121 auto *LHS0 = dyn_cast<LoadSDNode>(LHS.getOperand(0));
1122 auto *LHS1 = dyn_cast<ConstantSDNode>(LHS.getOperand(1));
1123 return LHS0 && LHS1 && RHSLd && LHS0->getExtensionType() == ISD::ZEXTLOAD &&
1124 LHS1->getAPIntValue() == LHS0->getMemoryVT().getScalarSizeInBits() &&
1125 RHSLd->getExtensionType() == ISD::ZEXTLOAD;
1126 };
1127 SDValue LHS = N->getOperand(0).getOperand(0);
1128 SDValue RHS = N->getOperand(0).getOperand(1);
1129 return !(IsShiftAndLoad(LHS, RHS) || IsShiftAndLoad(RHS, LHS));
1130}
1131
1132//===---------------------------------------------------------------------===//
1133// TargetLowering Callbacks
1134//===---------------------------------------------------------------------===//
1135
1137 bool IsVarArg) {
1138 switch (CC) {
1146 return CC_AMDGPU;
1149 return CC_AMDGPU_CS_CHAIN;
1150 case CallingConv::C:
1151 case CallingConv::Fast:
1152 case CallingConv::Cold:
1153 return CC_AMDGPU_Func;
1156 return CC_SI_Gfx;
1159 default:
1160 reportFatalUsageError("unsupported calling convention for call");
1161 }
1162}
1163
1165 bool IsVarArg) {
1166 switch (CC) {
1169 llvm_unreachable("kernels should not be handled here");
1179 return RetCC_SI_Shader;
1182 return RetCC_SI_Gfx;
1183 case CallingConv::C:
1184 case CallingConv::Fast:
1185 case CallingConv::Cold:
1186 return RetCC_AMDGPU_Func;
1187 default:
1188 reportFatalUsageError("unsupported calling convention");
1189 }
1190}
1191
1192/// The SelectionDAGBuilder will automatically promote function arguments
1193/// with illegal types. However, this does not work for the AMDGPU targets
1194/// since the function arguments are stored in memory as these illegal types.
1195/// In order to handle this properly we need to get the original types sizes
1196/// from the LLVM IR Function and fixup the ISD:InputArg values before
1197/// passing them to AnalyzeFormalArguments()
1198
1199/// When the SelectionDAGBuilder computes the Ins, it takes care of splitting
1200/// input values across multiple registers. Each item in the Ins array
1201/// represents a single value that will be stored in registers. Ins[x].VT is
1202/// the value type of the value that will be stored in the register, so
1203/// whatever SDNode we lower the argument to needs to be this type.
1204///
1205/// In order to correctly lower the arguments we need to know the size of each
1206/// argument. Since Ins[x].VT gives us the size of the register that will
1207/// hold the value, we need to look at Ins[x].ArgVT to see the 'real' type
1208/// for the original function argument so that we can deduce the correct memory
1209/// type to use for Ins[x]. In most cases the correct memory type will be
1210/// Ins[x].ArgVT. However, this will not always be the case. If, for example,
1211/// we have a kernel argument of type v8i8, this argument will be split into
1212/// 8 parts and each part will be represented by its own item in the Ins array.
1213/// For each part the Ins[x].ArgVT will be the v8i8, which is the full type of
1214/// the argument before it was split. From this, we deduce that the memory type
1215/// for each individual part is i8. We pass the memory type as LocVT to the
1216/// calling convention analysis function and the register type (Ins[x].VT) as
1217/// the ValVT.
1219 CCState &State,
1220 const SmallVectorImpl<ISD::InputArg> &Ins) const {
1221 const MachineFunction &MF = State.getMachineFunction();
1222 const Function &Fn = MF.getFunction();
1223 LLVMContext &Ctx = Fn.getContext();
1224 const unsigned ExplicitOffset = Subtarget->getExplicitKernelArgOffset();
1226
1227 Align MaxAlign = Align(1);
1228 uint64_t ExplicitArgOffset = 0;
1229 const DataLayout &DL = Fn.getDataLayout();
1230
1231 unsigned InIndex = 0;
1232
1233 for (const Argument &Arg : Fn.args()) {
1234 const bool IsByRef = Arg.hasByRefAttr();
1235 Type *BaseArgTy = Arg.getType();
1236 Type *MemArgTy = IsByRef ? Arg.getParamByRefType() : BaseArgTy;
1237 Align Alignment = DL.getValueOrABITypeAlignment(
1238 IsByRef ? Arg.getParamAlign() : std::nullopt, MemArgTy);
1239 MaxAlign = std::max(Alignment, MaxAlign);
1240 uint64_t AllocSize = DL.getTypeAllocSize(MemArgTy);
1241
1242 uint64_t ArgOffset = alignTo(ExplicitArgOffset, Alignment) + ExplicitOffset;
1243 ExplicitArgOffset = alignTo(ExplicitArgOffset, Alignment) + AllocSize;
1244
1245 // We're basically throwing away everything passed into us and starting over
1246 // to get accurate in-memory offsets. The "PartOffset" is completely useless
1247 // to us as computed in Ins.
1248 //
1249 // We also need to figure out what type legalization is trying to do to get
1250 // the correct memory offsets.
1251
1252 SmallVector<EVT, 16> ValueVTs;
1254 ComputeValueVTs(*this, DL, BaseArgTy, ValueVTs, /*MemVTs=*/nullptr,
1255 &Offsets, ArgOffset);
1256
1257 for (unsigned Value = 0, NumValues = ValueVTs.size();
1258 Value != NumValues; ++Value) {
1259 uint64_t BasePartOffset = Offsets[Value];
1260
1261 EVT ArgVT = ValueVTs[Value];
1262 EVT MemVT = ArgVT;
1263 MVT RegisterVT = getRegisterTypeForCallingConv(Ctx, CC, ArgVT);
1264 unsigned NumRegs = getNumRegistersForCallingConv(Ctx, CC, ArgVT);
1265
1266 if (NumRegs == 1) {
1267 // This argument is not split, so the IR type is the memory type.
1268 if (ArgVT.isExtended()) {
1269 // We have an extended type, like i24, so we should just use the
1270 // register type.
1271 MemVT = RegisterVT;
1272 } else {
1273 MemVT = ArgVT;
1274 }
1275 } else if (ArgVT.isVector() && RegisterVT.isVector() &&
1276 ArgVT.getScalarType() == RegisterVT.getScalarType()) {
1277 assert(ArgVT.getVectorNumElements() > RegisterVT.getVectorNumElements());
1278 // We have a vector value which has been split into a vector with
1279 // the same scalar type, but fewer elements. This should handle
1280 // all the floating-point vector types.
1281 MemVT = RegisterVT;
1282 } else if (ArgVT.isVector() &&
1283 ArgVT.getVectorNumElements() == NumRegs) {
1284 // This arg has been split so that each element is stored in a separate
1285 // register.
1286 MemVT = ArgVT.getScalarType();
1287 } else if (ArgVT.isExtended()) {
1288 // We have an extended type, like i65.
1289 MemVT = RegisterVT;
1290 } else {
1291 unsigned MemoryBits = ArgVT.getStoreSizeInBits() / NumRegs;
1292 assert(ArgVT.getStoreSizeInBits() % NumRegs == 0);
1293 if (RegisterVT.isInteger()) {
1294 MemVT = EVT::getIntegerVT(State.getContext(), MemoryBits);
1295 } else if (RegisterVT.isVector()) {
1296 assert(!RegisterVT.getScalarType().isFloatingPoint());
1297 unsigned NumElements = RegisterVT.getVectorNumElements();
1298 assert(MemoryBits % NumElements == 0);
1299 // This vector type has been split into another vector type with
1300 // a different elements size.
1301 EVT ScalarVT = EVT::getIntegerVT(State.getContext(),
1302 MemoryBits / NumElements);
1303 MemVT = EVT::getVectorVT(State.getContext(), ScalarVT, NumElements);
1304 } else {
1305 llvm_unreachable("cannot deduce memory type.");
1306 }
1307 }
1308
1309 // Convert one element vectors to scalar.
1310 if (MemVT.isVector() && MemVT.getVectorNumElements() == 1)
1311 MemVT = MemVT.getScalarType();
1312
1313 // Round up vec3/vec5 argument.
1314 if (MemVT.isVector() && !MemVT.isPow2VectorType()) {
1315 MemVT = MemVT.getPow2VectorType(State.getContext());
1316 } else if (!MemVT.isSimple() && !MemVT.isVector()) {
1317 MemVT = MemVT.getRoundIntegerType(State.getContext());
1318 }
1319
1320 unsigned PartOffset = 0;
1321 for (unsigned i = 0; i != NumRegs; ++i) {
1322 State.addLoc(CCValAssign::getCustomMem(InIndex++, RegisterVT,
1323 BasePartOffset + PartOffset,
1324 MemVT.getSimpleVT(),
1326 PartOffset += MemVT.getStoreSize();
1327 }
1328 }
1329 }
1330}
1331
1333 SDValue Chain, CallingConv::ID CallConv,
1334 bool isVarArg,
1336 const SmallVectorImpl<SDValue> &OutVals,
1337 const SDLoc &DL, SelectionDAG &DAG) const {
1338 // FIXME: Fails for r600 tests
1339 //assert(!isVarArg && Outs.empty() && OutVals.empty() &&
1340 // "wave terminate should not have return values");
1341 return DAG.getNode(AMDGPUISD::ENDPGM, DL, MVT::Other, Chain);
1342}
1343
1344//===---------------------------------------------------------------------===//
1345// Target specific lowering
1346//===---------------------------------------------------------------------===//
1347
1348/// Selects the correct CCAssignFn for a given CallingConvention value.
1353
1358
1360 SelectionDAG &DAG,
1361 MachineFrameInfo &MFI,
1362 int ClobberedFI) const {
1363 SmallVector<SDValue, 8> ArgChains;
1364 int64_t FirstByte = MFI.getObjectOffset(ClobberedFI);
1365 int64_t LastByte = FirstByte + MFI.getObjectSize(ClobberedFI) - 1;
1366
1367 // Include the original chain at the beginning of the list. When this is
1368 // used by target LowerCall hooks, this helps legalize find the
1369 // CALLSEQ_BEGIN node.
1370 ArgChains.push_back(Chain);
1371
1372 // Add a chain value for each stack argument corresponding
1373 for (SDNode *U : DAG.getEntryNode().getNode()->users()) {
1374 if (LoadSDNode *L = dyn_cast<LoadSDNode>(U)) {
1375 if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(L->getBasePtr())) {
1376 if (FI->getIndex() < 0) {
1377 int64_t InFirstByte = MFI.getObjectOffset(FI->getIndex());
1378 int64_t InLastByte = InFirstByte;
1379 InLastByte += MFI.getObjectSize(FI->getIndex()) - 1;
1380
1381 if ((InFirstByte <= FirstByte && FirstByte <= InLastByte) ||
1382 (FirstByte <= InFirstByte && InFirstByte <= LastByte))
1383 ArgChains.push_back(SDValue(L, 1));
1384 }
1385 }
1386 }
1387 }
1388
1389 // Build a tokenfactor for all the chains.
1390 return DAG.getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, ArgChains);
1391}
1392
1395 StringRef Reason) const {
1396 SDValue Callee = CLI.Callee;
1397 SelectionDAG &DAG = CLI.DAG;
1398
1399 const Function &Fn = DAG.getMachineFunction().getFunction();
1400
1401 StringRef FuncName("<unknown>");
1402
1404 FuncName = G->getSymbol();
1405 else if (const GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
1406 FuncName = G->getGlobal()->getName();
1407
1408 DAG.getContext()->diagnose(
1409 DiagnosticInfoUnsupported(Fn, Reason + FuncName, CLI.DL.getDebugLoc()));
1410
1411 if (!CLI.IsTailCall) {
1412 for (ISD::InputArg &Arg : CLI.Ins)
1413 InVals.push_back(DAG.getPOISON(Arg.VT));
1414 }
1415
1416 // FIXME: Hack because R600 doesn't handle callseq pseudos yet.
1417 if (getTargetMachine().getTargetTriple().getArch() == Triple::r600)
1418 return CLI.Chain;
1419
1420 SDValue Chain = DAG.getCALLSEQ_START(CLI.Chain, 0, 0, CLI.DL);
1421 return DAG.getCALLSEQ_END(Chain, 0, 0, /*InGlue=*/SDValue(), CLI.DL);
1422}
1423
1425 SmallVectorImpl<SDValue> &InVals) const {
1426 return lowerUnhandledCall(CLI, InVals, "unsupported call to function ");
1427}
1428
1430 SelectionDAG &DAG) const {
1431 const Function &Fn = DAG.getMachineFunction().getFunction();
1432
1434 Fn, "unsupported dynamic alloca", SDLoc(Op).getDebugLoc()));
1435 auto Ops = {DAG.getConstant(0, SDLoc(), Op.getValueType()), Op.getOperand(0)};
1436 return DAG.getMergeValues(Ops, SDLoc());
1437}
1438
1440 SelectionDAG &DAG) const {
1441 switch (Op.getOpcode()) {
1442 default:
1443 Op->print(errs(), &DAG);
1444 llvm_unreachable("Custom lowering code for this "
1445 "instruction is not implemented yet!");
1446 break;
1448 case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG);
1450 case ISD::UDIVREM: return LowerUDIVREM(Op, DAG);
1451 case ISD::SDIVREM:
1452 return LowerSDIVREM(Op, DAG);
1453 case ISD::FCEIL: return LowerFCEIL(Op, DAG);
1454 case ISD::FTRUNC: return LowerFTRUNC(Op, DAG);
1455 case ISD::FRINT: return LowerFRINT(Op, DAG);
1456 case ISD::FNEARBYINT: return LowerFNEARBYINT(Op, DAG);
1457 case ISD::FROUNDEVEN:
1458 return LowerFROUNDEVEN(Op, DAG);
1459 case ISD::FROUND: return LowerFROUND(Op, DAG);
1460 case ISD::FFLOOR: return LowerFFLOOR(Op, DAG);
1461 case ISD::FLOG2:
1462 return LowerFLOG2(Op, DAG);
1463 case ISD::FLOG:
1464 case ISD::FLOG10:
1465 return LowerFLOGCommon(Op, DAG);
1466 case ISD::FEXP:
1467 case ISD::FEXP10:
1468 return lowerFEXP(Op, DAG);
1469 case ISD::FEXP2:
1470 return lowerFEXP2(Op, DAG);
1471 case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG);
1472 case ISD::UINT_TO_FP: return LowerUINT_TO_FP(Op, DAG);
1473 case ISD::FP_TO_FP16: return LowerFP_TO_FP16(Op, DAG);
1474 case ISD::FP_TO_SINT:
1475 case ISD::FP_TO_UINT:
1476 return LowerFP_TO_INT(Op, DAG);
1479 return LowerFP_TO_INT_SAT(Op, DAG);
1480 case ISD::CTTZ:
1482 case ISD::CTLZ:
1484 return LowerCTLZ_CTTZ(Op, DAG);
1485 case ISD::CTLS:
1486 return LowerCTLS(Op, DAG);
1488 }
1489 return Op;
1490}
1491
1494 SelectionDAG &DAG) const {
1495 switch (N->getOpcode()) {
1497 // Different parts of legalization seem to interpret which type of
1498 // sign_extend_inreg is the one to check for custom lowering. The extended
1499 // from type is what really matters, but some places check for custom
1500 // lowering of the result type. This results in trying to use
1501 // ReplaceNodeResults to sext_in_reg to an illegal type, so we'll just do
1502 // nothing here and let the illegal result integer be handled normally.
1503 return;
1504 case ISD::FLOG2:
1505 if (SDValue Lowered = LowerFLOG2(SDValue(N, 0), DAG))
1506 Results.push_back(Lowered);
1507 return;
1508 case ISD::FLOG:
1509 case ISD::FLOG10:
1510 if (SDValue Lowered = LowerFLOGCommon(SDValue(N, 0), DAG))
1511 Results.push_back(Lowered);
1512 return;
1513 case ISD::FEXP2:
1514 if (SDValue Lowered = lowerFEXP2(SDValue(N, 0), DAG))
1515 Results.push_back(Lowered);
1516 return;
1517 case ISD::FEXP:
1518 case ISD::FEXP10:
1519 if (SDValue Lowered = lowerFEXP(SDValue(N, 0), DAG))
1520 Results.push_back(Lowered);
1521 return;
1522 case ISD::CTLZ:
1524 if (auto Lowered = lowerCTLZResults(SDValue(N, 0u), DAG))
1525 Results.push_back(Lowered);
1526 return;
1527 default:
1528 return;
1529 }
1530}
1531
1533 SelectionDAG &DAG) const {
1535 SDLoc SL(Op);
1536 EVT VT = Op.getValueType();
1537 return DAG.getTargetBlockAddress(BA->getBlockAddress(), VT, BA->getOffset(),
1538 BA->getTargetFlags());
1539}
1540
1542 SDValue Op,
1543 SelectionDAG &DAG) const {
1544
1545 const DataLayout &DL = DAG.getDataLayout();
1547 const GlobalValue *GV = G->getGlobal();
1548
1549 if (!MFI->isModuleEntryFunction()) {
1550 bool IsNamedBarrier = AMDGPU::isNamedBarrier(*cast<GlobalVariable>(GV));
1551 std::optional<uint32_t> Address =
1553 if (!Address && IsNamedBarrier)
1554 llvm_unreachable("named barrier should have an assigned address");
1555 if (Address) {
1556 if (IsNamedBarrier) {
1557 unsigned BarCnt = cast<GlobalVariable>(GV)->getGlobalSize(DL) / 16;
1558 MFI->recordNumNamedBarriers(Address.value(), BarCnt);
1559 }
1560 // A constant byte offset (e.g. from a GEP into an array of named
1561 // barriers) folds directly into the fixed LDS address.
1562 return DAG.getConstant(*Address + G->getOffset(), SDLoc(Op),
1563 Op.getValueType());
1564 }
1565 }
1566
1567 if (G->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS ||
1568 G->getAddressSpace() == AMDGPUAS::REGION_ADDRESS) {
1569 if (!MFI->isModuleEntryFunction() &&
1570 GV->getName() != "llvm.amdgcn.module.lds" &&
1572 SDLoc DL(Op);
1573 const Function &Fn = DAG.getMachineFunction().getFunction();
1575 Fn, "local memory global used by non-kernel function",
1576 DL.getDebugLoc(), DS_Warning));
1577
1578 // We currently don't have a way to correctly allocate LDS objects that
1579 // aren't directly associated with a kernel. We do force inlining of
1580 // functions that use local objects. However, if these dead functions are
1581 // not eliminated, we don't want a compile time error. Just emit a warning
1582 // and a trap, since there should be no callable path here.
1583 SDValue Trap = DAG.getNode(ISD::TRAP, DL, MVT::Other, DAG.getEntryNode());
1584 SDValue OutputChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
1585 Trap, DAG.getRoot());
1586 DAG.setRoot(OutputChain);
1587 return DAG.getPOISON(Op.getValueType());
1588 }
1589
1590 // TODO: We could emit code to handle the initialization somewhere.
1591 // We ignore the initializer for now and legalize it to allow selection.
1592 // The initializer will anyway get errored out during assembly emission.
1593 unsigned Offset = MFI->allocateLDSGlobal(DL, *cast<GlobalVariable>(GV));
1594 // A constant byte offset (e.g. from a GEP into an array of named barriers)
1595 // folds directly into the allocated LDS address.
1596 return DAG.getConstant(Offset + G->getOffset(), SDLoc(Op),
1597 Op.getValueType());
1598 }
1599 return SDValue();
1600}
1601
1603 SelectionDAG &DAG) const {
1605 SDLoc SL(Op);
1606
1607 EVT VT = Op.getValueType();
1608 if (VT.getVectorElementType().getSizeInBits() < 32) {
1609 unsigned OpBitSize = Op.getOperand(0).getValueType().getSizeInBits();
1610 if (OpBitSize >= 32 && OpBitSize % 32 == 0) {
1611 unsigned NewNumElt = OpBitSize / 32;
1612 EVT NewEltVT = (NewNumElt == 1) ? MVT::i32
1614 MVT::i32, NewNumElt);
1615 for (const SDUse &U : Op->ops()) {
1616 SDValue In = U.get();
1617 SDValue NewIn = DAG.getNode(ISD::BITCAST, SL, NewEltVT, In);
1618 if (NewNumElt > 1)
1619 DAG.ExtractVectorElements(NewIn, Args);
1620 else
1621 Args.push_back(NewIn);
1622 }
1623
1624 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32,
1625 NewNumElt * Op.getNumOperands());
1626 SDValue BV = DAG.getBuildVector(NewVT, SL, Args);
1627 return DAG.getNode(ISD::BITCAST, SL, VT, BV);
1628 }
1629 }
1630
1631 for (const SDUse &U : Op->ops())
1632 DAG.ExtractVectorElements(U.get(), Args);
1633
1634 return DAG.getBuildVector(Op.getValueType(), SL, Args);
1635}
1636
1638 SelectionDAG &DAG) const {
1639 SDLoc SL(Op);
1641 unsigned Start = Op.getConstantOperandVal(1);
1642 EVT VT = Op.getValueType();
1643 EVT SrcVT = Op.getOperand(0).getValueType();
1644
1645 if (VT.getScalarSizeInBits() == 16 && Start % 2 == 0) {
1646 unsigned NumElt = VT.getVectorNumElements();
1647 unsigned NumSrcElt = SrcVT.getVectorNumElements();
1648 assert(NumElt % 2 == 0 && NumSrcElt % 2 == 0 && "expect legal types");
1649
1650 // Extract 32-bit registers at a time.
1651 EVT NewSrcVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumSrcElt / 2);
1652 EVT NewVT = NumElt == 2
1653 ? MVT::i32
1654 : EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumElt / 2);
1655 SDValue Tmp = DAG.getNode(ISD::BITCAST, SL, NewSrcVT, Op.getOperand(0));
1656
1657 DAG.ExtractVectorElements(Tmp, Args, Start / 2, NumElt / 2);
1658 if (NumElt == 2)
1659 Tmp = Args[0];
1660 else
1661 Tmp = DAG.getBuildVector(NewVT, SL, Args);
1662
1663 return DAG.getNode(ISD::BITCAST, SL, VT, Tmp);
1664 }
1665
1666 DAG.ExtractVectorElements(Op.getOperand(0), Args, Start,
1668
1669 return DAG.getBuildVector(Op.getValueType(), SL, Args);
1670}
1671
1672// TODO: Handle fabs too
1674 if (Val.getOpcode() == ISD::FNEG)
1675 return Val.getOperand(0);
1676
1677 return Val;
1678}
1679
1681 if (Val.getOpcode() == ISD::FNEG)
1682 Val = Val.getOperand(0);
1683 if (Val.getOpcode() == ISD::FABS)
1684 Val = Val.getOperand(0);
1685 if (Val.getOpcode() == ISD::FCOPYSIGN)
1686 Val = Val.getOperand(0);
1687 return Val;
1688}
1689
1691 const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, SDValue True,
1692 SDValue False, SDValue CC, DAGCombinerInfo &DCI) const {
1693 SelectionDAG &DAG = DCI.DAG;
1694 ISD::CondCode CCOpcode = cast<CondCodeSDNode>(CC)->get();
1695 switch (CCOpcode) {
1696 case ISD::SETOEQ:
1697 case ISD::SETONE:
1698 case ISD::SETUNE:
1699 case ISD::SETNE:
1700 case ISD::SETUEQ:
1701 case ISD::SETEQ:
1702 case ISD::SETFALSE:
1703 case ISD::SETFALSE2:
1704 case ISD::SETTRUE:
1705 case ISD::SETTRUE2:
1706 case ISD::SETUO:
1707 case ISD::SETO:
1708 break;
1709 case ISD::SETULE:
1710 case ISD::SETULT: {
1711 if (LHS == True)
1712 return DAG.getNode(AMDGPUISD::FMIN_LEGACY, DL, VT, RHS, LHS);
1713 return DAG.getNode(AMDGPUISD::FMAX_LEGACY, DL, VT, LHS, RHS);
1714 }
1715 case ISD::SETOLE:
1716 case ISD::SETOLT:
1717 case ISD::SETLE:
1718 case ISD::SETLT: {
1719 // Ordered. Assume ordered for undefined.
1720
1721 // Only do this after legalization to avoid interfering with other combines
1722 // which might occur.
1724 !DCI.isCalledByLegalizer())
1725 return SDValue();
1726
1727 // We need to permute the operands to get the correct NaN behavior. The
1728 // selected operand is the second one based on the failing compare with NaN,
1729 // so permute it based on the compare type the hardware uses.
1730 if (LHS == True)
1731 return DAG.getNode(AMDGPUISD::FMIN_LEGACY, DL, VT, LHS, RHS);
1732 return DAG.getNode(AMDGPUISD::FMAX_LEGACY, DL, VT, RHS, LHS);
1733 }
1734 case ISD::SETUGE:
1735 case ISD::SETUGT: {
1736 if (LHS == True)
1737 return DAG.getNode(AMDGPUISD::FMAX_LEGACY, DL, VT, RHS, LHS);
1738 return DAG.getNode(AMDGPUISD::FMIN_LEGACY, DL, VT, LHS, RHS);
1739 }
1740 case ISD::SETGT:
1741 case ISD::SETGE:
1742 case ISD::SETOGE:
1743 case ISD::SETOGT: {
1745 !DCI.isCalledByLegalizer())
1746 return SDValue();
1747
1748 if (LHS == True)
1749 return DAG.getNode(AMDGPUISD::FMAX_LEGACY, DL, VT, LHS, RHS);
1750 return DAG.getNode(AMDGPUISD::FMIN_LEGACY, DL, VT, RHS, LHS);
1751 }
1752 case ISD::SETCC_INVALID:
1753 llvm_unreachable("Invalid setcc condcode!");
1754 }
1755 return SDValue();
1756}
1757
1758/// Generate Min/Max node
1760 SDValue LHS, SDValue RHS,
1761 SDValue True, SDValue False,
1762 SDValue CC,
1763 DAGCombinerInfo &DCI) const {
1764 if ((LHS == True && RHS == False) || (LHS == False && RHS == True))
1765 return combineFMinMaxLegacyImpl(DL, VT, LHS, RHS, True, False, CC, DCI);
1766
1767 SelectionDAG &DAG = DCI.DAG;
1768
1769 // If we can't directly match this, try to see if we can fold an fneg to
1770 // match.
1771
1774 SDValue NegTrue = peekFNeg(True);
1775
1776 // Undo the combine foldFreeOpFromSelect does if it helps us match the
1777 // fmin/fmax.
1778 //
1779 // select (fcmp olt (lhs, K)), (fneg lhs), -K
1780 // -> fneg (fmin_legacy lhs, K)
1781 //
1782 // TODO: Use getNegatedExpression
1783 if (LHS == NegTrue && CFalse && CRHS) {
1784 APFloat NegRHS = neg(CRHS->getValueAPF());
1785 if (NegRHS == CFalse->getValueAPF()) {
1786 SDValue Combined =
1787 combineFMinMaxLegacyImpl(DL, VT, LHS, RHS, NegTrue, False, CC, DCI);
1788 if (Combined)
1789 return DAG.getNode(ISD::FNEG, DL, VT, Combined);
1790 return SDValue();
1791 }
1792 }
1793
1794 return SDValue();
1795}
1796
1797std::pair<SDValue, SDValue>
1799 SDLoc SL(Op);
1800
1801 SDValue Vec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op);
1802
1803 const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);
1804 const SDValue One = DAG.getConstant(1, SL, MVT::i32);
1805
1806 SDValue Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, Zero);
1807 SDValue Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, One);
1808
1809 return std::pair(Lo, Hi);
1810}
1811
1813 SDLoc SL(Op);
1814
1815 SDValue Vec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op);
1816 const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);
1817 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, Zero);
1818}
1819
1821 SDLoc SL(Op);
1822
1823 SDValue Vec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op);
1824 const SDValue One = DAG.getConstant(1, SL, MVT::i32);
1825 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, One);
1826}
1827
1828// Split a vector type into two parts. The first part is a power of two vector.
1829// The second part is whatever is left over, and is a scalar if it would
1830// otherwise be a 1-vector.
1831std::pair<EVT, EVT>
1833 EVT LoVT, HiVT;
1834 EVT EltVT = VT.getVectorElementType();
1835 unsigned NumElts = VT.getVectorNumElements();
1836 unsigned LoNumElts = PowerOf2Ceil((NumElts + 1) / 2);
1837 LoVT = EVT::getVectorVT(*DAG.getContext(), EltVT, LoNumElts);
1838 HiVT = NumElts - LoNumElts == 1
1839 ? EltVT
1840 : EVT::getVectorVT(*DAG.getContext(), EltVT, NumElts - LoNumElts);
1841 return std::pair(LoVT, HiVT);
1842}
1843
1844// Split a vector value into two parts of types LoVT and HiVT. HiVT could be
1845// scalar.
1846std::pair<SDValue, SDValue>
1848 const EVT &LoVT, const EVT &HiVT,
1849 SelectionDAG &DAG) const {
1850 EVT VT = N.getValueType();
1852 (HiVT.isVector() ? HiVT.getVectorNumElements() : 1) <=
1853 VT.getVectorNumElements() &&
1854 "More vector elements requested than available!");
1856 DAG.getVectorIdxConstant(0, DL));
1857
1858 unsigned LoNumElts = LoVT.getVectorNumElements();
1859
1860 if (HiVT.isVector()) {
1861 unsigned HiNumElts = HiVT.getVectorNumElements();
1862 if ((VT.getVectorNumElements() % HiNumElts) == 0) {
1863 // Avoid creating an extract_subvector with an index that isn't a multiple
1864 // of the result type.
1866 DAG.getConstant(LoNumElts, DL, MVT::i32));
1867 return {Lo, Hi};
1868 }
1869
1871 DAG.ExtractVectorElements(N, Elts, /*Start=*/LoNumElts,
1872 /*Count=*/HiNumElts);
1873 SDValue Hi = DAG.getBuildVector(HiVT, DL, Elts);
1874 return {Lo, Hi};
1875 }
1876
1878 DAG.getVectorIdxConstant(LoNumElts, DL));
1879 return {Lo, Hi};
1880}
1881
1883 SelectionDAG &DAG) const {
1885 EVT VT = Op.getValueType();
1886 SDLoc SL(Op);
1887
1888
1889 // If this is a 2 element vector, we really want to scalarize and not create
1890 // weird 1 element vectors.
1891 if (VT.getVectorNumElements() == 2) {
1892 SDValue Ops[2];
1893 std::tie(Ops[0], Ops[1]) = scalarizeVectorLoad(Load, DAG);
1894 return DAG.getMergeValues(Ops, SL);
1895 }
1896
1897 SDValue BasePtr = Load->getBasePtr();
1898 EVT MemVT = Load->getMemoryVT();
1899
1900 const MachinePointerInfo &SrcValue = Load->getMemOperand()->getPointerInfo();
1901
1902 EVT LoVT, HiVT;
1903 EVT LoMemVT, HiMemVT;
1904 SDValue Lo, Hi;
1905
1906 std::tie(LoVT, HiVT) = getSplitDestVTs(VT, DAG);
1907 std::tie(LoMemVT, HiMemVT) = getSplitDestVTs(MemVT, DAG);
1908 std::tie(Lo, Hi) = splitVector(Op, SL, LoVT, HiVT, DAG);
1909
1910 unsigned Size = LoMemVT.getStoreSize();
1911 Align BaseAlign = Load->getAlign();
1912 Align HiAlign = commonAlignment(BaseAlign, Size);
1913
1914 SDValue LoLoad = DAG.getExtLoad(
1915 Load->getExtensionType(), SL, LoVT, Load->getChain(), BasePtr, SrcValue,
1916 LoMemVT, BaseAlign, Load->getMemOperand()->getFlags(), Load->getAAInfo());
1917 SDValue HiPtr = DAG.getObjectPtrOffset(SL, BasePtr, TypeSize::getFixed(Size));
1918 SDValue HiLoad = DAG.getExtLoad(
1919 Load->getExtensionType(), SL, HiVT, Load->getChain(), HiPtr,
1920 SrcValue.getWithOffset(LoMemVT.getStoreSize()), HiMemVT, HiAlign,
1921 Load->getMemOperand()->getFlags(), Load->getAAInfo());
1922
1923 SDValue Join;
1924 if (LoVT == HiVT) {
1925 // This is the case that the vector is power of two so was evenly split.
1926 Join = DAG.getNode(ISD::CONCAT_VECTORS, SL, VT, LoLoad, HiLoad);
1927 } else {
1928 Join = DAG.getNode(ISD::INSERT_SUBVECTOR, SL, VT, DAG.getPOISON(VT), LoLoad,
1929 DAG.getVectorIdxConstant(0, SL));
1930 Join = DAG.getNode(
1932 VT, Join, HiLoad,
1934 }
1935
1936 SDValue Ops[] = {Join, DAG.getNode(ISD::TokenFactor, SL, MVT::Other,
1937 LoLoad.getValue(1), HiLoad.getValue(1))};
1938
1939 return DAG.getMergeValues(Ops, SL);
1940}
1941
1943 SelectionDAG &DAG) const {
1945 EVT VT = Op.getValueType();
1946 SDValue BasePtr = Load->getBasePtr();
1947 EVT MemVT = Load->getMemoryVT();
1948 SDLoc SL(Op);
1949 const MachinePointerInfo &SrcValue = Load->getMemOperand()->getPointerInfo();
1950 Align BaseAlign = Load->getAlign();
1951 unsigned NumElements = MemVT.getVectorNumElements();
1952
1953 // Widen from vec3 to vec4 when the load is at least 8-byte aligned
1954 // or 16-byte fully dereferenceable. Otherwise, split the vector load.
1955 if (NumElements != 3 ||
1956 (BaseAlign < Align(8) &&
1957 !SrcValue.isDereferenceable(16, *DAG.getContext(), DAG.getDataLayout())))
1958 return SplitVectorLoad(Op, DAG);
1959
1960 assert(NumElements == 3);
1961
1962 EVT WideVT =
1964 EVT WideMemVT =
1966 SDValue WideLoad = DAG.getExtLoad(
1967 Load->getExtensionType(), SL, WideVT, Load->getChain(), BasePtr, SrcValue,
1968 WideMemVT, BaseAlign, Load->getMemOperand()->getFlags());
1969 return DAG.getMergeValues(
1970 {DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, VT, WideLoad,
1971 DAG.getVectorIdxConstant(0, SL)),
1972 WideLoad.getValue(1)},
1973 SL);
1974}
1975
1977 SelectionDAG &DAG) const {
1979 SDValue Val = Store->getValue();
1980 EVT VT = Val.getValueType();
1981
1982 // If this is a 2 element vector, we really want to scalarize and not create
1983 // weird 1 element vectors.
1984 if (VT.getVectorNumElements() == 2)
1985 return scalarizeVectorStore(Store, DAG);
1986
1987 EVT MemVT = Store->getMemoryVT();
1988 SDValue Chain = Store->getChain();
1989 SDValue BasePtr = Store->getBasePtr();
1990 SDLoc SL(Op);
1991
1992 EVT LoVT, HiVT;
1993 EVT LoMemVT, HiMemVT;
1994 SDValue Lo, Hi;
1995
1996 std::tie(LoVT, HiVT) = getSplitDestVTs(VT, DAG);
1997 std::tie(LoMemVT, HiMemVT) = getSplitDestVTs(MemVT, DAG);
1998 std::tie(Lo, Hi) = splitVector(Val, SL, LoVT, HiVT, DAG);
1999
2000 SDValue HiPtr = DAG.getObjectPtrOffset(SL, BasePtr, LoMemVT.getStoreSize());
2001
2002 const MachinePointerInfo &SrcValue = Store->getMemOperand()->getPointerInfo();
2003 Align BaseAlign = Store->getAlign();
2004 unsigned Size = LoMemVT.getStoreSize();
2005 Align HiAlign = commonAlignment(BaseAlign, Size);
2006
2007 SDValue LoStore =
2008 DAG.getTruncStore(Chain, SL, Lo, BasePtr, SrcValue, LoMemVT, BaseAlign,
2009 Store->getMemOperand()->getFlags(), Store->getAAInfo());
2010 SDValue HiStore = DAG.getTruncStore(
2011 Chain, SL, Hi, HiPtr, SrcValue.getWithOffset(Size), HiMemVT, HiAlign,
2012 Store->getMemOperand()->getFlags(), Store->getAAInfo());
2013
2014 return DAG.getNode(ISD::TokenFactor, SL, MVT::Other, LoStore, HiStore);
2015}
2016
2017// This is a shortcut for integer division because we have fast i32<->f32
2018// conversions, and fast f32 reciprocal instructions. The fractional part of a
2019// float is enough to accurately represent up to a 24-bit integer.
2021 bool Sign) const {
2022 SDLoc DL(Op);
2023 EVT VT = Op.getValueType();
2024 assert(VT == MVT::i32 && "LowerDIVREM24 expects an i32");
2025
2026 SDValue LHS = Op.getOperand(0);
2027 SDValue RHS = Op.getOperand(1);
2028 MVT IntVT = MVT::i32;
2029 MVT FltVT = MVT::f32;
2030
2031 unsigned LHSSignBits;
2032 unsigned RHSSignBits;
2033 if (Sign) {
2034 LHSSignBits = DAG.ComputeNumSignBits(LHS);
2035 RHSSignBits = DAG.ComputeNumSignBits(RHS);
2036 if (LHSSignBits < 9 || RHSSignBits < 9)
2037 return SDValue();
2038 } else {
2039 KnownBits LHSKnown = DAG.computeKnownBits(LHS);
2040 KnownBits RHSKnown = DAG.computeKnownBits(RHS);
2041 APInt U24Max = APInt::getLowBitsSet(32, 24);
2042 if (LHSKnown.getMaxValue().ugt(U24Max) ||
2043 RHSKnown.getMaxValue().ugt(U24Max))
2044 return SDValue();
2045 LHSSignBits = LHSKnown.countMinLeadingZeros();
2046 RHSSignBits = RHSKnown.countMinLeadingZeros();
2047 }
2048
2049 unsigned BitSize = VT.getSizeInBits();
2050 unsigned SignBits = std::min(LHSSignBits, RHSSignBits);
2051 unsigned DivBits = BitSize - SignBits;
2052 if (Sign)
2053 ++DivBits;
2054
2057
2058 SDValue jq = DAG.getConstant(1, DL, IntVT);
2059
2060 if (Sign) {
2061 // char|short jq = ia ^ ib;
2062 jq = DAG.getNode(ISD::XOR, DL, VT, LHS, RHS);
2063
2064 // jq = jq >> (bitsize - 2)
2065 jq = DAG.getNode(ISD::SRA, DL, VT, jq,
2066 DAG.getConstant(BitSize - 2, DL, VT));
2067
2068 // jq = jq | 0x1
2069 jq = DAG.getNode(ISD::OR, DL, VT, jq, DAG.getConstant(1, DL, VT));
2070 }
2071
2072 // int ia = (int)LHS;
2073 SDValue ia = LHS;
2074
2075 // int ib, (int)RHS;
2076 SDValue ib = RHS;
2077
2078 // float fa = (float)ia;
2079 SDValue fa = DAG.getNode(ToFp, DL, FltVT, ia);
2080
2081 // float fb = (float)ib;
2082 SDValue fb = DAG.getNode(ToFp, DL, FltVT, ib);
2083
2084 SDValue fq = DAG.getNode(ISD::FMUL, DL, FltVT,
2085 fa, DAG.getNode(AMDGPUISD::RCP, DL, FltVT, fb));
2086
2087 // fq = trunc(fq);
2088 fq = DAG.getNode(ISD::FTRUNC, DL, FltVT, fq);
2089
2090 // float fqneg = -fq;
2091 SDValue fqneg = DAG.getNode(ISD::FNEG, DL, FltVT, fq);
2092
2094
2095 bool UseFmadFtz = false;
2096 if (Subtarget->isGCN()) {
2098 UseFmadFtz =
2100 }
2101
2102 // float fr = mad(fqneg, fb, fa);
2103 unsigned OpCode = !Subtarget->hasMadMacF32Insts() ? (unsigned)ISD::FMA
2104 : UseFmadFtz ? (unsigned)AMDGPUISD::FMAD_FTZ
2106 SDValue fr = DAG.getNode(OpCode, DL, FltVT, fqneg, fb, fa);
2107
2108 // int iq = (int)fq;
2109 SDValue iq = DAG.getNode(ToInt, DL, IntVT, fq);
2110
2111 // fr = fabs(fr);
2112 fr = DAG.getNode(ISD::FABS, DL, FltVT, fr);
2113
2114 // fb = fabs(fb);
2115 fb = DAG.getNode(ISD::FABS, DL, FltVT, fb);
2116
2117 EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
2118
2119 // int cv = fr >= fb;
2120 SDValue cv = DAG.getSetCC(DL, SetCCVT, fr, fb, ISD::SETOGE);
2121
2122 // jq = (cv ? jq : 0);
2123 jq = DAG.getNode(ISD::SELECT, DL, VT, cv, jq, DAG.getConstant(0, DL, VT));
2124
2125 // dst = iq + jq;
2126 SDValue Div = DAG.getNode(ISD::ADD, DL, VT, iq, jq);
2127
2128 // Rem needs compensation, it's easier to recompute it
2129 SDValue Rem = DAG.getNode(ISD::MUL, DL, VT, Div, RHS);
2130 Rem = DAG.getNode(ISD::SUB, DL, VT, LHS, Rem);
2131
2132 // Truncate to number of bits this divide really is.
2133 if (Sign) {
2134 SDValue InRegSize
2135 = DAG.getValueType(EVT::getIntegerVT(*DAG.getContext(), DivBits));
2136 Div = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, Div, InRegSize);
2137 Rem = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, Rem, InRegSize);
2138 } else {
2139 SDValue TruncMask = DAG.getConstant((UINT64_C(1) << DivBits) - 1, DL, VT);
2140 Div = DAG.getNode(ISD::AND, DL, VT, Div, TruncMask);
2141 Rem = DAG.getNode(ISD::AND, DL, VT, Rem, TruncMask);
2142 }
2143
2144 return DAG.getMergeValues({ Div, Rem }, DL);
2145}
2146
2148 SelectionDAG &DAG,
2150 SDLoc DL(Op);
2151 EVT VT = Op.getValueType();
2152
2153 assert(VT == MVT::i64 && "LowerUDIVREM64 expects an i64");
2154
2155 EVT HalfVT = VT.getHalfSizedIntegerVT(*DAG.getContext());
2156
2157 SDValue One = DAG.getConstant(1, DL, HalfVT);
2158 SDValue Zero = DAG.getConstant(0, DL, HalfVT);
2159
2160 //HiLo split
2161 SDValue LHS_Lo, LHS_Hi;
2162 SDValue LHS = Op.getOperand(0);
2163 std::tie(LHS_Lo, LHS_Hi) = DAG.SplitScalar(LHS, DL, HalfVT, HalfVT);
2164
2165 SDValue RHS_Lo, RHS_Hi;
2166 SDValue RHS = Op.getOperand(1);
2167 std::tie(RHS_Lo, RHS_Hi) = DAG.SplitScalar(RHS, DL, HalfVT, HalfVT);
2168
2169 if (DAG.MaskedValueIsZero(RHS, APInt::getHighBitsSet(64, 32)) &&
2170 DAG.MaskedValueIsZero(LHS, APInt::getHighBitsSet(64, 32))) {
2171
2172 SDValue Res = DAG.getNode(ISD::UDIVREM, DL, DAG.getVTList(HalfVT, HalfVT),
2173 LHS_Lo, RHS_Lo);
2174
2175 SDValue DIV = DAG.getBuildVector(MVT::v2i32, DL, {Res.getValue(0), Zero});
2176 SDValue REM = DAG.getBuildVector(MVT::v2i32, DL, {Res.getValue(1), Zero});
2177
2178 Results.push_back(DAG.getNode(ISD::BITCAST, DL, MVT::i64, DIV));
2179 Results.push_back(DAG.getNode(ISD::BITCAST, DL, MVT::i64, REM));
2180 return;
2181 }
2182
2183 if (isTypeLegal(MVT::i64)) {
2184 // The algorithm here is based on ideas from "Software Integer Division",
2185 // Tom Rodeheffer, August 2008.
2186
2189
2190 // Compute denominator reciprocal.
2191 unsigned FMAD =
2192 !Subtarget->hasMadMacF32Insts() ? (unsigned)ISD::FMA
2195 : (unsigned)AMDGPUISD::FMAD_FTZ;
2196
2197 SDValue Cvt_Lo = DAG.getNode(ISD::UINT_TO_FP, DL, MVT::f32, RHS_Lo);
2198 SDValue Cvt_Hi = DAG.getNode(ISD::UINT_TO_FP, DL, MVT::f32, RHS_Hi);
2199 SDValue Mad1 = DAG.getNode(FMAD, DL, MVT::f32, Cvt_Hi,
2200 DAG.getConstantFP(APInt(32, 0x4f800000).bitsToFloat(), DL, MVT::f32),
2201 Cvt_Lo);
2202 SDValue Rcp = DAG.getNode(AMDGPUISD::RCP, DL, MVT::f32, Mad1);
2203 SDValue Mul1 = DAG.getNode(ISD::FMUL, DL, MVT::f32, Rcp,
2204 DAG.getConstantFP(APInt(32, 0x5f7ffffc).bitsToFloat(), DL, MVT::f32));
2205 SDValue Mul2 = DAG.getNode(ISD::FMUL, DL, MVT::f32, Mul1,
2206 DAG.getConstantFP(APInt(32, 0x2f800000).bitsToFloat(), DL, MVT::f32));
2207 SDValue Trunc = DAG.getNode(ISD::FTRUNC, DL, MVT::f32, Mul2);
2208 SDValue Mad2 = DAG.getNode(FMAD, DL, MVT::f32, Trunc,
2209 DAG.getConstantFP(APInt(32, 0xcf800000).bitsToFloat(), DL, MVT::f32),
2210 Mul1);
2211 SDValue Rcp_Lo = DAG.getNode(ISD::FP_TO_UINT, DL, HalfVT, Mad2);
2212 SDValue Rcp_Hi = DAG.getNode(ISD::FP_TO_UINT, DL, HalfVT, Trunc);
2213 SDValue Rcp64 = DAG.getBitcast(VT,
2214 DAG.getBuildVector(MVT::v2i32, DL, {Rcp_Lo, Rcp_Hi}));
2215
2216 SDValue Zero64 = DAG.getConstant(0, DL, VT);
2217 SDValue One64 = DAG.getConstant(1, DL, VT);
2218 SDValue Zero1 = DAG.getConstant(0, DL, MVT::i1);
2219 SDVTList HalfCarryVT = DAG.getVTList(HalfVT, MVT::i1);
2220
2221 // First round of UNR (Unsigned integer Newton-Raphson).
2222 SDValue Neg_RHS = DAG.getNode(ISD::SUB, DL, VT, Zero64, RHS);
2223 SDValue Mullo1 = DAG.getNode(ISD::MUL, DL, VT, Neg_RHS, Rcp64);
2224 SDValue Mulhi1 = DAG.getNode(ISD::MULHU, DL, VT, Rcp64, Mullo1);
2225 SDValue Mulhi1_Lo, Mulhi1_Hi;
2226 std::tie(Mulhi1_Lo, Mulhi1_Hi) =
2227 DAG.SplitScalar(Mulhi1, DL, HalfVT, HalfVT);
2228 SDValue Add1_Lo = DAG.getNode(ISD::UADDO_CARRY, DL, HalfCarryVT, Rcp_Lo,
2229 Mulhi1_Lo, Zero1);
2230 SDValue Add1_Hi = DAG.getNode(ISD::UADDO_CARRY, DL, HalfCarryVT, Rcp_Hi,
2231 Mulhi1_Hi, Add1_Lo.getValue(1));
2232 SDValue Add1 = DAG.getBitcast(VT,
2233 DAG.getBuildVector(MVT::v2i32, DL, {Add1_Lo, Add1_Hi}));
2234
2235 // Second round of UNR.
2236 SDValue Mullo2 = DAG.getNode(ISD::MUL, DL, VT, Neg_RHS, Add1);
2237 SDValue Mulhi2 = DAG.getNode(ISD::MULHU, DL, VT, Add1, Mullo2);
2238 SDValue Mulhi2_Lo, Mulhi2_Hi;
2239 std::tie(Mulhi2_Lo, Mulhi2_Hi) =
2240 DAG.SplitScalar(Mulhi2, DL, HalfVT, HalfVT);
2241 SDValue Add2_Lo = DAG.getNode(ISD::UADDO_CARRY, DL, HalfCarryVT, Add1_Lo,
2242 Mulhi2_Lo, Zero1);
2243 SDValue Add2_Hi = DAG.getNode(ISD::UADDO_CARRY, DL, HalfCarryVT, Add1_Hi,
2244 Mulhi2_Hi, Add2_Lo.getValue(1));
2245 SDValue Add2 = DAG.getBitcast(VT,
2246 DAG.getBuildVector(MVT::v2i32, DL, {Add2_Lo, Add2_Hi}));
2247
2248 SDValue Mulhi3 = DAG.getNode(ISD::MULHU, DL, VT, LHS, Add2);
2249
2250 SDValue Mul3 = DAG.getNode(ISD::MUL, DL, VT, RHS, Mulhi3);
2251
2252 SDValue Mul3_Lo, Mul3_Hi;
2253 std::tie(Mul3_Lo, Mul3_Hi) = DAG.SplitScalar(Mul3, DL, HalfVT, HalfVT);
2254 SDValue Sub1_Lo = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, LHS_Lo,
2255 Mul3_Lo, Zero1);
2256 SDValue Sub1_Hi = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, LHS_Hi,
2257 Mul3_Hi, Sub1_Lo.getValue(1));
2258 SDValue Sub1_Mi = DAG.getNode(ISD::SUB, DL, HalfVT, LHS_Hi, Mul3_Hi);
2259 SDValue Sub1 = DAG.getBitcast(VT,
2260 DAG.getBuildVector(MVT::v2i32, DL, {Sub1_Lo, Sub1_Hi}));
2261
2262 SDValue MinusOne = DAG.getConstant(0xffffffffu, DL, HalfVT);
2263 SDValue C1 = DAG.getSelectCC(DL, Sub1_Hi, RHS_Hi, MinusOne, Zero,
2264 ISD::SETUGE);
2265 SDValue C2 = DAG.getSelectCC(DL, Sub1_Lo, RHS_Lo, MinusOne, Zero,
2266 ISD::SETUGE);
2267 SDValue C3 = DAG.getSelectCC(DL, Sub1_Hi, RHS_Hi, C2, C1, ISD::SETEQ);
2268
2269 // TODO: Here and below portions of the code can be enclosed into if/endif.
2270 // Currently control flow is unconditional and we have 4 selects after
2271 // potential endif to substitute PHIs.
2272
2273 // if C3 != 0 ...
2274 SDValue Sub2_Lo = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub1_Lo,
2275 RHS_Lo, Zero1);
2276 SDValue Sub2_Mi = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub1_Mi,
2277 RHS_Hi, Sub1_Lo.getValue(1));
2278 SDValue Sub2_Hi = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub2_Mi,
2279 Zero, Sub2_Lo.getValue(1));
2280 SDValue Sub2 = DAG.getBitcast(VT,
2281 DAG.getBuildVector(MVT::v2i32, DL, {Sub2_Lo, Sub2_Hi}));
2282
2283 SDValue Add3 = DAG.getNode(ISD::ADD, DL, VT, Mulhi3, One64);
2284
2285 SDValue C4 = DAG.getSelectCC(DL, Sub2_Hi, RHS_Hi, MinusOne, Zero,
2286 ISD::SETUGE);
2287 SDValue C5 = DAG.getSelectCC(DL, Sub2_Lo, RHS_Lo, MinusOne, Zero,
2288 ISD::SETUGE);
2289 SDValue C6 = DAG.getSelectCC(DL, Sub2_Hi, RHS_Hi, C5, C4, ISD::SETEQ);
2290
2291 // if (C6 != 0)
2292 SDValue Add4 = DAG.getNode(ISD::ADD, DL, VT, Add3, One64);
2293
2294 SDValue Sub3_Lo = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub2_Lo,
2295 RHS_Lo, Zero1);
2296 SDValue Sub3_Mi = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub2_Mi,
2297 RHS_Hi, Sub2_Lo.getValue(1));
2298 SDValue Sub3_Hi = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub3_Mi,
2299 Zero, Sub3_Lo.getValue(1));
2300 SDValue Sub3 = DAG.getBitcast(VT,
2301 DAG.getBuildVector(MVT::v2i32, DL, {Sub3_Lo, Sub3_Hi}));
2302
2303 // endif C6
2304 // endif C3
2305
2306 SDValue Sel1 = DAG.getSelectCC(DL, C6, Zero, Add4, Add3, ISD::SETNE);
2307 SDValue Div = DAG.getSelectCC(DL, C3, Zero, Sel1, Mulhi3, ISD::SETNE);
2308
2309 SDValue Sel2 = DAG.getSelectCC(DL, C6, Zero, Sub3, Sub2, ISD::SETNE);
2310 SDValue Rem = DAG.getSelectCC(DL, C3, Zero, Sel2, Sub1, ISD::SETNE);
2311
2312 Results.push_back(Div);
2313 Results.push_back(Rem);
2314
2315 return;
2316 }
2317
2318 // r600 expandion.
2319 // Get Speculative values
2320 SDValue DIV_Part = DAG.getNode(ISD::UDIV, DL, HalfVT, LHS_Hi, RHS_Lo);
2321 SDValue REM_Part = DAG.getNode(ISD::UREM, DL, HalfVT, LHS_Hi, RHS_Lo);
2322
2323 SDValue REM_Lo = DAG.getSelectCC(DL, RHS_Hi, Zero, REM_Part, LHS_Hi, ISD::SETEQ);
2324 SDValue REM = DAG.getBuildVector(MVT::v2i32, DL, {REM_Lo, Zero});
2325 REM = DAG.getNode(ISD::BITCAST, DL, MVT::i64, REM);
2326
2327 SDValue DIV_Hi = DAG.getSelectCC(DL, RHS_Hi, Zero, DIV_Part, Zero, ISD::SETEQ);
2328 SDValue DIV_Lo = Zero;
2329
2330 const unsigned halfBitWidth = HalfVT.getSizeInBits();
2331
2332 for (unsigned i = 0; i < halfBitWidth; ++i) {
2333 const unsigned bitPos = halfBitWidth - i - 1;
2334 SDValue POS = DAG.getConstant(bitPos, DL, HalfVT);
2335 // Get value of high bit
2336 SDValue HBit = DAG.getNode(ISD::SRL, DL, HalfVT, LHS_Lo, POS);
2337 HBit = DAG.getNode(ISD::AND, DL, HalfVT, HBit, One);
2338 HBit = DAG.getNode(ISD::ZERO_EXTEND, DL, VT, HBit);
2339
2340 // Shift
2341 REM = DAG.getNode(ISD::SHL, DL, VT, REM, DAG.getConstant(1, DL, VT));
2342 // Add LHS high bit
2343 REM = DAG.getNode(ISD::OR, DL, VT, REM, HBit);
2344
2345 SDValue BIT = DAG.getConstant(1ULL << bitPos, DL, HalfVT);
2346 SDValue realBIT = DAG.getSelectCC(DL, REM, RHS, BIT, Zero, ISD::SETUGE);
2347
2348 DIV_Lo = DAG.getNode(ISD::OR, DL, HalfVT, DIV_Lo, realBIT);
2349
2350 // Update REM
2351 SDValue REM_sub = DAG.getNode(ISD::SUB, DL, VT, REM, RHS);
2352 REM = DAG.getSelectCC(DL, REM, RHS, REM_sub, REM, ISD::SETUGE);
2353 }
2354
2355 SDValue DIV = DAG.getBuildVector(MVT::v2i32, DL, {DIV_Lo, DIV_Hi});
2356 DIV = DAG.getNode(ISD::BITCAST, DL, MVT::i64, DIV);
2357 Results.push_back(DIV);
2358 Results.push_back(REM);
2359}
2360
2362 SelectionDAG &DAG) const {
2363 SDLoc DL(Op);
2364 EVT VT = Op.getValueType();
2365
2366 if (VT == MVT::i64) {
2368 LowerUDIVREM64(Op, DAG, Results);
2369 return DAG.getMergeValues(Results, DL);
2370 }
2371
2372 if (VT == MVT::i32) {
2373 if (SDValue Res = LowerDIVREM24(Op, DAG, false))
2374 return Res;
2375 }
2376
2377 SDValue X = Op.getOperand(0);
2378 SDValue Y = Op.getOperand(1);
2379
2380 // See AMDGPUCodeGenPrepare::expandDivRem32 for a description of the
2381 // algorithm used here.
2382
2383 // Initial estimate of inv(y).
2384 SDValue Z = DAG.getNode(AMDGPUISD::URECIP, DL, VT, Y);
2385
2386 // One round of UNR.
2387 SDValue NegY = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), Y);
2388 SDValue NegYZ = DAG.getNode(ISD::MUL, DL, VT, NegY, Z);
2389 Z = DAG.getNode(ISD::ADD, DL, VT, Z,
2390 DAG.getNode(ISD::MULHU, DL, VT, Z, NegYZ));
2391
2392 // Quotient/remainder estimate.
2393 SDValue Q = DAG.getNode(ISD::MULHU, DL, VT, X, Z);
2394 SDValue R =
2395 DAG.getNode(ISD::SUB, DL, VT, X, DAG.getNode(ISD::MUL, DL, VT, Q, Y));
2396
2397 // First quotient/remainder refinement.
2398 EVT CCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
2399 SDValue One = DAG.getConstant(1, DL, VT);
2400 SDValue Cond = DAG.getSetCC(DL, CCVT, R, Y, ISD::SETUGE);
2401 Q = DAG.getNode(ISD::SELECT, DL, VT, Cond,
2402 DAG.getNode(ISD::ADD, DL, VT, Q, One), Q);
2403 R = DAG.getNode(ISD::SELECT, DL, VT, Cond,
2404 DAG.getNode(ISD::SUB, DL, VT, R, Y), R);
2405
2406 // Second quotient/remainder refinement.
2407 Cond = DAG.getSetCC(DL, CCVT, R, Y, ISD::SETUGE);
2408 Q = DAG.getNode(ISD::SELECT, DL, VT, Cond,
2409 DAG.getNode(ISD::ADD, DL, VT, Q, One), Q);
2410 R = DAG.getNode(ISD::SELECT, DL, VT, Cond,
2411 DAG.getNode(ISD::SUB, DL, VT, R, Y), R);
2412
2413 return DAG.getMergeValues({Q, R}, DL);
2414}
2415
2417 SelectionDAG &DAG) const {
2418 SDLoc DL(Op);
2419 EVT VT = Op.getValueType();
2420
2421 SDValue LHS = Op.getOperand(0);
2422 SDValue RHS = Op.getOperand(1);
2423
2424 SDValue Zero = DAG.getConstant(0, DL, VT);
2425 SDValue NegOne = DAG.getAllOnesConstant(DL, VT);
2426
2427 if (VT == MVT::i32) {
2428 if (SDValue Res = LowerDIVREM24(Op, DAG, true))
2429 return Res;
2430 }
2431
2432 // LHS must have > 33 sign-bits to ensure that LHS != -2147483648
2433 // Otherwise 32-bit division cannot be used safely.
2434 // -2147483648/1 and -2147483648/-1 are not equal,
2435 // but they produce the same lower 32-bit result.
2436 if (VT == MVT::i64 && DAG.ComputeNumSignBits(LHS) > 33 &&
2437 DAG.ComputeNumSignBits(RHS) > 32) {
2438 EVT HalfVT = VT.getHalfSizedIntegerVT(*DAG.getContext());
2439
2440 //HiLo split
2441 SDValue LHS_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, LHS, Zero);
2442 SDValue RHS_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, RHS, Zero);
2443 SDValue DIVREM = DAG.getNode(ISD::SDIVREM, DL, DAG.getVTList(HalfVT, HalfVT),
2444 LHS_Lo, RHS_Lo);
2445 SDValue Res[2] = {
2446 DAG.getNode(ISD::SIGN_EXTEND, DL, VT, DIVREM.getValue(0)),
2447 DAG.getNode(ISD::SIGN_EXTEND, DL, VT, DIVREM.getValue(1))
2448 };
2449 return DAG.getMergeValues(Res, DL);
2450 }
2451
2452 SDValue LHSign = DAG.getSelectCC(DL, LHS, Zero, NegOne, Zero, ISD::SETLT);
2453 SDValue RHSign = DAG.getSelectCC(DL, RHS, Zero, NegOne, Zero, ISD::SETLT);
2454 SDValue DSign = DAG.getNode(ISD::XOR, DL, VT, LHSign, RHSign);
2455 SDValue RSign = LHSign; // Remainder sign is the same as LHS
2456
2457 LHS = DAG.getNode(ISD::ADD, DL, VT, LHS, LHSign);
2458 RHS = DAG.getNode(ISD::ADD, DL, VT, RHS, RHSign);
2459
2460 LHS = DAG.getNode(ISD::XOR, DL, VT, LHS, LHSign);
2461 RHS = DAG.getNode(ISD::XOR, DL, VT, RHS, RHSign);
2462
2463 SDValue Div = DAG.getNode(ISD::UDIVREM, DL, DAG.getVTList(VT, VT), LHS, RHS);
2464 SDValue Rem = Div.getValue(1);
2465
2466 Div = DAG.getNode(ISD::XOR, DL, VT, Div, DSign);
2467 Rem = DAG.getNode(ISD::XOR, DL, VT, Rem, RSign);
2468
2469 Div = DAG.getNode(ISD::SUB, DL, VT, Div, DSign);
2470 Rem = DAG.getNode(ISD::SUB, DL, VT, Rem, RSign);
2471
2472 SDValue Res[2] = {
2473 Div,
2474 Rem
2475 };
2476 return DAG.getMergeValues(Res, DL);
2477}
2478
2480 SDLoc SL(Op);
2481 SDValue Src = Op.getOperand(0);
2482
2483 // result = trunc(src)
2484 // if (src > 0.0 && src != result)
2485 // result += 1.0
2486
2487 SDValue Trunc = DAG.getNode(ISD::FTRUNC, SL, MVT::f64, Src);
2488
2489 const SDValue Zero = DAG.getConstantFP(0.0, SL, MVT::f64);
2490 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f64);
2491
2492 EVT SetCCVT =
2493 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f64);
2494
2495 SDValue Lt0 = DAG.getSetCC(SL, SetCCVT, Src, Zero, ISD::SETOGT);
2496 SDValue NeTrunc = DAG.getSetCC(SL, SetCCVT, Src, Trunc, ISD::SETONE);
2497 SDValue And = DAG.getNode(ISD::AND, SL, SetCCVT, Lt0, NeTrunc);
2498
2499 SDValue Add = DAG.getNode(ISD::SELECT, SL, MVT::f64, And, One, Zero);
2500 // TODO: Should this propagate fast-math-flags?
2501 return DAG.getNode(ISD::FADD, SL, MVT::f64, Trunc, Add);
2502}
2503
2505 SelectionDAG &DAG) {
2506 const unsigned FractBits = 52;
2507 const unsigned ExpBits = 11;
2508
2509 SDValue ExpPart = DAG.getNode(AMDGPUISD::BFE_U32, SL, MVT::i32,
2510 Hi,
2511 DAG.getConstant(FractBits - 32, SL, MVT::i32),
2512 DAG.getConstant(ExpBits, SL, MVT::i32));
2513 SDValue Exp = DAG.getNode(ISD::SUB, SL, MVT::i32, ExpPart,
2514 DAG.getConstant(1023, SL, MVT::i32));
2515
2516 return Exp;
2517}
2518
2520 SDLoc SL(Op);
2521 SDValue Src = Op.getOperand(0);
2522
2523 assert(Op.getValueType() == MVT::f64);
2524
2525 const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);
2526
2527 // Extract the upper half, since this is where we will find the sign and
2528 // exponent.
2529 SDValue Hi = getHiHalf64(Src, DAG);
2530
2531 SDValue Exp = extractF64Exponent(Hi, SL, DAG);
2532
2533 const unsigned FractBits = 52;
2534
2535 // Extract the sign bit.
2536 const SDValue SignBitMask = DAG.getConstant(UINT32_C(1) << 31, SL, MVT::i32);
2537 SDValue SignBit = DAG.getNode(ISD::AND, SL, MVT::i32, Hi, SignBitMask);
2538
2539 // Extend back to 64-bits.
2540 SDValue SignBit64 = DAG.getBuildVector(MVT::v2i32, SL, {Zero, SignBit});
2541 SignBit64 = DAG.getNode(ISD::BITCAST, SL, MVT::i64, SignBit64);
2542
2543 SDValue BcInt = DAG.getNode(ISD::BITCAST, SL, MVT::i64, Src);
2544 const SDValue FractMask
2545 = DAG.getConstant((UINT64_C(1) << FractBits) - 1, SL, MVT::i64);
2546
2547 SDValue Shr = DAG.getNode(ISD::SRA, SL, MVT::i64, FractMask, Exp);
2548 SDValue Not = DAG.getNOT(SL, Shr, MVT::i64);
2549 SDValue Tmp0 = DAG.getNode(ISD::AND, SL, MVT::i64, BcInt, Not);
2550
2551 EVT SetCCVT =
2552 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::i32);
2553
2554 const SDValue FiftyOne = DAG.getConstant(FractBits - 1, SL, MVT::i32);
2555
2556 SDValue ExpLt0 = DAG.getSetCC(SL, SetCCVT, Exp, Zero, ISD::SETLT);
2557 SDValue ExpGt51 = DAG.getSetCC(SL, SetCCVT, Exp, FiftyOne, ISD::SETGT);
2558
2559 SDValue Tmp1 = DAG.getNode(ISD::SELECT, SL, MVT::i64, ExpLt0, SignBit64, Tmp0);
2560 SDValue Tmp2 = DAG.getNode(ISD::SELECT, SL, MVT::i64, ExpGt51, BcInt, Tmp1);
2561
2562 return DAG.getNode(ISD::BITCAST, SL, MVT::f64, Tmp2);
2563}
2564
2566 SelectionDAG &DAG) const {
2567 SDLoc SL(Op);
2568 SDValue Src = Op.getOperand(0);
2569
2570 assert(Op.getValueType() == MVT::f64);
2571
2572 APFloat C1Val(APFloat::IEEEdouble(), "0x1.0p+52");
2573 SDValue C1 = DAG.getConstantFP(C1Val, SL, MVT::f64);
2574 SDValue CopySign = DAG.getNode(ISD::FCOPYSIGN, SL, MVT::f64, C1, Src);
2575
2576 // TODO: Should this propagate fast-math-flags?
2577
2578 SDValue Tmp1 = DAG.getNode(ISD::FADD, SL, MVT::f64, Src, CopySign);
2579 SDValue Tmp2 = DAG.getNode(ISD::FSUB, SL, MVT::f64, Tmp1, CopySign);
2580
2581 SDValue Fabs = DAG.getNode(ISD::FABS, SL, MVT::f64, Src);
2582
2583 APFloat C2Val(APFloat::IEEEdouble(), "0x1.fffffffffffffp+51");
2584 SDValue C2 = DAG.getConstantFP(C2Val, SL, MVT::f64);
2585
2586 EVT SetCCVT =
2587 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f64);
2588 SDValue Cond = DAG.getSetCC(SL, SetCCVT, Fabs, C2, ISD::SETOGT);
2589
2590 return DAG.getSelect(SL, MVT::f64, Cond, Src, Tmp2);
2591}
2592
2594 SelectionDAG &DAG) const {
2595 // FNEARBYINT and FRINT are the same, except in their handling of FP
2596 // exceptions. Those aren't really meaningful for us, and OpenCL only has
2597 // rint, so just treat them as equivalent.
2598 return DAG.getNode(ISD::FROUNDEVEN, SDLoc(Op), Op.getValueType(),
2599 Op.getOperand(0));
2600}
2601
2603 auto VT = Op.getValueType();
2604 auto Arg = Op.getOperand(0u);
2605 return DAG.getNode(ISD::FROUNDEVEN, SDLoc(Op), VT, Arg);
2606}
2607
2608// XXX - May require not supporting f32 denormals?
2609
2610// Don't handle v2f16. The extra instructions to scalarize and repack around the
2611// compare and vselect end up producing worse code than scalarizing the whole
2612// operation.
2614 SDLoc SL(Op);
2615 SDValue X = Op.getOperand(0);
2616 EVT VT = Op.getValueType();
2617
2618 SDValue T = DAG.getNode(ISD::FTRUNC, SL, VT, X);
2619
2620 // TODO: Should this propagate fast-math-flags?
2621
2622 SDValue Diff = DAG.getNode(ISD::FSUB, SL, VT, X, T);
2623
2624 SDValue AbsDiff = DAG.getNode(ISD::FABS, SL, VT, Diff);
2625
2626 const SDValue Zero = DAG.getConstantFP(0.0, SL, VT);
2627 const SDValue One = DAG.getConstantFP(1.0, SL, VT);
2628
2629 EVT SetCCVT =
2630 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
2631
2632 const SDValue Half = DAG.getConstantFP(0.5, SL, VT);
2633 SDValue Cmp = DAG.getSetCC(SL, SetCCVT, AbsDiff, Half, ISD::SETOGE);
2634 SDValue OneOrZeroFP = DAG.getNode(ISD::SELECT, SL, VT, Cmp, One, Zero);
2635
2636 SDValue SignedOffset = DAG.getNode(ISD::FCOPYSIGN, SL, VT, OneOrZeroFP, X);
2637 return DAG.getNode(ISD::FADD, SL, VT, T, SignedOffset);
2638}
2639
2641 SDLoc SL(Op);
2642 SDValue Src = Op.getOperand(0);
2643
2644 // result = trunc(src);
2645 // if (src < 0.0 && src != result)
2646 // result += -1.0.
2647
2648 SDValue Trunc = DAG.getNode(ISD::FTRUNC, SL, MVT::f64, Src);
2649
2650 const SDValue Zero = DAG.getConstantFP(0.0, SL, MVT::f64);
2651 const SDValue NegOne = DAG.getConstantFP(-1.0, SL, MVT::f64);
2652
2653 EVT SetCCVT =
2654 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f64);
2655
2656 SDValue Lt0 = DAG.getSetCC(SL, SetCCVT, Src, Zero, ISD::SETOLT);
2657 SDValue NeTrunc = DAG.getSetCC(SL, SetCCVT, Src, Trunc, ISD::SETONE);
2658 SDValue And = DAG.getNode(ISD::AND, SL, SetCCVT, Lt0, NeTrunc);
2659
2660 SDValue Add = DAG.getNode(ISD::SELECT, SL, MVT::f64, And, NegOne, Zero);
2661 // TODO: Should this propagate fast-math-flags?
2662 return DAG.getNode(ISD::FADD, SL, MVT::f64, Trunc, Add);
2663}
2664
2665/// Return true if it's known that \p Src can never be an f32 denormal value.
2667 switch (Src.getOpcode()) {
2668 case ISD::FP_EXTEND:
2669 return Src.getOperand(0).getValueType() == MVT::f16;
2670 case ISD::FP16_TO_FP:
2671 case ISD::FFREXP:
2672 case ISD::FSQRT:
2673 case AMDGPUISD::LOG:
2674 case AMDGPUISD::EXP:
2675 return true;
2677 unsigned IntrinsicID = Src.getConstantOperandVal(0);
2678 switch (IntrinsicID) {
2679 case Intrinsic::amdgcn_frexp_mant:
2680 case Intrinsic::amdgcn_log:
2681 case Intrinsic::amdgcn_log_clamp:
2682 case Intrinsic::amdgcn_exp2:
2683 case Intrinsic::amdgcn_sqrt:
2684 return true;
2685 default:
2686 return false;
2687 }
2688 }
2689 default:
2690 return false;
2691 }
2692
2693 llvm_unreachable("covered opcode switch");
2694}
2695
2697 SDNodeFlags Flags) {
2698 return Flags.hasApproximateFuncs();
2699}
2700
2709
2711 SDValue Src,
2712 SDNodeFlags Flags) const {
2713 SDLoc SL(Src);
2714 EVT VT = Src.getValueType();
2715 const fltSemantics &Semantics = VT.getFltSemantics();
2716 SDValue SmallestNormal =
2717 DAG.getConstantFP(APFloat::getSmallestNormalized(Semantics), SL, VT);
2718
2719 // Want to scale denormals up, but negatives and 0 work just as well on the
2720 // scaled path.
2721 SDValue IsLtSmallestNormal = DAG.getSetCC(
2722 SL, getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT), Src,
2723 SmallestNormal, ISD::SETOLT);
2724
2725 return IsLtSmallestNormal;
2726}
2727
2729 SDNodeFlags Flags) const {
2730 SDLoc SL(Src);
2731 EVT VT = Src.getValueType();
2732 const fltSemantics &Semantics = VT.getFltSemantics();
2733 SDValue Inf = DAG.getConstantFP(APFloat::getInf(Semantics), SL, VT);
2734
2735 SDValue Fabs = DAG.getNode(ISD::FABS, SL, VT, Src, Flags);
2736 SDValue IsFinite = DAG.getSetCC(
2737 SL, getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT), Fabs,
2738 Inf, ISD::SETOLT);
2739 return IsFinite;
2740}
2741
2742/// If denormal handling is required return the scaled input to FLOG2, and the
2743/// check for denormal range. Otherwise, return null values.
2744std::pair<SDValue, SDValue>
2746 SDValue Src, SDNodeFlags Flags) const {
2747 if (!needsDenormHandlingF32(DAG, Src, Flags))
2748 return {};
2749
2750 MVT VT = MVT::f32;
2751 const fltSemantics &Semantics = APFloat::IEEEsingle();
2752 SDValue SmallestNormal =
2753 DAG.getConstantFP(APFloat::getSmallestNormalized(Semantics), SL, VT);
2754
2755 SDValue IsLtSmallestNormal = DAG.getSetCC(
2756 SL, getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT), Src,
2757 SmallestNormal, ISD::SETOLT);
2758
2759 SDValue Scale32 = DAG.getConstantFP(0x1.0p+32, SL, VT);
2760 SDValue One = DAG.getConstantFP(1.0, SL, VT);
2761 SDValue ScaleFactor =
2762 DAG.getNode(ISD::SELECT, SL, VT, IsLtSmallestNormal, Scale32, One, Flags);
2763
2764 SDValue ScaledInput = DAG.getNode(ISD::FMUL, SL, VT, Src, ScaleFactor, Flags);
2765 return {ScaledInput, IsLtSmallestNormal};
2766}
2767
2769 // v_log_f32 is good enough for OpenCL, except it doesn't handle denormals.
2770 // If we have to handle denormals, scale up the input and adjust the result.
2771
2772 // scaled = x * (is_denormal ? 0x1.0p+32 : 1.0)
2773 // log2 = amdgpu_log2 - (is_denormal ? 32.0 : 0.0)
2774
2775 SDLoc SL(Op);
2776 EVT VT = Op.getValueType();
2777 SDValue Src = Op.getOperand(0);
2778 SDNodeFlags Flags = Op->getFlags();
2779
2780 if (VT == MVT::f16) {
2781 // Nothing in half is a denormal when promoted to f32.
2782 assert(!isTypeLegal(VT));
2783 SDValue Ext = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Src, Flags);
2784 SDValue Log = DAG.getNode(AMDGPUISD::LOG, SL, MVT::f32, Ext, Flags);
2785 return DAG.getNode(ISD::FP_ROUND, SL, VT, Log,
2786 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
2787 }
2788
2789 auto [ScaledInput, IsLtSmallestNormal] =
2790 getScaledLogInput(DAG, SL, Src, Flags);
2791 if (!ScaledInput)
2792 return DAG.getNode(AMDGPUISD::LOG, SL, VT, Src, Flags);
2793
2794 SDValue Log2 = DAG.getNode(AMDGPUISD::LOG, SL, VT, ScaledInput, Flags);
2795
2796 SDValue ThirtyTwo = DAG.getConstantFP(32.0, SL, VT);
2797 SDValue Zero = DAG.getConstantFP(0.0, SL, VT);
2798 SDValue ResultOffset =
2799 DAG.getNode(ISD::SELECT, SL, VT, IsLtSmallestNormal, ThirtyTwo, Zero);
2800 return DAG.getNode(ISD::FSUB, SL, VT, Log2, ResultOffset, Flags);
2801}
2802
2803static SDValue getMad(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue X,
2804 SDValue Y, SDValue C, SDNodeFlags Flags = SDNodeFlags()) {
2805 SDValue Mul = DAG.getNode(ISD::FMUL, SL, VT, X, Y, Flags);
2806 return DAG.getNode(ISD::FADD, SL, VT, Mul, C, Flags);
2807}
2808
2810 SelectionDAG &DAG) const {
2811 SDValue X = Op.getOperand(0);
2812 EVT VT = Op.getValueType();
2813 SDNodeFlags Flags = Op->getFlags();
2814 SDLoc DL(Op);
2815 const bool IsLog10 = Op.getOpcode() == ISD::FLOG10;
2816 assert(IsLog10 || Op.getOpcode() == ISD::FLOG);
2817
2818 if (VT == MVT::f16 || Flags.hasApproximateFuncs()) {
2819 // TODO: The direct f16 path is 1.79 ulp for f16. This should be used
2820 // depending on !fpmath metadata.
2821
2822 bool PromoteToF32 = VT == MVT::f16 && (!Flags.hasApproximateFuncs() ||
2823 !isTypeLegal(MVT::f16));
2824
2825 if (PromoteToF32) {
2826 // Log and multiply in f32 is always good enough for f16.
2827 X = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, X, Flags);
2828 }
2829
2830 SDValue Lowered = LowerFLOGUnsafe(X, DL, DAG, IsLog10, Flags);
2831 if (PromoteToF32) {
2832 return DAG.getNode(ISD::FP_ROUND, DL, VT, Lowered,
2833 DAG.getTargetConstant(0, DL, MVT::i32), Flags);
2834 }
2835
2836 return Lowered;
2837 }
2838
2839 SDValue ScaledInput, IsScaled;
2840 if (VT == MVT::f16)
2841 X = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, X, Flags);
2842 else {
2843 std::tie(ScaledInput, IsScaled) = getScaledLogInput(DAG, DL, X, Flags);
2844 if (ScaledInput)
2845 X = ScaledInput;
2846 }
2847
2848 SDValue Y = DAG.getNode(AMDGPUISD::LOG, DL, VT, X, Flags);
2849
2850 SDValue R;
2851 if (Subtarget->hasFastFMAF32()) {
2852 // c+cc are ln(2)/ln(10) to more than 49 bits
2853 const float c_log10 = 0x1.344134p-2f;
2854 const float cc_log10 = 0x1.09f79ep-26f;
2855
2856 // c + cc is ln(2) to more than 49 bits
2857 const float c_log = 0x1.62e42ep-1f;
2858 const float cc_log = 0x1.efa39ep-25f;
2859
2860 SDValue C = DAG.getConstantFP(IsLog10 ? c_log10 : c_log, DL, VT);
2861 SDValue CC = DAG.getConstantFP(IsLog10 ? cc_log10 : cc_log, DL, VT);
2862 // This adds correction terms for which contraction may lead to an increase
2863 // in the error of the approximation, so disable it.
2864 Flags.setAllowContract(false);
2865 R = DAG.getNode(ISD::FMUL, DL, VT, Y, C, Flags);
2866 SDValue NegR = DAG.getNode(ISD::FNEG, DL, VT, R, Flags);
2867 SDValue FMA0 = DAG.getNode(ISD::FMA, DL, VT, Y, C, NegR, Flags);
2868 SDValue FMA1 = DAG.getNode(ISD::FMA, DL, VT, Y, CC, FMA0, Flags);
2869 R = DAG.getNode(ISD::FADD, DL, VT, R, FMA1, Flags);
2870 } else {
2871 // ch+ct is ln(2)/ln(10) to more than 36 bits
2872 const float ch_log10 = 0x1.344000p-2f;
2873 const float ct_log10 = 0x1.3509f6p-18f;
2874
2875 // ch + ct is ln(2) to more than 36 bits
2876 const float ch_log = 0x1.62e000p-1f;
2877 const float ct_log = 0x1.0bfbe8p-15f;
2878
2879 SDValue CH = DAG.getConstantFP(IsLog10 ? ch_log10 : ch_log, DL, VT);
2880 SDValue CT = DAG.getConstantFP(IsLog10 ? ct_log10 : ct_log, DL, VT);
2881
2882 SDValue YAsInt = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Y);
2883 SDValue MaskConst = DAG.getConstant(0xfffff000, DL, MVT::i32);
2884 SDValue YHInt = DAG.getNode(ISD::AND, DL, MVT::i32, YAsInt, MaskConst);
2885 SDValue YH = DAG.getNode(ISD::BITCAST, DL, MVT::f32, YHInt);
2886 SDValue YT = DAG.getNode(ISD::FSUB, DL, VT, Y, YH, Flags);
2887 // This adds correction terms for which contraction may lead to an increase
2888 // in the error of the approximation, so disable it.
2889 Flags.setAllowContract(false);
2890 SDValue YTCT = DAG.getNode(ISD::FMUL, DL, VT, YT, CT, Flags);
2891 SDValue Mad0 = getMad(DAG, DL, VT, YH, CT, YTCT, Flags);
2892 SDValue Mad1 = getMad(DAG, DL, VT, YT, CH, Mad0, Flags);
2893 R = getMad(DAG, DL, VT, YH, CH, Mad1);
2894 }
2895
2896 const bool IsFiniteOnly = Flags.hasNoNaNs() && Flags.hasNoInfs();
2897
2898 // TODO: Check if known finite from source value.
2899 if (!IsFiniteOnly) {
2900 SDValue IsFinite = getIsFinite(DAG, Y, Flags);
2901 R = DAG.getNode(ISD::SELECT, DL, VT, IsFinite, R, Y, Flags);
2902 }
2903
2904 if (IsScaled) {
2905 SDValue Zero = DAG.getConstantFP(0.0f, DL, VT);
2906 SDValue ShiftK =
2907 DAG.getConstantFP(IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f, DL, VT);
2908 SDValue Shift =
2909 DAG.getNode(ISD::SELECT, DL, VT, IsScaled, ShiftK, Zero, Flags);
2910 R = DAG.getNode(ISD::FSUB, DL, VT, R, Shift, Flags);
2911 }
2912
2913 return R;
2914}
2915
2919
2920// Do f32 fast math expansion for flog2 or flog10. This is accurate enough for a
2921// promote f16 operation.
2923 SelectionDAG &DAG, bool IsLog10,
2924 SDNodeFlags Flags) const {
2925 EVT VT = Src.getValueType();
2926 unsigned LogOp =
2927 VT == MVT::f32 ? (unsigned)AMDGPUISD::LOG : (unsigned)ISD::FLOG2;
2928
2929 double Log2BaseInverted =
2931
2932 if (VT == MVT::f32) {
2933 auto [ScaledInput, IsScaled] = getScaledLogInput(DAG, SL, Src, Flags);
2934 if (ScaledInput) {
2935 SDValue LogSrc = DAG.getNode(AMDGPUISD::LOG, SL, VT, ScaledInput, Flags);
2936 SDValue ScaledResultOffset =
2937 DAG.getConstantFP(-32.0 * Log2BaseInverted, SL, VT);
2938
2939 SDValue Zero = DAG.getConstantFP(0.0f, SL, VT);
2940
2941 SDValue ResultOffset = DAG.getNode(ISD::SELECT, SL, VT, IsScaled,
2942 ScaledResultOffset, Zero, Flags);
2943
2944 SDValue Log2Inv = DAG.getConstantFP(Log2BaseInverted, SL, VT);
2945
2946 if (Subtarget->hasFastFMAF32())
2947 return DAG.getNode(ISD::FMA, SL, VT, LogSrc, Log2Inv, ResultOffset,
2948 Flags);
2949 SDValue Mul = DAG.getNode(ISD::FMUL, SL, VT, LogSrc, Log2Inv, Flags);
2950 return DAG.getNode(ISD::FADD, SL, VT, Mul, ResultOffset);
2951 }
2952 }
2953
2954 SDValue Log2Operand = DAG.getNode(LogOp, SL, VT, Src, Flags);
2955 SDValue Log2BaseInvertedOperand = DAG.getConstantFP(Log2BaseInverted, SL, VT);
2956
2957 return DAG.getNode(ISD::FMUL, SL, VT, Log2Operand, Log2BaseInvertedOperand,
2958 Flags);
2959}
2960
2961// This expansion gives a result slightly better than 1ulp.
2963 SelectionDAG &DAG) const {
2964 SDLoc DL(Op);
2965 SDValue X = Op.getOperand(0);
2966
2967 // TODO: Check if reassoc is safe. There is an output change in exp2 and
2968 // exp10, which slightly increases ulp.
2969 SDNodeFlags Flags = Op->getFlags() & ~SDNodeFlags::AllowReassociation;
2970
2971 SDValue DN, F, T;
2972
2973 if (Op.getOpcode() == ISD::FEXP2) {
2974 // dn = rint(x)
2975 DN = DAG.getNode(ISD::FRINT, DL, MVT::f64, X, Flags);
2976 // f = x - dn
2977 F = DAG.getNode(ISD::FSUB, DL, MVT::f64, X, DN, Flags);
2978 // t = f*C1 + f*C2
2979 SDValue C1 = DAG.getConstantFP(0x1.62e42fefa39efp-1, DL, MVT::f64);
2980 SDValue C2 = DAG.getConstantFP(0x1.abc9e3b39803fp-56, DL, MVT::f64);
2981 SDValue Mul2 = DAG.getNode(ISD::FMUL, DL, MVT::f64, F, C2, Flags);
2982 T = DAG.getNode(ISD::FMA, DL, MVT::f64, F, C1, Mul2, Flags);
2983 } else if (Op.getOpcode() == ISD::FEXP10) {
2984 // dn = rint(x * C1)
2985 SDValue C1 = DAG.getConstantFP(0x1.a934f0979a371p+1, DL, MVT::f64);
2986 SDValue Mul = DAG.getNode(ISD::FMUL, DL, MVT::f64, X, C1, Flags);
2987 DN = DAG.getNode(ISD::FRINT, DL, MVT::f64, Mul, Flags);
2988
2989 // f = FMA(-dn, C2, FMA(-dn, C3, x))
2990 SDValue NegDN = DAG.getNode(ISD::FNEG, DL, MVT::f64, DN, Flags);
2991 SDValue C2 = DAG.getConstantFP(-0x1.9dc1da994fd21p-59, DL, MVT::f64);
2992 SDValue C3 = DAG.getConstantFP(0x1.34413509f79ffp-2, DL, MVT::f64);
2993 SDValue Inner = DAG.getNode(ISD::FMA, DL, MVT::f64, NegDN, C3, X, Flags);
2994 F = DAG.getNode(ISD::FMA, DL, MVT::f64, NegDN, C2, Inner, Flags);
2995
2996 // t = FMA(f, C4, f*C5)
2997 SDValue C4 = DAG.getConstantFP(0x1.26bb1bbb55516p+1, DL, MVT::f64);
2998 SDValue C5 = DAG.getConstantFP(-0x1.f48ad494ea3e9p-53, DL, MVT::f64);
2999 SDValue MulF = DAG.getNode(ISD::FMUL, DL, MVT::f64, F, C5, Flags);
3000 T = DAG.getNode(ISD::FMA, DL, MVT::f64, F, C4, MulF, Flags);
3001 } else { // ISD::FEXP
3002 // dn = rint(x * C1)
3003 SDValue C1 = DAG.getConstantFP(0x1.71547652b82fep+0, DL, MVT::f64);
3004 SDValue Mul = DAG.getNode(ISD::FMUL, DL, MVT::f64, X, C1, Flags);
3005 DN = DAG.getNode(ISD::FRINT, DL, MVT::f64, Mul, Flags);
3006
3007 // t = FMA(-dn, C2, FMA(-dn, C3, x))
3008 SDValue NegDN = DAG.getNode(ISD::FNEG, DL, MVT::f64, DN, Flags);
3009 SDValue C2 = DAG.getConstantFP(0x1.abc9e3b39803fp-56, DL, MVT::f64);
3010 SDValue C3 = DAG.getConstantFP(0x1.62e42fefa39efp-1, DL, MVT::f64);
3011 SDValue Inner = DAG.getNode(ISD::FMA, DL, MVT::f64, NegDN, C3, X, Flags);
3012 T = DAG.getNode(ISD::FMA, DL, MVT::f64, NegDN, C2, Inner, Flags);
3013 }
3014
3015 // Polynomial expansion for p
3016 SDValue P = DAG.getConstantFP(0x1.ade156a5dcb37p-26, DL, MVT::f64);
3017 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
3018 DAG.getConstantFP(0x1.28af3fca7ab0cp-22, DL, MVT::f64),
3019 Flags);
3020 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
3021 DAG.getConstantFP(0x1.71dee623fde64p-19, DL, MVT::f64),
3022 Flags);
3023 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
3024 DAG.getConstantFP(0x1.a01997c89e6b0p-16, DL, MVT::f64),
3025 Flags);
3026 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
3027 DAG.getConstantFP(0x1.a01a014761f6ep-13, DL, MVT::f64),
3028 Flags);
3029 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
3030 DAG.getConstantFP(0x1.6c16c1852b7b0p-10, DL, MVT::f64),
3031 Flags);
3032 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
3033 DAG.getConstantFP(0x1.1111111122322p-7, DL, MVT::f64), Flags);
3034 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
3035 DAG.getConstantFP(0x1.55555555502a1p-5, DL, MVT::f64), Flags);
3036 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
3037 DAG.getConstantFP(0x1.5555555555511p-3, DL, MVT::f64), Flags);
3038 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
3039 DAG.getConstantFP(0x1.000000000000bp-1, DL, MVT::f64), Flags);
3040
3041 SDValue One = DAG.getConstantFP(1.0, DL, MVT::f64);
3042
3043 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P, One, Flags);
3044 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P, One, Flags);
3045
3046 // z = ldexp(p, (int)dn)
3047 SDValue DNInt = DAG.getNode(ISD::FP_TO_SINT, DL, MVT::i32, DN);
3048 SDValue Z = DAG.getNode(ISD::FLDEXP, DL, MVT::f64, P, DNInt, Flags);
3049
3050 // Overflow/underflow guards
3051 SDValue CondHi = DAG.getSetCC(
3052 DL, MVT::i1, X, DAG.getConstantFP(1024.0, DL, MVT::f64), ISD::SETULE);
3053
3054 if (!Flags.hasNoInfs()) {
3055 SDValue PInf = DAG.getConstantFP(std::numeric_limits<double>::infinity(),
3056 DL, MVT::f64);
3057 Z = DAG.getSelect(DL, MVT::f64, CondHi, Z, PInf, Flags);
3058 }
3059
3060 SDValue CondLo = DAG.getSetCC(
3061 DL, MVT::i1, X, DAG.getConstantFP(-1075.0, DL, MVT::f64), ISD::SETUGE);
3062 SDValue Zero = DAG.getConstantFP(0.0, DL, MVT::f64);
3063 Z = DAG.getSelect(DL, MVT::f64, CondLo, Z, Zero, Flags);
3064
3065 return Z;
3066}
3067
3069 // v_exp_f32 is good enough for OpenCL, except it doesn't handle denormals.
3070 // If we have to handle denormals, scale up the input and adjust the result.
3071
3072 EVT VT = Op.getValueType();
3073 if (VT == MVT::f64)
3074 return lowerFEXPF64(Op, DAG);
3075
3076 SDLoc SL(Op);
3077 SDValue Src = Op.getOperand(0);
3078 SDNodeFlags Flags = Op->getFlags();
3079
3080 if (VT == MVT::f16) {
3081 // Nothing in half is a denormal when promoted to f32.
3082 assert(!isTypeLegal(MVT::f16));
3083 SDValue Ext = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Src, Flags);
3084 SDValue Log = DAG.getNode(AMDGPUISD::EXP, SL, MVT::f32, Ext, Flags);
3085 return DAG.getNode(ISD::FP_ROUND, SL, VT, Log,
3086 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
3087 }
3088
3089 assert(VT == MVT::f32);
3090
3091 if (!needsDenormHandlingF32(DAG, Src, Flags))
3092 return DAG.getNode(AMDGPUISD::EXP, SL, MVT::f32, Src, Flags);
3093
3094 // bool needs_scaling = x < -0x1.f80000p+6f;
3095 // v_exp_f32(x + (s ? 0x1.0p+6f : 0.0f)) * (s ? 0x1.0p-64f : 1.0f);
3096
3097 // -nextafter(128.0, -1)
3098 SDValue RangeCheckConst = DAG.getConstantFP(-0x1.f80000p+6f, SL, VT);
3099
3100 EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
3101
3102 SDValue NeedsScaling =
3103 DAG.getSetCC(SL, SetCCVT, Src, RangeCheckConst, ISD::SETOLT);
3104
3105 SDValue SixtyFour = DAG.getConstantFP(0x1.0p+6f, SL, VT);
3106 SDValue Zero = DAG.getConstantFP(0.0, SL, VT);
3107
3108 SDValue AddOffset =
3109 DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, SixtyFour, Zero);
3110
3111 SDValue AddInput = DAG.getNode(ISD::FADD, SL, VT, Src, AddOffset, Flags);
3112 SDValue Exp2 = DAG.getNode(AMDGPUISD::EXP, SL, VT, AddInput, Flags);
3113
3114 SDValue TwoExpNeg64 = DAG.getConstantFP(0x1.0p-64f, SL, VT);
3115 SDValue One = DAG.getConstantFP(1.0, SL, VT);
3116 SDValue ResultScale =
3117 DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, TwoExpNeg64, One);
3118
3119 return DAG.getNode(ISD::FMUL, SL, VT, Exp2, ResultScale, Flags);
3120}
3121
3123 SelectionDAG &DAG,
3124 SDNodeFlags Flags,
3125 bool IsExp10) const {
3126 // exp(x) -> exp2(M_LOG2E_F * x);
3127 // exp10(x) -> exp2(log2(10) * x);
3128 EVT VT = X.getValueType();
3129 SDValue Const =
3130 DAG.getConstantFP(IsExp10 ? 0x1.a934f0p+1f : numbers::log2e, SL, VT);
3131
3132 SDValue Mul = DAG.getNode(ISD::FMUL, SL, VT, X, Const, Flags);
3133 return DAG.getNode(VT == MVT::f32 ? (unsigned)AMDGPUISD::EXP
3134 : (unsigned)ISD::FEXP2,
3135 SL, VT, Mul, Flags);
3136}
3137
3139 SelectionDAG &DAG,
3140 SDNodeFlags Flags) const {
3141 EVT VT = X.getValueType();
3142 if (VT != MVT::f32 || !needsDenormHandlingF32(DAG, X, Flags))
3143 return lowerFEXPUnsafeImpl(X, SL, DAG, Flags, /*IsExp10=*/false);
3144
3145 EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
3146
3147 SDValue Threshold = DAG.getConstantFP(-0x1.5d58a0p+6f, SL, VT);
3148 SDValue NeedsScaling = DAG.getSetCC(SL, SetCCVT, X, Threshold, ISD::SETOLT);
3149
3150 SDValue ScaleOffset = DAG.getConstantFP(0x1.0p+6f, SL, VT);
3151
3152 SDValue ScaledX = DAG.getNode(ISD::FADD, SL, VT, X, ScaleOffset, Flags);
3153
3154 SDValue AdjustedX =
3155 DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, ScaledX, X);
3156
3157 const SDValue Log2E = DAG.getConstantFP(numbers::log2e, SL, VT);
3158 SDValue ExpInput = DAG.getNode(ISD::FMUL, SL, VT, AdjustedX, Log2E, Flags);
3159
3160 SDValue Exp2 = DAG.getNode(AMDGPUISD::EXP, SL, VT, ExpInput, Flags);
3161
3162 SDValue ResultScaleFactor = DAG.getConstantFP(0x1.969d48p-93f, SL, VT);
3163 SDValue AdjustedResult =
3164 DAG.getNode(ISD::FMUL, SL, VT, Exp2, ResultScaleFactor, Flags);
3165
3166 return DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, AdjustedResult, Exp2,
3167 Flags);
3168}
3169
3170/// Emit approx-funcs appropriate lowering for exp10. inf/nan should still be
3171/// handled correctly.
3173 SelectionDAG &DAG,
3174 SDNodeFlags Flags) const {
3175 const EVT VT = X.getValueType();
3176
3177 const unsigned Exp2Op = VT == MVT::f32 ? static_cast<unsigned>(AMDGPUISD::EXP)
3178 : static_cast<unsigned>(ISD::FEXP2);
3179
3180 if (VT != MVT::f32 || !needsDenormHandlingF32(DAG, X, Flags)) {
3181 // exp2(x * 0x1.a92000p+1f) * exp2(x * 0x1.4f0978p-11f);
3182 SDValue K0 = DAG.getConstantFP(0x1.a92000p+1f, SL, VT);
3183 SDValue K1 = DAG.getConstantFP(0x1.4f0978p-11f, SL, VT);
3184
3185 SDValue Mul0 = DAG.getNode(ISD::FMUL, SL, VT, X, K0, Flags);
3186 SDValue Exp2_0 = DAG.getNode(Exp2Op, SL, VT, Mul0, Flags);
3187 SDValue Mul1 = DAG.getNode(ISD::FMUL, SL, VT, X, K1, Flags);
3188 SDValue Exp2_1 = DAG.getNode(Exp2Op, SL, VT, Mul1, Flags);
3189 return DAG.getNode(ISD::FMUL, SL, VT, Exp2_0, Exp2_1);
3190 }
3191
3192 // bool s = x < -0x1.2f7030p+5f;
3193 // x += s ? 0x1.0p+5f : 0.0f;
3194 // exp10 = exp2(x * 0x1.a92000p+1f) *
3195 // exp2(x * 0x1.4f0978p-11f) *
3196 // (s ? 0x1.9f623ep-107f : 1.0f);
3197
3198 EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
3199
3200 SDValue Threshold = DAG.getConstantFP(-0x1.2f7030p+5f, SL, VT);
3201 SDValue NeedsScaling = DAG.getSetCC(SL, SetCCVT, X, Threshold, ISD::SETOLT);
3202
3203 SDValue ScaleOffset = DAG.getConstantFP(0x1.0p+5f, SL, VT);
3204 SDValue ScaledX = DAG.getNode(ISD::FADD, SL, VT, X, ScaleOffset, Flags);
3205 SDValue AdjustedX =
3206 DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, ScaledX, X);
3207
3208 SDValue K0 = DAG.getConstantFP(0x1.a92000p+1f, SL, VT);
3209 SDValue K1 = DAG.getConstantFP(0x1.4f0978p-11f, SL, VT);
3210
3211 SDValue Mul0 = DAG.getNode(ISD::FMUL, SL, VT, AdjustedX, K0, Flags);
3212 SDValue Exp2_0 = DAG.getNode(Exp2Op, SL, VT, Mul0, Flags);
3213 SDValue Mul1 = DAG.getNode(ISD::FMUL, SL, VT, AdjustedX, K1, Flags);
3214 SDValue Exp2_1 = DAG.getNode(Exp2Op, SL, VT, Mul1, Flags);
3215
3216 SDValue MulExps = DAG.getNode(ISD::FMUL, SL, VT, Exp2_0, Exp2_1, Flags);
3217
3218 SDValue ResultScaleFactor = DAG.getConstantFP(0x1.9f623ep-107f, SL, VT);
3219 SDValue AdjustedResult =
3220 DAG.getNode(ISD::FMUL, SL, VT, MulExps, ResultScaleFactor, Flags);
3221
3222 return DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, AdjustedResult, MulExps,
3223 Flags);
3224}
3225
3227 EVT VT = Op.getValueType();
3228
3229 if (VT == MVT::f64)
3230 return lowerFEXPF64(Op, DAG);
3231
3232 SDLoc SL(Op);
3233 SDValue X = Op.getOperand(0);
3234 SDNodeFlags Flags = Op->getFlags();
3235 const bool IsExp10 = Op.getOpcode() == ISD::FEXP10;
3236
3237 // TODO: Interpret allowApproxFunc as ignoring DAZ. This is currently copying
3238 // library behavior. Also, is known-not-daz source sufficient?
3239 if (allowApproxFunc(DAG, Flags)) { // TODO: Does this really require fast?
3240 return IsExp10 ? lowerFEXP10Unsafe(X, SL, DAG, Flags)
3241 : lowerFEXPUnsafe(X, SL, DAG, Flags);
3242 }
3243
3244 if (VT.getScalarType() == MVT::f16) {
3245 if (VT.isVector())
3246 return SDValue();
3247
3248 // Nothing in half is a denormal when promoted to f32.
3249 //
3250 // exp(f16 x) ->
3251 // fptrunc (v_exp_f32 (fmul (fpext x), log2e))
3252 //
3253 // exp10(f16 x) ->
3254 // fptrunc (v_exp_f32 (fmul (fpext x), log2(10)))
3255 SDValue Ext = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, X, Flags);
3256 SDValue Lowered = lowerFEXPUnsafeImpl(Ext, SL, DAG, Flags, IsExp10);
3257 return DAG.getNode(ISD::FP_ROUND, SL, VT, Lowered,
3258 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
3259 }
3260
3261 assert(VT == MVT::f32);
3262
3263 // Algorithm:
3264 //
3265 // e^x = 2^(x/ln(2)) = 2^(x*(64/ln(2))/64)
3266 //
3267 // x*(64/ln(2)) = n + f, |f| <= 0.5, n is integer
3268 // n = 64*m + j, 0 <= j < 64
3269 //
3270 // e^x = 2^((64*m + j + f)/64)
3271 // = (2^m) * (2^(j/64)) * 2^(f/64)
3272 // = (2^m) * (2^(j/64)) * e^(f*(ln(2)/64))
3273 //
3274 // f = x*(64/ln(2)) - n
3275 // r = f*(ln(2)/64) = x - n*(ln(2)/64)
3276 //
3277 // e^x = (2^m) * (2^(j/64)) * e^r
3278 //
3279 // (2^(j/64)) is precomputed
3280 //
3281 // e^r = 1 + r + (r^2)/2! + (r^3)/3! + (r^4)/4! + (r^5)/5!
3282 // e^r = 1 + q
3283 //
3284 // q = r + (r^2)/2! + (r^3)/3! + (r^4)/4! + (r^5)/5!
3285 //
3286 // e^x = (2^m) * ( (2^(j/64)) + q*(2^(j/64)) )
3287 SDNodeFlags FlagsNoContract = Flags;
3288 FlagsNoContract.setAllowContract(false);
3289
3290 SDValue PH, PL;
3291 if (Subtarget->hasFastFMAF32()) {
3292 const float c_exp = numbers::log2ef;
3293 const float cc_exp = 0x1.4ae0bep-26f; // c+cc are 49 bits
3294 const float c_exp10 = 0x1.a934f0p+1f;
3295 const float cc_exp10 = 0x1.2f346ep-24f;
3296
3297 SDValue C = DAG.getConstantFP(IsExp10 ? c_exp10 : c_exp, SL, VT);
3298 SDValue CC = DAG.getConstantFP(IsExp10 ? cc_exp10 : cc_exp, SL, VT);
3299
3300 PH = DAG.getNode(ISD::FMUL, SL, VT, X, C, Flags);
3301 SDValue NegPH = DAG.getNode(ISD::FNEG, SL, VT, PH, Flags);
3302 SDValue FMA0 = DAG.getNode(ISD::FMA, SL, VT, X, C, NegPH, Flags);
3303 PL = DAG.getNode(ISD::FMA, SL, VT, X, CC, FMA0, Flags);
3304 } else {
3305 const float ch_exp = 0x1.714000p+0f;
3306 const float cl_exp = 0x1.47652ap-12f; // ch + cl are 36 bits
3307
3308 const float ch_exp10 = 0x1.a92000p+1f;
3309 const float cl_exp10 = 0x1.4f0978p-11f;
3310
3311 SDValue CH = DAG.getConstantFP(IsExp10 ? ch_exp10 : ch_exp, SL, VT);
3312 SDValue CL = DAG.getConstantFP(IsExp10 ? cl_exp10 : cl_exp, SL, VT);
3313
3314 SDValue XAsInt = DAG.getNode(ISD::BITCAST, SL, MVT::i32, X);
3315 SDValue MaskConst = DAG.getConstant(0xfffff000, SL, MVT::i32);
3316 SDValue XHAsInt = DAG.getNode(ISD::AND, SL, MVT::i32, XAsInt, MaskConst);
3317 SDValue XH = DAG.getNode(ISD::BITCAST, SL, VT, XHAsInt);
3318 SDValue XL = DAG.getNode(ISD::FSUB, SL, VT, X, XH, Flags);
3319
3320 PH = DAG.getNode(ISD::FMUL, SL, VT, XH, CH, Flags);
3321
3322 SDValue XLCL = DAG.getNode(ISD::FMUL, SL, VT, XL, CL, Flags);
3323 SDValue Mad0 = getMad(DAG, SL, VT, XL, CH, XLCL, Flags);
3324 PL = getMad(DAG, SL, VT, XH, CL, Mad0, Flags);
3325 }
3326
3327 SDValue E = DAG.getNode(ISD::FROUNDEVEN, SL, VT, PH, Flags);
3328
3329 // It is unsafe to contract this fsub into the PH multiply.
3330 SDValue PHSubE = DAG.getNode(ISD::FSUB, SL, VT, PH, E, FlagsNoContract);
3331
3332 SDValue A = DAG.getNode(ISD::FADD, SL, VT, PHSubE, PL, Flags);
3333 SDValue IntE = DAG.getNode(ISD::FP_TO_SINT, SL, MVT::i32, E);
3334 SDValue Exp2 = DAG.getNode(AMDGPUISD::EXP, SL, VT, A, Flags);
3335
3336 SDValue R = DAG.getNode(ISD::FLDEXP, SL, VT, Exp2, IntE, Flags);
3337
3338 SDValue UnderflowCheckConst =
3339 DAG.getConstantFP(IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f, SL, VT);
3340
3341 EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
3342 SDValue Zero = DAG.getConstantFP(0.0, SL, VT);
3343 SDValue Underflow =
3344 DAG.getSetCC(SL, SetCCVT, X, UnderflowCheckConst, ISD::SETOLT);
3345
3346 R = DAG.getNode(ISD::SELECT, SL, VT, Underflow, Zero, R);
3347
3348 if (!Flags.hasNoInfs()) {
3349 SDValue OverflowCheckConst =
3350 DAG.getConstantFP(IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f, SL, VT);
3351 SDValue Overflow =
3352 DAG.getSetCC(SL, SetCCVT, X, OverflowCheckConst, ISD::SETOGT);
3353 SDValue Inf =
3355 R = DAG.getNode(ISD::SELECT, SL, VT, Overflow, Inf, R);
3356 }
3357
3358 return R;
3359}
3360
3361static bool isCtlzOpc(unsigned Opc) {
3362 return Opc == ISD::CTLZ || Opc == ISD::CTLZ_ZERO_POISON;
3363}
3364
3365static bool isCttzOpc(unsigned Opc) {
3366 return Opc == ISD::CTTZ || Opc == ISD::CTTZ_ZERO_POISON;
3367}
3368
3370 SelectionDAG &DAG) const {
3371 auto SL = SDLoc(Op);
3372 auto Opc = Op.getOpcode();
3373 auto Arg = Op.getOperand(0u);
3374 auto ResultVT = Op.getValueType();
3375
3376 if (ResultVT != MVT::i8 && ResultVT != MVT::i16)
3377 return {};
3378
3380 assert(ResultVT == Arg.getValueType());
3381
3382 const uint64_t NumBits = ResultVT.getFixedSizeInBits();
3383 SDValue NumExtBits = DAG.getConstant(32u - NumBits, SL, MVT::i32);
3384 SDValue NewOp;
3385
3386 if (Opc == ISD::CTLZ_ZERO_POISON) {
3387 NewOp = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Arg);
3388 NewOp = DAG.getNode(ISD::SHL, SL, MVT::i32, NewOp, NumExtBits);
3389 NewOp = DAG.getNode(Opc, SL, MVT::i32, NewOp);
3390 } else {
3391 NewOp = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Arg);
3392 NewOp = DAG.getNode(Opc, SL, MVT::i32, NewOp);
3393 NewOp = DAG.getNode(ISD::SUB, SL, MVT::i32, NewOp, NumExtBits);
3394 }
3395
3396 return DAG.getNode(ISD::TRUNCATE, SL, ResultVT, NewOp);
3397}
3398
3400 SDLoc SL(Op);
3401 SDValue Src = Op.getOperand(0);
3402
3403 assert(isCtlzOpc(Op.getOpcode()) || isCttzOpc(Op.getOpcode()));
3404 bool Ctlz = isCtlzOpc(Op.getOpcode());
3405 unsigned NewOpc = Ctlz ? AMDGPUISD::FFBH_U32 : AMDGPUISD::FFBL_B32;
3406
3407 bool ZeroUndef = Op.getOpcode() == ISD::CTLZ_ZERO_POISON ||
3408 Op.getOpcode() == ISD::CTTZ_ZERO_POISON;
3409 bool Is64BitScalar = !Src->isDivergent() && Src.getValueType() == MVT::i64;
3410
3411 if (Src.getValueType() == MVT::i32 || Is64BitScalar) {
3412 // (ctlz hi:lo) -> (umin (ffbh src), 32)
3413 // (cttz hi:lo) -> (umin (ffbl src), 32)
3414 // (ctlz_zero_poison src) -> (ffbh src)
3415 // (cttz_zero_poison src) -> (ffbl src)
3416
3417 // 64-bit scalar version produce 32-bit result
3418 // (ctlz hi:lo) -> (umin (S_FLBIT_I32_B64 src), 64)
3419 // (cttz hi:lo) -> (umin (S_FF1_I32_B64 src), 64)
3420 // (ctlz_zero_poison src) -> (S_FLBIT_I32_B64 src)
3421 // (cttz_zero_poison src) -> (S_FF1_I32_B64 src)
3422 SDValue NewOpr = DAG.getNode(NewOpc, SL, MVT::i32, Src);
3423 if (!ZeroUndef) {
3424 const SDValue ConstVal = DAG.getConstant(
3425 Op.getValueType().getScalarSizeInBits(), SL, MVT::i32);
3426 NewOpr = DAG.getNode(ISD::UMIN, SL, MVT::i32, NewOpr, ConstVal);
3427 }
3428 return DAG.getNode(ISD::ZERO_EXTEND, SL, Src.getValueType(), NewOpr);
3429 }
3430
3431 SDValue Lo, Hi;
3432 std::tie(Lo, Hi) = split64BitValue(Src, DAG);
3433
3434 SDValue OprLo = DAG.getNode(NewOpc, SL, MVT::i32, Lo);
3435 SDValue OprHi = DAG.getNode(NewOpc, SL, MVT::i32, Hi);
3436
3437 // (ctlz hi:lo) -> (umin3 (ffbh hi), (uaddsat (ffbh lo), 32), 64)
3438 // (cttz hi:lo) -> (umin3 (uaddsat (ffbl hi), 32), (ffbl lo), 64)
3439 // (ctlz_zero_poison hi:lo) -> (umin (ffbh hi), (add (ffbh lo), 32))
3440 // (cttz_zero_poison hi:lo) -> (umin (add (ffbl hi), 32), (ffbl lo))
3441
3442 unsigned AddOpc = ZeroUndef ? ISD::ADD : ISD::UADDSAT;
3443 const SDValue Const32 = DAG.getConstant(32, SL, MVT::i32);
3444 if (Ctlz)
3445 OprLo = DAG.getNode(AddOpc, SL, MVT::i32, OprLo, Const32);
3446 else
3447 OprHi = DAG.getNode(AddOpc, SL, MVT::i32, OprHi, Const32);
3448
3449 SDValue NewOpr;
3450 NewOpr = DAG.getNode(ISD::UMIN, SL, MVT::i32, OprLo, OprHi);
3451 if (!ZeroUndef) {
3452 const SDValue Const64 = DAG.getConstant(64, SL, MVT::i32);
3453 NewOpr = DAG.getNode(ISD::UMIN, SL, MVT::i32, NewOpr, Const64);
3454 }
3455
3456 return DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i64, NewOpr);
3457}
3458
3460 SDLoc SL(Op);
3461 SDValue Src = Op.getOperand(0);
3462 assert(Src.getValueType() == MVT::i32 && "LowerCTLS only supports i32");
3463 SDValue Ffbh = DAG.getNode(
3464 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
3465 DAG.getTargetConstant(Intrinsic::amdgcn_sffbh, SL, MVT::i32), Src);
3466 SDValue Clamped = DAG.getNode(ISD::UMIN, SL, MVT::i32, Ffbh,
3467 DAG.getConstant(32, SL, MVT::i32));
3468 return DAG.getNode(ISD::ADD, SL, MVT::i32, Clamped,
3469 DAG.getAllOnesConstant(SL, MVT::i32));
3470}
3471
3473 EVT FP16Ty) const {
3474 assert(FP16Ty == MVT::f16 || FP16Ty == MVT::bf16);
3475 SDLoc SL(Op);
3476 SDValue Src = Op.getOperand(0);
3477 SDValue ToF32 = DAG.getNode(Op.getOpcode(), SL, MVT::f32, Src);
3478 SDValue FPRoundFlag = DAG.getIntPtrConstant(0, SL, /*isTarget=*/true);
3479 return DAG.getNode(ISD::FP_ROUND, SL, FP16Ty, ToF32, FPRoundFlag);
3480}
3481
3483 bool Signed) const {
3484 // The regular method converting a 64-bit integer to float roughly consists of
3485 // 2 steps: normalization and rounding. In fact, after normalization, the
3486 // conversion from a 64-bit integer to a float is essentially the same as the
3487 // one from a 32-bit integer. The only difference is that it has more
3488 // trailing bits to be rounded. To leverage the native 32-bit conversion, a
3489 // 64-bit integer could be preprocessed and fit into a 32-bit integer then
3490 // converted into the correct float number. The basic steps for the unsigned
3491 // conversion are illustrated in the following pseudo code:
3492 //
3493 // f32 uitofp(i64 u) {
3494 // i32 hi, lo = split(u);
3495 // // Only count the leading zeros in hi as we have native support of the
3496 // // conversion from i32 to f32. If hi is all 0s, the conversion is
3497 // // reduced to a 32-bit one automatically.
3498 // i32 shamt = clz(hi); // Return 32 if hi is all 0s.
3499 // u <<= shamt;
3500 // hi, lo = split(u);
3501 // hi |= (lo != 0) ? 1 : 0; // Adjust rounding bit in hi based on lo.
3502 // // convert it as a 32-bit integer and scale the result back.
3503 // return uitofp(hi) * 2^(32 - shamt);
3504 // }
3505 //
3506 // The signed one follows the same principle but uses 'ffbh_i32' to count its
3507 // sign bits instead. If 'ffbh_i32' is not available, its absolute value is
3508 // converted instead followed by negation based its sign bit.
3509
3510 SDLoc SL(Op);
3511 SDValue Src = Op.getOperand(0);
3512
3513 SDValue Lo, Hi;
3514 std::tie(Lo, Hi) = split64BitValue(Src, DAG);
3515 SDValue Sign;
3516 SDValue ShAmt;
3517 if (Signed && Subtarget->isGCN()) {
3518 // We also need to consider the sign bit in Lo if Hi has just sign bits,
3519 // i.e. Hi is 0 or -1. However, that only needs to take the MSB into
3520 // account. That is, the maximal shift is
3521 // - 32 if Lo and Hi have opposite signs;
3522 // - 33 if Lo and Hi have the same sign.
3523 //
3524 // Or, MaxShAmt = 33 + OppositeSign, where
3525 //
3526 // OppositeSign is defined as ((Lo ^ Hi) >> 31), which is
3527 // - -1 if Lo and Hi have opposite signs; and
3528 // - 0 otherwise.
3529 //
3530 // All in all, ShAmt is calculated as
3531 //
3532 // umin(sffbh(Hi), 33 + (Lo^Hi)>>31) - 1.
3533 //
3534 // or
3535 //
3536 // umin(sffbh(Hi) - 1, 32 + (Lo^Hi)>>31).
3537 //
3538 // to reduce the critical path.
3539 SDValue OppositeSign = DAG.getNode(
3540 ISD::SRA, SL, MVT::i32, DAG.getNode(ISD::XOR, SL, MVT::i32, Lo, Hi),
3541 DAG.getConstant(31, SL, MVT::i32));
3542 SDValue MaxShAmt =
3543 DAG.getNode(ISD::ADD, SL, MVT::i32, DAG.getConstant(32, SL, MVT::i32),
3544 OppositeSign);
3545 // Count the leading sign bits.
3546 ShAmt = DAG.getNode(
3547 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
3548 DAG.getTargetConstant(Intrinsic::amdgcn_sffbh, SL, MVT::i32), Hi);
3549 // Different from unsigned conversion, the shift should be one bit less to
3550 // preserve the sign bit.
3551 ShAmt = DAG.getNode(ISD::SUB, SL, MVT::i32, ShAmt,
3552 DAG.getConstant(1, SL, MVT::i32));
3553 ShAmt = DAG.getNode(ISD::UMIN, SL, MVT::i32, ShAmt, MaxShAmt);
3554 } else {
3555 if (Signed) {
3556 // Without 'ffbh_i32', only leading zeros could be counted. Take the
3557 // absolute value first.
3558 Sign = DAG.getNode(ISD::SRA, SL, MVT::i64, Src,
3559 DAG.getConstant(63, SL, MVT::i64));
3560 SDValue Abs =
3561 DAG.getNode(ISD::XOR, SL, MVT::i64,
3562 DAG.getNode(ISD::ADD, SL, MVT::i64, Src, Sign), Sign);
3563 std::tie(Lo, Hi) = split64BitValue(Abs, DAG);
3564 }
3565 // Count the leading zeros.
3566 ShAmt = DAG.getNode(ISD::CTLZ, SL, MVT::i32, Hi);
3567 // The shift amount for signed integers is [0, 32].
3568 }
3569 // Normalize the given 64-bit integer.
3570 SDValue Norm = DAG.getNode(ISD::SHL, SL, MVT::i64, Src, ShAmt);
3571 // Split it again.
3572 std::tie(Lo, Hi) = split64BitValue(Norm, DAG);
3573 // Calculate the adjust bit for rounding.
3574 // (lo != 0) ? 1 : 0 => (lo >= 1) ? 1 : 0 => umin(1, lo)
3575 SDValue Adjust = DAG.getNode(ISD::UMIN, SL, MVT::i32,
3576 DAG.getConstant(1, SL, MVT::i32), Lo);
3577 // Get the 32-bit normalized integer.
3578 Norm = DAG.getNode(ISD::OR, SL, MVT::i32, Hi, Adjust);
3579 // Convert the normalized 32-bit integer into f32.
3580
3581 bool UseLDEXP = isOperationLegal(ISD::FLDEXP, MVT::f32);
3582 unsigned Opc = Signed && UseLDEXP ? ISD::SINT_TO_FP : ISD::UINT_TO_FP;
3583 SDValue FVal = DAG.getNode(Opc, SL, MVT::f32, Norm);
3584
3585 // Finally, need to scale back the converted floating number as the original
3586 // 64-bit integer is converted as a 32-bit one.
3587 ShAmt = DAG.getNode(ISD::SUB, SL, MVT::i32, DAG.getConstant(32, SL, MVT::i32),
3588 ShAmt);
3589 // On GCN, use LDEXP directly.
3590 if (UseLDEXP)
3591 return DAG.getNode(ISD::FLDEXP, SL, MVT::f32, FVal, ShAmt);
3592
3593 // Otherwise, align 'ShAmt' to the exponent part and add it into the exponent
3594 // part directly to emulate the multiplication of 2^ShAmt. That 8-bit
3595 // exponent is enough to avoid overflowing into the sign bit.
3596 SDValue Exp = DAG.getNode(ISD::SHL, SL, MVT::i32, ShAmt,
3597 DAG.getConstant(23, SL, MVT::i32));
3598 SDValue IVal =
3599 DAG.getNode(ISD::ADD, SL, MVT::i32,
3600 DAG.getNode(ISD::BITCAST, SL, MVT::i32, FVal), Exp);
3601 if (Signed) {
3602 // Set the sign bit.
3603 Sign = DAG.getNode(ISD::SHL, SL, MVT::i32,
3604 DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Sign),
3605 DAG.getConstant(31, SL, MVT::i32));
3606 IVal = DAG.getNode(ISD::OR, SL, MVT::i32, IVal, Sign);
3607 }
3608 return DAG.getNode(ISD::BITCAST, SL, MVT::f32, IVal);
3609}
3610
3612 bool Signed) const {
3613 SDLoc SL(Op);
3614 SDValue Src = Op.getOperand(0);
3615
3616 SDValue Lo, Hi;
3617 std::tie(Lo, Hi) = split64BitValue(Src, DAG);
3618
3620 SL, MVT::f64, Hi);
3621
3622 SDValue CvtLo = DAG.getNode(ISD::UINT_TO_FP, SL, MVT::f64, Lo);
3623
3624 SDValue LdExp = DAG.getNode(ISD::FLDEXP, SL, MVT::f64, CvtHi,
3625 DAG.getConstant(32, SL, MVT::i32));
3626 // TODO: Should this propagate fast-math-flags?
3627 return DAG.getNode(ISD::FADD, SL, MVT::f64, LdExp, CvtLo);
3628}
3629
3631 SelectionDAG &DAG) const {
3632 // TODO: Factor out code common with LowerSINT_TO_FP.
3633 EVT DestVT = Op.getValueType();
3634 SDValue Src = Op.getOperand(0);
3635 EVT SrcVT = Src.getValueType();
3636
3637 if (SrcVT == MVT::i16) {
3638 if (DestVT == MVT::f16)
3639 return Op;
3640 SDLoc DL(Op);
3641
3642 // Promote src to i32
3643 SDValue Ext = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i32, Src);
3644 return DAG.getNode(ISD::UINT_TO_FP, DL, DestVT, Ext);
3645 }
3646
3647 if (DestVT == MVT::bf16 || DestVT == MVT::f16)
3648 return LowerINT_TO_FP16(Op, DAG, DestVT);
3649
3650 if (SrcVT != MVT::i64)
3651 return Op;
3652
3653 if (DestVT == MVT::f32)
3654 return LowerINT_TO_FP32(Op, DAG, false);
3655
3656 assert(DestVT == MVT::f64);
3657 return LowerINT_TO_FP64(Op, DAG, false);
3658}
3659
3661 SelectionDAG &DAG) const {
3662 EVT DestVT = Op.getValueType();
3663
3664 SDValue Src = Op.getOperand(0);
3665 EVT SrcVT = Src.getValueType();
3666
3667 if (SrcVT == MVT::i16) {
3668 if (DestVT == MVT::f16)
3669 return Op;
3670
3671 SDLoc DL(Op);
3672 // Promote src to i32
3673 SDValue Ext = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i32, Src);
3674 return DAG.getNode(ISD::SINT_TO_FP, DL, DestVT, Ext);
3675 }
3676
3677 if (DestVT == MVT::bf16 || DestVT == MVT::f16)
3678 return LowerINT_TO_FP16(Op, DAG, DestVT);
3679
3680 if (SrcVT != MVT::i64)
3681 return Op;
3682
3683 // TODO: Factor out code common with LowerUINT_TO_FP.
3684
3685 if (DestVT == MVT::f32)
3686 return LowerINT_TO_FP32(Op, DAG, true);
3687
3688 assert(DestVT == MVT::f64);
3689 return LowerINT_TO_FP64(Op, DAG, true);
3690}
3691
3693 bool Signed) const {
3694 SDLoc SL(Op);
3695
3696 SDValue Src = Op.getOperand(0);
3697 EVT SrcVT = Src.getValueType();
3698
3699 assert(SrcVT == MVT::f32 || SrcVT == MVT::f64);
3700
3701 // The basic idea of converting a floating point number into a pair of 32-bit
3702 // integers is illustrated as follows:
3703 //
3704 // tf := trunc(val);
3705 // hif := floor(tf * 2^-32);
3706 // lof := tf - hif * 2^32; // lof is always positive due to floor.
3707 // hi := fptoi(hif);
3708 // lo := fptoi(lof);
3709 //
3710 SDValue Trunc = DAG.getNode(ISD::FTRUNC, SL, SrcVT, Src);
3711 SDValue Sign;
3712 if (Signed && SrcVT == MVT::f32) {
3713 // However, a 32-bit floating point number has only 23 bits mantissa and
3714 // it's not enough to hold all the significant bits of `lof` if val is
3715 // negative. To avoid the loss of precision, We need to take the absolute
3716 // value after truncating and flip the result back based on the original
3717 // signedness.
3718 Sign = DAG.getNode(ISD::SRA, SL, MVT::i32,
3719 DAG.getNode(ISD::BITCAST, SL, MVT::i32, Trunc),
3720 DAG.getConstant(31, SL, MVT::i32));
3721 Trunc = DAG.getNode(ISD::FABS, SL, SrcVT, Trunc);
3722 }
3723
3724 SDValue K0, K1;
3725 if (SrcVT == MVT::f64) {
3726 K0 = DAG.getConstantFP(
3727 llvm::bit_cast<double>(UINT64_C(/*2^-32*/ 0x3df0000000000000)), SL,
3728 SrcVT);
3729 K1 = DAG.getConstantFP(
3730 llvm::bit_cast<double>(UINT64_C(/*-2^32*/ 0xc1f0000000000000)), SL,
3731 SrcVT);
3732 } else {
3733 K0 = DAG.getConstantFP(
3734 llvm::bit_cast<float>(UINT32_C(/*2^-32*/ 0x2f800000)), SL, SrcVT);
3735 K1 = DAG.getConstantFP(
3736 llvm::bit_cast<float>(UINT32_C(/*-2^32*/ 0xcf800000)), SL, SrcVT);
3737 }
3738 // TODO: Should this propagate fast-math-flags?
3739 SDValue Mul = DAG.getNode(ISD::FMUL, SL, SrcVT, Trunc, K0);
3740
3741 SDValue FloorMul = DAG.getNode(ISD::FFLOOR, SL, SrcVT, Mul);
3742
3743 SDValue Fma = DAG.getNode(ISD::FMA, SL, SrcVT, FloorMul, K1, Trunc);
3744
3745 SDValue Hi = DAG.getNode((Signed && SrcVT == MVT::f64) ? ISD::FP_TO_SINT
3747 SL, MVT::i32, FloorMul);
3748 SDValue Lo = DAG.getNode(ISD::FP_TO_UINT, SL, MVT::i32, Fma);
3749
3750 SDValue Result = DAG.getNode(ISD::BITCAST, SL, MVT::i64,
3751 DAG.getBuildVector(MVT::v2i32, SL, {Lo, Hi}));
3752
3753 if (Signed && SrcVT == MVT::f32) {
3754 assert(Sign);
3755 // Flip the result based on the signedness, which is either all 0s or 1s.
3756 Sign = DAG.getNode(ISD::BITCAST, SL, MVT::i64,
3757 DAG.getBuildVector(MVT::v2i32, SL, {Sign, Sign}));
3758 // r := xor(r, sign) - sign;
3759 Result =
3760 DAG.getNode(ISD::SUB, SL, MVT::i64,
3761 DAG.getNode(ISD::XOR, SL, MVT::i64, Result, Sign), Sign);
3762 }
3763
3764 return Result;
3765}
3766
3768 SDLoc DL(Op);
3769 SDValue N0 = Op.getOperand(0);
3770
3771 // Convert to target node to get known bits
3772 if (N0.getValueType() == MVT::f32)
3773 return DAG.getNode(AMDGPUISD::FP_TO_FP16, DL, Op.getValueType(), N0);
3774
3775 if (Op->getFlags().hasApproximateFuncs()) {
3776 // There is a generic expand for FP_TO_FP16 with unsafe fast math.
3777 return SDValue();
3778 }
3779
3780 return LowerF64ToF16Safe(N0, DL, DAG);
3781}
3782
3783// return node in i32
3785 SelectionDAG &DAG) const {
3786 assert(Src.getSimpleValueType() == MVT::f64);
3787
3788 // f64 -> f16 conversion using round-to-nearest-even rounding mode.
3789 // TODO: We can generate better code for True16.
3790 const unsigned ExpMask = 0x7ff;
3791 const unsigned ExpBiasf64 = 1023;
3792 const unsigned ExpBiasf16 = 15;
3793 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
3794 SDValue One = DAG.getConstant(1, DL, MVT::i32);
3795 SDValue U = DAG.getNode(ISD::BITCAST, DL, MVT::i64, Src);
3796 SDValue UH = DAG.getNode(ISD::SRL, DL, MVT::i64, U,
3797 DAG.getConstant(32, DL, MVT::i64));
3798 UH = DAG.getZExtOrTrunc(UH, DL, MVT::i32);
3799 U = DAG.getZExtOrTrunc(U, DL, MVT::i32);
3800 SDValue E = DAG.getNode(ISD::SRL, DL, MVT::i32, UH,
3801 DAG.getConstant(20, DL, MVT::i64));
3802 E = DAG.getNode(ISD::AND, DL, MVT::i32, E,
3803 DAG.getConstant(ExpMask, DL, MVT::i32));
3804 // Subtract the fp64 exponent bias (1023) to get the real exponent and
3805 // add the f16 bias (15) to get the biased exponent for the f16 format.
3806 E = DAG.getNode(ISD::ADD, DL, MVT::i32, E,
3807 DAG.getConstant(-ExpBiasf64 + ExpBiasf16, DL, MVT::i32));
3808
3809 SDValue M = DAG.getNode(ISD::SRL, DL, MVT::i32, UH,
3810 DAG.getConstant(8, DL, MVT::i32));
3811 M = DAG.getNode(ISD::AND, DL, MVT::i32, M,
3812 DAG.getConstant(0xffe, DL, MVT::i32));
3813
3814 SDValue MaskedSig = DAG.getNode(ISD::AND, DL, MVT::i32, UH,
3815 DAG.getConstant(0x1ff, DL, MVT::i32));
3816 MaskedSig = DAG.getNode(ISD::OR, DL, MVT::i32, MaskedSig, U);
3817
3818 SDValue Lo40Set = DAG.getSelectCC(DL, MaskedSig, Zero, Zero, One, ISD::SETEQ);
3819 M = DAG.getNode(ISD::OR, DL, MVT::i32, M, Lo40Set);
3820
3821 // (M != 0 ? 0x0200 : 0) | 0x7c00;
3822 SDValue I = DAG.getNode(ISD::OR, DL, MVT::i32,
3823 DAG.getSelectCC(DL, M, Zero, DAG.getConstant(0x0200, DL, MVT::i32),
3824 Zero, ISD::SETNE), DAG.getConstant(0x7c00, DL, MVT::i32));
3825
3826 // N = M | (E << 12);
3827 SDValue N = DAG.getNode(ISD::OR, DL, MVT::i32, M,
3828 DAG.getNode(ISD::SHL, DL, MVT::i32, E,
3829 DAG.getConstant(12, DL, MVT::i32)));
3830
3831 // B = clamp(1-E, 0, 13);
3832 SDValue OneSubExp = DAG.getNode(ISD::SUB, DL, MVT::i32,
3833 One, E);
3834 SDValue B = DAG.getNode(ISD::SMAX, DL, MVT::i32, OneSubExp, Zero);
3835 B = DAG.getNode(ISD::SMIN, DL, MVT::i32, B,
3836 DAG.getConstant(13, DL, MVT::i32));
3837
3838 SDValue SigSetHigh = DAG.getNode(ISD::OR, DL, MVT::i32, M,
3839 DAG.getConstant(0x1000, DL, MVT::i32));
3840
3841 SDValue D = DAG.getNode(ISD::SRL, DL, MVT::i32, SigSetHigh, B);
3842 SDValue D0 = DAG.getNode(ISD::SHL, DL, MVT::i32, D, B);
3843 SDValue D1 = DAG.getSelectCC(DL, D0, SigSetHigh, One, Zero, ISD::SETNE);
3844 D = DAG.getNode(ISD::OR, DL, MVT::i32, D, D1);
3845
3846 SDValue V = DAG.getSelectCC(DL, E, One, D, N, ISD::SETLT);
3847 SDValue VLow3 = DAG.getNode(ISD::AND, DL, MVT::i32, V,
3848 DAG.getConstant(0x7, DL, MVT::i32));
3849 V = DAG.getNode(ISD::SRL, DL, MVT::i32, V,
3850 DAG.getConstant(2, DL, MVT::i32));
3851 SDValue V0 = DAG.getSelectCC(DL, VLow3, DAG.getConstant(3, DL, MVT::i32),
3852 One, Zero, ISD::SETEQ);
3853 SDValue V1 = DAG.getSelectCC(DL, VLow3, DAG.getConstant(5, DL, MVT::i32),
3854 One, Zero, ISD::SETGT);
3855 V1 = DAG.getNode(ISD::OR, DL, MVT::i32, V0, V1);
3856 V = DAG.getNode(ISD::ADD, DL, MVT::i32, V, V1);
3857
3858 V = DAG.getSelectCC(DL, E, DAG.getConstant(30, DL, MVT::i32),
3859 DAG.getConstant(0x7c00, DL, MVT::i32), V, ISD::SETGT);
3860 V = DAG.getSelectCC(DL, E, DAG.getConstant(1039, DL, MVT::i32),
3861 I, V, ISD::SETEQ);
3862
3863 // Extract the sign bit.
3864 SDValue Sign = DAG.getNode(ISD::SRL, DL, MVT::i32, UH,
3865 DAG.getConstant(16, DL, MVT::i32));
3866 Sign = DAG.getNode(ISD::AND, DL, MVT::i32, Sign,
3867 DAG.getConstant(0x8000, DL, MVT::i32));
3868
3869 return DAG.getNode(ISD::OR, DL, MVT::i32, Sign, V);
3870}
3871
3873 SelectionDAG &DAG) const {
3874 SDValue Src = Op.getOperand(0);
3875 unsigned OpOpcode = Op.getOpcode();
3876 EVT SrcVT = Src.getValueType();
3877 EVT DestVT = Op.getValueType();
3878
3879 // Will be selected natively
3880 if (SrcVT == MVT::f16 && DestVT == MVT::i16)
3881 return Op;
3882
3883 if (SrcVT == MVT::bf16 || (SrcVT == MVT::f16 && DestVT == MVT::i32)) {
3884 SDLoc DL(Op);
3885 SDValue PromotedSrc = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Src);
3886 return DAG.getNode(Op.getOpcode(), DL, DestVT, PromotedSrc);
3887 }
3888
3889 // Promote i16 to i32
3890 if (DestVT == MVT::i16 && (SrcVT == MVT::f32 || SrcVT == MVT::f64)) {
3891 SDLoc DL(Op);
3892
3893 SDValue FpToInt32 = DAG.getNode(OpOpcode, DL, MVT::i32, Src);
3894 return DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FpToInt32);
3895 }
3896
3897 if (DestVT != MVT::i64)
3898 return Op;
3899
3900 if (SrcVT == MVT::f16 ||
3901 (SrcVT == MVT::f32 && Src.getOpcode() == ISD::FP16_TO_FP)) {
3902 SDLoc DL(Op);
3903
3904 SDValue FpToInt32 = DAG.getNode(OpOpcode, DL, MVT::i32, Src);
3905 unsigned Ext =
3907 return DAG.getNode(Ext, DL, MVT::i64, FpToInt32);
3908 }
3909
3910 if (SrcVT == MVT::f32 || SrcVT == MVT::f64)
3911 return LowerFP_TO_INT64(Op, DAG, OpOpcode == ISD::FP_TO_SINT);
3912
3913 return SDValue();
3914}
3915
3917 SelectionDAG &DAG) const {
3918 SDValue Src = Op.getOperand(0);
3919 unsigned OpOpcode = Op.getOpcode();
3920 EVT SrcVT = Src.getValueType();
3921 EVT DstVT = Op.getValueType();
3922 SDValue SatVTOp = Op.getNode()->getOperand(1);
3923 EVT SatVT = cast<VTSDNode>(SatVTOp)->getVT();
3924 SDLoc DL(Op);
3925
3926 uint64_t DstWidth = DstVT.getScalarSizeInBits();
3927 uint64_t SatWidth = SatVT.getScalarSizeInBits();
3928 assert(SatWidth <= DstWidth && "Saturation width cannot exceed result width");
3929
3930 // Scalar cases will be selected natively to v_cvt_/s_cvt_ instructions.
3931 // v2f32 -> v2i16 will be selected natively to v_cvt_pk_[iu]16_f32.
3932 if (SatWidth == DstWidth) {
3933 if ((DstVT == MVT::i32 && (SrcVT == MVT::f32 || SrcVT == MVT::f64)) ||
3934 (DstVT == MVT::i16 && (SrcVT == MVT::f16 || SrcVT == MVT::f32)) ||
3935 (DstVT == MVT::v2i16 && SrcVT == MVT::v2f32))
3936 return Op;
3937 }
3938
3939 // Vectors can only be selected natively.
3940 if (DstVT.isVector())
3941 return SDValue();
3942
3943 // Perform all saturation at selected width (i16 or i32) and truncate
3944 if (SatWidth < DstWidth && SatWidth <= 32) {
3945 // For f16 conversion with sub-i16 saturation perform saturation
3946 // at i16, if available in the target. This removes the need for extra f16
3947 // to f32 conversion. For all the others use i32.
3948 MVT ResultVT =
3949 Subtarget->has16BitInsts() && SrcVT == MVT::f16 && SatWidth < 16
3950 ? MVT::i16
3951 : MVT::i32;
3952
3953 const SDValue ResultVTOp = DAG.getValueType(ResultVT);
3954 const uint64_t ResultWidth = ResultVT.getScalarSizeInBits();
3955
3956 // First, convert input float into selected integer (i16 or i32)
3957 SDValue FpToInt = DAG.getNode(OpOpcode, DL, ResultVT, Src, ResultVTOp);
3958 SDValue IntSatVal;
3959
3960 // Then, clamp at the saturation width using either i16 or i32 instructions
3961 if (OpOpcode == ISD::FP_TO_SINT_SAT) {
3962 SDValue MinConst = DAG.getConstant(
3963 APInt::getSignedMaxValue(SatWidth).sext(ResultWidth), DL, ResultVT);
3964 SDValue MaxConst = DAG.getConstant(
3965 APInt::getSignedMinValue(SatWidth).sext(ResultWidth), DL, ResultVT);
3966 SDValue MinVal = DAG.getNode(ISD::SMIN, DL, ResultVT, FpToInt, MinConst);
3967 IntSatVal = DAG.getNode(ISD::SMAX, DL, ResultVT, MinVal, MaxConst);
3968 } else {
3969 SDValue MinConst = DAG.getConstant(
3970 APInt::getMaxValue(SatWidth).zext(ResultWidth), DL, ResultVT);
3971 IntSatVal = DAG.getNode(ISD::UMIN, DL, ResultVT, FpToInt, MinConst);
3972 }
3973
3974 // Finally, after saturating at i16 or i32 fit into the destination type
3975 return DAG.getExtOrTrunc(OpOpcode == ISD::FP_TO_SINT_SAT, IntSatVal, DL,
3976 DstVT);
3977 }
3978
3979 // SatWidth == DstWidth or SatWidth > 32
3980
3981 // Saturate at i32 for i64 dst and f16/bf16 src (will invoke f16 promotion
3982 // below)
3983 if (DstVT == MVT::i64 &&
3984 (SrcVT == MVT::f16 || SrcVT == MVT::bf16 ||
3985 (SrcVT == MVT::f32 && Src.getOpcode() == ISD::FP16_TO_FP))) {
3986 const SDValue Int32VTOp = DAG.getValueType(MVT::i32);
3987 return DAG.getNode(OpOpcode, DL, DstVT, Src, Int32VTOp);
3988 }
3989
3990 // Promote f16/bf16 src to f32 for i32 conversion
3991 if (DstVT == MVT::i32 && (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
3992 SDValue PromotedSrc = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Src);
3993 return DAG.getNode(Op.getOpcode(), DL, DstVT, PromotedSrc, SatVTOp);
3994 }
3995
3996 // For DstWidth < 16, promote i1 and i8 dst to i16 (if legal) with sub-i16
3997 // saturation. For DstWidth == 16, promote i16 dst to i32 with sub-i32
3998 // saturation; this covers i16.f32 and i16.f64
3999 if (DstWidth < 32) {
4000 // Note: this triggers SatWidth < DstWidth above to generate saturated
4001 // truncate by requesting MVT::i16/i32 destination with SatWidth < 16/32.
4002 MVT PromoteVT =
4003 (DstWidth < 16 && Subtarget->has16BitInsts()) ? MVT::i16 : MVT::i32;
4004 SDValue FpToInt = DAG.getNode(OpOpcode, DL, PromoteVT, Src, SatVTOp);
4005 return DAG.getNode(ISD::TRUNCATE, DL, DstVT, FpToInt);
4006 }
4007
4008 // TODO: can we implement i64 dst for f32/f64?
4009
4010 return SDValue();
4011}
4012
4014 SelectionDAG &DAG) const {
4015 EVT ExtraVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
4016 MVT VT = Op.getSimpleValueType();
4017 MVT ScalarVT = VT.getScalarType();
4018
4019 assert(VT.isVector());
4020
4021 SDValue Src = Op.getOperand(0);
4022 SDLoc DL(Op);
4023
4024 // TODO: Don't scalarize on Evergreen?
4025 unsigned NElts = VT.getVectorNumElements();
4027 DAG.ExtractVectorElements(Src, Args, 0, NElts);
4028
4029 SDValue VTOp = DAG.getValueType(ExtraVT.getScalarType());
4030 for (unsigned I = 0; I < NElts; ++I)
4031 Args[I] = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, ScalarVT, Args[I], VTOp);
4032
4033 return DAG.getBuildVector(VT, DL, Args);
4034}
4035
4036//===----------------------------------------------------------------------===//
4037// Custom DAG optimizations
4038//===----------------------------------------------------------------------===//
4039
4040static bool isU24(SDValue Op, SelectionDAG &DAG) {
4041 return AMDGPUTargetLowering::numBitsUnsigned(Op, DAG) <= 24;
4042}
4043
4044static bool isI24(SDValue Op, SelectionDAG &DAG) {
4045 EVT VT = Op.getValueType();
4046 return VT.getSizeInBits() >= 24 && // Types less than 24-bit should be treated
4047 // as unsigned 24-bit values.
4049}
4050
4053 SelectionDAG &DAG = DCI.DAG;
4054 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
4055 bool IsIntrin = Node24->getOpcode() == ISD::INTRINSIC_WO_CHAIN;
4056
4057 SDValue LHS = IsIntrin ? Node24->getOperand(1) : Node24->getOperand(0);
4058 SDValue RHS = IsIntrin ? Node24->getOperand(2) : Node24->getOperand(1);
4059 unsigned NewOpcode = Node24->getOpcode();
4060 if (IsIntrin) {
4061 unsigned IID = Node24->getConstantOperandVal(0);
4062 switch (IID) {
4063 case Intrinsic::amdgcn_mul_i24:
4064 NewOpcode = AMDGPUISD::MUL_I24;
4065 break;
4066 case Intrinsic::amdgcn_mul_u24:
4067 NewOpcode = AMDGPUISD::MUL_U24;
4068 break;
4069 case Intrinsic::amdgcn_mulhi_i24:
4070 NewOpcode = AMDGPUISD::MULHI_I24;
4071 break;
4072 case Intrinsic::amdgcn_mulhi_u24:
4073 NewOpcode = AMDGPUISD::MULHI_U24;
4074 break;
4075 default:
4076 llvm_unreachable("Expected 24-bit mul intrinsic");
4077 }
4078 }
4079
4080 APInt Demanded = APInt::getLowBitsSet(LHS.getValueSizeInBits(), 24);
4081
4082 // First try to simplify using SimplifyMultipleUseDemandedBits which allows
4083 // the operands to have other uses, but will only perform simplifications that
4084 // involve bypassing some nodes for this user.
4085 SDValue DemandedLHS = TLI.SimplifyMultipleUseDemandedBits(LHS, Demanded, DAG);
4086 SDValue DemandedRHS = TLI.SimplifyMultipleUseDemandedBits(RHS, Demanded, DAG);
4087 if (DemandedLHS || DemandedRHS)
4088 return DAG.getNode(NewOpcode, SDLoc(Node24), Node24->getVTList(),
4089 DemandedLHS ? DemandedLHS : LHS,
4090 DemandedRHS ? DemandedRHS : RHS);
4091
4092 // Now try SimplifyDemandedBits which can simplify the nodes used by our
4093 // operands if this node is the only user.
4094 if (TLI.SimplifyDemandedBits(LHS, Demanded, DCI))
4095 return SDValue(Node24, 0);
4096 if (TLI.SimplifyDemandedBits(RHS, Demanded, DCI))
4097 return SDValue(Node24, 0);
4098
4099 return SDValue();
4100}
4101
4102template <typename IntTy>
4104 uint32_t Width, const SDLoc &DL) {
4105 if (Width + Offset < 32) {
4106 uint32_t Shl = static_cast<uint32_t>(Src0) << (32 - Offset - Width);
4107 IntTy Result = static_cast<IntTy>(Shl) >> (32 - Width);
4108 if constexpr (std::is_signed_v<IntTy>) {
4109 return DAG.getSignedConstant(Result, DL, MVT::i32);
4110 } else {
4111 return DAG.getConstant(Result, DL, MVT::i32);
4112 }
4113 }
4114
4115 return DAG.getConstant(Src0 >> Offset, DL, MVT::i32);
4116}
4117
4118static bool hasVolatileUser(SDNode *Val) {
4119 for (SDNode *U : Val->users()) {
4120 if (MemSDNode *M = dyn_cast<MemSDNode>(U)) {
4121 if (M->isVolatile())
4122 return true;
4123 }
4124 }
4125
4126 return false;
4127}
4128
4130 // i32 vectors are the canonical memory type.
4131 if (VT.getScalarType() == MVT::i32 || isTypeLegal(VT))
4132 return false;
4133
4134 if (!VT.isByteSized())
4135 return false;
4136
4137 unsigned Size = VT.getStoreSize();
4138
4139 if ((Size == 1 || Size == 2 || Size == 4) && !VT.isVector())
4140 return false;
4141
4142 if (Size == 3 || (Size > 4 && (Size % 4 != 0)))
4143 return false;
4144
4145 return true;
4146}
4147
4148// Replace load of an illegal type with a bitcast from a load of a friendlier
4149// type.
4151 DAGCombinerInfo &DCI) const {
4152 if (!DCI.isBeforeLegalize())
4153 return SDValue();
4154
4156 if (!LN->isSimple() || !ISD::isNormalLoad(LN) || hasVolatileUser(LN))
4157 return SDValue();
4158
4159 SDLoc SL(N);
4160 SelectionDAG &DAG = DCI.DAG;
4161 EVT VT = LN->getMemoryVT();
4162
4163 unsigned Size = VT.getStoreSize();
4164 Align Alignment = LN->getAlign();
4165 if (Alignment < Size && isTypeLegal(VT)) {
4166 unsigned IsFast;
4167 unsigned AS = LN->getAddressSpace();
4168
4169 // Expand unaligned loads earlier than legalization. Due to visitation order
4170 // problems during legalization, the emitted instructions to pack and unpack
4171 // the bytes again are not eliminated in the case of an unaligned copy.
4173 VT, AS, Alignment, LN->getMemOperand()->getFlags(), &IsFast)) {
4174 if (VT.isVector())
4175 return SplitVectorLoad(SDValue(LN, 0), DAG);
4176
4177 SDValue Ops[2];
4178 std::tie(Ops[0], Ops[1]) = expandUnalignedLoad(LN, DAG);
4179
4180 return DAG.getMergeValues(Ops, SDLoc(N));
4181 }
4182
4183 if (!IsFast)
4184 return SDValue();
4185 }
4186
4187 if (!shouldCombineMemoryType(VT))
4188 return SDValue();
4189
4190 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VT);
4191
4192 SDValue NewLoad
4193 = DAG.getLoad(NewVT, SL, LN->getChain(),
4194 LN->getBasePtr(), LN->getMemOperand());
4195
4196 SDValue BC = DAG.getNode(ISD::BITCAST, SL, VT, NewLoad);
4197 DCI.CombineTo(N, BC, NewLoad.getValue(1));
4198 return SDValue(N, 0);
4199}
4200
4201// Replace store of an illegal type with a store of a bitcast to a friendlier
4202// type.
4204 DAGCombinerInfo &DCI) const {
4205 if (!DCI.isBeforeLegalize())
4206 return SDValue();
4207
4209 if (!SN->isSimple() || !ISD::isNormalStore(SN))
4210 return SDValue();
4211
4212 EVT VT = SN->getMemoryVT();
4213 unsigned Size = VT.getStoreSize();
4214
4215 SDLoc SL(N);
4216 SelectionDAG &DAG = DCI.DAG;
4217 Align Alignment = SN->getAlign();
4218 if (Alignment < Size && isTypeLegal(VT)) {
4219 unsigned IsFast;
4220 unsigned AS = SN->getAddressSpace();
4221
4222 // Expand unaligned stores earlier than legalization. Due to visitation
4223 // order problems during legalization, the emitted instructions to pack and
4224 // unpack the bytes again are not eliminated in the case of an unaligned
4225 // copy.
4227 VT, AS, Alignment, SN->getMemOperand()->getFlags(), &IsFast)) {
4228 if (VT.isVector())
4229 return SplitVectorStore(SDValue(SN, 0), DAG);
4230
4231 return expandUnalignedStore(SN, DAG);
4232 }
4233
4234 if (!IsFast)
4235 return SDValue();
4236 }
4237
4238 if (!shouldCombineMemoryType(VT))
4239 return SDValue();
4240
4241 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VT);
4242 SDValue Val = SN->getValue();
4243
4244 // DCI.AddToWorklist(Val.getNode());
4245
4246 bool OtherUses = !Val.hasOneUse();
4247 SDValue CastVal = DAG.getBitcast(NewVT, Val);
4248 if (OtherUses) {
4249 SDValue CastBack = DAG.getBitcast(VT, CastVal);
4250 DAG.ReplaceAllUsesOfValueWith(Val, CastBack);
4251 }
4252
4253 return DAG.getStore(SN->getChain(), SL, CastVal,
4254 SN->getBasePtr(), SN->getMemOperand());
4255}
4256
4257// FIXME: This should go in generic DAG combiner with an isTruncateFree check,
4258// but isTruncateFree is inaccurate for i16 now because of SALU vs. VALU
4259// issues.
4261 DAGCombinerInfo &DCI) const {
4262 SelectionDAG &DAG = DCI.DAG;
4263 SDValue N0 = N->getOperand(0);
4264
4265 // (vt2 (assertzext (truncate vt0:x), vt1)) ->
4266 // (vt2 (truncate (assertzext vt0:x, vt1)))
4267 if (N0.getOpcode() == ISD::TRUNCATE) {
4268 SDValue N1 = N->getOperand(1);
4269 EVT ExtVT = cast<VTSDNode>(N1)->getVT();
4270 SDLoc SL(N);
4271
4272 SDValue Src = N0.getOperand(0);
4273 EVT SrcVT = Src.getValueType();
4274 if (SrcVT.bitsGE(ExtVT)) {
4275 SDValue NewInReg = DAG.getNode(N->getOpcode(), SL, SrcVT, Src, N1);
4276 return DAG.getNode(ISD::TRUNCATE, SL, N->getValueType(0), NewInReg);
4277 }
4278 }
4279
4280 return SDValue();
4281}
4282
4284 SDNode *N, DAGCombinerInfo &DCI) const {
4285 unsigned IID = N->getConstantOperandVal(0);
4286 switch (IID) {
4287 case Intrinsic::amdgcn_mul_i24:
4288 case Intrinsic::amdgcn_mul_u24:
4289 case Intrinsic::amdgcn_mulhi_i24:
4290 case Intrinsic::amdgcn_mulhi_u24:
4291 return simplifyMul24(N, DCI);
4292 case Intrinsic::amdgcn_fract:
4293 case Intrinsic::amdgcn_rsq:
4294 case Intrinsic::amdgcn_rcp_legacy:
4295 case Intrinsic::amdgcn_rsq_legacy:
4296 case Intrinsic::amdgcn_rsq_clamp:
4297 case Intrinsic::amdgcn_tanh:
4298 case Intrinsic::amdgcn_prng_b32: {
4299 // FIXME: This is probably wrong. If src is an sNaN, it won't be quieted
4300 SDValue Src = N->getOperand(1);
4301 return Src.isUndef() ? Src : SDValue();
4302 }
4303 case Intrinsic::amdgcn_frexp_exp: {
4304 // frexp_exp (fneg x) -> frexp_exp x
4305 // frexp_exp (fabs x) -> frexp_exp x
4306 // frexp_exp (fneg (fabs x)) -> frexp_exp x
4307 SDValue Src = N->getOperand(1);
4308 SDValue PeekSign = peekFPSignOps(Src);
4309 if (PeekSign == Src)
4310 return SDValue();
4311 return SDValue(DCI.DAG.UpdateNodeOperands(N, N->getOperand(0), PeekSign),
4312 0);
4313 }
4314 default:
4315 return SDValue();
4316 }
4317}
4318
4319/// Split the 64-bit value \p LHS into two 32-bit components, and perform the
4320/// binary operation \p Opc to it with the corresponding constant operands.
4322 DAGCombinerInfo &DCI, const SDLoc &SL,
4323 unsigned Opc, SDValue LHS,
4324 uint32_t ValLo, uint32_t ValHi) const {
4325 SelectionDAG &DAG = DCI.DAG;
4326 SDValue Lo, Hi;
4327 std::tie(Lo, Hi) = split64BitValue(LHS, DAG);
4328
4329 SDValue LoRHS = DAG.getConstant(ValLo, SL, MVT::i32);
4330 SDValue HiRHS = DAG.getConstant(ValHi, SL, MVT::i32);
4331
4332 SDValue LoAnd = DAG.getNode(Opc, SL, MVT::i32, Lo, LoRHS);
4333 SDValue HiAnd = DAG.getNode(Opc, SL, MVT::i32, Hi, HiRHS);
4334
4335 // Re-visit the ands. It's possible we eliminated one of them and it could
4336 // simplify the vector.
4337 DCI.AddToWorklist(Lo.getNode());
4338 DCI.AddToWorklist(Hi.getNode());
4339
4340 SDValue Vec = DAG.getBuildVector(MVT::v2i32, SL, {LoAnd, HiAnd});
4341 return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
4342}
4343
4345 DAGCombinerInfo &DCI) const {
4346 EVT VT = N->getValueType(0);
4347 SDValue LHS = N->getOperand(0);
4348 SDValue RHS = N->getOperand(1);
4350 SDLoc SL(N);
4351 SelectionDAG &DAG = DCI.DAG;
4352
4353 unsigned RHSVal;
4354 if (CRHS) {
4355 RHSVal = CRHS->getZExtValue();
4356 if (!RHSVal)
4357 return LHS;
4358
4359 switch (LHS->getOpcode()) {
4360 default:
4361 break;
4362 case ISD::ZERO_EXTEND:
4363 case ISD::SIGN_EXTEND:
4364 case ISD::ANY_EXTEND: {
4365 SDValue X = LHS->getOperand(0);
4366
4367 if (VT == MVT::i32 && RHSVal == 16 && X.getValueType() == MVT::i16 &&
4368 isOperationLegal(ISD::BUILD_VECTOR, MVT::v2i16)) {
4369 // Prefer build_vector as the canonical form if packed types are legal.
4370 // (shl ([asz]ext i16:x), 16 -> build_vector 0, x
4371 SDValue Vec = DAG.getBuildVector(
4372 MVT::v2i16, SL,
4373 {DAG.getConstant(0, SL, MVT::i16), LHS->getOperand(0)});
4374 return DAG.getNode(ISD::BITCAST, SL, MVT::i32, Vec);
4375 }
4376
4377 // shl (ext x) => zext (shl x), if shift does not overflow int
4378 if (VT != MVT::i64)
4379 break;
4381 unsigned LZ = Known.countMinLeadingZeros();
4382 if (LZ < RHSVal)
4383 break;
4384 EVT XVT = X.getValueType();
4385 SDValue Shl = DAG.getNode(ISD::SHL, SL, XVT, X, SDValue(CRHS, 0));
4386 return DAG.getZExtOrTrunc(Shl, SL, VT);
4387 }
4388 }
4389 }
4390
4391 if (VT.getScalarType() != MVT::i64)
4392 return SDValue();
4393
4394 // On some subtargets, 64-bit shift is a quarter rate instruction. In the
4395 // common case, splitting this into a move and a 32-bit shift is faster and
4396 // the same code size.
4397 KnownBits Known = DAG.computeKnownBits(RHS);
4398
4399 EVT ElementType = VT.getScalarType();
4400 EVT TargetScalarType = ElementType.getHalfSizedIntegerVT(*DAG.getContext());
4401 EVT TargetType = VT.changeElementType(*DAG.getContext(), TargetScalarType);
4402
4403 if (Known.getMinValue().getZExtValue() < TargetScalarType.getSizeInBits())
4404 return SDValue();
4405 SDValue ShiftAmt;
4406
4407 if (CRHS) {
4408 ShiftAmt = DAG.getConstant(RHSVal - TargetScalarType.getSizeInBits(), SL,
4409 TargetType);
4410 } else {
4411 SDValue TruncShiftAmt = DAG.getNode(ISD::TRUNCATE, SL, TargetType, RHS);
4412 const SDValue ShiftMask =
4413 DAG.getConstant(TargetScalarType.getSizeInBits() - 1, SL, TargetType);
4414 // This AND instruction will clamp out of bounds shift values.
4415 // It will also be removed during later instruction selection.
4416 ShiftAmt = DAG.getNode(ISD::AND, SL, TargetType, TruncShiftAmt, ShiftMask);
4417 }
4418
4419 SDValue Lo = DAG.getNode(ISD::TRUNCATE, SL, TargetType, LHS);
4420 SDValue NewShift =
4421 DAG.getNode(ISD::SHL, SL, TargetType, Lo, ShiftAmt, N->getFlags());
4422
4423 const SDValue Zero = DAG.getConstant(0, SL, TargetScalarType);
4424 SDValue Vec;
4425
4426 if (VT.isVector()) {
4427 EVT ConcatType = TargetType.getDoubleNumVectorElementsVT(*DAG.getContext());
4428 unsigned NElts = TargetType.getVectorNumElements();
4430 SmallVector<SDValue, 16> HiAndLoOps(NElts * 2, Zero);
4431
4432 DAG.ExtractVectorElements(NewShift, HiOps, 0, NElts);
4433 for (unsigned I = 0; I != NElts; ++I)
4434 HiAndLoOps[2 * I + 1] = HiOps[I];
4435 Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, ConcatType, HiAndLoOps);
4436 } else {
4437 EVT ConcatType = EVT::getVectorVT(*DAG.getContext(), TargetType, 2);
4438 Vec = DAG.getBuildVector(ConcatType, SL, {Zero, NewShift});
4439 }
4440 return DAG.getNode(ISD::BITCAST, SL, VT, Vec);
4441}
4442
4444 DAGCombinerInfo &DCI) const {
4445 SDValue RHS = N->getOperand(1);
4447 EVT VT = N->getValueType(0);
4448 SDValue LHS = N->getOperand(0);
4449 SelectionDAG &DAG = DCI.DAG;
4450 SDLoc SL(N);
4451
4452 if (VT.getScalarType() != MVT::i64)
4453 return SDValue();
4454
4455 // For C >= 32
4456 // i64 (sra x, C) -> (build_pair (sra hi_32(x), C - 32), sra hi_32(x), 31))
4457
4458 // On some subtargets, 64-bit shift is a quarter rate instruction. In the
4459 // common case, splitting this into a move and a 32-bit shift is faster and
4460 // the same code size.
4461 KnownBits Known = DAG.computeKnownBits(RHS);
4462
4463 EVT ElementType = VT.getScalarType();
4464 EVT TargetScalarType = ElementType.getHalfSizedIntegerVT(*DAG.getContext());
4465 EVT TargetType = VT.changeElementType(*DAG.getContext(), TargetScalarType);
4466
4467 if (Known.getMinValue().getZExtValue() < TargetScalarType.getSizeInBits())
4468 return SDValue();
4469
4470 SDValue ShiftFullAmt =
4471 DAG.getConstant(TargetScalarType.getSizeInBits() - 1, SL, TargetType);
4472 SDValue ShiftAmt;
4473 if (CRHS) {
4474 unsigned RHSVal = CRHS->getZExtValue();
4475 ShiftAmt = DAG.getConstant(RHSVal - TargetScalarType.getSizeInBits(), SL,
4476 TargetType);
4477 } else if (Known.getMinValue().getZExtValue() ==
4478 (ElementType.getSizeInBits() - 1)) {
4479 ShiftAmt = ShiftFullAmt;
4480 } else {
4481 SDValue TruncShiftAmt = DAG.getNode(ISD::TRUNCATE, SL, TargetType, RHS);
4482 const SDValue ShiftMask =
4483 DAG.getConstant(TargetScalarType.getSizeInBits() - 1, SL, TargetType);
4484 // This AND instruction will clamp out of bounds shift values.
4485 // It will also be removed during later instruction selection.
4486 ShiftAmt = DAG.getNode(ISD::AND, SL, TargetType, TruncShiftAmt, ShiftMask);
4487 }
4488
4489 EVT ConcatType;
4490 SDValue Hi;
4491 SDLoc LHSSL(LHS);
4492 // Bitcast LHS into ConcatType so hi-half of source can be extracted into Hi
4493 if (VT.isVector()) {
4494 unsigned NElts = TargetType.getVectorNumElements();
4495 ConcatType = TargetType.getDoubleNumVectorElementsVT(*DAG.getContext());
4496 SDValue SplitLHS = DAG.getNode(ISD::BITCAST, LHSSL, ConcatType, LHS);
4497 SmallVector<SDValue, 8> HiOps(NElts);
4498 SmallVector<SDValue, 16> HiAndLoOps;
4499
4500 DAG.ExtractVectorElements(SplitLHS, HiAndLoOps, 0, NElts * 2);
4501 for (unsigned I = 0; I != NElts; ++I) {
4502 HiOps[I] = HiAndLoOps[2 * I + 1];
4503 }
4504 Hi = DAG.getNode(ISD::BUILD_VECTOR, LHSSL, TargetType, HiOps);
4505 } else {
4506 const SDValue One = DAG.getConstant(1, LHSSL, TargetScalarType);
4507 ConcatType = EVT::getVectorVT(*DAG.getContext(), TargetType, 2);
4508 SDValue SplitLHS = DAG.getNode(ISD::BITCAST, LHSSL, ConcatType, LHS);
4509 Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, LHSSL, TargetType, SplitLHS, One);
4510 }
4511
4512 KnownBits KnownLHS = DAG.computeKnownBits(LHS);
4513 SDValue NewShift, HiShift;
4514 if (KnownLHS.isNegative()) {
4515 HiShift = DAG.getAllOnesConstant(SL, TargetType);
4516 NewShift =
4517 DAG.getNode(ISD::SRA, SL, TargetType, Hi, ShiftAmt, N->getFlags());
4518 } else if (CRHS &&
4519 CRHS->getZExtValue() == (ElementType.getSizeInBits() - 1)) {
4520 NewShift = HiShift =
4521 DAG.getNode(ISD::SRA, SL, TargetType, Hi, ShiftAmt, N->getFlags());
4522 } else {
4523 Hi = DAG.getFreeze(Hi);
4524 HiShift = DAG.getNode(ISD::SRA, SL, TargetType, Hi, ShiftFullAmt);
4525 NewShift =
4526 DAG.getNode(ISD::SRA, SL, TargetType, Hi, ShiftAmt, N->getFlags());
4527 }
4528
4529 SDValue Vec;
4530 if (VT.isVector()) {
4531 unsigned NElts = TargetType.getVectorNumElements();
4534 SmallVector<SDValue, 16> HiAndLoOps(NElts * 2);
4535
4536 DAG.ExtractVectorElements(HiShift, HiOps, 0, NElts);
4537 DAG.ExtractVectorElements(NewShift, LoOps, 0, NElts);
4538 for (unsigned I = 0; I != NElts; ++I) {
4539 HiAndLoOps[2 * I + 1] = HiOps[I];
4540 HiAndLoOps[2 * I] = LoOps[I];
4541 }
4542 Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, ConcatType, HiAndLoOps);
4543 } else {
4544 Vec = DAG.getBuildVector(ConcatType, SL, {NewShift, HiShift});
4545 }
4546 return DAG.getNode(ISD::BITCAST, SL, VT, Vec);
4547}
4548
4550 DAGCombinerInfo &DCI) const {
4551 SDValue RHS = N->getOperand(1);
4553 EVT VT = N->getValueType(0);
4554 SDValue LHS = N->getOperand(0);
4555 SelectionDAG &DAG = DCI.DAG;
4556 SDLoc SL(N);
4557 unsigned RHSVal;
4558
4559 if (CRHS) {
4560 RHSVal = CRHS->getZExtValue();
4561
4562 // fold (srl (and x, c1 << c2), c2) -> (and (srl(x, c2), c1)
4563 // this improves the ability to match BFE patterns in isel.
4564 if (LHS.getOpcode() == ISD::AND) {
4565 if (auto *Mask = dyn_cast<ConstantSDNode>(LHS.getOperand(1))) {
4566 unsigned MaskIdx, MaskLen;
4567 if (Mask->getAPIntValue().isShiftedMask(MaskIdx, MaskLen) &&
4568 MaskIdx == RHSVal) {
4569 return DAG.getNode(ISD::AND, SL, VT,
4570 DAG.getNode(ISD::SRL, SL, VT, LHS.getOperand(0),
4571 N->getOperand(1)),
4572 DAG.getNode(ISD::SRL, SL, VT, LHS.getOperand(1),
4573 N->getOperand(1)));
4574 }
4575 }
4576 }
4577 }
4578
4579 if (VT.getScalarType() != MVT::i64)
4580 return SDValue();
4581
4582 // for C >= 32
4583 // i64 (srl x, C) -> (build_pair (srl hi_32(x), C - 32), 0)
4584
4585 // On some subtargets, 64-bit shift is a quarter rate instruction. In the
4586 // common case, splitting this into a move and a 32-bit shift is faster and
4587 // the same code size.
4588 KnownBits Known = DAG.computeKnownBits(RHS);
4589
4590 EVT ElementType = VT.getScalarType();
4591 EVT TargetScalarType = ElementType.getHalfSizedIntegerVT(*DAG.getContext());
4592 EVT TargetType = VT.changeElementType(*DAG.getContext(), TargetScalarType);
4593
4594 if (Known.getMinValue().getZExtValue() < TargetScalarType.getSizeInBits())
4595 return SDValue();
4596
4597 SDValue ShiftAmt;
4598 if (CRHS) {
4599 ShiftAmt = DAG.getConstant(RHSVal - TargetScalarType.getSizeInBits(), SL,
4600 TargetType);
4601 } else {
4602 SDValue TruncShiftAmt = DAG.getNode(ISD::TRUNCATE, SL, TargetType, RHS);
4603 const SDValue ShiftMask =
4604 DAG.getConstant(TargetScalarType.getSizeInBits() - 1, SL, TargetType);
4605 // This AND instruction will clamp out of bounds shift values.
4606 // It will also be removed during later instruction selection.
4607 ShiftAmt = DAG.getNode(ISD::AND, SL, TargetType, TruncShiftAmt, ShiftMask);
4608 }
4609
4610 const SDValue Zero = DAG.getConstant(0, SL, TargetScalarType);
4611 EVT ConcatType;
4612 SDValue Hi;
4613 SDLoc LHSSL(LHS);
4614 // Bitcast LHS into ConcatType so hi-half of source can be extracted into Hi
4615 if (VT.isVector()) {
4616 unsigned NElts = TargetType.getVectorNumElements();
4617 ConcatType = TargetType.getDoubleNumVectorElementsVT(*DAG.getContext());
4618 SDValue SplitLHS = DAG.getNode(ISD::BITCAST, LHSSL, ConcatType, LHS);
4619 SmallVector<SDValue, 8> HiOps(NElts);
4620 SmallVector<SDValue, 16> HiAndLoOps;
4621
4622 DAG.ExtractVectorElements(SplitLHS, HiAndLoOps, /*Start=*/0, NElts * 2);
4623 for (unsigned I = 0; I != NElts; ++I)
4624 HiOps[I] = HiAndLoOps[2 * I + 1];
4625 Hi = DAG.getNode(ISD::BUILD_VECTOR, LHSSL, TargetType, HiOps);
4626 } else {
4627 const SDValue One = DAG.getConstant(1, LHSSL, TargetScalarType);
4628 ConcatType = EVT::getVectorVT(*DAG.getContext(), TargetType, 2);
4629 SDValue SplitLHS = DAG.getNode(ISD::BITCAST, LHSSL, ConcatType, LHS);
4630 Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, LHSSL, TargetType, SplitLHS, One);
4631 }
4632
4633 SDValue NewShift =
4634 DAG.getNode(ISD::SRL, SL, TargetType, Hi, ShiftAmt, N->getFlags());
4635
4636 SDValue Vec;
4637 if (VT.isVector()) {
4638 unsigned NElts = TargetType.getVectorNumElements();
4640 SmallVector<SDValue, 16> HiAndLoOps(NElts * 2, Zero);
4641
4642 DAG.ExtractVectorElements(NewShift, LoOps, 0, NElts);
4643 for (unsigned I = 0; I != NElts; ++I)
4644 HiAndLoOps[2 * I] = LoOps[I];
4645 Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, ConcatType, HiAndLoOps);
4646 } else {
4647 Vec = DAG.getBuildVector(ConcatType, SL, {NewShift, Zero});
4648 }
4649 return DAG.getNode(ISD::BITCAST, SL, VT, Vec);
4650}
4651
4653 SDNode *N, DAGCombinerInfo &DCI) const {
4654 SDLoc SL(N);
4655 SelectionDAG &DAG = DCI.DAG;
4656 EVT VT = N->getValueType(0);
4657 SDValue Src = N->getOperand(0);
4658
4659 // vt1 (truncate (bitcast (build_vector vt0:x, ...))) -> vt1 (bitcast vt0:x)
4660 if (Src.getOpcode() == ISD::BITCAST && !VT.isVector()) {
4661 SDValue Vec = Src.getOperand(0);
4662 if (Vec.getOpcode() == ISD::BUILD_VECTOR) {
4663 SDValue Elt0 = Vec.getOperand(0);
4664 EVT EltVT = Elt0.getValueType();
4665 if (VT.getFixedSizeInBits() <= EltVT.getFixedSizeInBits()) {
4666 if (EltVT.isFloatingPoint()) {
4667 Elt0 = DAG.getNode(ISD::BITCAST, SL,
4668 EltVT.changeTypeToInteger(), Elt0);
4669 }
4670
4671 return DAG.getNode(ISD::TRUNCATE, SL, VT, Elt0);
4672 }
4673 }
4674 }
4675
4676 // Equivalent of above for accessing the high element of a vector as an
4677 // integer operation.
4678 // trunc (srl (bitcast (build_vector x, y))), 16 -> trunc (bitcast y)
4679 if (Src.getOpcode() == ISD::SRL && !VT.isVector()) {
4680 if (auto *K = isConstOrConstSplat(Src.getOperand(1))) {
4681 SDValue BV = stripBitcast(Src.getOperand(0));
4682 if (BV.getOpcode() == ISD::BUILD_VECTOR) {
4683 EVT SrcEltVT = BV.getOperand(0).getValueType();
4684 unsigned SrcEltSize = SrcEltVT.getSizeInBits();
4685 unsigned BitIndex = K->getZExtValue();
4686 unsigned PartIndex = BitIndex / SrcEltSize;
4687
4688 if (PartIndex * SrcEltSize == BitIndex &&
4689 PartIndex < BV.getNumOperands()) {
4690 if (SrcEltVT.getSizeInBits() == VT.getSizeInBits()) {
4691 SDValue SrcElt =
4692 DAG.getNode(ISD::BITCAST, SL, SrcEltVT.changeTypeToInteger(),
4693 BV.getOperand(PartIndex));
4694 return DAG.getNode(ISD::TRUNCATE, SL, VT, SrcElt);
4695 }
4696 }
4697 }
4698 }
4699 }
4700
4701 // Partially shrink 64-bit shifts to 32-bit if reduced to 16-bit.
4702 //
4703 // i16 (trunc (srl i64:x, K)), K <= 16 ->
4704 // i16 (trunc (srl (i32 (trunc x), K)))
4705 if (VT.getScalarSizeInBits() < 32) {
4706 EVT SrcVT = Src.getValueType();
4707 if (SrcVT.getScalarSizeInBits() > 32 &&
4708 (Src.getOpcode() == ISD::SRL ||
4709 Src.getOpcode() == ISD::SRA ||
4710 Src.getOpcode() == ISD::SHL)) {
4711 SDValue Amt = Src.getOperand(1);
4712 KnownBits Known = DAG.computeKnownBits(Amt);
4713
4714 // - For left shifts, do the transform as long as the shift
4715 // amount is still legal for i32, so when ShiftAmt < 32 (<= 31)
4716 // - For right shift, do it if ShiftAmt <= (32 - Size) to avoid
4717 // losing information stored in the high bits when truncating.
4718 const unsigned MaxCstSize =
4719 (Src.getOpcode() == ISD::SHL) ? 31 : (32 - VT.getScalarSizeInBits());
4720 if (Known.getMaxValue().ule(MaxCstSize)) {
4721 EVT MidVT = VT.isVector() ?
4722 EVT::getVectorVT(*DAG.getContext(), MVT::i32,
4723 VT.getVectorNumElements()) : MVT::i32;
4724
4725 EVT NewShiftVT = getShiftAmountTy(MidVT, DAG.getDataLayout());
4726 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SL, MidVT,
4727 Src.getOperand(0));
4728 DCI.AddToWorklist(Trunc.getNode());
4729
4730 if (Amt.getValueType() != NewShiftVT) {
4731 Amt = DAG.getZExtOrTrunc(Amt, SL, NewShiftVT);
4732 DCI.AddToWorklist(Amt.getNode());
4733 }
4734
4735 SDValue ShrunkShift = DAG.getNode(Src.getOpcode(), SL, MidVT,
4736 Trunc, Amt);
4737 return DAG.getNode(ISD::TRUNCATE, SL, VT, ShrunkShift);
4738 }
4739 }
4740 }
4741
4742 return SDValue();
4743}
4744
4745// We need to specifically handle i64 mul here to avoid unnecessary conversion
4746// instructions. If we only match on the legalized i64 mul expansion,
4747// SimplifyDemandedBits will be unable to remove them because there will be
4748// multiple uses due to the separate mul + mulh[su].
4749static SDValue getMul24(SelectionDAG &DAG, const SDLoc &SL,
4750 SDValue N0, SDValue N1, unsigned Size, bool Signed) {
4751 if (Size <= 32) {
4752 unsigned MulOpc = Signed ? AMDGPUISD::MUL_I24 : AMDGPUISD::MUL_U24;
4753 return DAG.getNode(MulOpc, SL, MVT::i32, N0, N1);
4754 }
4755
4756 unsigned MulLoOpc = Signed ? AMDGPUISD::MUL_I24 : AMDGPUISD::MUL_U24;
4757 unsigned MulHiOpc = Signed ? AMDGPUISD::MULHI_I24 : AMDGPUISD::MULHI_U24;
4758
4759 SDValue MulLo = DAG.getNode(MulLoOpc, SL, MVT::i32, N0, N1);
4760 SDValue MulHi = DAG.getNode(MulHiOpc, SL, MVT::i32, N0, N1);
4761
4762 return DAG.getNode(ISD::BUILD_PAIR, SL, MVT::i64, MulLo, MulHi);
4763}
4764
4765/// If \p V is an add of a constant 1, returns the other operand. Otherwise
4766/// return SDValue().
4767static SDValue getAddOneOp(const SDNode *V) {
4768 if (V->getOpcode() != ISD::ADD)
4769 return SDValue();
4770
4771 return isOneConstant(V->getOperand(1)) ? V->getOperand(0) : SDValue();
4772}
4773
4775 DAGCombinerInfo &DCI) const {
4776 assert(N->getOpcode() == ISD::MUL);
4777 EVT VT = N->getValueType(0);
4778
4779 // Don't generate 24-bit multiplies on values that are in SGPRs, since
4780 // we only have a 32-bit scalar multiply (avoid values being moved to VGPRs
4781 // unnecessarily). isDivergent() is used as an approximation of whether the
4782 // value is in an SGPR.
4783 if (!N->isDivergent())
4784 return SDValue();
4785
4786 unsigned Size = VT.getSizeInBits();
4787 if (VT.isVector() || Size > 64)
4788 return SDValue();
4789
4790 SelectionDAG &DAG = DCI.DAG;
4791 SDLoc DL(N);
4792
4793 SDValue N0 = N->getOperand(0);
4794 SDValue N1 = N->getOperand(1);
4795
4796 // Undo InstCombine canonicalize X * (Y + 1) -> X * Y + X to enable mad
4797 // matching.
4798
4799 // mul x, (add y, 1) -> add (mul x, y), x
4800 auto IsFoldableAdd = [](SDValue V) -> SDValue {
4801 SDValue AddOp = getAddOneOp(V.getNode());
4802 if (!AddOp)
4803 return SDValue();
4804
4805 if (V.hasOneUse() || all_of(V->users(), [](const SDNode *U) -> bool {
4806 return U->getOpcode() == ISD::MUL;
4807 }))
4808 return AddOp;
4809
4810 return SDValue();
4811 };
4812
4813 // FIXME: The selection pattern is not properly checking for commuted
4814 // operands, so we have to place the mul in the LHS
4815 if (SDValue MulOper = IsFoldableAdd(N0)) {
4816 SDValue MulVal = DAG.getNode(N->getOpcode(), DL, VT, N1, MulOper);
4817 return DAG.getNode(ISD::ADD, DL, VT, MulVal, N1);
4818 }
4819
4820 if (SDValue MulOper = IsFoldableAdd(N1)) {
4821 SDValue MulVal = DAG.getNode(N->getOpcode(), DL, VT, N0, MulOper);
4822 return DAG.getNode(ISD::ADD, DL, VT, MulVal, N0);
4823 }
4824
4825 // There are i16 integer mul/mad.
4826 if (isTypeLegal(MVT::i16) && VT.getScalarType().bitsLE(MVT::i16))
4827 return SDValue();
4828
4829 // SimplifyDemandedBits has the annoying habit of turning useful zero_extends
4830 // in the source into any_extends if the result of the mul is truncated. Since
4831 // we can assume the high bits are whatever we want, use the underlying value
4832 // to avoid the unknown high bits from interfering.
4833 if (N0.getOpcode() == ISD::ANY_EXTEND)
4834 N0 = N0.getOperand(0);
4835
4836 if (N1.getOpcode() == ISD::ANY_EXTEND)
4837 N1 = N1.getOperand(0);
4838
4839 SDValue Mul;
4840
4841 if (Subtarget->hasMulU24() && isU24(N0, DAG) && isU24(N1, DAG)) {
4842 N0 = DAG.getZExtOrTrunc(N0, DL, MVT::i32);
4843 N1 = DAG.getZExtOrTrunc(N1, DL, MVT::i32);
4844 Mul = getMul24(DAG, DL, N0, N1, Size, false);
4845 } else if (Subtarget->hasMulI24() && isI24(N0, DAG) && isI24(N1, DAG)) {
4846 N0 = DAG.getSExtOrTrunc(N0, DL, MVT::i32);
4847 N1 = DAG.getSExtOrTrunc(N1, DL, MVT::i32);
4848 Mul = getMul24(DAG, DL, N0, N1, Size, true);
4849 } else {
4850 return SDValue();
4851 }
4852
4853 // We need to use sext even for MUL_U24, because MUL_U24 is used
4854 // for signed multiply of 8 and 16-bit types.
4855 return DAG.getSExtOrTrunc(Mul, DL, VT);
4856}
4857
4858SDValue
4860 DAGCombinerInfo &DCI) const {
4861 if (N->getValueType(0) != MVT::i32)
4862 return SDValue();
4863
4864 SelectionDAG &DAG = DCI.DAG;
4865 SDLoc DL(N);
4866
4867 bool Signed = N->getOpcode() == ISD::SMUL_LOHI;
4868 SDValue N0 = N->getOperand(0);
4869 SDValue N1 = N->getOperand(1);
4870
4871 // SimplifyDemandedBits has the annoying habit of turning useful zero_extends
4872 // in the source into any_extends if the result of the mul is truncated. Since
4873 // we can assume the high bits are whatever we want, use the underlying value
4874 // to avoid the unknown high bits from interfering.
4875 if (N0.getOpcode() == ISD::ANY_EXTEND)
4876 N0 = N0.getOperand(0);
4877 if (N1.getOpcode() == ISD::ANY_EXTEND)
4878 N1 = N1.getOperand(0);
4879
4880 // Try to use two fast 24-bit multiplies (one for each half of the result)
4881 // instead of one slow extending multiply.
4882 unsigned LoOpcode = 0;
4883 unsigned HiOpcode = 0;
4884 if (Signed) {
4885 if (Subtarget->hasMulI24() && isI24(N0, DAG) && isI24(N1, DAG)) {
4886 N0 = DAG.getSExtOrTrunc(N0, DL, MVT::i32);
4887 N1 = DAG.getSExtOrTrunc(N1, DL, MVT::i32);
4888 LoOpcode = AMDGPUISD::MUL_I24;
4889 HiOpcode = AMDGPUISD::MULHI_I24;
4890 }
4891 } else {
4892 if (Subtarget->hasMulU24() && isU24(N0, DAG) && isU24(N1, DAG)) {
4893 N0 = DAG.getZExtOrTrunc(N0, DL, MVT::i32);
4894 N1 = DAG.getZExtOrTrunc(N1, DL, MVT::i32);
4895 LoOpcode = AMDGPUISD::MUL_U24;
4896 HiOpcode = AMDGPUISD::MULHI_U24;
4897 }
4898 }
4899 if (!LoOpcode)
4900 return SDValue();
4901
4902 SDValue Lo = DAG.getNode(LoOpcode, DL, MVT::i32, N0, N1);
4903 SDValue Hi = DAG.getNode(HiOpcode, DL, MVT::i32, N0, N1);
4904 DCI.CombineTo(N, Lo, Hi);
4905 return SDValue(N, 0);
4906}
4907
4909 DAGCombinerInfo &DCI) const {
4910 EVT VT = N->getValueType(0);
4911
4912 if (!Subtarget->hasMulI24() || VT.isVector())
4913 return SDValue();
4914
4915 // Don't generate 24-bit multiplies on values that are in SGPRs, since
4916 // we only have a 32-bit scalar multiply (avoid values being moved to VGPRs
4917 // unnecessarily). isDivergent() is used as an approximation of whether the
4918 // value is in an SGPR.
4919 // This doesn't apply if no s_mul_hi is available (since we'll end up with a
4920 // valu op anyway)
4921 if (Subtarget->hasSMulHi() && !N->isDivergent())
4922 return SDValue();
4923
4924 SelectionDAG &DAG = DCI.DAG;
4925 SDLoc DL(N);
4926
4927 SDValue N0 = N->getOperand(0);
4928 SDValue N1 = N->getOperand(1);
4929
4930 if (!isI24(N0, DAG) || !isI24(N1, DAG))
4931 return SDValue();
4932
4933 N0 = DAG.getSExtOrTrunc(N0, DL, MVT::i32);
4934 N1 = DAG.getSExtOrTrunc(N1, DL, MVT::i32);
4935
4936 SDValue Mulhi = DAG.getNode(AMDGPUISD::MULHI_I24, DL, MVT::i32, N0, N1);
4937 DCI.AddToWorklist(Mulhi.getNode());
4938 return DAG.getSExtOrTrunc(Mulhi, DL, VT);
4939}
4940
4942 DAGCombinerInfo &DCI) const {
4943 EVT VT = N->getValueType(0);
4944
4945 if (VT.isVector() || VT.getSizeInBits() > 32 || !Subtarget->hasMulU24())
4946 return SDValue();
4947
4948 // Don't generate 24-bit multiplies on values that are in SGPRs, since
4949 // we only have a 32-bit scalar multiply (avoid values being moved to VGPRs
4950 // unnecessarily). isDivergent() is used as an approximation of whether the
4951 // value is in an SGPR.
4952 // This doesn't apply if no s_mul_hi is available (since we'll end up with a
4953 // valu op anyway)
4954 if (!N->isDivergent() && Subtarget->hasSMulHi())
4955 return SDValue();
4956
4957 SelectionDAG &DAG = DCI.DAG;
4958 SDLoc DL(N);
4959
4960 SDValue N0 = N->getOperand(0);
4961 SDValue N1 = N->getOperand(1);
4962
4963 if (!isU24(N0, DAG) || !isU24(N1, DAG))
4964 return SDValue();
4965
4966 N0 = DAG.getZExtOrTrunc(N0, DL, MVT::i32);
4967 N1 = DAG.getZExtOrTrunc(N1, DL, MVT::i32);
4968
4969 SDValue Mulhi = DAG.getNode(AMDGPUISD::MULHI_U24, DL, MVT::i32, N0, N1);
4970 DCI.AddToWorklist(Mulhi.getNode());
4971 return DAG.getZExtOrTrunc(Mulhi, DL, VT);
4972}
4973
4974SDValue AMDGPUTargetLowering::getFFBX_U32(SelectionDAG &DAG,
4975 SDValue Op,
4976 const SDLoc &DL,
4977 unsigned Opc) const {
4978 EVT VT = Op.getValueType();
4979 if (VT.bitsGT(MVT::i32))
4980 return SDValue();
4981
4982 if (VT != MVT::i32)
4983 Op = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i32, Op);
4984
4985 SDValue FFBX = DAG.getNode(Opc, DL, MVT::i32, Op);
4986 if (VT != MVT::i32)
4987 FFBX = DAG.getNode(ISD::TRUNCATE, DL, VT, FFBX);
4988
4989 return FFBX;
4990}
4991
4992// The native instructions return -1 on 0 input. Optimize out a select that
4993// produces -1 on 0.
4994//
4995// TODO: If zero is not undef, we could also do this if the output is compared
4996// against the bitwidth.
4997//
4998// TODO: Should probably combine against FFBH_U32 instead of ctlz directly.
5000 SDValue LHS, SDValue RHS,
5001 DAGCombinerInfo &DCI) const {
5002 if (!isNullConstant(Cond.getOperand(1)))
5003 return SDValue();
5004
5005 SelectionDAG &DAG = DCI.DAG;
5006 ISD::CondCode CCOpcode = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
5007 SDValue CmpLHS = Cond.getOperand(0);
5008
5009 // select (setcc x, 0, eq), -1, (ctlz_zero_poison x) -> ffbh_u32 x
5010 // select (setcc x, 0, eq), -1, (cttz_zero_poison x) -> ffbl_u32 x
5011 if (CCOpcode == ISD::SETEQ &&
5012 (isCtlzOpc(RHS.getOpcode()) || isCttzOpc(RHS.getOpcode())) &&
5013 RHS.getOperand(0) == CmpLHS && isAllOnesConstant(LHS)) {
5014 unsigned Opc =
5015 isCttzOpc(RHS.getOpcode()) ? AMDGPUISD::FFBL_B32 : AMDGPUISD::FFBH_U32;
5016 return getFFBX_U32(DAG, CmpLHS, SL, Opc);
5017 }
5018
5019 // select (setcc x, 0, ne), (ctlz_zero_poison x), -1 -> ffbh_u32 x
5020 // select (setcc x, 0, ne), (cttz_zero_poison x), -1 -> ffbl_u32 x
5021 if (CCOpcode == ISD::SETNE &&
5022 (isCtlzOpc(LHS.getOpcode()) || isCttzOpc(LHS.getOpcode())) &&
5023 LHS.getOperand(0) == CmpLHS && isAllOnesConstant(RHS)) {
5024 unsigned Opc =
5025 isCttzOpc(LHS.getOpcode()) ? AMDGPUISD::FFBL_B32 : AMDGPUISD::FFBH_U32;
5026
5027 return getFFBX_U32(DAG, CmpLHS, SL, Opc);
5028 }
5029
5030 return SDValue();
5031}
5032
5034 unsigned Op,
5035 const SDLoc &SL,
5036 SDValue Cond,
5037 SDValue N1,
5038 SDValue N2) {
5039 SelectionDAG &DAG = DCI.DAG;
5040 EVT VT = N1.getValueType();
5041
5042 SDValue NewSelect = DAG.getNode(ISD::SELECT, SL, VT, Cond,
5043 N1.getOperand(0), N2.getOperand(0));
5044 DCI.AddToWorklist(NewSelect.getNode());
5045 return DAG.getNode(Op, SL, VT, NewSelect);
5046}
5047
5048// Pull a free FP operation out of a select so it may fold into uses.
5049//
5050// select c, (fneg x), (fneg y) -> fneg (select c, x, y)
5051// select c, (fneg x), k -> fneg (select c, x, (fneg k))
5052//
5053// select c, (fabs x), (fabs y) -> fabs (select c, x, y)
5054// select c, (fabs x), +k -> fabs (select c, x, k)
5055SDValue
5057 SDValue N) const {
5058 SelectionDAG &DAG = DCI.DAG;
5059 SDValue Cond = N.getOperand(0);
5060 SDValue LHS = N.getOperand(1);
5061 SDValue RHS = N.getOperand(2);
5062
5063 EVT VT = N.getValueType();
5064 if ((LHS.getOpcode() == ISD::FABS && RHS.getOpcode() == ISD::FABS) ||
5065 (LHS.getOpcode() == ISD::FNEG && RHS.getOpcode() == ISD::FNEG)) {
5067 return SDValue();
5068
5069 return distributeOpThroughSelect(DCI, LHS.getOpcode(),
5070 SDLoc(N), Cond, LHS, RHS);
5071 }
5072
5073 bool Inv = false;
5074 if (RHS.getOpcode() == ISD::FABS || RHS.getOpcode() == ISD::FNEG) {
5075 std::swap(LHS, RHS);
5076 Inv = true;
5077 }
5078
5079 // TODO: Support vector constants.
5081 if ((LHS.getOpcode() == ISD::FNEG || LHS.getOpcode() == ISD::FABS) && CRHS &&
5082 !selectSupportsSourceMods(N.getNode())) {
5083 SDLoc SL(N);
5084 // If one side is an fneg/fabs and the other is a constant, we can push the
5085 // fneg/fabs down. If it's an fabs, the constant needs to be non-negative.
5086 SDValue NewLHS = LHS.getOperand(0);
5087 SDValue NewRHS = RHS;
5088
5089 // Careful: if the neg can be folded up, don't try to pull it back down.
5090 bool ShouldFoldNeg = true;
5091
5092 if (NewLHS.hasOneUse()) {
5093 unsigned Opc = NewLHS.getOpcode();
5094 if (LHS.getOpcode() == ISD::FNEG && fnegFoldsIntoOp(NewLHS.getNode()))
5095 ShouldFoldNeg = false;
5096 if (LHS.getOpcode() == ISD::FABS && Opc == ISD::FMUL)
5097 ShouldFoldNeg = false;
5098 }
5099
5100 if (ShouldFoldNeg) {
5101 if (LHS.getOpcode() == ISD::FABS && CRHS->isNegative())
5102 return SDValue();
5103
5104 // We're going to be forced to use a source modifier anyway, there's no
5105 // point to pulling the negate out unless we can get a size reduction by
5106 // negating the constant.
5107 //
5108 // TODO: Generalize to use getCheaperNegatedExpression which doesn't know
5109 // about cheaper constants.
5110 if (NewLHS.getOpcode() == ISD::FABS &&
5112 return SDValue();
5113
5115 return SDValue();
5116
5117 if (LHS.getOpcode() == ISD::FNEG)
5118 NewRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
5119
5120 if (Inv)
5121 std::swap(NewLHS, NewRHS);
5122
5123 SDValue NewSelect = DAG.getNode(ISD::SELECT, SL, VT,
5124 Cond, NewLHS, NewRHS);
5125 DCI.AddToWorklist(NewSelect.getNode());
5126 return DAG.getNode(LHS.getOpcode(), SL, VT, NewSelect);
5127 }
5128 }
5129
5130 return SDValue();
5131}
5132
5134 DAGCombinerInfo &DCI) const {
5135 if (SDValue Folded = foldFreeOpFromSelect(DCI, SDValue(N, 0)))
5136 return Folded;
5137
5138 SDValue Cond = N->getOperand(0);
5139 if (Cond.getOpcode() != ISD::SETCC)
5140 return SDValue();
5141
5142 EVT VT = N->getValueType(0);
5143 SDValue LHS = Cond.getOperand(0);
5144 SDValue RHS = Cond.getOperand(1);
5145 SDValue CC = Cond.getOperand(2);
5146
5147 SDValue True = N->getOperand(1);
5148 SDValue False = N->getOperand(2);
5149
5150 if (Cond.hasOneUse()) { // TODO: Look for multiple select uses.
5151 SelectionDAG &DAG = DCI.DAG;
5152 if (DAG.isConstantValueOfAnyType(True) &&
5153 !DAG.isConstantValueOfAnyType(False)) {
5154 // Swap cmp + select pair to move constant to false input.
5155 // This will allow using VOPC cndmasks more often.
5156 // select (setcc x, y), k, x -> select (setccinv x, y), x, k
5157
5158 SDLoc SL(N);
5159 ISD::CondCode NewCC =
5160 getSetCCInverse(cast<CondCodeSDNode>(CC)->get(), LHS.getValueType());
5161
5162 SDValue NewCond = DAG.getSetCC(SL, Cond.getValueType(), LHS, RHS, NewCC);
5163 return DAG.getNode(ISD::SELECT, SL, VT, NewCond, False, True);
5164 }
5165
5166 if (VT == MVT::f32 && Subtarget->hasFminFmaxLegacy()) {
5168 = combineFMinMaxLegacy(SDLoc(N), VT, LHS, RHS, True, False, CC, DCI);
5169 // Revisit this node so we can catch min3/max3/med3 patterns.
5170 //DCI.AddToWorklist(MinMax.getNode());
5171 return MinMax;
5172 }
5173 }
5174
5175 // There's no reason to not do this if the condition has other uses.
5176 return performCtlz_CttzCombine(SDLoc(N), Cond, True, False, DCI);
5177}
5178
5179static bool isInv2Pi(const APFloat &APF) {
5180 static const APFloat KF16(APFloat::IEEEhalf(), APInt(16, 0x3118));
5181 static const APFloat KF32(APFloat::IEEEsingle(), APInt(32, 0x3e22f983));
5182 static const APFloat KF64(APFloat::IEEEdouble(), APInt(64, 0x3fc45f306dc9c882));
5183
5184 return APF.bitwiseIsEqual(KF16) ||
5185 APF.bitwiseIsEqual(KF32) ||
5186 APF.bitwiseIsEqual(KF64);
5187}
5188
5189// 0 and 1.0 / (0.5 * pi) do not have inline immmediates, so there is an
5190// additional cost to negate them.
5193 if (C->isZero())
5194 return C->isNegative() ? NegatibleCost::Cheaper : NegatibleCost::Expensive;
5195
5196 if (Subtarget->hasInv2PiInlineImm() && isInv2Pi(C->getValueAPF()))
5197 return C->isNegative() ? NegatibleCost::Cheaper : NegatibleCost::Expensive;
5198
5200}
5201
5207
5213
5214static unsigned inverseMinMax(unsigned Opc) {
5215 switch (Opc) {
5216 case ISD::FMAXNUM:
5217 return ISD::FMINNUM;
5218 case ISD::FMINNUM:
5219 return ISD::FMAXNUM;
5220 case ISD::FMAXNUM_IEEE:
5221 return ISD::FMINNUM_IEEE;
5222 case ISD::FMINNUM_IEEE:
5223 return ISD::FMAXNUM_IEEE;
5224 case ISD::FMAXIMUM:
5225 return ISD::FMINIMUM;
5226 case ISD::FMINIMUM:
5227 return ISD::FMAXIMUM;
5228 case ISD::FMAXIMUMNUM:
5229 return ISD::FMINIMUMNUM;
5230 case ISD::FMINIMUMNUM:
5231 return ISD::FMAXIMUMNUM;
5232 case AMDGPUISD::FMAX_LEGACY:
5233 return AMDGPUISD::FMIN_LEGACY;
5234 case AMDGPUISD::FMIN_LEGACY:
5235 return AMDGPUISD::FMAX_LEGACY;
5236 default:
5237 llvm_unreachable("invalid min/max opcode");
5238 }
5239}
5240
5241/// \return true if it's profitable to try to push an fneg into its source
5242/// instruction.
5244 // If the input has multiple uses and we can either fold the negate down, or
5245 // the other uses cannot, give up. This both prevents unprofitable
5246 // transformations and infinite loops: we won't repeatedly try to fold around
5247 // a negate that has no 'good' form.
5248 if (N0.hasOneUse()) {
5249 // This may be able to fold into the source, but at a code size cost. Don't
5250 // fold if the fold into the user is free.
5251 if (allUsesHaveSourceMods(N, 0))
5252 return false;
5253 } else {
5254 if (fnegFoldsIntoOp(N0.getNode()) &&
5256 return false;
5257 }
5258
5259 return true;
5260}
5261
5263 DAGCombinerInfo &DCI) const {
5264 SelectionDAG &DAG = DCI.DAG;
5265 SDValue N0 = N->getOperand(0);
5266 EVT VT = N->getValueType(0);
5267
5268 unsigned Opc = N0.getOpcode();
5269
5270 if (!shouldFoldFNegIntoSrc(N, N0))
5271 return SDValue();
5272
5273 SDLoc SL(N);
5274 switch (Opc) {
5275 case ISD::FADD: {
5276 if (!mayIgnoreSignedZero(N0) && !N->getFlags().hasNoSignedZeros())
5277 return SDValue();
5278
5279 // (fneg (fadd x, y)) -> (fadd (fneg x), (fneg y))
5280 SDValue LHS = N0.getOperand(0);
5281 SDValue RHS = N0.getOperand(1);
5282
5283 if (LHS.getOpcode() != ISD::FNEG)
5284 LHS = DAG.getNode(ISD::FNEG, SL, VT, LHS);
5285 else
5286 LHS = LHS.getOperand(0);
5287
5288 if (RHS.getOpcode() != ISD::FNEG)
5289 RHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
5290 else
5291 RHS = RHS.getOperand(0);
5292
5293 SDValue Res = DAG.getNode(ISD::FADD, SL, VT, LHS, RHS, N0->getFlags());
5294 if (Res.getOpcode() != ISD::FADD)
5295 return SDValue(); // Op got folded away.
5296 if (!N0.hasOneUse())
5297 DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Res));
5298 return Res;
5299 }
5300 case ISD::FMUL:
5301 case AMDGPUISD::FMUL_LEGACY: {
5302 // (fneg (fmul x, y)) -> (fmul x, (fneg y))
5303 // (fneg (fmul_legacy x, y)) -> (fmul_legacy x, (fneg y))
5304 SDValue LHS = N0.getOperand(0);
5305 SDValue RHS = N0.getOperand(1);
5306
5307 if (LHS.getOpcode() == ISD::FNEG)
5308 LHS = LHS.getOperand(0);
5309 else if (RHS.getOpcode() == ISD::FNEG)
5310 RHS = RHS.getOperand(0);
5311 else
5312 RHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
5313
5314 SDValue Res = DAG.getNode(Opc, SL, VT, LHS, RHS, N0->getFlags());
5315 if (Res.getOpcode() != Opc)
5316 return SDValue(); // Op got folded away.
5317 if (!N0.hasOneUse())
5318 DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Res));
5319 return Res;
5320 }
5321 case ISD::FMA:
5322 case ISD::FMAD: {
5323 // TODO: handle llvm.amdgcn.fma.legacy
5324 if (!mayIgnoreSignedZero(N0) && !N->getFlags().hasNoSignedZeros())
5325 return SDValue();
5326
5327 // (fneg (fma x, y, z)) -> (fma x, (fneg y), (fneg z))
5328 SDValue LHS = N0.getOperand(0);
5329 SDValue MHS = N0.getOperand(1);
5330 SDValue RHS = N0.getOperand(2);
5331
5332 if (LHS.getOpcode() == ISD::FNEG)
5333 LHS = LHS.getOperand(0);
5334 else if (MHS.getOpcode() == ISD::FNEG)
5335 MHS = MHS.getOperand(0);
5336 else
5337 MHS = DAG.getNode(ISD::FNEG, SL, VT, MHS);
5338
5339 if (RHS.getOpcode() != ISD::FNEG)
5340 RHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
5341 else
5342 RHS = RHS.getOperand(0);
5343
5344 SDValue Res = DAG.getNode(Opc, SL, VT, LHS, MHS, RHS);
5345 if (Res.getOpcode() != Opc)
5346 return SDValue(); // Op got folded away.
5347 if (!N0.hasOneUse())
5348 DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Res));
5349 return Res;
5350 }
5351 case ISD::FMAXNUM:
5352 case ISD::FMINNUM:
5353 case ISD::FMAXNUM_IEEE:
5354 case ISD::FMINNUM_IEEE:
5355 case ISD::FMINIMUM:
5356 case ISD::FMAXIMUM:
5357 case ISD::FMINIMUMNUM:
5358 case ISD::FMAXIMUMNUM:
5359 case AMDGPUISD::FMAX_LEGACY:
5360 case AMDGPUISD::FMIN_LEGACY: {
5361 // fneg (fmaxnum x, y) -> fminnum (fneg x), (fneg y)
5362 // fneg (fminnum x, y) -> fmaxnum (fneg x), (fneg y)
5363 // fneg (fmax_legacy x, y) -> fmin_legacy (fneg x), (fneg y)
5364 // fneg (fmin_legacy x, y) -> fmax_legacy (fneg x), (fneg y)
5365
5366 SDValue LHS = N0.getOperand(0);
5367 SDValue RHS = N0.getOperand(1);
5368
5369 // 0 doesn't have a negated inline immediate.
5370 // TODO: This constant check should be generalized to other operations.
5372 return SDValue();
5373
5374 SDValue NegLHS = DAG.getNode(ISD::FNEG, SL, VT, LHS);
5375 SDValue NegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
5376 unsigned Opposite = inverseMinMax(Opc);
5377
5378 SDValue Res = DAG.getNode(Opposite, SL, VT, NegLHS, NegRHS, N0->getFlags());
5379 if (Res.getOpcode() != Opposite)
5380 return SDValue(); // Op got folded away.
5381 if (!N0.hasOneUse())
5382 DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Res));
5383 return Res;
5384 }
5385 case AMDGPUISD::FMED3: {
5386 // med3 sorts a NaN input as smaller than everything regardless of its sign,
5387 // so negating all operands does not sign-flip the median when an input may
5388 // be NaN.
5389 if (!N0->getFlags().hasNoNaNs())
5390 return SDValue();
5391
5392 SDValue Ops[3];
5393 for (unsigned I = 0; I < 3; ++I)
5394 Ops[I] = DAG.getNode(ISD::FNEG, SL, VT, N0->getOperand(I), N0->getFlags());
5395
5396 SDValue Res = DAG.getNode(AMDGPUISD::FMED3, SL, VT, Ops, N0->getFlags());
5397 if (Res.getOpcode() != AMDGPUISD::FMED3)
5398 return SDValue(); // Op got folded away.
5399
5400 if (!N0.hasOneUse()) {
5401 SDValue Neg = DAG.getNode(ISD::FNEG, SL, VT, Res);
5402 DAG.ReplaceAllUsesWith(N0, Neg);
5403
5404 for (SDNode *U : Neg->users())
5405 DCI.AddToWorklist(U);
5406 }
5407
5408 return Res;
5409 }
5410 case ISD::FP_EXTEND:
5411 case ISD::FTRUNC:
5412 case ISD::FRINT:
5413 case ISD::FNEARBYINT: // XXX - Should fround be handled?
5414 case ISD::FROUNDEVEN:
5415 case ISD::FSIN:
5416 case ISD::FCANONICALIZE:
5417 case AMDGPUISD::RCP:
5418 case AMDGPUISD::RCP_LEGACY:
5419 case AMDGPUISD::RCP_IFLAG:
5420 case AMDGPUISD::SIN_HW: {
5421 SDValue CvtSrc = N0.getOperand(0);
5422 if (CvtSrc.getOpcode() == ISD::FNEG) {
5423 // (fneg (fp_extend (fneg x))) -> (fp_extend x)
5424 // (fneg (rcp (fneg x))) -> (rcp x)
5425 return DAG.getNode(Opc, SL, VT, CvtSrc.getOperand(0));
5426 }
5427
5428 if (!N0.hasOneUse())
5429 return SDValue();
5430
5431 // (fneg (fp_extend x)) -> (fp_extend (fneg x))
5432 // (fneg (rcp x)) -> (rcp (fneg x))
5433 SDValue Neg = DAG.getNode(ISD::FNEG, SL, CvtSrc.getValueType(), CvtSrc);
5434 return DAG.getNode(Opc, SL, VT, Neg, N0->getFlags());
5435 }
5436 case ISD::FP_ROUND: {
5437 SDValue CvtSrc = N0.getOperand(0);
5438
5439 if (CvtSrc.getOpcode() == ISD::FNEG) {
5440 // (fneg (fp_round (fneg x))) -> (fp_round x)
5441 return DAG.getNode(ISD::FP_ROUND, SL, VT,
5442 CvtSrc.getOperand(0), N0.getOperand(1));
5443 }
5444
5445 if (!N0.hasOneUse())
5446 return SDValue();
5447
5448 // (fneg (fp_round x)) -> (fp_round (fneg x))
5449 SDValue Neg = DAG.getNode(ISD::FNEG, SL, CvtSrc.getValueType(), CvtSrc);
5450 return DAG.getNode(ISD::FP_ROUND, SL, VT, Neg, N0.getOperand(1));
5451 }
5452 case ISD::FP16_TO_FP: {
5453 // v_cvt_f32_f16 supports source modifiers on pre-VI targets without legal
5454 // f16, but legalization of f16 fneg ends up pulling it out of the source.
5455 // Put the fneg back as a legal source operation that can be matched later.
5456 SDLoc SL(N);
5457
5458 SDValue Src = N0.getOperand(0);
5459 EVT SrcVT = Src.getValueType();
5460
5461 // fneg (fp16_to_fp x) -> fp16_to_fp (xor x, 0x8000)
5462 SDValue IntFNeg = DAG.getNode(ISD::XOR, SL, SrcVT, Src,
5463 DAG.getConstant(0x8000, SL, SrcVT));
5464 return DAG.getNode(ISD::FP16_TO_FP, SL, N->getValueType(0), IntFNeg);
5465 }
5466 case ISD::SELECT: {
5467 // fneg (select c, a, b) -> select c, (fneg a), (fneg b)
5468 // TODO: Invert conditions of foldFreeOpFromSelect
5469 return SDValue();
5470 }
5471 case ISD::BITCAST: {
5472 SDLoc SL(N);
5473 SDValue BCSrc = N0.getOperand(0);
5474 if (BCSrc.getOpcode() == ISD::BUILD_VECTOR) {
5475 SDValue HighBits = BCSrc.getOperand(BCSrc.getNumOperands() - 1);
5476 if (VT != MVT::f64 || HighBits.getValueType().getSizeInBits() != 32 ||
5477 !fnegFoldsIntoOp(HighBits.getNode()))
5478 return SDValue();
5479
5480 // f64 fneg only really needs to operate on the high half of of the
5481 // register, so try to force it to an f32 operation to help make use of
5482 // source modifiers.
5483 //
5484 //
5485 // fneg (f64 (bitcast (build_vector x, y))) ->
5486 // f64 (bitcast (build_vector (bitcast i32:x to f32),
5487 // (fneg (bitcast i32:y to f32)))
5488
5489 SDValue CastHi = DAG.getNode(ISD::BITCAST, SL, MVT::f32, HighBits);
5490 SDValue NegHi = DAG.getNode(ISD::FNEG, SL, MVT::f32, CastHi);
5491 SDValue CastBack =
5492 DAG.getNode(ISD::BITCAST, SL, HighBits.getValueType(), NegHi);
5493
5495 Ops.back() = CastBack;
5496 DCI.AddToWorklist(NegHi.getNode());
5497 SDValue Build =
5498 DAG.getNode(ISD::BUILD_VECTOR, SL, BCSrc.getValueType(), Ops);
5499 SDValue Result = DAG.getNode(ISD::BITCAST, SL, VT, Build);
5500
5501 if (!N0.hasOneUse())
5502 DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Result));
5503 return Result;
5504 }
5505
5506 if (BCSrc.getOpcode() == ISD::SELECT && VT == MVT::f32 &&
5507 BCSrc.hasOneUse()) {
5508 // fneg (bitcast (f32 (select cond, i32:lhs, i32:rhs))) ->
5509 // select cond, (bitcast i32:lhs to f32), (bitcast i32:rhs to f32)
5510
5511 // TODO: Cast back result for multiple uses is beneficial in some cases.
5512
5513 SDValue LHS =
5514 DAG.getNode(ISD::BITCAST, SL, MVT::f32, BCSrc.getOperand(1));
5515 SDValue RHS =
5516 DAG.getNode(ISD::BITCAST, SL, MVT::f32, BCSrc.getOperand(2));
5517
5518 SDValue NegLHS = DAG.getNode(ISD::FNEG, SL, MVT::f32, LHS);
5519 SDValue NegRHS = DAG.getNode(ISD::FNEG, SL, MVT::f32, RHS);
5520
5521 return DAG.getNode(ISD::SELECT, SL, MVT::f32, BCSrc.getOperand(0), NegLHS,
5522 NegRHS);
5523 }
5524
5525 return SDValue();
5526 }
5527 default:
5528 return SDValue();
5529 }
5530}
5531
5533 DAGCombinerInfo &DCI) const {
5534 SelectionDAG &DAG = DCI.DAG;
5535 SDValue N0 = N->getOperand(0);
5536
5537 if (!N0.hasOneUse())
5538 return SDValue();
5539
5540 switch (N0.getOpcode()) {
5541 case ISD::FP16_TO_FP: {
5542 assert(!isTypeLegal(MVT::f16) && "should only see if f16 is illegal");
5543 SDLoc SL(N);
5544 SDValue Src = N0.getOperand(0);
5545 EVT SrcVT = Src.getValueType();
5546
5547 // fabs (fp16_to_fp x) -> fp16_to_fp (and x, 0x7fff)
5548 SDValue IntFAbs = DAG.getNode(ISD::AND, SL, SrcVT, Src,
5549 DAG.getConstant(0x7fff, SL, SrcVT));
5550 return DAG.getNode(ISD::FP16_TO_FP, SL, N->getValueType(0), IntFAbs);
5551 }
5552 case ISD::FP_ROUND: {
5553 SDLoc SL(N);
5554 SDValue CvtSrc = N0.getOperand(0);
5555
5556 // fabs (fp_round x) -> fp_round (fabs x)
5557 SDValue Abs = DAG.getNode(ISD::FABS, SL, CvtSrc.getValueType(), CvtSrc,
5558 N->getFlags());
5559 return DAG.getNode(ISD::FP_ROUND, SL, N->getValueType(0), Abs,
5560 N0.getOperand(1), N0->getFlags());
5561 }
5562 default:
5563 return SDValue();
5564 }
5565}
5566
5568 DAGCombinerInfo &DCI) const {
5569 const auto *CFP = dyn_cast<ConstantFPSDNode>(N->getOperand(0));
5570 if (!CFP)
5571 return SDValue();
5572
5573 // XXX - Should this flush denormals?
5574 const APFloat &Val = CFP->getValueAPF();
5576 return DCI.DAG.getConstantFP(One / Val, SDLoc(N), N->getValueType(0));
5577}
5578
5580 if (!Subtarget->isGCN())
5581 return false;
5582
5585 auto &ST = DAG.getSubtarget<GCNSubtarget>();
5586 const auto *TII = ST.getInstrInfo();
5587
5588 if (!ST.hasVMovB64Inst() || (!SDConstant && !SDFPConstant))
5589 return false;
5590
5591 if (ST.has64BitLiterals())
5592 return true;
5593
5594 if (SDConstant) {
5595 const APInt &APVal = SDConstant->getAPIntValue();
5596 return isUInt<32>(APVal.getZExtValue()) || TII->isInlineConstant(APVal);
5597 }
5598
5599 APInt Val = SDFPConstant->getValueAPF().bitcastToAPInt();
5600 return isUInt<32>(Val.getZExtValue()) || TII->isInlineConstant(Val);
5601}
5602
5604 DAGCombinerInfo &DCI) const {
5605 SelectionDAG &DAG = DCI.DAG;
5606 SDLoc DL(N);
5607
5608 switch(N->getOpcode()) {
5609 default:
5610 break;
5611 case ISD::BITCAST: {
5612 EVT DestVT = N->getValueType(0);
5613
5614 // Push casts through vector builds. This helps avoid emitting a large
5615 // number of copies when materializing floating point vector constants.
5616 //
5617 // vNt1 bitcast (vNt0 (build_vector t0:x, t0:y)) =>
5618 // vnt1 = build_vector (t1 (bitcast t0:x)), (t1 (bitcast t0:y))
5619 if (DestVT.isVector()) {
5620 SDValue Src = N->getOperand(0);
5621 if (Src.getOpcode() == ISD::BUILD_VECTOR &&
5624 EVT SrcVT = Src.getValueType();
5625 unsigned NElts = DestVT.getVectorNumElements();
5626
5627 if (SrcVT.getVectorNumElements() == NElts) {
5628 EVT DestEltVT = DestVT.getVectorElementType();
5629
5630 SmallVector<SDValue, 8> CastedElts;
5631 SDLoc SL(N);
5632 for (unsigned I = 0, E = SrcVT.getVectorNumElements(); I != E; ++I) {
5633 SDValue Elt = Src.getOperand(I);
5634 CastedElts.push_back(DAG.getNode(ISD::BITCAST, DL, DestEltVT, Elt));
5635 }
5636
5637 return DAG.getBuildVector(DestVT, SL, CastedElts);
5638 }
5639 }
5640 }
5641
5642 if (DestVT.getSizeInBits() != 64 || !DestVT.isVector())
5643 break;
5644
5645 // Fold bitcasts of constants.
5646 //
5647 // v2i32 (bitcast i64:k) -> build_vector lo_32(k), hi_32(k)
5648 // TODO: Generalize and move to DAGCombiner
5649 SDValue Src = N->getOperand(0);
5651 SDLoc SL(N);
5652 if (isInt64ImmLegal(C, DAG))
5653 break;
5654 uint64_t CVal = C->getZExtValue();
5655 SDValue BV = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32,
5656 DAG.getConstant(Lo_32(CVal), SL, MVT::i32),
5657 DAG.getConstant(Hi_32(CVal), SL, MVT::i32));
5658 return DAG.getNode(ISD::BITCAST, SL, DestVT, BV);
5659 }
5660
5662 const APInt &Val = C->getValueAPF().bitcastToAPInt();
5663 SDLoc SL(N);
5664 if (isInt64ImmLegal(C, DAG))
5665 break;
5666 uint64_t CVal = Val.getZExtValue();
5667 SDValue Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32,
5668 DAG.getConstant(Lo_32(CVal), SL, MVT::i32),
5669 DAG.getConstant(Hi_32(CVal), SL, MVT::i32));
5670
5671 return DAG.getNode(ISD::BITCAST, SL, DestVT, Vec);
5672 }
5673
5674 break;
5675 }
5676 case ISD::SHL:
5677 case ISD::SRA:
5678 case ISD::SRL: {
5679 // Range metadata can be invalidated when loads are converted to legal types
5680 // (e.g. v2i64 -> v4i32).
5681 // Try to convert vector shl/sra/srl before type legalization so that range
5682 // metadata can be utilized.
5683 if (!(N->getValueType(0).isVector() &&
5686 break;
5687 if (N->getOpcode() == ISD::SHL)
5688 return performShlCombine(N, DCI);
5689 if (N->getOpcode() == ISD::SRA)
5690 return performSraCombine(N, DCI);
5691 return performSrlCombine(N, DCI);
5692 }
5693 case ISD::TRUNCATE:
5694 return performTruncateCombine(N, DCI);
5695 case ISD::MUL:
5696 return performMulCombine(N, DCI);
5697 case AMDGPUISD::MUL_U24:
5698 case AMDGPUISD::MUL_I24: {
5699 if (SDValue Simplified = simplifyMul24(N, DCI))
5700 return Simplified;
5701 break;
5702 }
5703 case AMDGPUISD::MULHI_I24:
5704 case AMDGPUISD::MULHI_U24:
5705 return simplifyMul24(N, DCI);
5706 case ISD::SMUL_LOHI:
5707 case ISD::UMUL_LOHI:
5708 return performMulLoHiCombine(N, DCI);
5709 case ISD::MULHS:
5710 return performMulhsCombine(N, DCI);
5711 case ISD::MULHU:
5712 return performMulhuCombine(N, DCI);
5713 case ISD::SELECT:
5714 return performSelectCombine(N, DCI);
5715 case ISD::FNEG:
5716 return performFNegCombine(N, DCI);
5717 case ISD::FABS:
5718 return performFAbsCombine(N, DCI);
5719 case AMDGPUISD::BFE_I32:
5720 case AMDGPUISD::BFE_U32: {
5721 assert(!N->getValueType(0).isVector() &&
5722 "Vector handling of BFE not implemented");
5723 ConstantSDNode *Width = dyn_cast<ConstantSDNode>(N->getOperand(2));
5724 if (!Width)
5725 break;
5726
5727 uint32_t WidthVal = Width->getZExtValue() & 0x1f;
5728 if (WidthVal == 0)
5729 return DAG.getConstant(0, DL, MVT::i32);
5730
5732 if (!Offset)
5733 break;
5734
5735 SDValue BitsFrom = N->getOperand(0);
5736 uint32_t OffsetVal = Offset->getZExtValue() & 0x1f;
5737
5738 bool Signed = N->getOpcode() == AMDGPUISD::BFE_I32;
5739
5740 if (OffsetVal == 0) {
5741 // This is already sign / zero extended, so try to fold away extra BFEs.
5742 unsigned SignBits = Signed ? (32 - WidthVal + 1) : (32 - WidthVal);
5743
5744 unsigned OpSignBits = DAG.ComputeNumSignBits(BitsFrom);
5745 if (OpSignBits >= SignBits)
5746 return BitsFrom;
5747
5748 EVT SmallVT = EVT::getIntegerVT(*DAG.getContext(), WidthVal);
5749 if (Signed) {
5750 // This is a sign_extend_inreg. Replace it to take advantage of existing
5751 // DAG Combines. If not eliminated, we will match back to BFE during
5752 // selection.
5753
5754 // TODO: The sext_inreg of extended types ends, although we can could
5755 // handle them in a single BFE.
5756 return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i32, BitsFrom,
5757 DAG.getValueType(SmallVT));
5758 }
5759
5760 return DAG.getZeroExtendInReg(BitsFrom, DL, SmallVT);
5761 }
5762
5763 if (ConstantSDNode *CVal = dyn_cast<ConstantSDNode>(BitsFrom)) {
5764 if (Signed) {
5765 return constantFoldBFE<int32_t>(DAG,
5766 CVal->getSExtValue(),
5767 OffsetVal,
5768 WidthVal,
5769 DL);
5770 }
5771
5772 return constantFoldBFE<uint32_t>(DAG,
5773 CVal->getZExtValue(),
5774 OffsetVal,
5775 WidthVal,
5776 DL);
5777 }
5778
5779 if ((OffsetVal + WidthVal) >= 32 &&
5780 !(OffsetVal == 16 && WidthVal == 16 && Subtarget->hasSDWA())) {
5781 SDValue ShiftVal = DAG.getConstant(OffsetVal, DL, MVT::i32);
5782 return DAG.getNode(Signed ? ISD::SRA : ISD::SRL, DL, MVT::i32,
5783 BitsFrom, ShiftVal);
5784 }
5785
5786 if (BitsFrom.hasOneUse()) {
5787 APInt Demanded = APInt::getBitsSet(32,
5788 OffsetVal,
5789 OffsetVal + WidthVal);
5790
5793 !DCI.isBeforeLegalizeOps());
5794 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
5795 if (TLI.ShrinkDemandedConstant(BitsFrom, Demanded, TLO) ||
5796 TLI.SimplifyDemandedBits(BitsFrom, Demanded, Known, TLO)) {
5797 DCI.CommitTargetLoweringOpt(TLO);
5798 }
5799 }
5800
5801 break;
5802 }
5803 case ISD::LOAD:
5804 return performLoadCombine(N, DCI);
5805 case ISD::STORE:
5806 return performStoreCombine(N, DCI);
5807 case AMDGPUISD::RCP:
5808 case AMDGPUISD::RCP_IFLAG:
5809 return performRcpCombine(N, DCI);
5810 case ISD::AssertZext:
5811 case ISD::AssertSext:
5812 return performAssertSZExtCombine(N, DCI);
5814 return performIntrinsicWOChainCombine(N, DCI);
5815 case AMDGPUISD::FMAD_FTZ: {
5816 SDValue N0 = N->getOperand(0);
5817 SDValue N1 = N->getOperand(1);
5818 SDValue N2 = N->getOperand(2);
5819 EVT VT = N->getValueType(0);
5820
5821 // FMAD_FTZ is a FMAD + flush denormals to zero.
5822 // We flush the inputs, the intermediate step, and the output.
5826 if (N0CFP && N1CFP && N2CFP) {
5827 const auto FTZ = [](const APFloat &V) {
5828 if (V.isDenormal()) {
5829 APFloat Zero(V.getSemantics(), 0);
5830 return V.isNegative() ? -Zero : Zero;
5831 }
5832 return V;
5833 };
5834
5835 APFloat V0 = FTZ(N0CFP->getValueAPF());
5836 APFloat V1 = FTZ(N1CFP->getValueAPF());
5837 APFloat V2 = FTZ(N2CFP->getValueAPF());
5839 V0 = FTZ(V0);
5841 return DAG.getConstantFP(FTZ(V0), DL, VT);
5842 }
5843 break;
5844 }
5845 }
5846 return SDValue();
5847}
5848
5850 SDValue Op, const APInt &OriginalDemandedBits,
5851 const APInt &OriginalDemandedElts, KnownBits &Known, TargetLoweringOpt &TLO,
5852 unsigned Depth) const {
5853 switch (Op.getOpcode()) {
5855 switch (Op.getConstantOperandVal(0)) {
5856 case Intrinsic::amdgcn_readfirstlane:
5857 case Intrinsic::amdgcn_readlane:
5858 case Intrinsic::amdgcn_set_inactive:
5859 case Intrinsic::amdgcn_wwm: {
5860 if (SimplifyDemandedBits(Op.getOperand(1), OriginalDemandedBits,
5861 OriginalDemandedElts, Known, TLO, Depth + 1))
5862 return true;
5863 break;
5864 }
5865 default:
5866 break;
5867 }
5868 break;
5869 }
5870 default:
5871 break;
5872 }
5873
5874 return false;
5875}
5876
5877//===----------------------------------------------------------------------===//
5878// Helper functions
5879//===----------------------------------------------------------------------===//
5880
5882 const TargetRegisterClass *RC,
5883 Register Reg, EVT VT,
5884 const SDLoc &SL,
5885 bool RawReg) const {
5887 MachineRegisterInfo &MRI = MF.getRegInfo();
5888 Register VReg;
5889
5890 if (!MRI.isLiveIn(Reg)) {
5891 VReg = MRI.createVirtualRegister(RC);
5892 MRI.addLiveIn(Reg, VReg);
5893 } else {
5894 VReg = MRI.getLiveInVirtReg(Reg);
5895 }
5896
5897 if (RawReg)
5898 return DAG.getRegister(VReg, VT);
5899
5900 return DAG.getCopyFromReg(DAG.getEntryNode(), SL, VReg, VT);
5901}
5902
5903// This may be called multiple times, and nothing prevents creating multiple
5904// objects at the same offset. See if we already defined this object.
5906 int64_t Offset) {
5907 for (int I = MFI.getObjectIndexBegin(); I < 0; ++I) {
5908 if (MFI.getObjectOffset(I) == Offset) {
5909 assert(MFI.getObjectSize(I) == Size);
5910 return I;
5911 }
5912 }
5913
5914 return MFI.CreateFixedObject(Size, Offset, true);
5915}
5916
5918 EVT VT,
5919 const SDLoc &SL,
5920 int64_t Offset) const {
5922 MachineFrameInfo &MFI = MF.getFrameInfo();
5923 int FI = getOrCreateFixedStackObject(MFI, VT.getStoreSize(), Offset);
5924
5925 auto SrcPtrInfo = MachinePointerInfo::getStack(MF, Offset);
5926 SDValue Ptr = DAG.getFrameIndex(FI, MVT::i32);
5927
5928 return DAG.getLoad(VT, SL, DAG.getEntryNode(), Ptr, SrcPtrInfo, Align(4),
5931}
5932
5934 const SDLoc &SL,
5935 SDValue Chain,
5936 SDValue ArgVal,
5937 int64_t Offset) const {
5941
5942 SDValue Ptr = DAG.getConstant(Offset, SL, MVT::i32);
5943 // Stores to the argument stack area are relative to the stack pointer.
5944 SDValue SP =
5945 DAG.getCopyFromReg(Chain, SL, Info->getStackPtrOffsetReg(), MVT::i32);
5946 Ptr = DAG.getNode(ISD::ADD, SL, MVT::i32, SP, Ptr);
5947 SDValue Store = DAG.getStore(Chain, SL, ArgVal, Ptr, DstInfo, Align(4),
5949 return Store;
5950}
5951
5953 const TargetRegisterClass *RC,
5954 EVT VT, const SDLoc &SL,
5955 const ArgDescriptor &Arg) const {
5956 assert(Arg && "Attempting to load missing argument");
5957
5958 SDValue V = Arg.isRegister() ?
5959 CreateLiveInRegister(DAG, RC, Arg.getRegister(), VT, SL) :
5960 loadStackInputValue(DAG, VT, SL, Arg.getStackOffset());
5961
5962 if (!Arg.isMasked())
5963 return V;
5964
5965 unsigned Mask = Arg.getMask();
5966 unsigned Shift = llvm::countr_zero<unsigned>(Mask);
5967 V = DAG.getNode(ISD::SRL, SL, VT, V,
5968 DAG.getShiftAmountConstant(Shift, VT, SL));
5969 return DAG.getNode(ISD::AND, SL, VT, V,
5970 DAG.getConstant(Mask >> Shift, SL, VT));
5971}
5972
5974 uint64_t ExplicitKernArgSize, const ImplicitParameter Param) const {
5975 unsigned ExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();
5976 const Align Alignment = Subtarget->getAlignmentForImplicitArgPtr();
5977 uint64_t ArgOffset =
5978 alignTo(ExplicitKernArgSize, Alignment) + ExplicitArgOffset;
5979 switch (Param) {
5980 case FIRST_IMPLICIT:
5981 return ArgOffset;
5982 case PRIVATE_BASE:
5984 case SHARED_BASE:
5985 return ArgOffset + AMDGPU::ImplicitArg::SHARED_BASE_OFFSET;
5986 case QUEUE_PTR:
5987 return ArgOffset + AMDGPU::ImplicitArg::QUEUE_PTR_OFFSET;
5988 }
5989 llvm_unreachable("unexpected implicit parameter type");
5990}
5991
5998
6000 SelectionDAG &DAG, int Enabled,
6001 int &RefinementSteps,
6002 bool &UseOneConstNR,
6003 bool Reciprocal) const {
6004 EVT VT = Operand.getValueType();
6005
6006 if (VT == MVT::f32) {
6007 RefinementSteps = 0;
6008 return DAG.getNode(AMDGPUISD::RSQ, SDLoc(Operand), VT, Operand);
6009 }
6010
6011 // TODO: There is also f64 rsq instruction, but the documentation is less
6012 // clear on its precision.
6013
6014 return SDValue();
6015}
6016
6018 SelectionDAG &DAG, int Enabled,
6019 int &RefinementSteps) const {
6020 EVT VT = Operand.getValueType();
6021
6022 if (VT == MVT::f32) {
6023 // Reciprocal, < 1 ulp error.
6024 //
6025 // This reciprocal approximation converges to < 0.5 ulp error with one
6026 // newton rhapson performed with two fused multiple adds (FMAs).
6027
6028 RefinementSteps = 0;
6029 return DAG.getNode(AMDGPUISD::RCP, SDLoc(Operand), VT, Operand);
6030 }
6031
6032 // TODO: There is also f64 rcp instruction, but the documentation is less
6033 // clear on its precision.
6034
6035 return SDValue();
6036}
6037
6038static unsigned workitemIntrinsicDim(unsigned ID) {
6039 switch (ID) {
6040 case Intrinsic::amdgcn_workitem_id_x:
6041 return 0;
6042 case Intrinsic::amdgcn_workitem_id_y:
6043 return 1;
6044 case Intrinsic::amdgcn_workitem_id_z:
6045 return 2;
6046 default:
6047 llvm_unreachable("not a workitem intrinsic");
6048 }
6049}
6050
6052 const SDValue Op, KnownBits &Known,
6053 const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const {
6054
6055 Known.resetAll(); // Don't know anything.
6056
6057 unsigned Opc = Op.getOpcode();
6058
6059 switch (Opc) {
6060 default:
6061 break;
6062 case AMDGPUISD::CARRY:
6063 case AMDGPUISD::BORROW: {
6064 Known.Zero = APInt::getHighBitsSet(32, 31);
6065 break;
6066 }
6067
6068 case AMDGPUISD::BFE_I32:
6069 case AMDGPUISD::BFE_U32: {
6070 ConstantSDNode *CWidth = dyn_cast<ConstantSDNode>(Op.getOperand(2));
6071 if (!CWidth)
6072 return;
6073
6074 uint32_t Width = CWidth->getZExtValue() & 0x1f;
6075
6076 if (Opc == AMDGPUISD::BFE_U32)
6077 Known.Zero = APInt::getHighBitsSet(32, 32 - Width);
6078
6079 break;
6080 }
6081 case AMDGPUISD::FP_TO_FP16: {
6082 unsigned BitWidth = Known.getBitWidth();
6083
6084 // High bits are zero.
6086 break;
6087 }
6088 case AMDGPUISD::MUL_U24:
6089 case AMDGPUISD::MUL_I24: {
6090 KnownBits LHSKnown = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
6091 KnownBits RHSKnown = DAG.computeKnownBits(Op.getOperand(1), Depth + 1);
6092 unsigned BitWidth = Op.getScalarValueSizeInBits();
6093
6094 // Sign/Zero extend from 24 bits.
6095 if (Opc == AMDGPUISD::MUL_I24) {
6096 LHSKnown = LHSKnown.trunc(24).sext(BitWidth);
6097 RHSKnown = RHSKnown.trunc(24).sext(BitWidth);
6098 } else {
6099 LHSKnown = LHSKnown.trunc(24).zext(BitWidth);
6100 RHSKnown = RHSKnown.trunc(24).zext(BitWidth);
6101 }
6102
6103 // TODO: SelfMultiply can be poison, but not undef.
6104 bool SelfMultiply = Op.getOperand(0) == Op.getOperand(1);
6105 if (SelfMultiply)
6106 SelfMultiply &= DAG.isGuaranteedNotToBeUndefOrPoison(
6107 Op.getOperand(0), DemandedElts, UndefPoisonKind::UndefOrPoison,
6108 Depth + 1);
6109
6110 Known = KnownBits::mul(LHSKnown, RHSKnown, SelfMultiply);
6111 break;
6112 }
6113 case AMDGPUISD::PERM: {
6114 ConstantSDNode *CMask = dyn_cast<ConstantSDNode>(Op.getOperand(2));
6115 if (!CMask)
6116 return;
6117
6118 KnownBits LHSKnown = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
6119 KnownBits RHSKnown = DAG.computeKnownBits(Op.getOperand(1), Depth + 1);
6120 unsigned Sel = CMask->getZExtValue();
6121
6122 for (unsigned I = 0; I < 32; I += 8) {
6123 unsigned SelBits = Sel & 0xff;
6124 if (SelBits < 4) {
6125 SelBits *= 8;
6126 Known.One |= ((RHSKnown.One.getZExtValue() >> SelBits) & 0xff) << I;
6127 Known.Zero |= ((RHSKnown.Zero.getZExtValue() >> SelBits) & 0xff) << I;
6128 } else if (SelBits < 7) {
6129 SelBits = (SelBits & 3) * 8;
6130 Known.One |= ((LHSKnown.One.getZExtValue() >> SelBits) & 0xff) << I;
6131 Known.Zero |= ((LHSKnown.Zero.getZExtValue() >> SelBits) & 0xff) << I;
6132 } else if (SelBits == 0x0c) {
6133 Known.Zero |= 0xFFull << I;
6134 } else if (SelBits > 0x0c) {
6135 Known.One |= 0xFFull << I;
6136 }
6137 Sel >>= 8;
6138 }
6139 break;
6140 }
6141 case AMDGPUISD::BUFFER_LOAD_UBYTE: {
6142 Known.Zero.setHighBits(24);
6143 break;
6144 }
6145 case AMDGPUISD::BUFFER_LOAD_USHORT: {
6146 Known.Zero.setHighBits(16);
6147 break;
6148 }
6149 case AMDGPUISD::LDS: {
6150 auto *GA = cast<GlobalAddressSDNode>(Op.getOperand(0).getNode());
6151 Align Alignment = GA->getGlobal()->getPointerAlignment(DAG.getDataLayout());
6152
6153 Known.Zero.setHighBits(16);
6154 Known.Zero.setLowBits(Log2(Alignment));
6155 break;
6156 }
6157 case AMDGPUISD::SMIN3:
6158 case AMDGPUISD::SMAX3:
6159 case AMDGPUISD::SMED3:
6160 case AMDGPUISD::UMIN3:
6161 case AMDGPUISD::UMAX3:
6162 case AMDGPUISD::UMED3: {
6163 KnownBits Known2 = DAG.computeKnownBits(Op.getOperand(2), Depth + 1);
6164 if (Known2.isUnknown())
6165 break;
6166
6167 KnownBits Known1 = DAG.computeKnownBits(Op.getOperand(1), Depth + 1);
6168 if (Known1.isUnknown())
6169 break;
6170
6171 KnownBits Known0 = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
6172 if (Known0.isUnknown())
6173 break;
6174
6175 // TODO: Handle LeadZero/LeadOne from UMIN/UMAX handling.
6176 Known.Zero = Known0.Zero & Known1.Zero & Known2.Zero;
6177 Known.One = Known0.One & Known1.One & Known2.One;
6178 break;
6179 }
6181 unsigned IID = Op.getConstantOperandVal(0);
6182 switch (IID) {
6183 case Intrinsic::amdgcn_workitem_id_x:
6184 case Intrinsic::amdgcn_workitem_id_y:
6185 case Intrinsic::amdgcn_workitem_id_z: {
6186 unsigned MaxValue = Subtarget->getMaxWorkitemID(
6188 Known.Zero.setHighBits(llvm::countl_zero(MaxValue));
6189 break;
6190 }
6191 default:
6192 break;
6193 }
6194 }
6195 }
6196}
6197
6199 SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG,
6200 unsigned Depth) const {
6201 switch (Op.getOpcode()) {
6202 case AMDGPUISD::BFE_I32: {
6203 ConstantSDNode *Width = dyn_cast<ConstantSDNode>(Op.getOperand(2));
6204 if (!Width)
6205 return 1;
6206
6207 unsigned SignBits = 32 - (Width->getZExtValue() & 0x1f) + 1;
6208 if (!isNullConstant(Op.getOperand(1)))
6209 return SignBits;
6210
6211 // TODO: Could probably figure something out with non-0 offsets.
6212 unsigned Op0SignBits = DAG.ComputeNumSignBits(Op.getOperand(0), Depth + 1);
6213 return std::max(SignBits, Op0SignBits);
6214 }
6215
6216 case AMDGPUISD::BFE_U32: {
6217 ConstantSDNode *Width = dyn_cast<ConstantSDNode>(Op.getOperand(2));
6218 return Width ? 32 - (Width->getZExtValue() & 0x1f) : 1;
6219 }
6220
6221 case AMDGPUISD::CARRY:
6222 case AMDGPUISD::BORROW:
6223 return 31;
6224 case AMDGPUISD::BUFFER_LOAD_BYTE:
6225 return 25;
6226 case AMDGPUISD::BUFFER_LOAD_SHORT:
6227 return 17;
6228 case AMDGPUISD::BUFFER_LOAD_UBYTE:
6229 return 24;
6230 case AMDGPUISD::BUFFER_LOAD_USHORT:
6231 return 16;
6232 case AMDGPUISD::FP_TO_FP16:
6233 return 16;
6234 case AMDGPUISD::SMIN3:
6235 case AMDGPUISD::SMAX3:
6236 case AMDGPUISD::SMED3:
6237 case AMDGPUISD::UMIN3:
6238 case AMDGPUISD::UMAX3:
6239 case AMDGPUISD::UMED3: {
6240 unsigned Tmp2 = DAG.ComputeNumSignBits(Op.getOperand(2), Depth + 1);
6241 if (Tmp2 == 1)
6242 return 1; // Early out.
6243
6244 unsigned Tmp1 = DAG.ComputeNumSignBits(Op.getOperand(1), Depth + 1);
6245 if (Tmp1 == 1)
6246 return 1; // Early out.
6247
6248 unsigned Tmp0 = DAG.ComputeNumSignBits(Op.getOperand(0), Depth + 1);
6249 if (Tmp0 == 1)
6250 return 1; // Early out.
6251
6252 return std::min({Tmp0, Tmp1, Tmp2});
6253 }
6254 default:
6255 return 1;
6256 }
6257}
6258
6260 GISelValueTracking &Analysis, Register R, const APInt &DemandedElts,
6261 const MachineRegisterInfo &MRI, unsigned Depth) const {
6262 const MachineInstr *MI = MRI.getVRegDef(R);
6263 if (!MI)
6264 return 1;
6265
6266 // TODO: Check range metadata on MMO.
6267 switch (MI->getOpcode()) {
6268 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SBYTE:
6269 return 25;
6270 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SSHORT:
6271 return 17;
6272 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
6273 return 24;
6274 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
6275 return 16;
6276 case AMDGPU::G_AMDGPU_SMED3:
6277 case AMDGPU::G_AMDGPU_UMED3: {
6278 auto [Dst, Src0, Src1, Src2] = MI->getFirst4Regs();
6279 unsigned Tmp2 = Analysis.computeNumSignBits(Src2, DemandedElts, Depth + 1);
6280 if (Tmp2 == 1)
6281 return 1;
6282 unsigned Tmp1 = Analysis.computeNumSignBits(Src1, DemandedElts, Depth + 1);
6283 if (Tmp1 == 1)
6284 return 1;
6285 unsigned Tmp0 = Analysis.computeNumSignBits(Src0, DemandedElts, Depth + 1);
6286 if (Tmp0 == 1)
6287 return 1;
6288 return std::min({Tmp0, Tmp1, Tmp2});
6289 }
6290 default:
6291 return 1;
6292 }
6293}
6294
6296 SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG,
6297 UndefPoisonKind Kind, bool ConsiderFlags, unsigned Depth) const {
6298 unsigned Opcode = Op.getOpcode();
6299 switch (Opcode) {
6300 case AMDGPUISD::BFE_I32:
6301 case AMDGPUISD::BFE_U32:
6302 return false;
6303 }
6305 Op, DemandedElts, DAG, Kind, ConsiderFlags, Depth);
6306}
6307
6309 SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN,
6310 unsigned Depth) const {
6311 unsigned Opcode = Op.getOpcode();
6312 switch (Opcode) {
6313 case AMDGPUISD::FMIN_LEGACY:
6314 case AMDGPUISD::FMAX_LEGACY: {
6315 if (SNaN)
6316 return true;
6317
6318 // TODO: Can check no nans on one of the operands for each one, but which
6319 // one?
6320 return false;
6321 }
6322 case AMDGPUISD::FMUL_LEGACY:
6323 case AMDGPUISD::CVT_PKRTZ_F16_F32: {
6324 if (SNaN)
6325 return true;
6326 return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1) &&
6327 DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1);
6328 }
6329 case AMDGPUISD::FMED3:
6330 case AMDGPUISD::FMIN3:
6331 case AMDGPUISD::FMAX3:
6332 case AMDGPUISD::FMINIMUM3:
6333 case AMDGPUISD::FMAXIMUM3:
6334 case AMDGPUISD::FMAD_FTZ: {
6335 if (SNaN)
6336 return true;
6337 return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1) &&
6338 DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1) &&
6339 DAG.isKnownNeverNaN(Op.getOperand(2), SNaN, Depth + 1);
6340 }
6341 case AMDGPUISD::CVT_F32_UBYTE0:
6342 case AMDGPUISD::CVT_F32_UBYTE1:
6343 case AMDGPUISD::CVT_F32_UBYTE2:
6344 case AMDGPUISD::CVT_F32_UBYTE3:
6345 return true;
6346
6347 case AMDGPUISD::RCP:
6348 case AMDGPUISD::RSQ:
6349 case AMDGPUISD::RCP_LEGACY:
6350 case AMDGPUISD::RSQ_CLAMP: {
6351 if (SNaN)
6352 return true;
6353
6354 // TODO: Need is known positive check.
6355 return false;
6356 }
6357 case ISD::FLDEXP:
6358 case AMDGPUISD::FRACT: {
6359 if (SNaN)
6360 return true;
6361 return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1);
6362 }
6363 case AMDGPUISD::DIV_SCALE:
6364 case AMDGPUISD::DIV_FMAS:
6365 case AMDGPUISD::DIV_FIXUP:
6366 // TODO: Refine on operands.
6367 return SNaN;
6368 case AMDGPUISD::SIN_HW:
6369 case AMDGPUISD::COS_HW: {
6370 // TODO: Need check for infinity
6371 return SNaN;
6372 }
6374 unsigned IntrinsicID = Op.getConstantOperandVal(0);
6375 // TODO: Handle more intrinsics
6376 switch (IntrinsicID) {
6377 case Intrinsic::amdgcn_cubeid:
6378 case Intrinsic::amdgcn_cvt_off_f32_i4:
6379 return true;
6380
6381 case Intrinsic::amdgcn_frexp_mant: {
6382 if (SNaN)
6383 return true;
6384 return DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1);
6385 }
6386 case Intrinsic::amdgcn_cvt_pkrtz: {
6387 if (SNaN)
6388 return true;
6389 return DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1) &&
6390 DAG.isKnownNeverNaN(Op.getOperand(2), SNaN, Depth + 1);
6391 }
6392 case Intrinsic::amdgcn_rcp:
6393 case Intrinsic::amdgcn_rsq:
6394 case Intrinsic::amdgcn_rcp_legacy:
6395 case Intrinsic::amdgcn_rsq_legacy:
6396 case Intrinsic::amdgcn_rsq_clamp:
6397 case Intrinsic::amdgcn_tanh: {
6398 if (SNaN)
6399 return true;
6400
6401 // TODO: Need is known positive check.
6402 return false;
6403 }
6404 case Intrinsic::amdgcn_trig_preop:
6405 case Intrinsic::amdgcn_fdot2:
6406 // TODO: Refine on operand
6407 return SNaN;
6408 case Intrinsic::amdgcn_fma_legacy:
6409 if (SNaN)
6410 return true;
6411 return DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1) &&
6412 DAG.isKnownNeverNaN(Op.getOperand(2), SNaN, Depth + 1) &&
6413 DAG.isKnownNeverNaN(Op.getOperand(3), SNaN, Depth + 1);
6414 default:
6415 return false;
6416 }
6417 }
6418 default:
6419 return false;
6420 }
6421}
6422
6424 Register N0, Register N1) const {
6425 return MRI.hasOneNonDBGUse(N0); // FIXME: handle regbanks
6426}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static LLVM_READONLY bool hasSourceMods(const MachineInstr &MI)
static bool isInv2Pi(const APFloat &APF)
static LLVM_READONLY bool opMustUseVOP3Encoding(const MachineInstr &MI, const MachineRegisterInfo &MRI)
returns true if the operation will definitely need to use a 64-bit encoding, and thus will use a VOP3...
static unsigned inverseMinMax(unsigned Opc)
static SDValue extractF64Exponent(SDValue Hi, const SDLoc &SL, SelectionDAG &DAG)
static unsigned workitemIntrinsicDim(unsigned ID)
static int getOrCreateFixedStackObject(MachineFrameInfo &MFI, unsigned Size, int64_t Offset)
static SDValue constantFoldBFE(SelectionDAG &DAG, IntTy Src0, uint32_t Offset, uint32_t Width, const SDLoc &DL)
static SDValue getMad(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue X, SDValue Y, SDValue C, SDNodeFlags Flags=SDNodeFlags())
static SDValue getAddOneOp(const SDNode *V)
If V is an add of a constant 1, returns the other operand.
static LLVM_READONLY bool selectSupportsSourceMods(const SDNode *N)
Return true if v_cndmask_b32 will support fabs/fneg source modifiers for the type for ISD::SELECT.
static cl::opt< bool > AMDGPUBypassSlowDiv("amdgpu-bypass-slow-div", cl::desc("Skip 64-bit divide for dynamic 32-bit values"), cl::init(true))
static SDValue getMul24(SelectionDAG &DAG, const SDLoc &SL, SDValue N0, SDValue N1, unsigned Size, bool Signed)
static bool fnegFoldsIntoOp(const SDNode *N)
static bool isI24(SDValue Op, SelectionDAG &DAG)
static bool isCttzOpc(unsigned Opc)
static bool isU24(SDValue Op, SelectionDAG &DAG)
static SDValue peekFPSignOps(SDValue Val)
static bool valueIsKnownNeverF32Denorm(SDValue Src)
Return true if it's known that Src can never be an f32 denormal value.
static SDValue distributeOpThroughSelect(TargetLowering::DAGCombinerInfo &DCI, unsigned Op, const SDLoc &SL, SDValue Cond, SDValue N1, SDValue N2)
static SDValue peekFNeg(SDValue Val)
static SDValue simplifyMul24(SDNode *Node24, TargetLowering::DAGCombinerInfo &DCI)
static bool isCtlzOpc(unsigned Opc)
static LLVM_READNONE bool fnegFoldsIntoOpcode(unsigned Opc)
static bool hasVolatileUser(SDNode *Val)
Interface definition of the TargetLowering class that is common to all AMD GPUs.
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
block Block Frequency Analysis
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_READNONE
Definition Compiler.h:317
#define LLVM_READONLY
Definition Compiler.h:324
Provides analysis for querying information about KnownBits during GISel passes.
const HexagonInstrInfo * TII
static MaybeAlign getAlign(Value *Ptr)
IRTranslator LLVM IR MI
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
#define T
#define P(N)
const SmallVectorImpl< MachineOperand > & Cond
#define CH(x, y, z)
Definition SHA256.cpp:34
Func MI getDebugLoc()))
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
Value * RHS
Value * LHS
BinaryOperator * Mul
static CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg)
static CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool IsVarArg)
unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV)
void recordNumNamedBarriers(uint32_t GVAddr, unsigned BarCnt)
static std::optional< uint32_t > getLDSAbsoluteAddress(const GlobalValue &GV)
static unsigned numBitsSigned(SDValue Op, SelectionDAG &DAG)
SDValue combineFMinMaxLegacy(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, SDValue True, SDValue False, SDValue CC, DAGCombinerInfo &DCI) const
Generate Min/Max node.
unsigned ComputeNumSignBitsForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
This method can be implemented by targets that want to expose additional information about sign bits ...
SDValue performMulhuCombine(SDNode *N, DAGCombinerInfo &DCI) const
EVT getTypeForExtReturn(LLVMContext &Context, EVT VT, ISD::NodeType ExtendKind) const override
Return the type that should be used to zero or sign extend a zeroext/signext integer return value.
SDValue SplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Split a vector load into 2 loads of half the vector.
SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const
SDValue performLoadCombine(SDNode *N, DAGCombinerInfo &DCI) const
void analyzeFormalArgumentsCompute(CCState &State, const SmallVectorImpl< ISD::InputArg > &Ins) const
The SelectionDAGBuilder will automatically promote function arguments with illegal types.
SDValue LowerF64ToF16Safe(SDValue Src, const SDLoc &DL, SelectionDAG &DAG) const
SDValue LowerFROUND(SDValue Op, SelectionDAG &DAG) const
SDValue storeStackInputValue(SelectionDAG &DAG, const SDLoc &SL, SDValue Chain, SDValue ArgVal, int64_t Offset) const
bool storeOfVectorConstantIsCheap(bool IsZero, EVT MemVT, unsigned NumElem, unsigned AS) const override
Return true if it is expected to be cheaper to do a store of vector constant with the given size and ...
SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG) const
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool shouldCombineMemoryType(EVT VT) const
SDValue splitBinaryBitConstantOpImpl(DAGCombinerInfo &DCI, const SDLoc &SL, unsigned Opc, SDValue LHS, uint32_t ValLo, uint32_t ValHi) const
Split the 64-bit value LHS into two 32-bit components, and perform the binary operation Opc to it wit...
SDValue lowerUnhandledCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals, StringRef Reason) const
virtual SDValue LowerGlobalAddress(AMDGPUMachineFunctionInfo *MFI, SDValue Op, SelectionDAG &DAG) const
SDValue performAssertSZExtCombine(SDNode *N, DAGCombinerInfo &DCI) const
bool isTruncateFree(EVT Src, EVT Dest) const override
bool aggressivelyPreferBuildVectorSources(EVT VecVT) const override
SDValue LowerFCEIL(SDValue Op, SelectionDAG &DAG) const
TargetLowering::NegatibleCost getConstantNegateCost(const ConstantFPSDNode *C) const
SDValue LowerFLOGUnsafe(SDValue Op, const SDLoc &SL, SelectionDAG &DAG, bool IsLog10, SDNodeFlags Flags) const
SDValue performMulhsCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue lowerFEXPUnsafeImpl(SDValue Op, const SDLoc &SL, SelectionDAG &DAG, SDNodeFlags Flags, bool IsExp10) const
bool isSDNodeAlwaysUniform(const SDNode *N) const override
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
SDValue performShlCombine(SDNode *N, DAGCombinerInfo &DCI) const
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
SDValue LowerSDIVREM(SDValue Op, SelectionDAG &DAG) const
bool isFNegFree(EVT VT) const override
Return true if an fneg operation is free to the point where it is never worthwhile to replace it with...
SDValue LowerFLOG10(SDValue Op, SelectionDAG &DAG) const
SDValue LowerINT_TO_FP64(SDValue Op, SelectionDAG &DAG, bool Signed) const
unsigned computeNumSignBitsForTargetInstr(GISelValueTracking &Analysis, Register R, const APInt &DemandedElts, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
This method can be implemented by targets that want to expose additional information about sign bits ...
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
SDValue LowerFP_TO_FP16(SDValue Op, SelectionDAG &DAG) const
SDValue addTokenForArgument(SDValue Chain, SelectionDAG &DAG, MachineFrameInfo &MFI, int ClobberedFI) const
bool isConstantCheaperToNegate(SDValue N) const
bool isReassocProfitable(MachineRegisterInfo &MRI, Register N0, Register N1) const override
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN=false, unsigned Depth=0) const override
If SNaN is false,.
static bool needsDenormHandlingF32(const SelectionDAG &DAG, SDValue Src, SDNodeFlags Flags)
uint32_t getImplicitParameterOffset(const MachineFunction &MF, const ImplicitParameter Param) const
Helper function that returns the byte offset of the given type of implicit parameter.
SDValue lowerFEXPF64(SDValue Op, SelectionDAG &DAG) const
SDValue LowerFFLOOR(SDValue Op, SelectionDAG &DAG) const
SDValue performSelectCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue performFNegCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const
bool isConstantCostlierToNegate(SDValue N) const
SDValue loadInputValue(SelectionDAG &DAG, const TargetRegisterClass *RC, EVT VT, const SDLoc &SL, const ArgDescriptor &Arg) const
SDValue LowerDIVREM24(SDValue Op, SelectionDAG &DAG, bool sign) const
SDValue lowerFEXP10Unsafe(SDValue Op, const SDLoc &SL, SelectionDAG &DAG, SDNodeFlags Flags) const
Emit approx-funcs appropriate lowering for exp10.
bool shouldReduceLoadWidth(SDNode *Load, ISD::LoadExtType ExtType, EVT ExtVT, std::optional< unsigned > ByteOffset) const override
Return true if it is profitable to reduce a load to a smaller type.
SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, UndefPoisonKind Kind, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
SDValue performCtlz_CttzCombine(const SDLoc &SL, SDValue Cond, SDValue LHS, SDValue RHS, DAGCombinerInfo &DCI) const
SDValue performSraCombine(SDNode *N, DAGCombinerInfo &DCI) const
bool isSelectSupported(SelectSupportKind) const override
bool isZExtFree(Type *Src, Type *Dest) const override
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
SDValue lowerFEXP2(SDValue Op, SelectionDAG &DAG) const
SDValue LowerCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
SDValue performSrlCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue lowerFEXP(SDValue Op, SelectionDAG &DAG) const
SDValue getIsLtSmallestNormal(SelectionDAG &DAG, SDValue Op, SDNodeFlags Flags) const
bool mayIgnoreSignedZero(SDValue Op) const
SDValue getIsFinite(SelectionDAG &DAG, SDValue Op, SDNodeFlags Flags) const
bool isLoadBitCastBeneficial(EVT, EVT, const SelectionDAG &DAG, const MachineMemOperand &MMO) const final
Return true if the following transform is beneficial: fold (conv (load x)) -> (load (conv*)x) On arch...
std::pair< SDValue, SDValue > splitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HighVT, SelectionDAG &DAG) const
Split a vector value into two parts of types LoVT and HiVT.
AMDGPUTargetLowering(const TargetMachine &TM, const TargetSubtargetInfo &STI, const AMDGPUSubtarget &AMDGPUSTI)
SDValue LowerFLOGCommon(SDValue Op, SelectionDAG &DAG) const
SDValue foldFreeOpFromSelect(TargetLowering::DAGCombinerInfo &DCI, SDValue N) const
SDValue LowerINT_TO_FP32(SDValue Op, SelectionDAG &DAG, bool Signed) const
bool isFAbsFree(EVT VT) const override
Return true if an fabs operation is free to the point where it is never worthwhile to replace it with...
bool isInt64ImmLegal(SDNode *Val, SelectionDAG &DAG) const
Check whether value Val can be supported by v_mov_b64, for the current target.
SDValue loadStackInputValue(SelectionDAG &DAG, EVT VT, const SDLoc &SL, int64_t Offset) const
Similar to CreateLiveInRegister, except value maybe loaded from a stack slot rather than passed in a ...
SDValue LowerFLOG2(SDValue Op, SelectionDAG &DAG) const
static EVT getEquivalentMemType(LLVMContext &Context, EVT VT)
SDValue LowerCTLS(SDValue Op, SelectionDAG &DAG) const
Split a vector store into multiple scalar stores.
SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps, bool &UseOneConstNR, bool Reciprocal) const override
Hooks for building estimates in place of slower divisions and square roots.
SDValue performTruncateCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const
static SDValue stripBitcast(SDValue Val)
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const
SDValue CreateLiveInRegister(SelectionDAG &DAG, const TargetRegisterClass *RC, Register Reg, EVT VT, const SDLoc &SL, bool RawReg=false) const
Helper function that adds Reg to the LiveIn list of the DAG's MachineFunction.
SDValue SplitVectorStore(SDValue Op, SelectionDAG &DAG) const
Split a vector store into 2 stores of half the vector.
SDValue LowerCTLZ_CTTZ(SDValue Op, SelectionDAG &DAG) const
SDValue getNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOperations, bool ForCodeSize, NegatibleCost &Cost, unsigned Depth) const override
Return the newly negated expression if the cost is not expensive and set the cost in Cost to indicate...
std::pair< SDValue, SDValue > split64BitValue(SDValue Op, SelectionDAG &DAG) const
Return 64-bit value Op as two 32-bit integers.
SDValue performMulCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps) const override
Return a reciprocal estimate value for the input operand.
SDValue LowerFNEARBYINT(SDValue Op, SelectionDAG &DAG) const
SDValue LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) const
static CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool IsVarArg)
std::pair< SDValue, SDValue > getScaledLogInput(SelectionDAG &DAG, const SDLoc SL, SDValue Op, SDNodeFlags Flags) const
If denormal handling is required return the scaled input to FLOG2, and the check for denormal range.
static CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg)
Selects the correct CCAssignFn for a given CallingConvention value.
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &OriginalDemandedBits, const APInt &OriginalDemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
static bool allUsesHaveSourceMods(const SDNode *N, unsigned CostThreshold=4)
SDValue LowerFROUNDEVEN(SDValue Op, SelectionDAG &DAG) const
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override
Returns true if the target can instruction select the specified FP immediate natively.
static unsigned numBitsUnsigned(SDValue Op, SelectionDAG &DAG)
SDValue lowerFEXPUnsafe(SDValue Op, const SDLoc &SL, SelectionDAG &DAG, SDNodeFlags Flags) const
SDValue LowerFTRUNC(SDValue Op, SelectionDAG &DAG) const
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const
static bool allowApproxFunc(const SelectionDAG &DAG, SDNodeFlags Flags)
bool ShouldShrinkFPConstant(EVT VT) const override
If true, then instruction selection should seek to shrink the FP constant of the specified type to a ...
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
SDValue performStoreCombine(SDNode *N, DAGCombinerInfo &DCI) const
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
SDValue performRcpCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue getLoHalf64(SDValue Op, SelectionDAG &DAG) const
SDValue lowerCTLZResults(SDValue Op, SelectionDAG &DAG) const
SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const
SDValue performFAbsCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue LowerFP_TO_INT64(SDValue Op, SelectionDAG &DAG, bool Signed) const
static bool shouldFoldFNegIntoSrc(SDNode *FNeg, SDValue FNegSrc)
bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const override
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
SDValue LowerFRINT(SDValue Op, SelectionDAG &DAG) const
SDValue performIntrinsicWOChainCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue LowerUDIVREM(SDValue Op, SelectionDAG &DAG) const
SDValue performMulLoHiCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
void LowerUDIVREM64(SDValue Op, SelectionDAG &DAG, SmallVectorImpl< SDValue > &Results) const
SDValue WidenOrSplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Widen a suitably aligned v3 load.
std::pair< EVT, EVT > getSplitDestVTs(const EVT &VT, SelectionDAG &DAG) const
Split a vector type into two parts.
SDValue getHiHalf64(SDValue Op, SelectionDAG &DAG) const
SDValue LowerINT_TO_FP16(SDValue Op, SelectionDAG &DAG, EVT FP16Ty) const
SDValue combineFMinMaxLegacyImpl(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, SDValue True, SDValue False, SDValue CC, DAGCombinerInfo &DCI) const
unsigned getVectorIdxWidth(const DataLayout &) const override
Returns the type to be used for the index operand vector operations.
static const fltSemantics & IEEEsingle()
Definition APFloat.h:297
static const fltSemantics & IEEEdouble()
Definition APFloat.h:298
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:345
static const fltSemantics & IEEEhalf()
Definition APFloat.h:295
bool bitwiseIsEqual(const APFloat &RHS) const
Definition APFloat.h:1530
opStatus add(const APFloat &RHS, roundingMode RM)
Definition APFloat.h:1267
const fltSemantics & getSemantics() const
Definition APFloat.h:1573
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
Definition APFloat.h:1174
opStatus multiply(const APFloat &RHS, roundingMode RM)
Definition APFloat.h:1285
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
Definition APFloat.h:1244
APInt bitcastToAPInt() const
Definition APFloat.h:1457
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Definition APFloat.h:1184
Class for arbitrary precision integers.
Definition APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1565
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
Definition APInt.h:207
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
Definition APInt.h:1191
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
Definition APInt.h:259
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
Definition APInt.h:210
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
Definition APInt.h:220
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
Definition APInt.h:307
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
Definition APInt.h:297
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
const BlockAddress * getBlockAddress() const
CCState - This class holds information needed while lowering arguments and return values.
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
const APFloat & getValueAPF() const
bool isNegative() const
Return true if the value is negative.
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
Diagnostic information for unsupported feature in backend.
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Definition Function.cpp:357
iterator_range< arg_iterator > args()
Definition Function.h:866
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:272
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:353
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
Machine Value Type.
static auto integer_fixedlen_vector_valuetypes()
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
static auto integer_valuetypes()
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
int getObjectIndexBegin() const
Return the minimum frame object index.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Representation of each machine instruction.
A description of a memory reference used in the backend.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOInvariant
The memory access always returns the same value (or traps).
Flags getFlags() const
Return the raw flags of the source value,.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI bool isLiveIn(Register Reg) const
LLVM_ABI Register getLiveInVirtReg(MCRegister PReg) const
getLiveInVirtReg - If PReg is a live-in physical register, return the corresponding live-in virtual r...
void addLiveIn(MCRegister Reg, Register vreg=Register())
addLiveIn - Add the specified register as a live-in.
This is an abstract virtual class for memory operations.
unsigned getAddressSpace() const
Return the address space for the associated pointer.
Align getAlign() const
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getChain() const
bool isInvariant() const
EVT getMemoryVT() const
Return the type of the in-memory value.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
const DebugLoc & getDebugLoc() const
Represents one node in the SelectionDAG.
ArrayRef< SDUse > ops() const
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
SDNodeFlags getFlags() const
SDVTList getVTList() const
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
iterator_range< user_iterator > users()
Represents a use of a SDNode.
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
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
unsigned getNumOperands() const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
SIModeRegisterDefaults getMode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT, unsigned Opcode)
Convert Op, which must be of integer type, to the integer type VT, by either any/sign/zero-extending ...
LLVM_ABI unsigned ComputeMaxSignificantBits(SDValue Op, unsigned Depth=0) const
Get the upper bound on bit size for this Value Op as a signed integer.
const SDValue & getRoot() const
Return the root tag of the SelectionDAG.
const TargetSubtargetInfo & getSubtarget() const
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
bool isConstantValueOfAnyType(SDValue N) const
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(SDValue Op, UndefPoisonKind Kind=UndefPoisonKind::UndefOrPoison, unsigned Depth=0) const
Return true if this function can prove that Op is never poison and, Kind can be used to track poison ...
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI bool isKnownNeverNaN(SDValue Op, const APInt &DemandedElts, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN in...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
const SDValue & setRoot(SDValue N)
Set the current root tag of the SelectionDAG.
LLVM_ABI SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getValue() const
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
void setMaxDivRemBitWidthSupported(unsigned SizeInBits)
Set the size in bits of the maximum div/rem the backend supports.
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
virtual bool shouldReduceLoadWidth(SDNode *Load, ISD::LoadExtType ExtTy, EVT NewVT, std::optional< unsigned > ByteOffset=std::nullopt) const
Return true if it is profitable to reduce a load to a smaller type.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
unsigned MaxGluedStoresPerMemcpy
Specify max number of store instructions to glue in inlined memcpy.
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void addBypassSlowDiv(unsigned int SlowBitWidth, unsigned int FastBitWidth)
Tells the code generator which bitwidths to bypass.
void setMaxLargeFPConvertBitWidthSupported(unsigned SizeInBits)
Set the size in bits of the maximum fp to/from int conversion the backend supports.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
SelectSupportKind
Enum that describes what type of support for selects the target has.
virtual bool allowsMisalignedMemoryAccesses(EVT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *=nullptr) const
Determine if the target supports unaligned memory accesses.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL) const
Returns the type for the shift amount of a shift opcode.
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
virtual EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const
Return the ValueType of the result of SETCC operations.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setSupportsUnalignedAtomics(bool UnalignedSupported)
Sets whether unaligned atomic operations are supported.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
unsigned GatherAllAliasesMaxDepth
Depth that GatherAllAliases should continue looking for chain dependencies when trying to find a more...
NegatibleCost
Enum that specifies when a float negation is beneficial.
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
void setJumpIsExpensive(bool isExpensive=true)
Tells the code generator not to expand logic operations on comparison predicates into separate sequen...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
SDValue scalarizeVectorStore(StoreSDNode *ST, SelectionDAG &DAG) const
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const
Expands an unaligned store to 2 half-size stores for integer values, and possibly more for vectors.
bool ShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const
Check to see if the specified operand of the specified instruction is a constant integer.
std::pair< SDValue, SDValue > expandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Expands an unaligned load to 2 half-size loads for an integer, and possibly more for vectors.
virtual SDValue getNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOps, bool OptForSize, NegatibleCost &Cost, unsigned Depth=0) const
Return the newly negated expression if the cost is not expensive and set the cost in Cost to indicate...
std::pair< SDValue, SDValue > scalarizeVectorLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Turn load of vector type into a load of the individual elements.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
TargetLowering(const TargetLowering &)=delete
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, UndefPoisonKind Kind, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
Primary interface to the complete machine description for the target machine.
TargetSubtargetInfo - Generic base class for all target subtargets.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Definition Type.cpp:232
LLVM Value Representation.
Definition Value.h:75
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
bool isIntrinsicAlwaysUniform(unsigned IntrID)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
bool isUniformMMO(const MachineMemOperand *MMO)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_Gfx
Used for AMD graphics targets.
@ AMDGPU_CS_ChainPreserve
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_CS_Chain
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ Cold
Attempts to make code in the caller as efficient as possible under the assumption that the call is no...
Definition CallingConv.h:47
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition CallingConv.h:41
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
@ 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:829
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition ISDOpcodes.h:275
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:602
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:789
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADDC
Carry-setting nodes for multiple precision addition and subtraction.
Definition ISDOpcodes.h:294
@ FMAD
FMAD - Perform a * b + c, while getting the same result as the separately rounded operations.
Definition ISDOpcodes.h:524
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:863
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:520
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:890
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
Definition ISDOpcodes.h:586
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:417
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:749
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
Definition ISDOpcodes.h:280
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
Definition ISDOpcodes.h:254
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ CTLZ_ZERO_POISON
Definition ISDOpcodes.h:798
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:854
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BRIND
BRIND - Indirect branch.
@ BR_JT
BR_JT - Jumptable branch.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition ISDOpcodes.h:543
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
Definition ISDOpcodes.h:550
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:806
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
Definition ISDOpcodes.h:247
@ CTLS
Count leading redundant sign bits.
Definition ISDOpcodes.h:802
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:706
@ STRICT_FP16_TO_FP
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:771
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:651
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:616
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ EntryToken
EntryToken - This is the marker used to indicate the start of a region.
Definition ISDOpcodes.h:48
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:578
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
Definition ISDOpcodes.h:224
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:860
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:821
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:898
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:729
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:988
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:815
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
Definition ISDOpcodes.h:328
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:936
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:205
@ ADDE
Carry-using nodes for multiple precision addition and subtraction.
Definition ISDOpcodes.h:304
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:567
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:53
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
Definition ISDOpcodes.h:797
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:969
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
@ INLINEASM
INLINEASM - Represents an inline asm block.
@ 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:955
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:866
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:62
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:536
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition ISDOpcodes.h:213
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:558
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
initializer< Ty > init(const Ty &Val)
constexpr double ln2
constexpr double ln10
constexpr float log2ef
Definition MathExtras.h:51
constexpr double log2e
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:573
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
InstructionCost Cost
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Known
Known to have no common set bits.
LLVM_ABI void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, SmallVectorImpl< EVT > &ValueVTs, SmallVectorImpl< EVT > *MemVTs=nullptr, SmallVectorImpl< TypeSize > *Offsets=nullptr, TypeSize StartingOffset=TypeSize::getZero())
ComputeValueVTs - Given an LLVM IR type, compute a sequence of EVTs that represent all the individual...
Definition Analysis.cpp:119
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
Definition MathExtras.h:385
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
Definition bit.h:263
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:150
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:189
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:155
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
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
CombineLevel
Definition DAGCombine.h:15
@ AfterLegalizeDAG
Definition DAGCombine.h:19
@ BeforeLegalizeTypes
Definition DAGCombine.h:16
@ AfterLegalizeTypes
Definition DAGCombine.h:17
To bit_cast(const From &from) noexcept
Definition bit.h:90
@ Mul
Product of integers.
@ Add
Sum of integers.
DWARFExpression::Operation Op
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
UndefPoisonKind
Enumeration to track whether we are interested in Undef, Poison, or both.
Definition UndefPoison.h:20
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:201
static cl::opt< unsigned > CostThreshold("dfa-cost-threshold", cl::desc("Maximum cost accepted for the transformation"), cl::Hidden, cl::init(50))
APFloat neg(APFloat X)
Returns the negated value of the argument.
Definition APFloat.h:1709
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition Alignment.h:197
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:862
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
MCRegister getRegister() const
unsigned getStackOffset() const
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
@ PreserveSign
The sign of a flushed-to-zero number is preserved in the sign of 0.
static constexpr DenormalMode getPreserveSign()
Extended Value Type.
Definition ValueTypes.h:35
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
Definition ValueTypes.h:418
EVT getPow2VectorType(LLVMContext &Context) const
Widens the length of the given vector EVT up to the nearest power of 2 and returns that type.
Definition ValueTypes.h:508
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition ValueTypes.h:145
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
Definition ValueTypes.h:70
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
Definition ValueTypes.h:129
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
Definition ValueTypes.h:307
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition ValueTypes.h:155
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:494
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
bool isByteSized() const
Return true if the bit size is a multiple of 8.
Definition ValueTypes.h:266
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:408
EVT getHalfSizedIntegerVT(LLVMContext &Context) const
Finds the smallest simple value type that is greater than or equal to half the width of this EVT.
Definition ValueTypes.h:453
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
Definition ValueTypes.h:501
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
Definition ValueTypes.h:435
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:339
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
Definition ValueTypes.h:61
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
Definition ValueTypes.h:404
EVT getRoundIntegerType(LLVMContext &Context) const
Rounds the bit-width of the given integer EVT up to the nearest power of two (and at least to eight),...
Definition ValueTypes.h:442
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:176
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:346
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
Definition ValueTypes.h:315
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
bool isExtended() const
Test if the given EVT is extended (as opposed to being simple).
Definition ValueTypes.h:150
EVT changeElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
Definition ValueTypes.h:121
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:359
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
Definition ValueTypes.h:331
bool isInteger() const
Return true if this is an integer or a vector integer type.
Definition ValueTypes.h:160
InputArg - This struct carries flags and type information about a single incoming (formal) argument o...
MVT VT
Legalized type of this argument part.
bool isUnknown() const
Returns true if we don't know any bits.
Definition KnownBits.h:64
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
Definition KnownBits.h:165
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
Definition KnownBits.h:176
unsigned countMaxActiveBits() const
Returns the maximum number of bits needed to represent all possible unsigned values with these known ...
Definition KnownBits.h:310
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
Definition KnownBits.h:184
unsigned countMinLeadingZeros() const
Returns the minimum number of leading zero bits.
Definition KnownBits.h:262
APInt getMaxValue() const
Return the maximal unsigned value possible given these KnownBits.
Definition KnownBits.h:146
bool isNegative() const
Returns true if this value is known to be negative.
Definition KnownBits.h:103
static LLVM_ABI KnownBits mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply=false)
Compute known bits resulting from multiplying LHS and RHS.
Matching combinators.
This class contains a discriminated union of information about pointers in memory operands,...
LLVM_ABI bool isDereferenceable(unsigned Size, LLVMContext &C, const DataLayout &DL) const
Return true if memory region [V, V+Offset+Size) is known to be dereferenceable.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
MachinePointerInfo getWithOffset(int64_t O) const
These are IR-level optimization flags that may be propagated to SDNodes.
void setAllowContract(bool b)
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
LLVM_ABI void AddToWorklist(SDNode *N)
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
LLVM_ABI void CommitTargetLoweringOpt(const TargetLoweringOpt &TLO)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...