LLVM 24.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
651//===----------------------------------------------------------------------===//
652// Target Information
653//===----------------------------------------------------------------------===//
654
656static bool fnegFoldsIntoOpcode(unsigned Opc) {
657 switch (Opc) {
658 case ISD::FADD:
659 case ISD::FSUB:
660 case ISD::FMUL:
661 case ISD::FMA:
662 case ISD::FMAD:
663 case ISD::FMINNUM:
664 case ISD::FMAXNUM:
667 case ISD::FMINIMUM:
668 case ISD::FMAXIMUM:
669 case ISD::FMINIMUMNUM:
670 case ISD::FMAXIMUMNUM:
671 case ISD::SELECT:
672 case ISD::FSIN:
673 case ISD::FTRUNC:
674 case ISD::FRINT:
675 case ISD::FNEARBYINT:
676 case ISD::FROUNDEVEN:
678 case AMDGPUISD::RCP:
679 case AMDGPUISD::RCP_LEGACY:
680 case AMDGPUISD::RCP_IFLAG:
681 case AMDGPUISD::SIN_HW:
682 case AMDGPUISD::FMUL_LEGACY:
683 case AMDGPUISD::FMIN_LEGACY:
684 case AMDGPUISD::FMAX_LEGACY:
685 case AMDGPUISD::FMED3:
686 // TODO: handle llvm.amdgcn.fma.legacy
687 return true;
688 case ISD::BITCAST:
689 llvm_unreachable("bitcast is special cased");
690 default:
691 return false;
692 }
693}
694
695static bool fnegFoldsIntoOp(const SDNode *N) {
696 unsigned Opc = N->getOpcode();
697 if (Opc == ISD::BITCAST) {
698 // TODO: Is there a benefit to checking the conditions performFNegCombine
699 // does? We don't for the other cases.
700 SDValue BCSrc = N->getOperand(0);
701 if (BCSrc.getOpcode() == ISD::BUILD_VECTOR) {
702 return BCSrc.getNumOperands() == 2 &&
703 BCSrc.getOperand(1).getValueSizeInBits() == 32;
704 }
705
706 return BCSrc.getOpcode() == ISD::SELECT && BCSrc.getValueType() == MVT::f32;
707 }
708
709 return fnegFoldsIntoOpcode(Opc);
710}
711
712/// \p returns true if the operation will definitely need to use a 64-bit
713/// encoding, and thus will use a VOP3 encoding regardless of the source
714/// modifiers.
716static bool opMustUseVOP3Encoding(const SDNode *N, MVT VT) {
717 return (N->getNumOperands() > 2 && N->getOpcode() != ISD::SELECT) ||
718 VT == MVT::f64;
719}
720
721/// Return true if v_cndmask_b32 will support fabs/fneg source modifiers for the
722/// type for ISD::SELECT.
724static bool selectSupportsSourceMods(const SDNode *N) {
725 // TODO: Only applies if select will be vector
726 return N->getValueType(0) == MVT::f32;
727}
728
729// Most FP instructions support source modifiers, but this could be refined
730// slightly.
732static bool hasSourceMods(const SDNode *N) {
733 if (isa<MemSDNode>(N))
734 return false;
735
736 switch (N->getOpcode()) {
737 case ISD::CopyToReg:
738 case ISD::FDIV:
739 case ISD::FREM:
740 case ISD::INLINEASM:
742 case AMDGPUISD::DIV_SCALE:
744
745 // TODO: Should really be looking at the users of the bitcast. These are
746 // problematic because bitcasts are used to legalize all stores to integer
747 // types.
748 case ISD::BITCAST:
749 return false;
751 switch (N->getConstantOperandVal(0)) {
752 case Intrinsic::amdgcn_interp_p1:
753 case Intrinsic::amdgcn_interp_p2:
754 case Intrinsic::amdgcn_interp_mov:
755 case Intrinsic::amdgcn_interp_p1_f16:
756 case Intrinsic::amdgcn_interp_p2_f16:
757 return false;
758 default:
759 return true;
760 }
761 }
762 case ISD::SELECT:
764 default:
765 return true;
766 }
767}
768
770 unsigned CostThreshold) {
771 // Some users (such as 3-operand FMA/MAD) must use a VOP3 encoding, and thus
772 // it is truly free to use a source modifier in all cases. If there are
773 // multiple users but for each one will necessitate using VOP3, there will be
774 // a code size increase. Try to avoid increasing code size unless we know it
775 // will save on the instruction count.
776 unsigned NumMayIncreaseSize = 0;
777 MVT VT = N->getValueType(0).getScalarType().getSimpleVT();
778
779 assert(!N->use_empty());
780
781 // XXX - Should this limit number of uses to check?
782 for (const SDNode *U : N->users()) {
783 if (!hasSourceMods(U))
784 return false;
785
786 if (!opMustUseVOP3Encoding(U, VT)) {
787 if (++NumMayIncreaseSize > CostThreshold)
788 return false;
789 }
790 }
791
792 return true;
793}
794
796 ISD::NodeType ExtendKind) const {
797 assert(!VT.isVector() && "only scalar expected");
798
799 // Round to the next multiple of 32-bits.
800 unsigned Size = VT.getSizeInBits();
801 if (Size <= 32)
802 return MVT::i32;
803 return EVT::getIntegerVT(Context, 32 * ((Size + 31) / 32));
804}
805
807 return 32;
808}
809
811 return true;
812}
813
814// The backend supports 32 and 64 bit floating point immediates.
815// FIXME: Why are we reporting vectors of FP immediates as legal?
817 bool ForCodeSize) const {
818 return isTypeLegal(VT.getScalarType());
819}
820
821// We don't want to shrink f64 / f32 constants.
823 EVT ScalarVT = VT.getScalarType();
824 return (ScalarVT != MVT::f32 && ScalarVT != MVT::f64);
825}
826
828 SDNode *N, ISD::LoadExtType ExtTy, EVT NewVT,
829 std::optional<unsigned> ByteOffset) const {
830 // TODO: This may be worth removing. Check regression tests for diffs.
831 if (!TargetLoweringBase::shouldReduceLoadWidth(N, ExtTy, NewVT, ByteOffset))
832 return false;
833
834 unsigned NewSize = NewVT.getStoreSizeInBits();
835
836 // If we are reducing to a 32-bit load or a smaller multi-dword load,
837 // this is always better.
838 if (NewSize >= 32)
839 return true;
840
841 EVT OldVT = N->getValueType(0);
842 unsigned OldSize = OldVT.getStoreSizeInBits();
843
845 unsigned AS = MN->getAddressSpace();
846 // Do not shrink an aligned scalar load to sub-dword.
847 // Scalar engine cannot do sub-dword loads.
848 // TODO: Update this for GFX12 which does have scalar sub-dword loads.
849 if (OldSize >= 32 && NewSize < 32 && MN->getAlign() >= Align(4) &&
853 MN->isInvariant())) &&
855 return false;
856
857 // Don't produce extloads from sub 32-bit types. SI doesn't have scalar
858 // extloads, so doing one requires using a buffer_load. In cases where we
859 // still couldn't use a scalar load, using the wider load shouldn't really
860 // hurt anything.
861
862 // If the old size already had to be an extload, there's no harm in continuing
863 // to reduce the width.
864 return (OldSize < 32);
865}
866
868 const SelectionDAG &DAG,
869 const MachineMemOperand &MMO) const {
870
871 assert(LoadTy.getSizeInBits() == CastTy.getSizeInBits());
872
873 if (LoadTy.getScalarType() == MVT::i32)
874 return false;
875
876 unsigned LScalarSize = LoadTy.getScalarSizeInBits();
877 unsigned CastScalarSize = CastTy.getScalarSizeInBits();
878
879 if ((LScalarSize >= CastScalarSize) && (CastScalarSize < 32))
880 return false;
881
882 unsigned Fast = 0;
884 CastTy, MMO, &Fast) &&
885 Fast;
886}
887
888// SI+ has instructions for cttz / ctlz for 32-bit values. This is probably also
889// profitable with the expansion for 64-bit since it's generally good to
890// speculate things.
892 return true;
893}
894
896 return true;
897}
898
900 switch (N->getOpcode()) {
901 case ISD::EntryToken:
902 case ISD::TokenFactor:
903 return true;
905 unsigned IntrID = N->getConstantOperandVal(0);
907 }
909 unsigned IntrID = N->getConstantOperandVal(1);
911 }
912 case ISD::LOAD:
913 if (cast<LoadSDNode>(N)->getMemOperand()->getAddrSpace() ==
915 return true;
916 return false;
917 case AMDGPUISD::SETCC: // ballot-style instruction
918 return true;
919 }
920 return false;
921}
922
924 SDValue Op, SelectionDAG &DAG, bool LegalOperations, bool ForCodeSize,
925 NegatibleCost &Cost, unsigned Depth) const {
926
927 switch (Op.getOpcode()) {
928 case ISD::FMA:
929 case ISD::FMAD: {
930 // Negating a fma is not free if it has users without source mods.
931 if (!allUsesHaveSourceMods(Op.getNode()))
932 return SDValue();
933 break;
934 }
935 case AMDGPUISD::RCP: {
936 SDValue Src = Op.getOperand(0);
937 EVT VT = Op.getValueType();
938 SDLoc SL(Op);
939
940 SDValue NegSrc = getNegatedExpression(Src, DAG, LegalOperations,
941 ForCodeSize, Cost, Depth + 1);
942 if (NegSrc)
943 return DAG.getNode(AMDGPUISD::RCP, SL, VT, NegSrc, Op->getFlags());
944 return SDValue();
945 }
946 default:
947 break;
948 }
949
950 return TargetLowering::getNegatedExpression(Op, DAG, LegalOperations,
951 ForCodeSize, Cost, Depth);
952}
953
954//===---------------------------------------------------------------------===//
955// Target Properties
956//===---------------------------------------------------------------------===//
957
960
961 // Packed operations do not have a fabs modifier.
962 // Report this based on the end legalized type.
963 return VT == MVT::f32 || VT == MVT::f64 || VT == MVT::f16 || VT == MVT::bf16;
964}
965
968 // Report this based on the end legalized type.
969 VT = VT.getScalarType();
970 return VT == MVT::f32 || VT == MVT::f64 || VT == MVT::f16 || VT == MVT::bf16;
971}
972
974 unsigned NumElem,
975 unsigned AS) const {
976 return true;
977}
978
980 // There are few operations which truly have vector input operands. Any vector
981 // operation is going to involve operations on each component, and a
982 // build_vector will be a copy per element, so it always makes sense to use a
983 // build_vector input in place of the extracted element to avoid a copy into a
984 // super register.
985 //
986 // We should probably only do this if all users are extracts only, but this
987 // should be the common case.
988 return true;
989}
990
992 // Truncate is just accessing a subregister.
993
994 unsigned SrcSize = Source.getSizeInBits();
995 unsigned DestSize = Dest.getSizeInBits();
996
997 return DestSize < SrcSize && DestSize % 32 == 0 ;
998}
999
1001 // Truncate is just accessing a subregister.
1002
1003 unsigned SrcSize = Source->getScalarSizeInBits();
1004 unsigned DestSize = Dest->getScalarSizeInBits();
1005
1006 if (DestSize== 16 && Subtarget->has16BitInsts())
1007 return SrcSize >= 32;
1008
1009 return DestSize < SrcSize && DestSize % 32 == 0;
1010}
1011
1013 unsigned SrcSize = Src->getScalarSizeInBits();
1014 unsigned DestSize = Dest->getScalarSizeInBits();
1015
1016 if (SrcSize == 16 && Subtarget->has16BitInsts())
1017 return DestSize >= 32;
1018
1019 return SrcSize == 32 && DestSize == 64;
1020}
1021
1023 // Any register load of a 64-bit value really requires 2 32-bit moves. For all
1024 // practical purposes, the extra mov 0 to load a 64-bit is free. As used,
1025 // this will enable reducing 64-bit operations the 32-bit, which is always
1026 // good.
1027
1028 if (Src == MVT::i16)
1029 return Dest == MVT::i32 ||Dest == MVT::i64 ;
1030
1031 return Src == MVT::i32 && Dest == MVT::i64;
1032}
1033
1035 EVT DestVT) const {
1036 switch (N->getOpcode()) {
1037 case ISD::ABS:
1038 case ISD::ADD:
1039 case ISD::SUB:
1040 case ISD::SHL:
1041 case ISD::SRL:
1042 case ISD::SRA:
1043 case ISD::AND:
1044 case ISD::OR:
1045 case ISD::XOR:
1046 case ISD::MUL:
1047 case ISD::SETCC:
1048 case ISD::SELECT:
1049 case ISD::SMIN:
1050 case ISD::SMAX:
1051 case ISD::UMIN:
1052 case ISD::UMAX:
1053 case ISD::USUBSAT:
1054 case ISD::UADDSAT:
1055 if (isTypeLegal(MVT::i16) &&
1056 (!DestVT.isVector() ||
1057 !isOperationLegal(ISD::ADD, MVT::v2i16))) { // Check if VOP3P
1058 // Don't narrow back down to i16 if promoted to i32 already.
1059 if (!N->isDivergent() && DestVT.isInteger() &&
1060 DestVT.getScalarSizeInBits() > 1 &&
1061 DestVT.getScalarSizeInBits() <= 16 &&
1062 SrcVT.getScalarSizeInBits() > 16) {
1063 return false;
1064 }
1065 }
1066 return true;
1067 default:
1068 break;
1069 }
1070
1071 // There aren't really 64-bit registers, but pairs of 32-bit ones and only a
1072 // limited number of native 64-bit operations. Shrinking an operation to fit
1073 // in a single 32-bit register should always be helpful. As currently used,
1074 // this is much less general than the name suggests, and is only used in
1075 // places trying to reduce the sizes of loads. Shrinking loads to < 32-bits is
1076 // not profitable, and may actually be harmful.
1077 if (isa<LoadSDNode>(N))
1078 return SrcVT.getSizeInBits() > 32 && DestVT.getSizeInBits() == 32;
1079
1080 return true;
1081}
1082
1084 const SDNode* N, CombineLevel Level) const {
1085 assert((N->getOpcode() == ISD::SHL || N->getOpcode() == ISD::SRA ||
1086 N->getOpcode() == ISD::SRL) &&
1087 "Expected shift op");
1088
1089 SDValue ShiftLHS = N->getOperand(0);
1090 if (!ShiftLHS->hasOneUse())
1091 return false;
1092
1093 if (ShiftLHS.getOpcode() == ISD::SIGN_EXTEND &&
1094 !ShiftLHS.getOperand(0)->hasOneUse())
1095 return false;
1096
1097 // Always commute pre-type legalization and right shifts.
1098 // We're looking for shl(or(x,y),z) patterns.
1100 N->getOpcode() != ISD::SHL || N->getOperand(0).getOpcode() != ISD::OR)
1101 return true;
1102
1103 // If only user is a i32 right-shift, then don't destroy a BFE pattern.
1104 if (N->getValueType(0) == MVT::i32 && N->hasOneUse() &&
1105 (N->user_begin()->getOpcode() == ISD::SRA ||
1106 N->user_begin()->getOpcode() == ISD::SRL))
1107 return false;
1108
1109 // Don't destroy or(shl(load_zext(),c), load_zext()) patterns.
1110 auto IsShiftAndLoad = [](SDValue LHS, SDValue RHS) {
1111 if (LHS.getOpcode() != ISD::SHL)
1112 return false;
1113 auto *RHSLd = dyn_cast<LoadSDNode>(RHS);
1114 auto *LHS0 = dyn_cast<LoadSDNode>(LHS.getOperand(0));
1115 auto *LHS1 = dyn_cast<ConstantSDNode>(LHS.getOperand(1));
1116 return LHS0 && LHS1 && RHSLd && LHS0->getExtensionType() == ISD::ZEXTLOAD &&
1117 LHS1->getAPIntValue() == LHS0->getMemoryVT().getScalarSizeInBits() &&
1118 RHSLd->getExtensionType() == ISD::ZEXTLOAD;
1119 };
1120 SDValue LHS = N->getOperand(0).getOperand(0);
1121 SDValue RHS = N->getOperand(0).getOperand(1);
1122 return !(IsShiftAndLoad(LHS, RHS) || IsShiftAndLoad(RHS, LHS));
1123}
1124
1125//===---------------------------------------------------------------------===//
1126// TargetLowering Callbacks
1127//===---------------------------------------------------------------------===//
1128
1130 bool IsVarArg) {
1131 switch (CC) {
1139 return CC_AMDGPU;
1142 return CC_AMDGPU_CS_CHAIN;
1143 case CallingConv::C:
1144 case CallingConv::Fast:
1145 case CallingConv::Cold:
1146 return CC_AMDGPU_Func;
1149 return CC_SI_Gfx;
1152 default:
1153 reportFatalUsageError("unsupported calling convention for call");
1154 }
1155}
1156
1158 bool IsVarArg) {
1159 switch (CC) {
1162 llvm_unreachable("kernels should not be handled here");
1172 return RetCC_SI_Shader;
1175 return RetCC_SI_Gfx;
1176 case CallingConv::C:
1177 case CallingConv::Fast:
1178 case CallingConv::Cold:
1179 return RetCC_AMDGPU_Func;
1180 default:
1181 reportFatalUsageError("unsupported calling convention");
1182 }
1183}
1184
1185/// The SelectionDAGBuilder will automatically promote function arguments
1186/// with illegal types. However, this does not work for the AMDGPU targets
1187/// since the function arguments are stored in memory as these illegal types.
1188/// In order to handle this properly we need to get the original types sizes
1189/// from the LLVM IR Function and fixup the ISD:InputArg values before
1190/// passing them to AnalyzeFormalArguments()
1191
1192/// When the SelectionDAGBuilder computes the Ins, it takes care of splitting
1193/// input values across multiple registers. Each item in the Ins array
1194/// represents a single value that will be stored in registers. Ins[x].VT is
1195/// the value type of the value that will be stored in the register, so
1196/// whatever SDNode we lower the argument to needs to be this type.
1197///
1198/// In order to correctly lower the arguments we need to know the size of each
1199/// argument. Since Ins[x].VT gives us the size of the register that will
1200/// hold the value, we need to look at Ins[x].ArgVT to see the 'real' type
1201/// for the original function argument so that we can deduce the correct memory
1202/// type to use for Ins[x]. In most cases the correct memory type will be
1203/// Ins[x].ArgVT. However, this will not always be the case. If, for example,
1204/// we have a kernel argument of type v8i8, this argument will be split into
1205/// 8 parts and each part will be represented by its own item in the Ins array.
1206/// For each part the Ins[x].ArgVT will be the v8i8, which is the full type of
1207/// the argument before it was split. From this, we deduce that the memory type
1208/// for each individual part is i8. We pass the memory type as LocVT to the
1209/// calling convention analysis function and the register type (Ins[x].VT) as
1210/// the ValVT.
1212 CCState &State,
1213 const SmallVectorImpl<ISD::InputArg> &Ins) const {
1214 const MachineFunction &MF = State.getMachineFunction();
1215 const Function &Fn = MF.getFunction();
1216 LLVMContext &Ctx = Fn.getContext();
1217 const unsigned ExplicitOffset = Subtarget->getExplicitKernelArgOffset();
1219
1220 Align MaxAlign = Align(1);
1221 uint64_t ExplicitArgOffset = 0;
1222 const DataLayout &DL = Fn.getDataLayout();
1223
1224 unsigned InIndex = 0;
1225
1226 for (const Argument &Arg : Fn.args()) {
1227 const bool IsByRef = Arg.hasByRefAttr();
1228 Type *BaseArgTy = Arg.getType();
1229 Type *MemArgTy = IsByRef ? Arg.getParamByRefType() : BaseArgTy;
1230 Align Alignment = DL.getValueOrABITypeAlignment(
1231 IsByRef ? Arg.getParamAlign() : std::nullopt, MemArgTy);
1232 MaxAlign = std::max(Alignment, MaxAlign);
1233 uint64_t AllocSize = DL.getTypeAllocSize(MemArgTy);
1234
1235 uint64_t ArgOffset = alignTo(ExplicitArgOffset, Alignment) + ExplicitOffset;
1236 ExplicitArgOffset = alignTo(ExplicitArgOffset, Alignment) + AllocSize;
1237
1238 // We're basically throwing away everything passed into us and starting over
1239 // to get accurate in-memory offsets. The "PartOffset" is completely useless
1240 // to us as computed in Ins.
1241 //
1242 // We also need to figure out what type legalization is trying to do to get
1243 // the correct memory offsets.
1244
1245 SmallVector<EVT, 16> ValueVTs;
1247 ComputeValueVTs(*this, DL, BaseArgTy, ValueVTs, /*MemVTs=*/nullptr,
1248 &Offsets, ArgOffset);
1249
1250 for (unsigned Value = 0, NumValues = ValueVTs.size();
1251 Value != NumValues; ++Value) {
1252 uint64_t BasePartOffset = Offsets[Value];
1253
1254 EVT ArgVT = ValueVTs[Value];
1255 EVT MemVT = ArgVT;
1256 MVT RegisterVT = getRegisterTypeForCallingConv(Ctx, CC, ArgVT);
1257 unsigned NumRegs = getNumRegistersForCallingConv(Ctx, CC, ArgVT);
1258
1259 if (NumRegs == 1) {
1260 // This argument is not split, so the IR type is the memory type.
1261 if (ArgVT.isExtended()) {
1262 // We have an extended type, like i24, so we should just use the
1263 // register type.
1264 MemVT = RegisterVT;
1265 } else {
1266 MemVT = ArgVT;
1267 }
1268 } else if (ArgVT.isVector() && RegisterVT.isVector() &&
1269 ArgVT.getScalarType() == RegisterVT.getScalarType()) {
1270 assert(ArgVT.getVectorNumElements() > RegisterVT.getVectorNumElements());
1271 // We have a vector value which has been split into a vector with
1272 // the same scalar type, but fewer elements. This should handle
1273 // all the floating-point vector types.
1274 MemVT = RegisterVT;
1275 } else if (ArgVT.isVector() &&
1276 ArgVT.getVectorNumElements() == NumRegs) {
1277 // This arg has been split so that each element is stored in a separate
1278 // register.
1279 MemVT = ArgVT.getScalarType();
1280 } else if (ArgVT.isExtended()) {
1281 // We have an extended type, like i65.
1282 MemVT = RegisterVT;
1283 } else {
1284 unsigned MemoryBits = ArgVT.getStoreSizeInBits() / NumRegs;
1285 assert(ArgVT.getStoreSizeInBits() % NumRegs == 0);
1286 if (RegisterVT.isInteger()) {
1287 MemVT = EVT::getIntegerVT(State.getContext(), MemoryBits);
1288 } else if (RegisterVT.isVector()) {
1289 assert(!RegisterVT.getScalarType().isFloatingPoint());
1290 unsigned NumElements = RegisterVT.getVectorNumElements();
1291 assert(MemoryBits % NumElements == 0);
1292 // This vector type has been split into another vector type with
1293 // a different elements size.
1294 EVT ScalarVT = EVT::getIntegerVT(State.getContext(),
1295 MemoryBits / NumElements);
1296 MemVT = EVT::getVectorVT(State.getContext(), ScalarVT, NumElements);
1297 } else {
1298 llvm_unreachable("cannot deduce memory type.");
1299 }
1300 }
1301
1302 // Convert one element vectors to scalar.
1303 if (MemVT.isVector() && MemVT.getVectorNumElements() == 1)
1304 MemVT = MemVT.getScalarType();
1305
1306 // Round up vec3/vec5 argument.
1307 if (MemVT.isVector() && !MemVT.isPow2VectorType()) {
1308 MemVT = MemVT.getPow2VectorType(State.getContext());
1309 } else if (!MemVT.isSimple() && !MemVT.isVector()) {
1310 MemVT = MemVT.getRoundIntegerType(State.getContext());
1311 }
1312
1313 unsigned PartOffset = 0;
1314 for (unsigned i = 0; i != NumRegs; ++i) {
1315 State.addLoc(CCValAssign::getCustomMem(InIndex++, RegisterVT,
1316 BasePartOffset + PartOffset,
1317 MemVT.getSimpleVT(),
1319 PartOffset += MemVT.getStoreSize();
1320 }
1321 }
1322 }
1323}
1324
1326 SDValue Chain, CallingConv::ID CallConv,
1327 bool isVarArg,
1329 const SmallVectorImpl<SDValue> &OutVals,
1330 const SDLoc &DL, SelectionDAG &DAG) const {
1331 // FIXME: Fails for r600 tests
1332 //assert(!isVarArg && Outs.empty() && OutVals.empty() &&
1333 // "wave terminate should not have return values");
1334 return DAG.getNode(AMDGPUISD::ENDPGM, DL, MVT::Other, Chain);
1335}
1336
1337//===---------------------------------------------------------------------===//
1338// Target specific lowering
1339//===---------------------------------------------------------------------===//
1340
1341/// Selects the correct CCAssignFn for a given CallingConvention value.
1346
1351
1353 SelectionDAG &DAG,
1354 MachineFrameInfo &MFI,
1355 int ClobberedFI) const {
1356 SmallVector<SDValue, 8> ArgChains;
1357 int64_t FirstByte = MFI.getObjectOffset(ClobberedFI);
1358 int64_t LastByte = FirstByte + MFI.getObjectSize(ClobberedFI) - 1;
1359
1360 // Include the original chain at the beginning of the list. When this is
1361 // used by target LowerCall hooks, this helps legalize find the
1362 // CALLSEQ_BEGIN node.
1363 ArgChains.push_back(Chain);
1364
1365 // Add a chain value for each stack argument corresponding
1366 for (SDNode *U : DAG.getEntryNode().getNode()->users()) {
1367 if (LoadSDNode *L = dyn_cast<LoadSDNode>(U)) {
1368 if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(L->getBasePtr())) {
1369 if (FI->getIndex() < 0) {
1370 int64_t InFirstByte = MFI.getObjectOffset(FI->getIndex());
1371 int64_t InLastByte = InFirstByte;
1372 InLastByte += MFI.getObjectSize(FI->getIndex()) - 1;
1373
1374 if ((InFirstByte <= FirstByte && FirstByte <= InLastByte) ||
1375 (FirstByte <= InFirstByte && InFirstByte <= LastByte))
1376 ArgChains.push_back(SDValue(L, 1));
1377 }
1378 }
1379 }
1380 }
1381
1382 // Build a tokenfactor for all the chains.
1383 return DAG.getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, ArgChains);
1384}
1385
1388 StringRef Reason) const {
1389 SDValue Callee = CLI.Callee;
1390 SelectionDAG &DAG = CLI.DAG;
1391
1392 const Function &Fn = DAG.getMachineFunction().getFunction();
1393
1394 StringRef FuncName("<unknown>");
1395
1397 FuncName = G->getSymbol();
1398 else if (const GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
1399 FuncName = G->getGlobal()->getName();
1400
1401 DAG.getContext()->diagnose(
1402 DiagnosticInfoUnsupported(Fn, Reason + FuncName, CLI.DL.getDebugLoc()));
1403
1404 if (!CLI.IsTailCall) {
1405 for (ISD::InputArg &Arg : CLI.Ins)
1406 InVals.push_back(DAG.getPOISON(Arg.VT));
1407 }
1408
1409 // FIXME: Hack because R600 doesn't handle callseq pseudos yet.
1410 if (getTargetMachine().getTargetTriple().getArch() == Triple::r600)
1411 return CLI.Chain;
1412
1413 SDValue Chain = DAG.getCALLSEQ_START(CLI.Chain, 0, 0, CLI.DL);
1414 return DAG.getCALLSEQ_END(Chain, 0, 0, /*InGlue=*/SDValue(), CLI.DL);
1415}
1416
1418 SmallVectorImpl<SDValue> &InVals) const {
1419 return lowerUnhandledCall(CLI, InVals, "unsupported call to function ");
1420}
1421
1423 SelectionDAG &DAG) const {
1424 const Function &Fn = DAG.getMachineFunction().getFunction();
1425
1427 Fn, "unsupported dynamic alloca", SDLoc(Op).getDebugLoc()));
1428 auto Ops = {DAG.getConstant(0, SDLoc(), Op.getValueType()), Op.getOperand(0)};
1429 return DAG.getMergeValues(Ops, SDLoc());
1430}
1431
1433 SelectionDAG &DAG) const {
1434 switch (Op.getOpcode()) {
1435 default:
1436 Op->print(errs(), &DAG);
1437 llvm_unreachable("Custom lowering code for this "
1438 "instruction is not implemented yet!");
1439 break;
1441 case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG);
1443 case ISD::UDIVREM: return LowerUDIVREM(Op, DAG);
1444 case ISD::SDIVREM:
1445 return LowerSDIVREM(Op, DAG);
1446 case ISD::FCEIL: return LowerFCEIL(Op, DAG);
1447 case ISD::FTRUNC: return LowerFTRUNC(Op, DAG);
1448 case ISD::FRINT: return LowerFRINT(Op, DAG);
1449 case ISD::FNEARBYINT: return LowerFNEARBYINT(Op, DAG);
1450 case ISD::FROUNDEVEN:
1451 return LowerFROUNDEVEN(Op, DAG);
1452 case ISD::FROUND: return LowerFROUND(Op, DAG);
1453 case ISD::FFLOOR: return LowerFFLOOR(Op, DAG);
1454 case ISD::FLOG2:
1455 return LowerFLOG2(Op, DAG);
1456 case ISD::FLOG:
1457 case ISD::FLOG10:
1458 return LowerFLOGCommon(Op, DAG);
1459 case ISD::FEXP:
1460 case ISD::FEXP10:
1461 return lowerFEXP(Op, DAG);
1462 case ISD::FEXP2:
1463 return lowerFEXP2(Op, DAG);
1464 case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG);
1465 case ISD::UINT_TO_FP: return LowerUINT_TO_FP(Op, DAG);
1466 case ISD::FP_TO_FP16: return LowerFP_TO_FP16(Op, DAG);
1467 case ISD::FP_TO_SINT:
1468 case ISD::FP_TO_UINT:
1469 return LowerFP_TO_INT(Op, DAG);
1472 return LowerFP_TO_INT_SAT(Op, DAG);
1473 case ISD::CTTZ:
1475 case ISD::CTLZ:
1477 return LowerCTLZ_CTTZ(Op, DAG);
1478 case ISD::CTLS:
1479 return LowerCTLS(Op, DAG);
1481 }
1482 return Op;
1483}
1484
1487 SelectionDAG &DAG) const {
1488 switch (N->getOpcode()) {
1490 // Different parts of legalization seem to interpret which type of
1491 // sign_extend_inreg is the one to check for custom lowering. The extended
1492 // from type is what really matters, but some places check for custom
1493 // lowering of the result type. This results in trying to use
1494 // ReplaceNodeResults to sext_in_reg to an illegal type, so we'll just do
1495 // nothing here and let the illegal result integer be handled normally.
1496 return;
1497 case ISD::FLOG2:
1498 if (SDValue Lowered = LowerFLOG2(SDValue(N, 0), DAG))
1499 Results.push_back(Lowered);
1500 return;
1501 case ISD::FLOG:
1502 case ISD::FLOG10:
1503 if (SDValue Lowered = LowerFLOGCommon(SDValue(N, 0), DAG))
1504 Results.push_back(Lowered);
1505 return;
1506 case ISD::FEXP2:
1507 if (SDValue Lowered = lowerFEXP2(SDValue(N, 0), DAG))
1508 Results.push_back(Lowered);
1509 return;
1510 case ISD::FEXP:
1511 case ISD::FEXP10:
1512 if (SDValue Lowered = lowerFEXP(SDValue(N, 0), DAG))
1513 Results.push_back(Lowered);
1514 return;
1515 case ISD::CTLZ:
1517 if (auto Lowered = lowerCTLZResults(SDValue(N, 0u), DAG))
1518 Results.push_back(Lowered);
1519 return;
1520 default:
1521 return;
1522 }
1523}
1524
1526 SelectionDAG &DAG) const {
1528 SDLoc SL(Op);
1529 EVT VT = Op.getValueType();
1530 return DAG.getTargetBlockAddress(BA->getBlockAddress(), VT, BA->getOffset(),
1531 BA->getTargetFlags());
1532}
1533
1535 SDValue Op,
1536 SelectionDAG &DAG) const {
1537
1538 const DataLayout &DL = DAG.getDataLayout();
1540 const GlobalValue *GV = G->getGlobal();
1541
1542 if (!MFI->isModuleEntryFunction()) {
1543 bool IsNamedBarrier = AMDGPU::isNamedBarrier(*cast<GlobalVariable>(GV));
1544 std::optional<uint32_t> Address =
1546 if (!Address && IsNamedBarrier)
1547 llvm_unreachable("named barrier should have an assigned address");
1548 if (Address) {
1549 if (IsNamedBarrier) {
1550 unsigned BarCnt = cast<GlobalVariable>(GV)->getGlobalSize(DL) / 16;
1551 MFI->recordNumNamedBarriers(Address.value(), BarCnt);
1552 }
1553 // A constant byte offset (e.g. from a GEP into an array of named
1554 // barriers) folds directly into the fixed LDS address.
1555 return DAG.getConstant(*Address + G->getOffset(), SDLoc(Op),
1556 Op.getValueType());
1557 }
1558 }
1559
1560 if (G->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS ||
1561 G->getAddressSpace() == AMDGPUAS::REGION_ADDRESS) {
1562 if (!MFI->isModuleEntryFunction() &&
1563 GV->getName() != "llvm.amdgcn.module.lds" &&
1565 SDLoc DL(Op);
1566 const Function &Fn = DAG.getMachineFunction().getFunction();
1568 Fn, "local memory global used by non-kernel function",
1569 DL.getDebugLoc(), DS_Warning));
1570
1571 // We currently don't have a way to correctly allocate LDS objects that
1572 // aren't directly associated with a kernel. We do force inlining of
1573 // functions that use local objects. However, if these dead functions are
1574 // not eliminated, we don't want a compile time error. Just emit a warning
1575 // and a trap, since there should be no callable path here.
1576 SDValue Trap = DAG.getNode(ISD::TRAP, DL, MVT::Other, DAG.getEntryNode());
1577 SDValue OutputChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
1578 Trap, DAG.getRoot());
1579 DAG.setRoot(OutputChain);
1580 return DAG.getPOISON(Op.getValueType());
1581 }
1582
1583 // TODO: We could emit code to handle the initialization somewhere.
1584 // We ignore the initializer for now and legalize it to allow selection.
1585 // The initializer will anyway get errored out during assembly emission.
1586 unsigned Offset = MFI->allocateLDSGlobal(DL, *cast<GlobalVariable>(GV));
1587 // A constant byte offset (e.g. from a GEP into an array of named barriers)
1588 // folds directly into the allocated LDS address.
1589 return DAG.getConstant(Offset + G->getOffset(), SDLoc(Op),
1590 Op.getValueType());
1591 }
1592 return SDValue();
1593}
1594
1596 SelectionDAG &DAG) const {
1598 SDLoc SL(Op);
1599
1600 EVT VT = Op.getValueType();
1601 if (VT.getVectorElementType().getSizeInBits() < 32) {
1602 unsigned OpBitSize = Op.getOperand(0).getValueType().getSizeInBits();
1603 if (OpBitSize >= 32 && OpBitSize % 32 == 0) {
1604 unsigned NewNumElt = OpBitSize / 32;
1605 EVT NewEltVT = (NewNumElt == 1) ? MVT::i32
1607 MVT::i32, NewNumElt);
1608 for (const SDUse &U : Op->ops()) {
1609 SDValue In = U.get();
1610 SDValue NewIn = DAG.getNode(ISD::BITCAST, SL, NewEltVT, In);
1611 if (NewNumElt > 1)
1612 DAG.ExtractVectorElements(NewIn, Args);
1613 else
1614 Args.push_back(NewIn);
1615 }
1616
1617 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32,
1618 NewNumElt * Op.getNumOperands());
1619 SDValue BV = DAG.getBuildVector(NewVT, SL, Args);
1620 return DAG.getNode(ISD::BITCAST, SL, VT, BV);
1621 }
1622 }
1623
1624 for (const SDUse &U : Op->ops())
1625 DAG.ExtractVectorElements(U.get(), Args);
1626
1627 return DAG.getBuildVector(Op.getValueType(), SL, Args);
1628}
1629
1631 SelectionDAG &DAG) const {
1632 SDLoc SL(Op);
1634 unsigned Start = Op.getConstantOperandVal(1);
1635 EVT VT = Op.getValueType();
1636 EVT SrcVT = Op.getOperand(0).getValueType();
1637
1638 if (VT.getScalarSizeInBits() == 16 && Start % 2 == 0) {
1639 unsigned NumElt = VT.getVectorNumElements();
1640 unsigned NumSrcElt = SrcVT.getVectorNumElements();
1641 assert(NumElt % 2 == 0 && NumSrcElt % 2 == 0 && "expect legal types");
1642
1643 // Extract 32-bit registers at a time.
1644 EVT NewSrcVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumSrcElt / 2);
1645 EVT NewVT = NumElt == 2
1646 ? MVT::i32
1647 : EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumElt / 2);
1648 SDValue Tmp = DAG.getNode(ISD::BITCAST, SL, NewSrcVT, Op.getOperand(0));
1649
1650 DAG.ExtractVectorElements(Tmp, Args, Start / 2, NumElt / 2);
1651 if (NumElt == 2)
1652 Tmp = Args[0];
1653 else
1654 Tmp = DAG.getBuildVector(NewVT, SL, Args);
1655
1656 return DAG.getNode(ISD::BITCAST, SL, VT, Tmp);
1657 }
1658
1659 DAG.ExtractVectorElements(Op.getOperand(0), Args, Start,
1661
1662 return DAG.getBuildVector(Op.getValueType(), SL, Args);
1663}
1664
1665// TODO: Handle fabs too
1667 if (Val.getOpcode() == ISD::FNEG)
1668 return Val.getOperand(0);
1669
1670 return Val;
1671}
1672
1674 if (Val.getOpcode() == ISD::FNEG)
1675 Val = Val.getOperand(0);
1676 if (Val.getOpcode() == ISD::FABS)
1677 Val = Val.getOperand(0);
1678 if (Val.getOpcode() == ISD::FCOPYSIGN)
1679 Val = Val.getOperand(0);
1680 return Val;
1681}
1682
1683// SelectionDAG twin of AMDGPUCombinerHelper::canIgnoreLegacyMinMaxTies.
1685 SDNodeFlags Flags, SDValue LHS,
1686 SDValue RHS) {
1687 return Flags.hasNoSignedZeros() || DAG.isKnownNeverLogicalZero(LHS) ||
1689}
1690
1692 const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, SDValue True,
1693 SDValue False, SDValue CC, SDNodeFlags Flags, DAGCombinerInfo &DCI) const {
1694 SelectionDAG &DAG = DCI.DAG;
1695 ISD::CondCode CCOpcode = cast<CondCodeSDNode>(CC)->get();
1696 assert(CCOpcode != ISD::SETCC_INVALID && "Invalid setcc condcode!");
1697
1698 switch (CCOpcode) {
1699 case ISD::SETOLE:
1700 case ISD::SETOLT:
1701 case ISD::SETLE:
1702 case ISD::SETLT:
1703 case ISD::SETOGE:
1704 case ISD::SETOGT:
1705 case ISD::SETGE:
1706 case ISD::SETGT:
1707 // Only do this after legalization to avoid interfering with other combines
1708 // which might occur.
1710 !DCI.isCalledByLegalizer())
1711 return SDValue();
1712 break;
1713 default:
1714 break;
1715 }
1716
1717 // Canonicalize so the select returns the compare's LHS on a true predicate.
1718 if (LHS != True)
1719 CCOpcode = ISD::getSetCCInverse(CCOpcode, VT);
1720
1721 unsigned Opc;
1722 bool Swap; // Emit (rhs, lhs) instead of (lhs, rhs).
1723 switch (CCOpcode) {
1724 case ISD::SETOLT:
1725 case ISD::SETLT:
1726 case ISD::SETOLE:
1727 Opc = AMDGPUISD::FMIN_LEGACY;
1728 Swap = false;
1729 break;
1730 case ISD::SETULE:
1731 case ISD::SETLE:
1732 case ISD::SETULT:
1733 Opc = AMDGPUISD::FMIN_LEGACY;
1734 Swap = true;
1735 break;
1736 case ISD::SETOGE:
1737 case ISD::SETGE:
1738 case ISD::SETOGT:
1739 Opc = AMDGPUISD::FMAX_LEGACY;
1740 Swap = false;
1741 break;
1742 case ISD::SETUGT:
1743 case ISD::SETGT:
1744 case ISD::SETUGE:
1745 Opc = AMDGPUISD::FMAX_LEGACY;
1746 Swap = true;
1747 break;
1748 default:
1749 return SDValue();
1750 }
1751
1752 // For these predicates the NaN-correct operand order is the signed zero
1753 // tie-incorrect one, so the fold needs the tie to be unobservable.
1754 if ((CCOpcode == ISD::SETOLE || CCOpcode == ISD::SETULT ||
1755 CCOpcode == ISD::SETOGT || CCOpcode == ISD::SETUGE) &&
1756 !canIgnoreLegacyMinMaxTies(DAG, Flags, LHS, RHS))
1757 return SDValue();
1758
1759 if (Swap)
1760 std::swap(LHS, RHS);
1761 return DAG.getNode(Opc, DL, VT, LHS, RHS, Flags);
1762}
1763
1764/// Generate Min/Max node
1766 const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, SDValue True,
1767 SDValue False, SDValue CC, SDNodeFlags Flags, DAGCombinerInfo &DCI) const {
1768 if ((LHS == True && RHS == False) || (LHS == False && RHS == True))
1769 return combineFMinMaxLegacyImpl(DL, VT, LHS, RHS, True, False, CC, Flags,
1770 DCI);
1771
1772 SelectionDAG &DAG = DCI.DAG;
1773
1774 // If we can't directly match this, try to see if we can fold an fneg to
1775 // match.
1776
1779 SDValue NegTrue = peekFNeg(True);
1780
1781 // Undo the combine foldFreeOpFromSelect does if it helps us match the
1782 // fmin/fmax.
1783 //
1784 // select (fcmp olt (lhs, K)), (fneg lhs), -K
1785 // -> fneg (fmin_legacy lhs, K)
1786 //
1787 // TODO: Use getNegatedExpression
1788 if (LHS == NegTrue && CFalse && CRHS) {
1789 APFloat NegRHS = neg(CRHS->getValueAPF());
1790 if (NegRHS == CFalse->getValueAPF()) {
1791 SDValue Combined = combineFMinMaxLegacyImpl(DL, VT, LHS, RHS, NegTrue,
1792 False, CC, Flags, DCI);
1793 if (Combined)
1794 return DAG.getNode(ISD::FNEG, DL, VT, Combined);
1795 return SDValue();
1796 }
1797 }
1798
1799 return SDValue();
1800}
1801
1802std::pair<SDValue, SDValue>
1804 SDLoc SL(Op);
1805
1806 SDValue Vec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op);
1807
1808 const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);
1809 const SDValue One = DAG.getConstant(1, SL, MVT::i32);
1810
1811 SDValue Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, Zero);
1812 SDValue Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, One);
1813
1814 return std::pair(Lo, Hi);
1815}
1816
1818 SDLoc SL(Op);
1819
1820 SDValue Vec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op);
1821 const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);
1822 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, Zero);
1823}
1824
1826 SDLoc SL(Op);
1827
1828 SDValue Vec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op);
1829 const SDValue One = DAG.getConstant(1, SL, MVT::i32);
1830 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, One);
1831}
1832
1833// Split a vector type into two parts. The first part is a power of two vector.
1834// The second part is whatever is left over, and is a scalar if it would
1835// otherwise be a 1-vector.
1836std::pair<EVT, EVT>
1838 EVT LoVT, HiVT;
1839 EVT EltVT = VT.getVectorElementType();
1840 unsigned NumElts = VT.getVectorNumElements();
1841 unsigned LoNumElts = PowerOf2Ceil((NumElts + 1) / 2);
1842 LoVT = EVT::getVectorVT(*DAG.getContext(), EltVT, LoNumElts);
1843 HiVT = NumElts - LoNumElts == 1
1844 ? EltVT
1845 : EVT::getVectorVT(*DAG.getContext(), EltVT, NumElts - LoNumElts);
1846 return std::pair(LoVT, HiVT);
1847}
1848
1849// Split a vector value into two parts of types LoVT and HiVT. HiVT could be
1850// scalar.
1851std::pair<SDValue, SDValue>
1853 const EVT &LoVT, const EVT &HiVT,
1854 SelectionDAG &DAG) const {
1855 EVT VT = N.getValueType();
1857 (HiVT.isVector() ? HiVT.getVectorNumElements() : 1) <=
1858 VT.getVectorNumElements() &&
1859 "More vector elements requested than available!");
1861 DAG.getVectorIdxConstant(0, DL));
1862
1863 unsigned LoNumElts = LoVT.getVectorNumElements();
1864
1865 if (HiVT.isVector()) {
1866 unsigned HiNumElts = HiVT.getVectorNumElements();
1867 if ((VT.getVectorNumElements() % HiNumElts) == 0) {
1868 // Avoid creating an extract_subvector with an index that isn't a multiple
1869 // of the result type.
1871 DAG.getConstant(LoNumElts, DL, MVT::i32));
1872 return {Lo, Hi};
1873 }
1874
1876 DAG.ExtractVectorElements(N, Elts, /*Start=*/LoNumElts,
1877 /*Count=*/HiNumElts);
1878 SDValue Hi = DAG.getBuildVector(HiVT, DL, Elts);
1879 return {Lo, Hi};
1880 }
1881
1883 DAG.getVectorIdxConstant(LoNumElts, DL));
1884 return {Lo, Hi};
1885}
1886
1888 SelectionDAG &DAG) const {
1890 EVT VT = Op.getValueType();
1891 SDLoc SL(Op);
1892
1893
1894 // If this is a 2 element vector, we really want to scalarize and not create
1895 // weird 1 element vectors.
1896 if (VT.getVectorNumElements() == 2) {
1897 SDValue Ops[2];
1898 std::tie(Ops[0], Ops[1]) = scalarizeVectorLoad(Load, DAG);
1899 return DAG.getMergeValues(Ops, SL);
1900 }
1901
1902 SDValue BasePtr = Load->getBasePtr();
1903 EVT MemVT = Load->getMemoryVT();
1904
1905 const MachinePointerInfo &SrcValue = Load->getMemOperand()->getPointerInfo();
1906
1907 EVT LoVT, HiVT;
1908 EVT LoMemVT, HiMemVT;
1909 SDValue Lo, Hi;
1910
1911 std::tie(LoVT, HiVT) = getSplitDestVTs(VT, DAG);
1912 std::tie(LoMemVT, HiMemVT) = getSplitDestVTs(MemVT, DAG);
1913 std::tie(Lo, Hi) = splitVector(Op, SL, LoVT, HiVT, DAG);
1914
1915 unsigned Size = LoMemVT.getStoreSize();
1916 Align BaseAlign = Load->getAlign();
1917 Align HiAlign = commonAlignment(BaseAlign, Size);
1918
1919 SDValue LoLoad = DAG.getExtLoad(
1920 Load->getExtensionType(), SL, LoVT, Load->getChain(), BasePtr, SrcValue,
1921 LoMemVT, BaseAlign, Load->getMemOperand()->getFlags(), Load->getAAInfo());
1922 SDValue HiPtr = DAG.getObjectPtrOffset(SL, BasePtr, TypeSize::getFixed(Size));
1923 SDValue HiLoad = DAG.getExtLoad(
1924 Load->getExtensionType(), SL, HiVT, Load->getChain(), HiPtr,
1925 SrcValue.getWithOffset(LoMemVT.getStoreSize()), HiMemVT, HiAlign,
1926 Load->getMemOperand()->getFlags(), Load->getAAInfo());
1927
1928 SDValue Join;
1929 if (LoVT == HiVT) {
1930 // This is the case that the vector is power of two so was evenly split.
1931 Join = DAG.getNode(ISD::CONCAT_VECTORS, SL, VT, LoLoad, HiLoad);
1932 } else {
1933 Join = DAG.getNode(ISD::INSERT_SUBVECTOR, SL, VT, DAG.getPOISON(VT), LoLoad,
1934 DAG.getVectorIdxConstant(0, SL));
1935 Join = DAG.getNode(
1937 VT, Join, HiLoad,
1939 }
1940
1941 SDValue Ops[] = {Join, DAG.getNode(ISD::TokenFactor, SL, MVT::Other,
1942 LoLoad.getValue(1), HiLoad.getValue(1))};
1943
1944 return DAG.getMergeValues(Ops, SL);
1945}
1946
1948 SelectionDAG &DAG) const {
1950 EVT VT = Op.getValueType();
1951 SDValue BasePtr = Load->getBasePtr();
1952 EVT MemVT = Load->getMemoryVT();
1953 SDLoc SL(Op);
1954 const MachinePointerInfo &SrcValue = Load->getMemOperand()->getPointerInfo();
1955 Align BaseAlign = Load->getAlign();
1956 unsigned NumElements = MemVT.getVectorNumElements();
1957
1958 // Widen from vec3 to vec4 when the load is at least 8-byte aligned
1959 // or 16-byte fully dereferenceable. Otherwise, split the vector load.
1960 if (NumElements != 3 ||
1961 (BaseAlign < Align(8) &&
1962 !SrcValue.isDereferenceable(16, *DAG.getContext(), DAG.getDataLayout())))
1963 return SplitVectorLoad(Op, DAG);
1964
1965 assert(NumElements == 3);
1966
1967 EVT WideVT =
1969 EVT WideMemVT =
1971 SDValue WideLoad = DAG.getExtLoad(
1972 Load->getExtensionType(), SL, WideVT, Load->getChain(), BasePtr, SrcValue,
1973 WideMemVT, BaseAlign, Load->getMemOperand()->getFlags());
1974 return DAG.getMergeValues(
1975 {DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, VT, WideLoad,
1976 DAG.getVectorIdxConstant(0, SL)),
1977 WideLoad.getValue(1)},
1978 SL);
1979}
1980
1982 SelectionDAG &DAG) const {
1984 SDValue Val = Store->getValue();
1985 EVT VT = Val.getValueType();
1986
1987 // If this is a 2 element vector, we really want to scalarize and not create
1988 // weird 1 element vectors.
1989 if (VT.getVectorNumElements() == 2)
1990 return scalarizeVectorStore(Store, DAG);
1991
1992 EVT MemVT = Store->getMemoryVT();
1993 SDValue Chain = Store->getChain();
1994 SDValue BasePtr = Store->getBasePtr();
1995 SDLoc SL(Op);
1996
1997 EVT LoVT, HiVT;
1998 EVT LoMemVT, HiMemVT;
1999 SDValue Lo, Hi;
2000
2001 std::tie(LoVT, HiVT) = getSplitDestVTs(VT, DAG);
2002 std::tie(LoMemVT, HiMemVT) = getSplitDestVTs(MemVT, DAG);
2003 std::tie(Lo, Hi) = splitVector(Val, SL, LoVT, HiVT, DAG);
2004
2005 SDValue HiPtr = DAG.getObjectPtrOffset(SL, BasePtr, LoMemVT.getStoreSize());
2006
2007 const MachinePointerInfo &SrcValue = Store->getMemOperand()->getPointerInfo();
2008 Align BaseAlign = Store->getAlign();
2009 unsigned Size = LoMemVT.getStoreSize();
2010 Align HiAlign = commonAlignment(BaseAlign, Size);
2011
2012 SDValue LoStore =
2013 DAG.getTruncStore(Chain, SL, Lo, BasePtr, SrcValue, LoMemVT, BaseAlign,
2014 Store->getMemOperand()->getFlags(), Store->getAAInfo());
2015 SDValue HiStore = DAG.getTruncStore(
2016 Chain, SL, Hi, HiPtr, SrcValue.getWithOffset(Size), HiMemVT, HiAlign,
2017 Store->getMemOperand()->getFlags(), Store->getAAInfo());
2018
2019 return DAG.getNode(ISD::TokenFactor, SL, MVT::Other, LoStore, HiStore);
2020}
2021
2022// This is a shortcut for integer division because we have fast i32<->f32
2023// conversions, and fast f32 reciprocal instructions.
2025 bool Sign) const {
2026 SDLoc DL(Op);
2027 EVT VT = Op.getValueType();
2028 assert(VT == MVT::i32 && "LowerDIVREMToFloat expects an i32");
2029
2030 SDValue LHS = Op.getOperand(0);
2031 SDValue RHS = Op.getOperand(1);
2032 MVT IntVT = MVT::i32;
2033 MVT FltVT = MVT::f32;
2034
2035 unsigned LHSSignBits;
2036 unsigned RHSSignBits;
2037 if (Sign) {
2038 LHSSignBits = DAG.ComputeNumSignBits(LHS);
2039 RHSSignBits = DAG.ComputeNumSignBits(RHS);
2040 if (LHSSignBits < 9 || RHSSignBits < 9)
2041 return SDValue();
2042 } else {
2043 KnownBits LHSKnown = DAG.computeKnownBits(LHS);
2044 KnownBits RHSKnown = DAG.computeKnownBits(RHS);
2045
2046 LHSSignBits = LHSKnown.countMinLeadingZeros();
2047 RHSSignBits = RHSKnown.countMinLeadingZeros();
2048 }
2049
2050 unsigned BitSize = VT.getSizeInBits();
2051 unsigned SignBits = std::min(LHSSignBits, RHSSignBits);
2052 unsigned DivBits = BitSize - SignBits;
2053 if (Sign)
2054 ++DivBits;
2055
2056 // In order to avoid problems due to 1 ulp accuracy issues with v_rcp_f32,
2057 // limit LowerDIVREMToFloat to:
2058 // [-0x400000,0x3FFFFF] for Sign
2059 // [ 0x000000,0x3FFFFF] for !Sign
2060 // This matches what is done in expandDivRemToFloatImpl.
2061 if (DivBits > (Sign ? 23 : 22))
2062 return SDValue();
2063
2066
2067 // int ia = (int)LHS;
2068 SDValue ia = LHS;
2069
2070 // int ib, (int)RHS;
2071 SDValue ib = RHS;
2072
2073 // The calculation:
2074 // fq = fa*recip(fb)
2075 // may be too small due to the 1ulp accuracy in the recip
2076 // operation and rounding issues. Since fq is truncated to produce
2077 // an integer value it may be too small by one. This is
2078 // dealt with by incrementing fa by 1ulp:
2079 // fq = (fa+1ulp)*recip(fb)
2080 // This will increase fa's magnitude by at most 0.5
2081 // (i.e. when fabs(fa)==0x400000 the LSB of the mantissa represents 0.5).
2082 // Thus, this method is safe since fa must be incremented by at least 1.0
2083 // for the quotient to increase by one.
2084 SDValue fa = DAG.getNode(ToFp, DL, FltVT, ia);
2085 SDValue faAsInt = DAG.getNode(ISD::BITCAST, DL, MVT::i32, fa);
2086 SDValue faIncremented = DAG.getNode(ISD::ADD, DL, MVT::i32, faAsInt,
2087 DAG.getConstant(1, DL, MVT::i32));
2088 fa = DAG.getNode(ISD::BITCAST, DL, FltVT, faIncremented);
2089
2090 // float fb = (float)ib;
2091 SDValue fb = DAG.getNode(ToFp, DL, FltVT, ib);
2092
2093 SDValue fq = DAG.getNode(ISD::FMUL, DL, FltVT,
2094 fa, DAG.getNode(AMDGPUISD::RCP, DL, FltVT, fb));
2095
2096 // fq = trunc(fq);
2097 fq = DAG.getNode(ISD::FTRUNC, DL, FltVT, fq);
2098
2099 // int iq = (int)fq;
2100 SDValue Div = DAG.getNode(ToInt, DL, IntVT, fq);
2101
2102 // Rem needs compensation, it's easier to recompute it
2103 SDValue Rem = DAG.getNode(ISD::MUL, DL, VT, Div, RHS);
2104 Rem = DAG.getNode(ISD::SUB, DL, VT, LHS, Rem);
2105
2106 return DAG.getMergeValues({ Div, Rem }, DL);
2107}
2108
2110 SelectionDAG &DAG,
2112 SDLoc DL(Op);
2113 EVT VT = Op.getValueType();
2114
2115 assert(VT == MVT::i64 && "LowerUDIVREM64 expects an i64");
2116
2117 EVT HalfVT = VT.getHalfSizedIntegerVT(*DAG.getContext());
2118
2119 SDValue One = DAG.getConstant(1, DL, HalfVT);
2120 SDValue Zero = DAG.getConstant(0, DL, HalfVT);
2121
2122 //HiLo split
2123 SDValue LHS_Lo, LHS_Hi;
2124 SDValue LHS = Op.getOperand(0);
2125 std::tie(LHS_Lo, LHS_Hi) = DAG.SplitScalar(LHS, DL, HalfVT, HalfVT);
2126
2127 SDValue RHS_Lo, RHS_Hi;
2128 SDValue RHS = Op.getOperand(1);
2129 std::tie(RHS_Lo, RHS_Hi) = DAG.SplitScalar(RHS, DL, HalfVT, HalfVT);
2130
2131 if (DAG.MaskedValueIsZero(RHS, APInt::getHighBitsSet(64, 32)) &&
2132 DAG.MaskedValueIsZero(LHS, APInt::getHighBitsSet(64, 32))) {
2133
2134 SDValue Res = DAG.getNode(ISD::UDIVREM, DL, DAG.getVTList(HalfVT, HalfVT),
2135 LHS_Lo, RHS_Lo);
2136
2137 SDValue DIV = DAG.getBuildVector(MVT::v2i32, DL, {Res.getValue(0), Zero});
2138 SDValue REM = DAG.getBuildVector(MVT::v2i32, DL, {Res.getValue(1), Zero});
2139
2140 Results.push_back(DAG.getNode(ISD::BITCAST, DL, MVT::i64, DIV));
2141 Results.push_back(DAG.getNode(ISD::BITCAST, DL, MVT::i64, REM));
2142 return;
2143 }
2144
2145 if (isTypeLegal(MVT::i64)) {
2146 // The algorithm here is based on ideas from "Software Integer Division",
2147 // Tom Rodeheffer, August 2008.
2148
2151
2152 // Compute denominator reciprocal.
2153 unsigned FMAD =
2154 !Subtarget->hasMadMacF32Insts() ? (unsigned)ISD::FMA
2157 : (unsigned)AMDGPUISD::FMAD_FTZ;
2158
2159 SDValue Cvt_Lo = DAG.getNode(ISD::UINT_TO_FP, DL, MVT::f32, RHS_Lo);
2160 SDValue Cvt_Hi = DAG.getNode(ISD::UINT_TO_FP, DL, MVT::f32, RHS_Hi);
2161 SDValue Mad1 = DAG.getNode(FMAD, DL, MVT::f32, Cvt_Hi,
2162 DAG.getConstantFP(APInt(32, 0x4f800000).bitsToFloat(), DL, MVT::f32),
2163 Cvt_Lo);
2164 SDValue Rcp = DAG.getNode(AMDGPUISD::RCP, DL, MVT::f32, Mad1);
2165 SDValue Mul1 = DAG.getNode(ISD::FMUL, DL, MVT::f32, Rcp,
2166 DAG.getConstantFP(APInt(32, 0x5f7ffffc).bitsToFloat(), DL, MVT::f32));
2167 SDValue Mul2 = DAG.getNode(ISD::FMUL, DL, MVT::f32, Mul1,
2168 DAG.getConstantFP(APInt(32, 0x2f800000).bitsToFloat(), DL, MVT::f32));
2169 SDValue Trunc = DAG.getNode(ISD::FTRUNC, DL, MVT::f32, Mul2);
2170 SDValue Mad2 = DAG.getNode(FMAD, DL, MVT::f32, Trunc,
2171 DAG.getConstantFP(APInt(32, 0xcf800000).bitsToFloat(), DL, MVT::f32),
2172 Mul1);
2173 SDValue Rcp_Lo = DAG.getNode(ISD::FP_TO_UINT, DL, HalfVT, Mad2);
2174 SDValue Rcp_Hi = DAG.getNode(ISD::FP_TO_UINT, DL, HalfVT, Trunc);
2175 SDValue Rcp64 = DAG.getBitcast(VT,
2176 DAG.getBuildVector(MVT::v2i32, DL, {Rcp_Lo, Rcp_Hi}));
2177
2178 SDValue Zero64 = DAG.getConstant(0, DL, VT);
2179 SDValue One64 = DAG.getConstant(1, DL, VT);
2180 SDValue Zero1 = DAG.getConstant(0, DL, MVT::i1);
2181 SDVTList HalfCarryVT = DAG.getVTList(HalfVT, MVT::i1);
2182
2183 // First round of UNR (Unsigned integer Newton-Raphson).
2184 SDValue Neg_RHS = DAG.getNode(ISD::SUB, DL, VT, Zero64, RHS);
2185 SDValue Mullo1 = DAG.getNode(ISD::MUL, DL, VT, Neg_RHS, Rcp64);
2186 SDValue Mulhi1 = DAG.getNode(ISD::MULHU, DL, VT, Rcp64, Mullo1);
2187 SDValue Mulhi1_Lo, Mulhi1_Hi;
2188 std::tie(Mulhi1_Lo, Mulhi1_Hi) =
2189 DAG.SplitScalar(Mulhi1, DL, HalfVT, HalfVT);
2190 SDValue Add1_Lo = DAG.getNode(ISD::UADDO_CARRY, DL, HalfCarryVT, Rcp_Lo,
2191 Mulhi1_Lo, Zero1);
2192 SDValue Add1_Hi = DAG.getNode(ISD::UADDO_CARRY, DL, HalfCarryVT, Rcp_Hi,
2193 Mulhi1_Hi, Add1_Lo.getValue(1));
2194 SDValue Add1 = DAG.getBitcast(VT,
2195 DAG.getBuildVector(MVT::v2i32, DL, {Add1_Lo, Add1_Hi}));
2196
2197 // Second round of UNR.
2198 SDValue Mullo2 = DAG.getNode(ISD::MUL, DL, VT, Neg_RHS, Add1);
2199 SDValue Mulhi2 = DAG.getNode(ISD::MULHU, DL, VT, Add1, Mullo2);
2200 SDValue Mulhi2_Lo, Mulhi2_Hi;
2201 std::tie(Mulhi2_Lo, Mulhi2_Hi) =
2202 DAG.SplitScalar(Mulhi2, DL, HalfVT, HalfVT);
2203 SDValue Add2_Lo = DAG.getNode(ISD::UADDO_CARRY, DL, HalfCarryVT, Add1_Lo,
2204 Mulhi2_Lo, Zero1);
2205 SDValue Add2_Hi = DAG.getNode(ISD::UADDO_CARRY, DL, HalfCarryVT, Add1_Hi,
2206 Mulhi2_Hi, Add2_Lo.getValue(1));
2207 SDValue Add2 = DAG.getBitcast(VT,
2208 DAG.getBuildVector(MVT::v2i32, DL, {Add2_Lo, Add2_Hi}));
2209
2210 SDValue Mulhi3 = DAG.getNode(ISD::MULHU, DL, VT, LHS, Add2);
2211
2212 SDValue Mul3 = DAG.getNode(ISD::MUL, DL, VT, RHS, Mulhi3);
2213
2214 SDValue Mul3_Lo, Mul3_Hi;
2215 std::tie(Mul3_Lo, Mul3_Hi) = DAG.SplitScalar(Mul3, DL, HalfVT, HalfVT);
2216 SDValue Sub1_Lo = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, LHS_Lo,
2217 Mul3_Lo, Zero1);
2218 SDValue Sub1_Hi = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, LHS_Hi,
2219 Mul3_Hi, Sub1_Lo.getValue(1));
2220 SDValue Sub1_Mi = DAG.getNode(ISD::SUB, DL, HalfVT, LHS_Hi, Mul3_Hi);
2221 SDValue Sub1 = DAG.getBitcast(VT,
2222 DAG.getBuildVector(MVT::v2i32, DL, {Sub1_Lo, Sub1_Hi}));
2223
2224 SDValue MinusOne = DAG.getConstant(0xffffffffu, DL, HalfVT);
2225 SDValue C1 = DAG.getSelectCC(DL, Sub1_Hi, RHS_Hi, MinusOne, Zero,
2226 ISD::SETUGE);
2227 SDValue C2 = DAG.getSelectCC(DL, Sub1_Lo, RHS_Lo, MinusOne, Zero,
2228 ISD::SETUGE);
2229 SDValue C3 = DAG.getSelectCC(DL, Sub1_Hi, RHS_Hi, C2, C1, ISD::SETEQ);
2230
2231 // TODO: Here and below portions of the code can be enclosed into if/endif.
2232 // Currently control flow is unconditional and we have 4 selects after
2233 // potential endif to substitute PHIs.
2234
2235 // if C3 != 0 ...
2236 SDValue Sub2_Lo = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub1_Lo,
2237 RHS_Lo, Zero1);
2238 SDValue Sub2_Mi = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub1_Mi,
2239 RHS_Hi, Sub1_Lo.getValue(1));
2240 SDValue Sub2_Hi = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub2_Mi,
2241 Zero, Sub2_Lo.getValue(1));
2242 SDValue Sub2 = DAG.getBitcast(VT,
2243 DAG.getBuildVector(MVT::v2i32, DL, {Sub2_Lo, Sub2_Hi}));
2244
2245 SDValue Add3 = DAG.getNode(ISD::ADD, DL, VT, Mulhi3, One64);
2246
2247 SDValue C4 = DAG.getSelectCC(DL, Sub2_Hi, RHS_Hi, MinusOne, Zero,
2248 ISD::SETUGE);
2249 SDValue C5 = DAG.getSelectCC(DL, Sub2_Lo, RHS_Lo, MinusOne, Zero,
2250 ISD::SETUGE);
2251 SDValue C6 = DAG.getSelectCC(DL, Sub2_Hi, RHS_Hi, C5, C4, ISD::SETEQ);
2252
2253 // if (C6 != 0)
2254 SDValue Add4 = DAG.getNode(ISD::ADD, DL, VT, Add3, One64);
2255
2256 SDValue Sub3_Lo = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub2_Lo,
2257 RHS_Lo, Zero1);
2258 SDValue Sub3_Mi = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub2_Mi,
2259 RHS_Hi, Sub2_Lo.getValue(1));
2260 SDValue Sub3_Hi = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub3_Mi,
2261 Zero, Sub3_Lo.getValue(1));
2262 SDValue Sub3 = DAG.getBitcast(VT,
2263 DAG.getBuildVector(MVT::v2i32, DL, {Sub3_Lo, Sub3_Hi}));
2264
2265 // endif C6
2266 // endif C3
2267
2268 SDValue Sel1 = DAG.getSelectCC(DL, C6, Zero, Add4, Add3, ISD::SETNE);
2269 SDValue Div = DAG.getSelectCC(DL, C3, Zero, Sel1, Mulhi3, ISD::SETNE);
2270
2271 SDValue Sel2 = DAG.getSelectCC(DL, C6, Zero, Sub3, Sub2, ISD::SETNE);
2272 SDValue Rem = DAG.getSelectCC(DL, C3, Zero, Sel2, Sub1, ISD::SETNE);
2273
2274 Results.push_back(Div);
2275 Results.push_back(Rem);
2276
2277 return;
2278 }
2279
2280 // r600 expandion.
2281 // Get Speculative values
2282 SDValue DIV_Part = DAG.getNode(ISD::UDIV, DL, HalfVT, LHS_Hi, RHS_Lo);
2283 SDValue REM_Part = DAG.getNode(ISD::UREM, DL, HalfVT, LHS_Hi, RHS_Lo);
2284
2285 SDValue REM_Lo = DAG.getSelectCC(DL, RHS_Hi, Zero, REM_Part, LHS_Hi, ISD::SETEQ);
2286 SDValue REM = DAG.getBuildVector(MVT::v2i32, DL, {REM_Lo, Zero});
2287 REM = DAG.getNode(ISD::BITCAST, DL, MVT::i64, REM);
2288
2289 SDValue DIV_Hi = DAG.getSelectCC(DL, RHS_Hi, Zero, DIV_Part, Zero, ISD::SETEQ);
2290 SDValue DIV_Lo = Zero;
2291
2292 const unsigned halfBitWidth = HalfVT.getSizeInBits();
2293
2294 for (unsigned i = 0; i < halfBitWidth; ++i) {
2295 const unsigned bitPos = halfBitWidth - i - 1;
2296 SDValue POS = DAG.getConstant(bitPos, DL, HalfVT);
2297 // Get value of high bit
2298 SDValue HBit = DAG.getNode(ISD::SRL, DL, HalfVT, LHS_Lo, POS);
2299 HBit = DAG.getNode(ISD::AND, DL, HalfVT, HBit, One);
2300 HBit = DAG.getNode(ISD::ZERO_EXTEND, DL, VT, HBit);
2301
2302 // Shift
2303 REM = DAG.getNode(ISD::SHL, DL, VT, REM, DAG.getConstant(1, DL, VT));
2304 // Add LHS high bit
2305 REM = DAG.getNode(ISD::OR, DL, VT, REM, HBit);
2306
2307 SDValue BIT = DAG.getConstant(1ULL << bitPos, DL, HalfVT);
2308 SDValue realBIT = DAG.getSelectCC(DL, REM, RHS, BIT, Zero, ISD::SETUGE);
2309
2310 DIV_Lo = DAG.getNode(ISD::OR, DL, HalfVT, DIV_Lo, realBIT);
2311
2312 // Update REM
2313 SDValue REM_sub = DAG.getNode(ISD::SUB, DL, VT, REM, RHS);
2314 REM = DAG.getSelectCC(DL, REM, RHS, REM_sub, REM, ISD::SETUGE);
2315 }
2316
2317 SDValue DIV = DAG.getBuildVector(MVT::v2i32, DL, {DIV_Lo, DIV_Hi});
2318 DIV = DAG.getNode(ISD::BITCAST, DL, MVT::i64, DIV);
2319 Results.push_back(DIV);
2320 Results.push_back(REM);
2321}
2322
2324 SelectionDAG &DAG) const {
2325 SDLoc DL(Op);
2326 EVT VT = Op.getValueType();
2327
2328 if (VT == MVT::i64) {
2330 LowerUDIVREM64(Op, DAG, Results);
2331 return DAG.getMergeValues(Results, DL);
2332 }
2333
2334 if (VT == MVT::i32) {
2335 if (SDValue Res = LowerDIVREMToFloat(Op, DAG, false))
2336 return Res;
2337 }
2338
2339 SDValue X = Op.getOperand(0);
2340 SDValue Y = Op.getOperand(1);
2341
2342 // See AMDGPUCodeGenPrepare::expandDivRem32 for a description of the
2343 // algorithm used here.
2344
2345 // Initial estimate of inv(y).
2346 SDValue Z = DAG.getNode(AMDGPUISD::URECIP, DL, VT, Y);
2347
2348 // One round of UNR.
2349 SDValue NegY = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), Y);
2350 SDValue NegYZ = DAG.getNode(ISD::MUL, DL, VT, NegY, Z);
2351 Z = DAG.getNode(ISD::ADD, DL, VT, Z,
2352 DAG.getNode(ISD::MULHU, DL, VT, Z, NegYZ));
2353
2354 // Quotient/remainder estimate.
2355 SDValue Q = DAG.getNode(ISD::MULHU, DL, VT, X, Z);
2356 SDValue R =
2357 DAG.getNode(ISD::SUB, DL, VT, X, DAG.getNode(ISD::MUL, DL, VT, Q, Y));
2358
2359 // First quotient/remainder refinement.
2360 EVT CCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
2361 SDValue One = DAG.getConstant(1, DL, VT);
2362 SDValue Cond = DAG.getSetCC(DL, CCVT, R, Y, ISD::SETUGE);
2363 Q = DAG.getNode(ISD::SELECT, DL, VT, Cond,
2364 DAG.getNode(ISD::ADD, DL, VT, Q, One), Q);
2365 R = DAG.getNode(ISD::SELECT, DL, VT, Cond,
2366 DAG.getNode(ISD::SUB, DL, VT, R, Y), R);
2367
2368 // Second quotient/remainder refinement.
2369 Cond = DAG.getSetCC(DL, CCVT, R, Y, ISD::SETUGE);
2370 Q = DAG.getNode(ISD::SELECT, DL, VT, Cond,
2371 DAG.getNode(ISD::ADD, DL, VT, Q, One), Q);
2372 R = DAG.getNode(ISD::SELECT, DL, VT, Cond,
2373 DAG.getNode(ISD::SUB, DL, VT, R, Y), R);
2374
2375 return DAG.getMergeValues({Q, R}, DL);
2376}
2377
2379 SelectionDAG &DAG) const {
2380 SDLoc DL(Op);
2381 EVT VT = Op.getValueType();
2382
2383 SDValue LHS = Op.getOperand(0);
2384 SDValue RHS = Op.getOperand(1);
2385
2386 SDValue Zero = DAG.getConstant(0, DL, VT);
2387 SDValue NegOne = DAG.getAllOnesConstant(DL, VT);
2388
2389 if (VT == MVT::i32) {
2390 if (SDValue Res = LowerDIVREMToFloat(Op, DAG, true))
2391 return Res;
2392 }
2393
2394 // LHS must have > 33 sign-bits to ensure that LHS != -2147483648
2395 // Otherwise 32-bit division cannot be used safely.
2396 // -2147483648/1 and -2147483648/-1 are not equal,
2397 // but they produce the same lower 32-bit result.
2398 if (VT == MVT::i64 && DAG.ComputeNumSignBits(LHS) > 33 &&
2399 DAG.ComputeNumSignBits(RHS) > 32) {
2400 EVT HalfVT = VT.getHalfSizedIntegerVT(*DAG.getContext());
2401
2402 //HiLo split
2403 SDValue LHS_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, LHS, Zero);
2404 SDValue RHS_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, RHS, Zero);
2405 SDValue DIVREM = DAG.getNode(ISD::SDIVREM, DL, DAG.getVTList(HalfVT, HalfVT),
2406 LHS_Lo, RHS_Lo);
2407 SDValue Res[2] = {
2408 DAG.getNode(ISD::SIGN_EXTEND, DL, VT, DIVREM.getValue(0)),
2409 DAG.getNode(ISD::SIGN_EXTEND, DL, VT, DIVREM.getValue(1))
2410 };
2411 return DAG.getMergeValues(Res, DL);
2412 }
2413
2414 SDValue LHSign = DAG.getSelectCC(DL, LHS, Zero, NegOne, Zero, ISD::SETLT);
2415 SDValue RHSign = DAG.getSelectCC(DL, RHS, Zero, NegOne, Zero, ISD::SETLT);
2416 SDValue DSign = DAG.getNode(ISD::XOR, DL, VT, LHSign, RHSign);
2417 SDValue RSign = LHSign; // Remainder sign is the same as LHS
2418
2419 LHS = DAG.getNode(ISD::ADD, DL, VT, LHS, LHSign);
2420 RHS = DAG.getNode(ISD::ADD, DL, VT, RHS, RHSign);
2421
2422 LHS = DAG.getNode(ISD::XOR, DL, VT, LHS, LHSign);
2423 RHS = DAG.getNode(ISD::XOR, DL, VT, RHS, RHSign);
2424
2425 SDValue Div = DAG.getNode(ISD::UDIVREM, DL, DAG.getVTList(VT, VT), LHS, RHS);
2426 SDValue Rem = Div.getValue(1);
2427
2428 Div = DAG.getNode(ISD::XOR, DL, VT, Div, DSign);
2429 Rem = DAG.getNode(ISD::XOR, DL, VT, Rem, RSign);
2430
2431 Div = DAG.getNode(ISD::SUB, DL, VT, Div, DSign);
2432 Rem = DAG.getNode(ISD::SUB, DL, VT, Rem, RSign);
2433
2434 SDValue Res[2] = {
2435 Div,
2436 Rem
2437 };
2438 return DAG.getMergeValues(Res, DL);
2439}
2440
2442 SDLoc SL(Op);
2443 SDValue Src = Op.getOperand(0);
2444
2445 // result = trunc(src)
2446 // if (src > 0.0 && src != result)
2447 // result += 1.0
2448
2449 SDValue Trunc = DAG.getNode(ISD::FTRUNC, SL, MVT::f64, Src);
2450
2451 const SDValue Zero = DAG.getConstantFP(0.0, SL, MVT::f64);
2452 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f64);
2453
2454 EVT SetCCVT =
2455 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f64);
2456
2457 SDValue Lt0 = DAG.getSetCC(SL, SetCCVT, Src, Zero, ISD::SETOGT);
2458 SDValue NeTrunc = DAG.getSetCC(SL, SetCCVT, Src, Trunc, ISD::SETONE);
2459 SDValue And = DAG.getNode(ISD::AND, SL, SetCCVT, Lt0, NeTrunc);
2460
2461 SDValue Add = DAG.getNode(ISD::SELECT, SL, MVT::f64, And, One, Zero);
2462 // TODO: Should this propagate fast-math-flags?
2463 return DAG.getNode(ISD::FADD, SL, MVT::f64, Trunc, Add);
2464}
2465
2467 SelectionDAG &DAG) {
2468 const unsigned FractBits = 52;
2469 const unsigned ExpBits = 11;
2470
2471 SDValue ExpPart = DAG.getNode(AMDGPUISD::BFE_U32, SL, MVT::i32,
2472 Hi,
2473 DAG.getConstant(FractBits - 32, SL, MVT::i32),
2474 DAG.getConstant(ExpBits, SL, MVT::i32));
2475 SDValue Exp = DAG.getNode(ISD::SUB, SL, MVT::i32, ExpPart,
2476 DAG.getConstant(1023, SL, MVT::i32));
2477
2478 return Exp;
2479}
2480
2482 SDLoc SL(Op);
2483 SDValue Src = Op.getOperand(0);
2484
2485 assert(Op.getValueType() == MVT::f64);
2486
2487 const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);
2488
2489 // Extract the upper half, since this is where we will find the sign and
2490 // exponent.
2491 SDValue Hi = getHiHalf64(Src, DAG);
2492
2493 SDValue Exp = extractF64Exponent(Hi, SL, DAG);
2494
2495 const unsigned FractBits = 52;
2496
2497 // Extract the sign bit.
2498 const SDValue SignBitMask = DAG.getConstant(UINT32_C(1) << 31, SL, MVT::i32);
2499 SDValue SignBit = DAG.getNode(ISD::AND, SL, MVT::i32, Hi, SignBitMask);
2500
2501 // Extend back to 64-bits.
2502 SDValue SignBit64 = DAG.getBuildVector(MVT::v2i32, SL, {Zero, SignBit});
2503 SignBit64 = DAG.getNode(ISD::BITCAST, SL, MVT::i64, SignBit64);
2504
2505 SDValue BcInt = DAG.getNode(ISD::BITCAST, SL, MVT::i64, Src);
2506 const SDValue FractMask
2507 = DAG.getConstant((UINT64_C(1) << FractBits) - 1, SL, MVT::i64);
2508
2509 SDValue Shr = DAG.getNode(ISD::SRA, SL, MVT::i64, FractMask, Exp);
2510 SDValue Not = DAG.getNOT(SL, Shr, MVT::i64);
2511 SDValue Tmp0 = DAG.getNode(ISD::AND, SL, MVT::i64, BcInt, Not);
2512
2513 EVT SetCCVT =
2514 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::i32);
2515
2516 const SDValue FiftyOne = DAG.getConstant(FractBits - 1, SL, MVT::i32);
2517
2518 SDValue ExpLt0 = DAG.getSetCC(SL, SetCCVT, Exp, Zero, ISD::SETLT);
2519 SDValue ExpGt51 = DAG.getSetCC(SL, SetCCVT, Exp, FiftyOne, ISD::SETGT);
2520
2521 SDValue Tmp1 = DAG.getNode(ISD::SELECT, SL, MVT::i64, ExpLt0, SignBit64, Tmp0);
2522 SDValue Tmp2 = DAG.getNode(ISD::SELECT, SL, MVT::i64, ExpGt51, BcInt, Tmp1);
2523
2524 return DAG.getNode(ISD::BITCAST, SL, MVT::f64, Tmp2);
2525}
2526
2528 SelectionDAG &DAG) const {
2529 SDLoc SL(Op);
2530 SDValue Src = Op.getOperand(0);
2531
2532 assert(Op.getValueType() == MVT::f64);
2533
2534 APFloat C1Val(APFloat::IEEEdouble(), "0x1.0p+52");
2535 SDValue C1 = DAG.getConstantFP(C1Val, SL, MVT::f64);
2536 SDValue CopySign = DAG.getNode(ISD::FCOPYSIGN, SL, MVT::f64, C1, Src);
2537
2538 // TODO: Should this propagate fast-math-flags?
2539
2540 SDValue Tmp1 = DAG.getNode(ISD::FADD, SL, MVT::f64, Src, CopySign);
2541 SDValue Tmp2 = DAG.getNode(ISD::FSUB, SL, MVT::f64, Tmp1, CopySign);
2542
2543 SDValue Fabs = DAG.getNode(ISD::FABS, SL, MVT::f64, Src);
2544
2545 APFloat C2Val(APFloat::IEEEdouble(), "0x1.fffffffffffffp+51");
2546 SDValue C2 = DAG.getConstantFP(C2Val, SL, MVT::f64);
2547
2548 EVT SetCCVT =
2549 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f64);
2550 SDValue Cond = DAG.getSetCC(SL, SetCCVT, Fabs, C2, ISD::SETOGT);
2551
2552 return DAG.getSelect(SL, MVT::f64, Cond, Src, Tmp2);
2553}
2554
2556 SelectionDAG &DAG) const {
2557 // FNEARBYINT and FRINT are the same, except in their handling of FP
2558 // exceptions. Those aren't really meaningful for us, and OpenCL only has
2559 // rint, so just treat them as equivalent.
2560 return DAG.getNode(ISD::FROUNDEVEN, SDLoc(Op), Op.getValueType(),
2561 Op.getOperand(0));
2562}
2563
2565 auto VT = Op.getValueType();
2566 auto Arg = Op.getOperand(0u);
2567 return DAG.getNode(ISD::FROUNDEVEN, SDLoc(Op), VT, Arg);
2568}
2569
2570// XXX - May require not supporting f32 denormals?
2571
2572// Don't handle v2f16. The extra instructions to scalarize and repack around the
2573// compare and vselect end up producing worse code than scalarizing the whole
2574// operation.
2576 SDLoc SL(Op);
2577 SDValue X = Op.getOperand(0);
2578 EVT VT = Op.getValueType();
2579
2580 SDValue T = DAG.getNode(ISD::FTRUNC, SL, VT, X);
2581
2582 // TODO: Should this propagate fast-math-flags?
2583
2584 SDValue Diff = DAG.getNode(ISD::FSUB, SL, VT, X, T);
2585
2586 SDValue AbsDiff = DAG.getNode(ISD::FABS, SL, VT, Diff);
2587
2588 const SDValue Zero = DAG.getConstantFP(0.0, SL, VT);
2589 const SDValue One = DAG.getConstantFP(1.0, SL, VT);
2590
2591 EVT SetCCVT =
2592 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
2593
2594 const SDValue Half = DAG.getConstantFP(0.5, SL, VT);
2595 SDValue Cmp = DAG.getSetCC(SL, SetCCVT, AbsDiff, Half, ISD::SETOGE);
2596 SDValue OneOrZeroFP = DAG.getNode(ISD::SELECT, SL, VT, Cmp, One, Zero);
2597
2598 SDValue SignedOffset = DAG.getNode(ISD::FCOPYSIGN, SL, VT, OneOrZeroFP, X);
2599 return DAG.getNode(ISD::FADD, SL, VT, T, SignedOffset);
2600}
2601
2603 SDLoc SL(Op);
2604 SDValue Src = Op.getOperand(0);
2605
2606 // result = trunc(src);
2607 // if (src < 0.0 && src != result)
2608 // result += -1.0.
2609
2610 SDValue Trunc = DAG.getNode(ISD::FTRUNC, SL, MVT::f64, Src);
2611
2612 const SDValue Zero = DAG.getConstantFP(0.0, SL, MVT::f64);
2613 const SDValue NegOne = DAG.getConstantFP(-1.0, SL, MVT::f64);
2614
2615 EVT SetCCVT =
2616 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f64);
2617
2618 SDValue Lt0 = DAG.getSetCC(SL, SetCCVT, Src, Zero, ISD::SETOLT);
2619 SDValue NeTrunc = DAG.getSetCC(SL, SetCCVT, Src, Trunc, ISD::SETONE);
2620 SDValue And = DAG.getNode(ISD::AND, SL, SetCCVT, Lt0, NeTrunc);
2621
2622 SDValue Add = DAG.getNode(ISD::SELECT, SL, MVT::f64, And, NegOne, Zero);
2623 // TODO: Should this propagate fast-math-flags?
2624 return DAG.getNode(ISD::FADD, SL, MVT::f64, Trunc, Add);
2625}
2626
2627/// Return true if it's known that \p Src can never be an f32 denormal value.
2629 switch (Src.getOpcode()) {
2630 case ISD::FP_EXTEND:
2631 return Src.getOperand(0).getValueType() == MVT::f16;
2632 case ISD::FP16_TO_FP:
2633 case ISD::FFREXP:
2634 case ISD::FSQRT:
2635 case AMDGPUISD::LOG:
2636 case AMDGPUISD::EXP:
2637 return true;
2639 unsigned IntrinsicID = Src.getConstantOperandVal(0);
2640 switch (IntrinsicID) {
2641 case Intrinsic::amdgcn_frexp_mant:
2642 case Intrinsic::amdgcn_log:
2643 case Intrinsic::amdgcn_log_clamp:
2644 case Intrinsic::amdgcn_exp2:
2645 case Intrinsic::amdgcn_sqrt:
2646 return true;
2647 default:
2648 return false;
2649 }
2650 }
2651 default:
2652 return false;
2653 }
2654
2655 llvm_unreachable("covered opcode switch");
2656}
2657
2659 SDNodeFlags Flags) {
2660 return Flags.hasApproximateFuncs();
2661}
2662
2671
2673 SDValue Src,
2674 SDNodeFlags Flags) const {
2675 SDLoc SL(Src);
2676 EVT VT = Src.getValueType();
2677 const fltSemantics &Semantics = VT.getFltSemantics();
2678 SDValue SmallestNormal =
2679 DAG.getConstantFP(APFloat::getSmallestNormalized(Semantics), SL, VT);
2680
2681 // Want to scale denormals up, but negatives and 0 work just as well on the
2682 // scaled path.
2683 SDValue IsLtSmallestNormal = DAG.getSetCC(
2684 SL, getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT), Src,
2685 SmallestNormal, ISD::SETOLT);
2686
2687 return IsLtSmallestNormal;
2688}
2689
2691 SDNodeFlags Flags) const {
2692 SDLoc SL(Src);
2693 EVT VT = Src.getValueType();
2694 const fltSemantics &Semantics = VT.getFltSemantics();
2695 SDValue Inf = DAG.getConstantFP(APFloat::getInf(Semantics), SL, VT);
2696
2697 SDValue Fabs = DAG.getNode(ISD::FABS, SL, VT, Src, Flags);
2698 SDValue IsFinite = DAG.getSetCC(
2699 SL, getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT), Fabs,
2700 Inf, ISD::SETOLT);
2701 return IsFinite;
2702}
2703
2704/// If denormal handling is required return the scaled input to FLOG2, and the
2705/// check for denormal range. Otherwise, return null values.
2706std::pair<SDValue, SDValue>
2708 SDValue Src, SDNodeFlags Flags) const {
2709 if (!needsDenormHandlingF32(DAG, Src, Flags))
2710 return {};
2711
2712 MVT VT = MVT::f32;
2713 const fltSemantics &Semantics = APFloat::IEEEsingle();
2714 SDValue SmallestNormal =
2715 DAG.getConstantFP(APFloat::getSmallestNormalized(Semantics), SL, VT);
2716
2717 SDValue IsLtSmallestNormal = DAG.getSetCC(
2718 SL, getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT), Src,
2719 SmallestNormal, ISD::SETOLT);
2720
2721 SDValue Scale32 = DAG.getConstantFP(0x1.0p+32, SL, VT);
2722 SDValue One = DAG.getConstantFP(1.0, SL, VT);
2723 SDValue ScaleFactor =
2724 DAG.getNode(ISD::SELECT, SL, VT, IsLtSmallestNormal, Scale32, One, Flags);
2725
2726 SDValue ScaledInput = DAG.getNode(ISD::FMUL, SL, VT, Src, ScaleFactor, Flags);
2727 return {ScaledInput, IsLtSmallestNormal};
2728}
2729
2731 // v_log_f32 is good enough for OpenCL, except it doesn't handle denormals.
2732 // If we have to handle denormals, scale up the input and adjust the result.
2733
2734 // scaled = x * (is_denormal ? 0x1.0p+32 : 1.0)
2735 // log2 = amdgpu_log2 - (is_denormal ? 32.0 : 0.0)
2736
2737 SDLoc SL(Op);
2738 EVT VT = Op.getValueType();
2739 SDValue Src = Op.getOperand(0);
2740 SDNodeFlags Flags = Op->getFlags();
2741
2742 if (VT == MVT::f16) {
2743 // Nothing in half is a denormal when promoted to f32.
2744 assert(!isTypeLegal(VT));
2745 SDValue Ext = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Src, Flags);
2746 SDValue Log = DAG.getNode(AMDGPUISD::LOG, SL, MVT::f32, Ext, Flags);
2747 return DAG.getNode(ISD::FP_ROUND, SL, VT, Log,
2748 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
2749 }
2750
2751 auto [ScaledInput, IsLtSmallestNormal] =
2752 getScaledLogInput(DAG, SL, Src, Flags);
2753 if (!ScaledInput)
2754 return DAG.getNode(AMDGPUISD::LOG, SL, VT, Src, Flags);
2755
2756 SDValue Log2 = DAG.getNode(AMDGPUISD::LOG, SL, VT, ScaledInput, Flags);
2757
2758 SDValue ThirtyTwo = DAG.getConstantFP(32.0, SL, VT);
2759 SDValue Zero = DAG.getConstantFP(0.0, SL, VT);
2760 SDValue ResultOffset =
2761 DAG.getNode(ISD::SELECT, SL, VT, IsLtSmallestNormal, ThirtyTwo, Zero);
2762 return DAG.getNode(ISD::FSUB, SL, VT, Log2, ResultOffset, Flags);
2763}
2764
2765static SDValue getMad(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue X,
2766 SDValue Y, SDValue C, SDNodeFlags Flags = SDNodeFlags()) {
2767 SDValue Mul = DAG.getNode(ISD::FMUL, SL, VT, X, Y, Flags);
2768 return DAG.getNode(ISD::FADD, SL, VT, Mul, C, Flags);
2769}
2770
2772 SelectionDAG &DAG) const {
2773 SDValue X = Op.getOperand(0);
2774 EVT VT = Op.getValueType();
2775 SDNodeFlags Flags = Op->getFlags();
2776 SDLoc DL(Op);
2777 const bool IsLog10 = Op.getOpcode() == ISD::FLOG10;
2778 assert(IsLog10 || Op.getOpcode() == ISD::FLOG);
2779
2780 if (VT == MVT::f16 || Flags.hasApproximateFuncs()) {
2781 // TODO: The direct f16 path is 1.79 ulp for f16. This should be used
2782 // depending on !fpmath metadata.
2783
2784 bool PromoteToF32 = VT == MVT::f16 && (!Flags.hasApproximateFuncs() ||
2785 !isTypeLegal(MVT::f16));
2786
2787 if (PromoteToF32) {
2788 // Log and multiply in f32 is always good enough for f16.
2789 X = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, X, Flags);
2790 }
2791
2792 SDValue Lowered = LowerFLOGUnsafe(X, DL, DAG, IsLog10, Flags);
2793 if (PromoteToF32) {
2794 return DAG.getNode(ISD::FP_ROUND, DL, VT, Lowered,
2795 DAG.getTargetConstant(0, DL, MVT::i32), Flags);
2796 }
2797
2798 return Lowered;
2799 }
2800
2801 SDValue ScaledInput, IsScaled;
2802 if (VT == MVT::f16)
2803 X = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, X, Flags);
2804 else {
2805 std::tie(ScaledInput, IsScaled) = getScaledLogInput(DAG, DL, X, Flags);
2806 if (ScaledInput)
2807 X = ScaledInput;
2808 }
2809
2810 SDValue Y = DAG.getNode(AMDGPUISD::LOG, DL, VT, X, Flags);
2811
2812 SDValue R;
2813 if (Subtarget->hasFastFMAF32()) {
2814 // c+cc are ln(2)/ln(10) to more than 49 bits
2815 const float c_log10 = 0x1.344134p-2f;
2816 const float cc_log10 = 0x1.09f79ep-26f;
2817
2818 // c + cc is ln(2) to more than 49 bits
2819 const float c_log = 0x1.62e42ep-1f;
2820 const float cc_log = 0x1.efa39ep-25f;
2821
2822 SDValue C = DAG.getConstantFP(IsLog10 ? c_log10 : c_log, DL, VT);
2823 SDValue CC = DAG.getConstantFP(IsLog10 ? cc_log10 : cc_log, DL, VT);
2824 // This adds correction terms for which contraction may lead to an increase
2825 // in the error of the approximation, so disable it.
2826 Flags.setAllowContract(false);
2827 R = DAG.getNode(ISD::FMUL, DL, VT, Y, C, Flags);
2828 SDValue NegR = DAG.getNode(ISD::FNEG, DL, VT, R, Flags);
2829 SDValue FMA0 = DAG.getNode(ISD::FMA, DL, VT, Y, C, NegR, Flags);
2830 SDValue FMA1 = DAG.getNode(ISD::FMA, DL, VT, Y, CC, FMA0, Flags);
2831 R = DAG.getNode(ISD::FADD, DL, VT, R, FMA1, Flags);
2832 } else {
2833 // ch+ct is ln(2)/ln(10) to more than 36 bits
2834 const float ch_log10 = 0x1.344000p-2f;
2835 const float ct_log10 = 0x1.3509f6p-18f;
2836
2837 // ch + ct is ln(2) to more than 36 bits
2838 const float ch_log = 0x1.62e000p-1f;
2839 const float ct_log = 0x1.0bfbe8p-15f;
2840
2841 SDValue CH = DAG.getConstantFP(IsLog10 ? ch_log10 : ch_log, DL, VT);
2842 SDValue CT = DAG.getConstantFP(IsLog10 ? ct_log10 : ct_log, DL, VT);
2843
2844 SDValue YAsInt = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Y);
2845 SDValue MaskConst = DAG.getConstant(0xfffff000, DL, MVT::i32);
2846 SDValue YHInt = DAG.getNode(ISD::AND, DL, MVT::i32, YAsInt, MaskConst);
2847 SDValue YH = DAG.getNode(ISD::BITCAST, DL, MVT::f32, YHInt);
2848 SDValue YT = DAG.getNode(ISD::FSUB, DL, VT, Y, YH, Flags);
2849 // This adds correction terms for which contraction may lead to an increase
2850 // in the error of the approximation, so disable it.
2851 Flags.setAllowContract(false);
2852 SDValue YTCT = DAG.getNode(ISD::FMUL, DL, VT, YT, CT, Flags);
2853 SDValue Mad0 = getMad(DAG, DL, VT, YH, CT, YTCT, Flags);
2854 SDValue Mad1 = getMad(DAG, DL, VT, YT, CH, Mad0, Flags);
2855 R = getMad(DAG, DL, VT, YH, CH, Mad1);
2856 }
2857
2858 const bool IsFiniteOnly = Flags.hasNoNaNs() && Flags.hasNoInfs();
2859
2860 // TODO: Check if known finite from source value.
2861 if (!IsFiniteOnly) {
2862 SDValue IsFinite = getIsFinite(DAG, Y, Flags);
2863 R = DAG.getNode(ISD::SELECT, DL, VT, IsFinite, R, Y, Flags);
2864 }
2865
2866 if (IsScaled) {
2867 SDValue Zero = DAG.getConstantFP(0.0f, DL, VT);
2868 SDValue ShiftK =
2869 DAG.getConstantFP(IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f, DL, VT);
2870 SDValue Shift =
2871 DAG.getNode(ISD::SELECT, DL, VT, IsScaled, ShiftK, Zero, Flags);
2872 R = DAG.getNode(ISD::FSUB, DL, VT, R, Shift, Flags);
2873 }
2874
2875 return R;
2876}
2877
2881
2882// Do f32 fast math expansion for flog2 or flog10. This is accurate enough for a
2883// promote f16 operation.
2885 SelectionDAG &DAG, bool IsLog10,
2886 SDNodeFlags Flags) const {
2887 EVT VT = Src.getValueType();
2888 unsigned LogOp =
2889 VT == MVT::f32 ? (unsigned)AMDGPUISD::LOG : (unsigned)ISD::FLOG2;
2890
2891 double Log2BaseInverted =
2893
2894 if (VT == MVT::f32) {
2895 auto [ScaledInput, IsScaled] = getScaledLogInput(DAG, SL, Src, Flags);
2896 if (ScaledInput) {
2897 SDValue LogSrc = DAG.getNode(AMDGPUISD::LOG, SL, VT, ScaledInput, Flags);
2898 SDValue ScaledResultOffset =
2899 DAG.getConstantFP(-32.0 * Log2BaseInverted, SL, VT);
2900
2901 SDValue Zero = DAG.getConstantFP(0.0f, SL, VT);
2902
2903 SDValue ResultOffset = DAG.getNode(ISD::SELECT, SL, VT, IsScaled,
2904 ScaledResultOffset, Zero, Flags);
2905
2906 SDValue Log2Inv = DAG.getConstantFP(Log2BaseInverted, SL, VT);
2907
2908 if (Subtarget->hasFastFMAF32())
2909 return DAG.getNode(ISD::FMA, SL, VT, LogSrc, Log2Inv, ResultOffset,
2910 Flags);
2911 SDValue Mul = DAG.getNode(ISD::FMUL, SL, VT, LogSrc, Log2Inv, Flags);
2912 return DAG.getNode(ISD::FADD, SL, VT, Mul, ResultOffset);
2913 }
2914 }
2915
2916 SDValue Log2Operand = DAG.getNode(LogOp, SL, VT, Src, Flags);
2917 SDValue Log2BaseInvertedOperand = DAG.getConstantFP(Log2BaseInverted, SL, VT);
2918
2919 return DAG.getNode(ISD::FMUL, SL, VT, Log2Operand, Log2BaseInvertedOperand,
2920 Flags);
2921}
2922
2923// This expansion gives a result slightly better than 1ulp.
2925 SelectionDAG &DAG) const {
2926 SDLoc DL(Op);
2927 SDValue X = Op.getOperand(0);
2928
2929 // TODO: Check if reassoc is safe. There is an output change in exp2 and
2930 // exp10, which slightly increases ulp.
2931 SDNodeFlags Flags = Op->getFlags() & ~SDNodeFlags::AllowReassociation;
2932
2933 SDValue DN, F, T;
2934
2935 if (Op.getOpcode() == ISD::FEXP2) {
2936 // dn = rint(x)
2937 DN = DAG.getNode(ISD::FRINT, DL, MVT::f64, X, Flags);
2938 // f = x - dn
2939 F = DAG.getNode(ISD::FSUB, DL, MVT::f64, X, DN, Flags);
2940 // t = f*C1 + f*C2
2941 SDValue C1 = DAG.getConstantFP(0x1.62e42fefa39efp-1, DL, MVT::f64);
2942 SDValue C2 = DAG.getConstantFP(0x1.abc9e3b39803fp-56, DL, MVT::f64);
2943 SDValue Mul2 = DAG.getNode(ISD::FMUL, DL, MVT::f64, F, C2, Flags);
2944 T = DAG.getNode(ISD::FMA, DL, MVT::f64, F, C1, Mul2, Flags);
2945 } else if (Op.getOpcode() == ISD::FEXP10) {
2946 // dn = rint(x * C1)
2947 SDValue C1 = DAG.getConstantFP(0x1.a934f0979a371p+1, DL, MVT::f64);
2948 SDValue Mul = DAG.getNode(ISD::FMUL, DL, MVT::f64, X, C1, Flags);
2949 DN = DAG.getNode(ISD::FRINT, DL, MVT::f64, Mul, Flags);
2950
2951 // f = FMA(-dn, C2, FMA(-dn, C3, x))
2952 SDValue NegDN = DAG.getNode(ISD::FNEG, DL, MVT::f64, DN, Flags);
2953 SDValue C2 = DAG.getConstantFP(-0x1.9dc1da994fd21p-59, DL, MVT::f64);
2954 SDValue C3 = DAG.getConstantFP(0x1.34413509f79ffp-2, DL, MVT::f64);
2955 SDValue Inner = DAG.getNode(ISD::FMA, DL, MVT::f64, NegDN, C3, X, Flags);
2956 F = DAG.getNode(ISD::FMA, DL, MVT::f64, NegDN, C2, Inner, Flags);
2957
2958 // t = FMA(f, C4, f*C5)
2959 SDValue C4 = DAG.getConstantFP(0x1.26bb1bbb55516p+1, DL, MVT::f64);
2960 SDValue C5 = DAG.getConstantFP(-0x1.f48ad494ea3e9p-53, DL, MVT::f64);
2961 SDValue MulF = DAG.getNode(ISD::FMUL, DL, MVT::f64, F, C5, Flags);
2962 T = DAG.getNode(ISD::FMA, DL, MVT::f64, F, C4, MulF, Flags);
2963 } else { // ISD::FEXP
2964 // dn = rint(x * C1)
2965 SDValue C1 = DAG.getConstantFP(0x1.71547652b82fep+0, DL, MVT::f64);
2966 SDValue Mul = DAG.getNode(ISD::FMUL, DL, MVT::f64, X, C1, Flags);
2967 DN = DAG.getNode(ISD::FRINT, DL, MVT::f64, Mul, Flags);
2968
2969 // t = FMA(-dn, C2, FMA(-dn, C3, x))
2970 SDValue NegDN = DAG.getNode(ISD::FNEG, DL, MVT::f64, DN, Flags);
2971 SDValue C2 = DAG.getConstantFP(0x1.abc9e3b39803fp-56, DL, MVT::f64);
2972 SDValue C3 = DAG.getConstantFP(0x1.62e42fefa39efp-1, DL, MVT::f64);
2973 SDValue Inner = DAG.getNode(ISD::FMA, DL, MVT::f64, NegDN, C3, X, Flags);
2974 T = DAG.getNode(ISD::FMA, DL, MVT::f64, NegDN, C2, Inner, Flags);
2975 }
2976
2977 // Polynomial expansion for p
2978 SDValue P = DAG.getConstantFP(0x1.ade156a5dcb37p-26, DL, MVT::f64);
2979 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
2980 DAG.getConstantFP(0x1.28af3fca7ab0cp-22, DL, MVT::f64),
2981 Flags);
2982 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
2983 DAG.getConstantFP(0x1.71dee623fde64p-19, DL, MVT::f64),
2984 Flags);
2985 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
2986 DAG.getConstantFP(0x1.a01997c89e6b0p-16, DL, MVT::f64),
2987 Flags);
2988 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
2989 DAG.getConstantFP(0x1.a01a014761f6ep-13, DL, MVT::f64),
2990 Flags);
2991 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
2992 DAG.getConstantFP(0x1.6c16c1852b7b0p-10, DL, MVT::f64),
2993 Flags);
2994 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
2995 DAG.getConstantFP(0x1.1111111122322p-7, DL, MVT::f64), Flags);
2996 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
2997 DAG.getConstantFP(0x1.55555555502a1p-5, DL, MVT::f64), Flags);
2998 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
2999 DAG.getConstantFP(0x1.5555555555511p-3, DL, MVT::f64), Flags);
3000 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P,
3001 DAG.getConstantFP(0x1.000000000000bp-1, DL, MVT::f64), Flags);
3002
3003 SDValue One = DAG.getConstantFP(1.0, DL, MVT::f64);
3004
3005 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P, One, Flags);
3006 P = DAG.getNode(ISD::FMA, DL, MVT::f64, T, P, One, Flags);
3007
3008 // z = ldexp(p, (int)dn)
3009 SDValue DNInt = DAG.getNode(ISD::FP_TO_SINT, DL, MVT::i32, DN);
3010 SDValue Z = DAG.getNode(ISD::FLDEXP, DL, MVT::f64, P, DNInt, Flags);
3011
3012 // Overflow/underflow guards
3013 SDValue CondHi = DAG.getSetCC(
3014 DL, MVT::i1, X, DAG.getConstantFP(1024.0, DL, MVT::f64), ISD::SETULE);
3015
3016 if (!Flags.hasNoInfs()) {
3017 SDValue PInf = DAG.getConstantFP(std::numeric_limits<double>::infinity(),
3018 DL, MVT::f64);
3019 Z = DAG.getSelect(DL, MVT::f64, CondHi, Z, PInf, Flags);
3020 }
3021
3022 SDValue CondLo = DAG.getSetCC(
3023 DL, MVT::i1, X, DAG.getConstantFP(-1075.0, DL, MVT::f64), ISD::SETUGE);
3024 SDValue Zero = DAG.getConstantFP(0.0, DL, MVT::f64);
3025 Z = DAG.getSelect(DL, MVT::f64, CondLo, Z, Zero, Flags);
3026
3027 return Z;
3028}
3029
3031 // v_exp_f32 is good enough for OpenCL, except it doesn't handle denormals.
3032 // If we have to handle denormals, scale up the input and adjust the result.
3033
3034 EVT VT = Op.getValueType();
3035 if (VT == MVT::f64)
3036 return lowerFEXPF64(Op, DAG);
3037
3038 SDLoc SL(Op);
3039 SDValue Src = Op.getOperand(0);
3040 SDNodeFlags Flags = Op->getFlags();
3041
3042 if (VT == MVT::f16) {
3043 // Nothing in half is a denormal when promoted to f32.
3044 assert(!isTypeLegal(MVT::f16));
3045 SDValue Ext = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Src, Flags);
3046 SDValue Log = DAG.getNode(AMDGPUISD::EXP, SL, MVT::f32, Ext, Flags);
3047 return DAG.getNode(ISD::FP_ROUND, SL, VT, Log,
3048 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
3049 }
3050
3051 assert(VT == MVT::f32);
3052
3053 if (!needsDenormHandlingF32(DAG, Src, Flags))
3054 return DAG.getNode(AMDGPUISD::EXP, SL, MVT::f32, Src, Flags);
3055
3056 // bool needs_scaling = x < -0x1.f80000p+6f;
3057 // v_exp_f32(x + (s ? 0x1.0p+6f : 0.0f)) * (s ? 0x1.0p-64f : 1.0f);
3058
3059 // -nextafter(128.0, -1)
3060 SDValue RangeCheckConst = DAG.getConstantFP(-0x1.f80000p+6f, SL, VT);
3061
3062 EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
3063
3064 SDValue NeedsScaling =
3065 DAG.getSetCC(SL, SetCCVT, Src, RangeCheckConst, ISD::SETOLT);
3066
3067 SDValue SixtyFour = DAG.getConstantFP(0x1.0p+6f, SL, VT);
3068 SDValue Zero = DAG.getConstantFP(0.0, SL, VT);
3069
3070 SDValue AddOffset =
3071 DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, SixtyFour, Zero);
3072
3073 SDValue AddInput = DAG.getNode(ISD::FADD, SL, VT, Src, AddOffset, Flags);
3074 SDValue Exp2 = DAG.getNode(AMDGPUISD::EXP, SL, VT, AddInput, Flags);
3075
3076 SDValue TwoExpNeg64 = DAG.getConstantFP(0x1.0p-64f, SL, VT);
3077 SDValue One = DAG.getConstantFP(1.0, SL, VT);
3078 SDValue ResultScale =
3079 DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, TwoExpNeg64, One);
3080
3081 return DAG.getNode(ISD::FMUL, SL, VT, Exp2, ResultScale, Flags);
3082}
3083
3085 SelectionDAG &DAG,
3086 SDNodeFlags Flags,
3087 bool IsExp10) const {
3088 // exp(x) -> exp2(M_LOG2E_F * x);
3089 // exp10(x) -> exp2(log2(10) * x);
3090 EVT VT = X.getValueType();
3091 SDValue Const =
3092 DAG.getConstantFP(IsExp10 ? 0x1.a934f0p+1f : numbers::log2e, SL, VT);
3093
3094 SDValue Mul = DAG.getNode(ISD::FMUL, SL, VT, X, Const, Flags);
3095 return DAG.getNode(VT == MVT::f32 ? (unsigned)AMDGPUISD::EXP
3096 : (unsigned)ISD::FEXP2,
3097 SL, VT, Mul, Flags);
3098}
3099
3101 SelectionDAG &DAG,
3102 SDNodeFlags Flags) const {
3103 EVT VT = X.getValueType();
3104 if (VT != MVT::f32 || !needsDenormHandlingF32(DAG, X, Flags))
3105 return lowerFEXPUnsafeImpl(X, SL, DAG, Flags, /*IsExp10=*/false);
3106
3107 EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
3108
3109 SDValue Threshold = DAG.getConstantFP(-0x1.5d58a0p+6f, SL, VT);
3110 SDValue NeedsScaling = DAG.getSetCC(SL, SetCCVT, X, Threshold, ISD::SETOLT);
3111
3112 SDValue ScaleOffset = DAG.getConstantFP(0x1.0p+6f, SL, VT);
3113
3114 SDValue ScaledX = DAG.getNode(ISD::FADD, SL, VT, X, ScaleOffset, Flags);
3115
3116 SDValue AdjustedX =
3117 DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, ScaledX, X);
3118
3119 const SDValue Log2E = DAG.getConstantFP(numbers::log2e, SL, VT);
3120 SDValue ExpInput = DAG.getNode(ISD::FMUL, SL, VT, AdjustedX, Log2E, Flags);
3121
3122 SDValue Exp2 = DAG.getNode(AMDGPUISD::EXP, SL, VT, ExpInput, Flags);
3123
3124 SDValue ResultScaleFactor = DAG.getConstantFP(0x1.969d48p-93f, SL, VT);
3125 SDValue AdjustedResult =
3126 DAG.getNode(ISD::FMUL, SL, VT, Exp2, ResultScaleFactor, Flags);
3127
3128 return DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, AdjustedResult, Exp2,
3129 Flags);
3130}
3131
3132/// Emit approx-funcs appropriate lowering for exp10. inf/nan should still be
3133/// handled correctly.
3135 SelectionDAG &DAG,
3136 SDNodeFlags Flags) const {
3137 const EVT VT = X.getValueType();
3138
3139 const unsigned Exp2Op = VT == MVT::f32 ? static_cast<unsigned>(AMDGPUISD::EXP)
3140 : static_cast<unsigned>(ISD::FEXP2);
3141
3142 if (VT != MVT::f32 || !needsDenormHandlingF32(DAG, X, Flags)) {
3143 // exp2(x * 0x1.a92000p+1f) * exp2(x * 0x1.4f0978p-11f);
3144 SDValue K0 = DAG.getConstantFP(0x1.a92000p+1f, SL, VT);
3145 SDValue K1 = DAG.getConstantFP(0x1.4f0978p-11f, SL, VT);
3146
3147 SDValue Mul0 = DAG.getNode(ISD::FMUL, SL, VT, X, K0, Flags);
3148 SDValue Exp2_0 = DAG.getNode(Exp2Op, SL, VT, Mul0, Flags);
3149 SDValue Mul1 = DAG.getNode(ISD::FMUL, SL, VT, X, K1, Flags);
3150 SDValue Exp2_1 = DAG.getNode(Exp2Op, SL, VT, Mul1, Flags);
3151 return DAG.getNode(ISD::FMUL, SL, VT, Exp2_0, Exp2_1);
3152 }
3153
3154 // bool s = x < -0x1.2f7030p+5f;
3155 // x += s ? 0x1.0p+5f : 0.0f;
3156 // exp10 = exp2(x * 0x1.a92000p+1f) *
3157 // exp2(x * 0x1.4f0978p-11f) *
3158 // (s ? 0x1.9f623ep-107f : 1.0f);
3159
3160 EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
3161
3162 SDValue Threshold = DAG.getConstantFP(-0x1.2f7030p+5f, SL, VT);
3163 SDValue NeedsScaling = DAG.getSetCC(SL, SetCCVT, X, Threshold, ISD::SETOLT);
3164
3165 SDValue ScaleOffset = DAG.getConstantFP(0x1.0p+5f, SL, VT);
3166 SDValue ScaledX = DAG.getNode(ISD::FADD, SL, VT, X, ScaleOffset, Flags);
3167 SDValue AdjustedX =
3168 DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, ScaledX, X);
3169
3170 SDValue K0 = DAG.getConstantFP(0x1.a92000p+1f, SL, VT);
3171 SDValue K1 = DAG.getConstantFP(0x1.4f0978p-11f, SL, VT);
3172
3173 SDValue Mul0 = DAG.getNode(ISD::FMUL, SL, VT, AdjustedX, K0, Flags);
3174 SDValue Exp2_0 = DAG.getNode(Exp2Op, SL, VT, Mul0, Flags);
3175 SDValue Mul1 = DAG.getNode(ISD::FMUL, SL, VT, AdjustedX, K1, Flags);
3176 SDValue Exp2_1 = DAG.getNode(Exp2Op, SL, VT, Mul1, Flags);
3177
3178 SDValue MulExps = DAG.getNode(ISD::FMUL, SL, VT, Exp2_0, Exp2_1, Flags);
3179
3180 SDValue ResultScaleFactor = DAG.getConstantFP(0x1.9f623ep-107f, SL, VT);
3181 SDValue AdjustedResult =
3182 DAG.getNode(ISD::FMUL, SL, VT, MulExps, ResultScaleFactor, Flags);
3183
3184 return DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, AdjustedResult, MulExps,
3185 Flags);
3186}
3187
3189 EVT VT = Op.getValueType();
3190
3191 if (VT == MVT::f64)
3192 return lowerFEXPF64(Op, DAG);
3193
3194 SDLoc SL(Op);
3195 SDValue X = Op.getOperand(0);
3196 SDNodeFlags Flags = Op->getFlags();
3197 const bool IsExp10 = Op.getOpcode() == ISD::FEXP10;
3198
3199 // TODO: Interpret allowApproxFunc as ignoring DAZ. This is currently copying
3200 // library behavior. Also, is known-not-daz source sufficient?
3201 if (allowApproxFunc(DAG, Flags)) { // TODO: Does this really require fast?
3202 return IsExp10 ? lowerFEXP10Unsafe(X, SL, DAG, Flags)
3203 : lowerFEXPUnsafe(X, SL, DAG, Flags);
3204 }
3205
3206 if (VT.getScalarType() == MVT::f16) {
3207 if (VT.isVector())
3208 return SDValue();
3209
3210 // Nothing in half is a denormal when promoted to f32.
3211 //
3212 // exp(f16 x) ->
3213 // fptrunc (v_exp_f32 (fmul (fpext x), log2e))
3214 //
3215 // exp10(f16 x) ->
3216 // fptrunc (v_exp_f32 (fmul (fpext x), log2(10)))
3217 SDValue Ext = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, X, Flags);
3218 SDValue Lowered = lowerFEXPUnsafeImpl(Ext, SL, DAG, Flags, IsExp10);
3219 return DAG.getNode(ISD::FP_ROUND, SL, VT, Lowered,
3220 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
3221 }
3222
3223 assert(VT == MVT::f32);
3224
3225 // Algorithm:
3226 //
3227 // e^x = 2^(x/ln(2)) = 2^(x*(64/ln(2))/64)
3228 //
3229 // x*(64/ln(2)) = n + f, |f| <= 0.5, n is integer
3230 // n = 64*m + j, 0 <= j < 64
3231 //
3232 // e^x = 2^((64*m + j + f)/64)
3233 // = (2^m) * (2^(j/64)) * 2^(f/64)
3234 // = (2^m) * (2^(j/64)) * e^(f*(ln(2)/64))
3235 //
3236 // f = x*(64/ln(2)) - n
3237 // r = f*(ln(2)/64) = x - n*(ln(2)/64)
3238 //
3239 // e^x = (2^m) * (2^(j/64)) * e^r
3240 //
3241 // (2^(j/64)) is precomputed
3242 //
3243 // e^r = 1 + r + (r^2)/2! + (r^3)/3! + (r^4)/4! + (r^5)/5!
3244 // e^r = 1 + q
3245 //
3246 // q = r + (r^2)/2! + (r^3)/3! + (r^4)/4! + (r^5)/5!
3247 //
3248 // e^x = (2^m) * ( (2^(j/64)) + q*(2^(j/64)) )
3249 SDNodeFlags FlagsNoContract = Flags;
3250 FlagsNoContract.setAllowContract(false);
3251
3252 SDValue PH, PL;
3253 if (Subtarget->hasFastFMAF32()) {
3254 const float c_exp = numbers::log2ef;
3255 const float cc_exp = 0x1.4ae0bep-26f; // c+cc are 49 bits
3256 const float c_exp10 = 0x1.a934f0p+1f;
3257 const float cc_exp10 = 0x1.2f346ep-24f;
3258
3259 SDValue C = DAG.getConstantFP(IsExp10 ? c_exp10 : c_exp, SL, VT);
3260 SDValue CC = DAG.getConstantFP(IsExp10 ? cc_exp10 : cc_exp, SL, VT);
3261
3262 PH = DAG.getNode(ISD::FMUL, SL, VT, X, C, Flags);
3263 SDValue NegPH = DAG.getNode(ISD::FNEG, SL, VT, PH, Flags);
3264 SDValue FMA0 = DAG.getNode(ISD::FMA, SL, VT, X, C, NegPH, Flags);
3265 PL = DAG.getNode(ISD::FMA, SL, VT, X, CC, FMA0, Flags);
3266 } else {
3267 const float ch_exp = 0x1.714000p+0f;
3268 const float cl_exp = 0x1.47652ap-12f; // ch + cl are 36 bits
3269
3270 const float ch_exp10 = 0x1.a92000p+1f;
3271 const float cl_exp10 = 0x1.4f0978p-11f;
3272
3273 SDValue CH = DAG.getConstantFP(IsExp10 ? ch_exp10 : ch_exp, SL, VT);
3274 SDValue CL = DAG.getConstantFP(IsExp10 ? cl_exp10 : cl_exp, SL, VT);
3275
3276 SDValue XAsInt = DAG.getNode(ISD::BITCAST, SL, MVT::i32, X);
3277 SDValue MaskConst = DAG.getConstant(0xfffff000, SL, MVT::i32);
3278 SDValue XHAsInt = DAG.getNode(ISD::AND, SL, MVT::i32, XAsInt, MaskConst);
3279 SDValue XH = DAG.getNode(ISD::BITCAST, SL, VT, XHAsInt);
3280 SDValue XL = DAG.getNode(ISD::FSUB, SL, VT, X, XH, Flags);
3281
3282 PH = DAG.getNode(ISD::FMUL, SL, VT, XH, CH, Flags);
3283
3284 SDValue XLCL = DAG.getNode(ISD::FMUL, SL, VT, XL, CL, Flags);
3285 SDValue Mad0 = getMad(DAG, SL, VT, XL, CH, XLCL, Flags);
3286 PL = getMad(DAG, SL, VT, XH, CL, Mad0, Flags);
3287 }
3288
3289 SDValue E = DAG.getNode(ISD::FROUNDEVEN, SL, VT, PH, Flags);
3290
3291 // It is unsafe to contract this fsub into the PH multiply.
3292 SDValue PHSubE = DAG.getNode(ISD::FSUB, SL, VT, PH, E, FlagsNoContract);
3293
3294 SDValue A = DAG.getNode(ISD::FADD, SL, VT, PHSubE, PL, Flags);
3295 SDValue IntE = DAG.getNode(ISD::FP_TO_SINT, SL, MVT::i32, E);
3296 SDValue Exp2 = DAG.getNode(AMDGPUISD::EXP, SL, VT, A, Flags);
3297
3298 SDValue R = DAG.getNode(ISD::FLDEXP, SL, VT, Exp2, IntE, Flags);
3299
3300 SDValue UnderflowCheckConst =
3301 DAG.getConstantFP(IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f, SL, VT);
3302
3303 EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
3304 SDValue Zero = DAG.getConstantFP(0.0, SL, VT);
3305 SDValue Underflow =
3306 DAG.getSetCC(SL, SetCCVT, X, UnderflowCheckConst, ISD::SETOLT);
3307
3308 R = DAG.getNode(ISD::SELECT, SL, VT, Underflow, Zero, R);
3309
3310 if (!Flags.hasNoInfs()) {
3311 SDValue OverflowCheckConst =
3312 DAG.getConstantFP(IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f, SL, VT);
3313 SDValue Overflow =
3314 DAG.getSetCC(SL, SetCCVT, X, OverflowCheckConst, ISD::SETOGT);
3315 SDValue Inf =
3317 R = DAG.getNode(ISD::SELECT, SL, VT, Overflow, Inf, R);
3318 }
3319
3320 return R;
3321}
3322
3323static bool isCtlzOpc(unsigned Opc) {
3324 return Opc == ISD::CTLZ || Opc == ISD::CTLZ_ZERO_POISON;
3325}
3326
3327static bool isCttzOpc(unsigned Opc) {
3328 return Opc == ISD::CTTZ || Opc == ISD::CTTZ_ZERO_POISON;
3329}
3330
3332 SelectionDAG &DAG) const {
3333 auto SL = SDLoc(Op);
3334 auto Opc = Op.getOpcode();
3335 auto Arg = Op.getOperand(0u);
3336 auto ResultVT = Op.getValueType();
3337
3338 if (ResultVT != MVT::i8 && ResultVT != MVT::i16)
3339 return {};
3340
3342 assert(ResultVT == Arg.getValueType());
3343
3344 const uint64_t NumBits = ResultVT.getFixedSizeInBits();
3345 SDValue NumExtBits = DAG.getConstant(32u - NumBits, SL, MVT::i32);
3346 SDValue NewOp;
3347
3348 if (Opc == ISD::CTLZ_ZERO_POISON) {
3349 NewOp = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Arg);
3350 NewOp = DAG.getNode(ISD::SHL, SL, MVT::i32, NewOp, NumExtBits);
3351 NewOp = DAG.getNode(Opc, SL, MVT::i32, NewOp);
3352 } else {
3353 NewOp = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Arg);
3354 NewOp = DAG.getNode(Opc, SL, MVT::i32, NewOp);
3355 NewOp = DAG.getNode(ISD::SUB, SL, MVT::i32, NewOp, NumExtBits);
3356 }
3357
3358 return DAG.getNode(ISD::TRUNCATE, SL, ResultVT, NewOp);
3359}
3360
3362 SDLoc SL(Op);
3363 SDValue Src = Op.getOperand(0);
3364
3365 assert(isCtlzOpc(Op.getOpcode()) || isCttzOpc(Op.getOpcode()));
3366 bool Ctlz = isCtlzOpc(Op.getOpcode());
3367 unsigned NewOpc = Ctlz ? AMDGPUISD::FFBH_U32 : AMDGPUISD::FFBL_B32;
3368
3369 bool ZeroUndef = Op.getOpcode() == ISD::CTLZ_ZERO_POISON ||
3370 Op.getOpcode() == ISD::CTTZ_ZERO_POISON;
3371 bool Is64BitScalar = !Src->isDivergent() && Src.getValueType() == MVT::i64;
3372
3373 if (Src.getValueType() == MVT::i32 || Is64BitScalar) {
3374 // (ctlz hi:lo) -> (umin (ffbh src), 32)
3375 // (cttz hi:lo) -> (umin (ffbl src), 32)
3376 // (ctlz_zero_poison src) -> (ffbh src)
3377 // (cttz_zero_poison src) -> (ffbl src)
3378
3379 // 64-bit scalar version produce 32-bit result
3380 // (ctlz hi:lo) -> (umin (S_FLBIT_I32_B64 src), 64)
3381 // (cttz hi:lo) -> (umin (S_FF1_I32_B64 src), 64)
3382 // (ctlz_zero_poison src) -> (S_FLBIT_I32_B64 src)
3383 // (cttz_zero_poison src) -> (S_FF1_I32_B64 src)
3384 SDValue NewOpr = DAG.getNode(NewOpc, SL, MVT::i32, Src);
3385 if (!ZeroUndef) {
3386 const SDValue ConstVal = DAG.getConstant(
3387 Op.getValueType().getScalarSizeInBits(), SL, MVT::i32);
3388 NewOpr = DAG.getNode(ISD::UMIN, SL, MVT::i32, NewOpr, ConstVal);
3389 }
3390 return DAG.getNode(ISD::ZERO_EXTEND, SL, Src.getValueType(), NewOpr);
3391 }
3392
3393 SDValue Lo, Hi;
3394 std::tie(Lo, Hi) = split64BitValue(Src, DAG);
3395
3396 SDValue OprLo = DAG.getNode(NewOpc, SL, MVT::i32, Lo);
3397 SDValue OprHi = DAG.getNode(NewOpc, SL, MVT::i32, Hi);
3398
3399 // (ctlz hi:lo) -> (umin3 (ffbh hi), (uaddsat (ffbh lo), 32), 64)
3400 // (cttz hi:lo) -> (umin3 (uaddsat (ffbl hi), 32), (ffbl lo), 64)
3401 // (ctlz_zero_poison hi:lo) -> (umin (ffbh hi), (add (ffbh lo), 32))
3402 // (cttz_zero_poison hi:lo) -> (umin (add (ffbl hi), 32), (ffbl lo))
3403
3404 unsigned AddOpc = ZeroUndef ? ISD::ADD : ISD::UADDSAT;
3405 const SDValue Const32 = DAG.getConstant(32, SL, MVT::i32);
3406 if (Ctlz)
3407 OprLo = DAG.getNode(AddOpc, SL, MVT::i32, OprLo, Const32);
3408 else
3409 OprHi = DAG.getNode(AddOpc, SL, MVT::i32, OprHi, Const32);
3410
3411 SDValue NewOpr;
3412 NewOpr = DAG.getNode(ISD::UMIN, SL, MVT::i32, OprLo, OprHi);
3413 if (!ZeroUndef) {
3414 const SDValue Const64 = DAG.getConstant(64, SL, MVT::i32);
3415 NewOpr = DAG.getNode(ISD::UMIN, SL, MVT::i32, NewOpr, Const64);
3416 }
3417
3418 return DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i64, NewOpr);
3419}
3420
3422 SDLoc SL(Op);
3423 SDValue Src = Op.getOperand(0);
3424 assert(Src.getValueType() == MVT::i32 && "LowerCTLS only supports i32");
3425 SDValue Ffbh = DAG.getNode(
3426 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
3427 DAG.getTargetConstant(Intrinsic::amdgcn_sffbh, SL, MVT::i32), Src);
3428 SDValue Clamped = DAG.getNode(ISD::UMIN, SL, MVT::i32, Ffbh,
3429 DAG.getConstant(32, SL, MVT::i32));
3430 return DAG.getNode(ISD::ADD, SL, MVT::i32, Clamped,
3431 DAG.getAllOnesConstant(SL, MVT::i32));
3432}
3433
3435 EVT FP16Ty) const {
3436 assert(FP16Ty == MVT::f16 || FP16Ty == MVT::bf16);
3437 SDLoc SL(Op);
3438 SDValue Src = Op.getOperand(0);
3439 SDValue ToF32 = DAG.getNode(Op.getOpcode(), SL, MVT::f32, Src);
3440 SDValue FPRoundFlag = DAG.getIntPtrConstant(0, SL, /*isTarget=*/true);
3441 return DAG.getNode(ISD::FP_ROUND, SL, FP16Ty, ToF32, FPRoundFlag);
3442}
3443
3445 bool Signed) const {
3446 // The regular method converting a 64-bit integer to float roughly consists of
3447 // 2 steps: normalization and rounding. In fact, after normalization, the
3448 // conversion from a 64-bit integer to a float is essentially the same as the
3449 // one from a 32-bit integer. The only difference is that it has more
3450 // trailing bits to be rounded. To leverage the native 32-bit conversion, a
3451 // 64-bit integer could be preprocessed and fit into a 32-bit integer then
3452 // converted into the correct float number. The basic steps for the unsigned
3453 // conversion are illustrated in the following pseudo code:
3454 //
3455 // f32 uitofp(i64 u) {
3456 // i32 hi, lo = split(u);
3457 // // Only count the leading zeros in hi as we have native support of the
3458 // // conversion from i32 to f32. If hi is all 0s, the conversion is
3459 // // reduced to a 32-bit one automatically.
3460 // i32 shamt = clz(hi); // Return 32 if hi is all 0s.
3461 // u <<= shamt;
3462 // hi, lo = split(u);
3463 // hi |= (lo != 0) ? 1 : 0; // Adjust rounding bit in hi based on lo.
3464 // // convert it as a 32-bit integer and scale the result back.
3465 // return uitofp(hi) * 2^(32 - shamt);
3466 // }
3467 //
3468 // The signed one follows the same principle but uses 'ffbh_i32' to count its
3469 // sign bits instead. If 'ffbh_i32' is not available, its absolute value is
3470 // converted instead followed by negation based its sign bit.
3471
3472 SDLoc SL(Op);
3473 SDValue Src = Op.getOperand(0);
3474
3475 SDValue Lo, Hi;
3476 std::tie(Lo, Hi) = split64BitValue(Src, DAG);
3477 SDValue Sign;
3478 SDValue ShAmt;
3479 if (Signed && Subtarget->isGCN()) {
3480 // We also need to consider the sign bit in Lo if Hi has just sign bits,
3481 // i.e. Hi is 0 or -1. However, that only needs to take the MSB into
3482 // account. That is, the maximal shift is
3483 // - 32 if Lo and Hi have opposite signs;
3484 // - 33 if Lo and Hi have the same sign.
3485 //
3486 // Or, MaxShAmt = 33 + OppositeSign, where
3487 //
3488 // OppositeSign is defined as ((Lo ^ Hi) >> 31), which is
3489 // - -1 if Lo and Hi have opposite signs; and
3490 // - 0 otherwise.
3491 //
3492 // All in all, ShAmt is calculated as
3493 //
3494 // umin(sffbh(Hi), 33 + (Lo^Hi)>>31) - 1.
3495 //
3496 // or
3497 //
3498 // umin(sffbh(Hi) - 1, 32 + (Lo^Hi)>>31).
3499 //
3500 // to reduce the critical path.
3501 SDValue OppositeSign = DAG.getNode(
3502 ISD::SRA, SL, MVT::i32, DAG.getNode(ISD::XOR, SL, MVT::i32, Lo, Hi),
3503 DAG.getConstant(31, SL, MVT::i32));
3504 SDValue MaxShAmt =
3505 DAG.getNode(ISD::ADD, SL, MVT::i32, DAG.getConstant(32, SL, MVT::i32),
3506 OppositeSign);
3507 // Count the leading sign bits.
3508 ShAmt = DAG.getNode(
3509 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
3510 DAG.getTargetConstant(Intrinsic::amdgcn_sffbh, SL, MVT::i32), Hi);
3511 // Different from unsigned conversion, the shift should be one bit less to
3512 // preserve the sign bit.
3513 ShAmt = DAG.getNode(ISD::SUB, SL, MVT::i32, ShAmt,
3514 DAG.getConstant(1, SL, MVT::i32));
3515 ShAmt = DAG.getNode(ISD::UMIN, SL, MVT::i32, ShAmt, MaxShAmt);
3516 } else {
3517 if (Signed) {
3518 // Without 'ffbh_i32', only leading zeros could be counted. Take the
3519 // absolute value first.
3520 Sign = DAG.getNode(ISD::SRA, SL, MVT::i64, Src,
3521 DAG.getConstant(63, SL, MVT::i64));
3522 SDValue Abs =
3523 DAG.getNode(ISD::XOR, SL, MVT::i64,
3524 DAG.getNode(ISD::ADD, SL, MVT::i64, Src, Sign), Sign);
3525 std::tie(Lo, Hi) = split64BitValue(Abs, DAG);
3526 }
3527 // Count the leading zeros.
3528 ShAmt = DAG.getNode(ISD::CTLZ, SL, MVT::i32, Hi);
3529 // The shift amount for signed integers is [0, 32].
3530 }
3531 // Normalize the given 64-bit integer.
3532 SDValue Norm = DAG.getNode(ISD::SHL, SL, MVT::i64, Src, ShAmt);
3533 // Split it again.
3534 std::tie(Lo, Hi) = split64BitValue(Norm, DAG);
3535 // Calculate the adjust bit for rounding.
3536 // (lo != 0) ? 1 : 0 => (lo >= 1) ? 1 : 0 => umin(1, lo)
3537 SDValue Adjust = DAG.getNode(ISD::UMIN, SL, MVT::i32,
3538 DAG.getConstant(1, SL, MVT::i32), Lo);
3539 // Get the 32-bit normalized integer.
3540 Norm = DAG.getNode(ISD::OR, SL, MVT::i32, Hi, Adjust);
3541 // Convert the normalized 32-bit integer into f32.
3542
3543 bool UseLDEXP = isOperationLegal(ISD::FLDEXP, MVT::f32);
3544 unsigned Opc = Signed && UseLDEXP ? ISD::SINT_TO_FP : ISD::UINT_TO_FP;
3545 SDValue FVal = DAG.getNode(Opc, SL, MVT::f32, Norm);
3546
3547 // Finally, need to scale back the converted floating number as the original
3548 // 64-bit integer is converted as a 32-bit one.
3549 ShAmt = DAG.getNode(ISD::SUB, SL, MVT::i32, DAG.getConstant(32, SL, MVT::i32),
3550 ShAmt);
3551 // On GCN, use LDEXP directly.
3552 if (UseLDEXP)
3553 return DAG.getNode(ISD::FLDEXP, SL, MVT::f32, FVal, ShAmt);
3554
3555 // Otherwise, align 'ShAmt' to the exponent part and add it into the exponent
3556 // part directly to emulate the multiplication of 2^ShAmt. That 8-bit
3557 // exponent is enough to avoid overflowing into the sign bit.
3558 SDValue Exp = DAG.getNode(ISD::SHL, SL, MVT::i32, ShAmt,
3559 DAG.getConstant(23, SL, MVT::i32));
3560 SDValue IVal =
3561 DAG.getNode(ISD::ADD, SL, MVT::i32,
3562 DAG.getNode(ISD::BITCAST, SL, MVT::i32, FVal), Exp);
3563 if (Signed) {
3564 // Set the sign bit.
3565 Sign = DAG.getNode(ISD::SHL, SL, MVT::i32,
3566 DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Sign),
3567 DAG.getConstant(31, SL, MVT::i32));
3568 IVal = DAG.getNode(ISD::OR, SL, MVT::i32, IVal, Sign);
3569 }
3570 return DAG.getNode(ISD::BITCAST, SL, MVT::f32, IVal);
3571}
3572
3574 bool Signed) const {
3575 SDLoc SL(Op);
3576 SDValue Src = Op.getOperand(0);
3577
3578 SDValue Lo, Hi;
3579 std::tie(Lo, Hi) = split64BitValue(Src, DAG);
3580
3582 SL, MVT::f64, Hi);
3583
3584 SDValue CvtLo = DAG.getNode(ISD::UINT_TO_FP, SL, MVT::f64, Lo);
3585
3586 SDValue LdExp = DAG.getNode(ISD::FLDEXP, SL, MVT::f64, CvtHi,
3587 DAG.getConstant(32, SL, MVT::i32));
3588 // TODO: Should this propagate fast-math-flags?
3589 return DAG.getNode(ISD::FADD, SL, MVT::f64, LdExp, CvtLo);
3590}
3591
3593 SelectionDAG &DAG) const {
3594 // TODO: Factor out code common with LowerSINT_TO_FP.
3595 EVT DestVT = Op.getValueType();
3596 SDValue Src = Op.getOperand(0);
3597 EVT SrcVT = Src.getValueType();
3598
3599 if (SrcVT == MVT::i16) {
3600 if (DestVT == MVT::f16)
3601 return Op;
3602 SDLoc DL(Op);
3603
3604 // Promote src to i32
3605 SDValue Ext = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i32, Src);
3606 return DAG.getNode(ISD::UINT_TO_FP, DL, DestVT, Ext);
3607 }
3608
3609 if (DestVT == MVT::bf16 || DestVT == MVT::f16)
3610 return LowerINT_TO_FP16(Op, DAG, DestVT);
3611
3612 if (SrcVT != MVT::i64)
3613 return Op;
3614
3615 if (DestVT == MVT::f32)
3616 return LowerINT_TO_FP32(Op, DAG, false);
3617
3618 assert(DestVT == MVT::f64);
3619 return LowerINT_TO_FP64(Op, DAG, false);
3620}
3621
3623 SelectionDAG &DAG) const {
3624 EVT DestVT = Op.getValueType();
3625
3626 SDValue Src = Op.getOperand(0);
3627 EVT SrcVT = Src.getValueType();
3628
3629 if (SrcVT == MVT::i16) {
3630 if (DestVT == MVT::f16)
3631 return Op;
3632
3633 SDLoc DL(Op);
3634 // Promote src to i32
3635 SDValue Ext = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i32, Src);
3636 return DAG.getNode(ISD::SINT_TO_FP, DL, DestVT, Ext);
3637 }
3638
3639 if (DestVT == MVT::bf16 || DestVT == MVT::f16)
3640 return LowerINT_TO_FP16(Op, DAG, DestVT);
3641
3642 if (SrcVT != MVT::i64)
3643 return Op;
3644
3645 // TODO: Factor out code common with LowerUINT_TO_FP.
3646
3647 if (DestVT == MVT::f32)
3648 return LowerINT_TO_FP32(Op, DAG, true);
3649
3650 assert(DestVT == MVT::f64);
3651 return LowerINT_TO_FP64(Op, DAG, true);
3652}
3653
3655 bool Signed) const {
3656 SDLoc SL(Op);
3657
3658 SDValue Src = Op.getOperand(0);
3659 EVT SrcVT = Src.getValueType();
3660
3661 assert(SrcVT == MVT::f32 || SrcVT == MVT::f64);
3662
3663 // The basic idea of converting a floating point number into a pair of 32-bit
3664 // integers is illustrated as follows:
3665 //
3666 // tf := trunc(val);
3667 // hif := floor(tf * 2^-32);
3668 // lof := tf - hif * 2^32; // lof is always positive due to floor.
3669 // hi := fptoi(hif);
3670 // lo := fptoi(lof);
3671 //
3672 SDValue Trunc = DAG.getNode(ISD::FTRUNC, SL, SrcVT, Src);
3673 SDValue Sign;
3674 if (Signed && SrcVT == MVT::f32) {
3675 // However, a 32-bit floating point number has only 23 bits mantissa and
3676 // it's not enough to hold all the significant bits of `lof` if val is
3677 // negative. To avoid the loss of precision, We need to take the absolute
3678 // value after truncating and flip the result back based on the original
3679 // signedness.
3680 Sign = DAG.getNode(ISD::SRA, SL, MVT::i32,
3681 DAG.getNode(ISD::BITCAST, SL, MVT::i32, Trunc),
3682 DAG.getConstant(31, SL, MVT::i32));
3683 Trunc = DAG.getNode(ISD::FABS, SL, SrcVT, Trunc);
3684 }
3685
3686 SDValue K0, K1;
3687 if (SrcVT == MVT::f64) {
3688 K0 = DAG.getConstantFP(
3689 llvm::bit_cast<double>(UINT64_C(/*2^-32*/ 0x3df0000000000000)), SL,
3690 SrcVT);
3691 K1 = DAG.getConstantFP(
3692 llvm::bit_cast<double>(UINT64_C(/*-2^32*/ 0xc1f0000000000000)), SL,
3693 SrcVT);
3694 } else {
3695 K0 = DAG.getConstantFP(
3696 llvm::bit_cast<float>(UINT32_C(/*2^-32*/ 0x2f800000)), SL, SrcVT);
3697 K1 = DAG.getConstantFP(
3698 llvm::bit_cast<float>(UINT32_C(/*-2^32*/ 0xcf800000)), SL, SrcVT);
3699 }
3700 // TODO: Should this propagate fast-math-flags?
3701 SDValue Mul = DAG.getNode(ISD::FMUL, SL, SrcVT, Trunc, K0);
3702
3703 SDValue FloorMul = DAG.getNode(ISD::FFLOOR, SL, SrcVT, Mul);
3704
3705 SDValue Fma = DAG.getNode(ISD::FMA, SL, SrcVT, FloorMul, K1, Trunc);
3706
3707 SDValue Hi = DAG.getNode((Signed && SrcVT == MVT::f64) ? ISD::FP_TO_SINT
3709 SL, MVT::i32, FloorMul);
3710 SDValue Lo = DAG.getNode(ISD::FP_TO_UINT, SL, MVT::i32, Fma);
3711
3712 SDValue Result = DAG.getNode(ISD::BITCAST, SL, MVT::i64,
3713 DAG.getBuildVector(MVT::v2i32, SL, {Lo, Hi}));
3714
3715 if (Signed && SrcVT == MVT::f32) {
3716 assert(Sign);
3717 // Flip the result based on the signedness, which is either all 0s or 1s.
3718 Sign = DAG.getNode(ISD::BITCAST, SL, MVT::i64,
3719 DAG.getBuildVector(MVT::v2i32, SL, {Sign, Sign}));
3720 // r := xor(r, sign) - sign;
3721 Result =
3722 DAG.getNode(ISD::SUB, SL, MVT::i64,
3723 DAG.getNode(ISD::XOR, SL, MVT::i64, Result, Sign), Sign);
3724 }
3725
3726 return Result;
3727}
3728
3730 SDLoc DL(Op);
3731 SDValue N0 = Op.getOperand(0);
3732
3733 // Convert to target node to get known bits
3734 if (N0.getValueType() == MVT::f32)
3735 return DAG.getNode(AMDGPUISD::FP_TO_FP16, DL, Op.getValueType(), N0);
3736
3737 if (Op->getFlags().hasApproximateFuncs()) {
3738 // There is a generic expand for FP_TO_FP16 with unsafe fast math.
3739 return SDValue();
3740 }
3741
3742 return LowerF64ToF16Safe(N0, DL, DAG);
3743}
3744
3745// return node in i32
3747 SelectionDAG &DAG) const {
3748 assert(Src.getSimpleValueType() == MVT::f64);
3749
3750 // f64 -> f16 conversion using round-to-nearest-even rounding mode.
3751 // TODO: We can generate better code for True16.
3752 const unsigned ExpMask = 0x7ff;
3753 const unsigned ExpBiasf64 = 1023;
3754 const unsigned ExpBiasf16 = 15;
3755 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
3756 SDValue One = DAG.getConstant(1, DL, MVT::i32);
3757 SDValue U = DAG.getNode(ISD::BITCAST, DL, MVT::i64, Src);
3758 SDValue UH = DAG.getNode(ISD::SRL, DL, MVT::i64, U,
3759 DAG.getConstant(32, DL, MVT::i64));
3760 UH = DAG.getZExtOrTrunc(UH, DL, MVT::i32);
3761 U = DAG.getZExtOrTrunc(U, DL, MVT::i32);
3762 SDValue E = DAG.getNode(ISD::SRL, DL, MVT::i32, UH,
3763 DAG.getConstant(20, DL, MVT::i64));
3764 E = DAG.getNode(ISD::AND, DL, MVT::i32, E,
3765 DAG.getConstant(ExpMask, DL, MVT::i32));
3766 // Subtract the fp64 exponent bias (1023) to get the real exponent and
3767 // add the f16 bias (15) to get the biased exponent for the f16 format.
3768 E = DAG.getNode(ISD::ADD, DL, MVT::i32, E,
3769 DAG.getConstant(-ExpBiasf64 + ExpBiasf16, DL, MVT::i32));
3770
3771 SDValue M = DAG.getNode(ISD::SRL, DL, MVT::i32, UH,
3772 DAG.getConstant(8, DL, MVT::i32));
3773 M = DAG.getNode(ISD::AND, DL, MVT::i32, M,
3774 DAG.getConstant(0xffe, DL, MVT::i32));
3775
3776 SDValue MaskedSig = DAG.getNode(ISD::AND, DL, MVT::i32, UH,
3777 DAG.getConstant(0x1ff, DL, MVT::i32));
3778 MaskedSig = DAG.getNode(ISD::OR, DL, MVT::i32, MaskedSig, U);
3779
3780 SDValue Lo40Set = DAG.getSelectCC(DL, MaskedSig, Zero, Zero, One, ISD::SETEQ);
3781 M = DAG.getNode(ISD::OR, DL, MVT::i32, M, Lo40Set);
3782
3783 // (M != 0 ? 0x0200 : 0) | 0x7c00;
3784 SDValue I = DAG.getNode(ISD::OR, DL, MVT::i32,
3785 DAG.getSelectCC(DL, M, Zero, DAG.getConstant(0x0200, DL, MVT::i32),
3786 Zero, ISD::SETNE), DAG.getConstant(0x7c00, DL, MVT::i32));
3787
3788 // N = M | (E << 12);
3789 SDValue N = DAG.getNode(ISD::OR, DL, MVT::i32, M,
3790 DAG.getNode(ISD::SHL, DL, MVT::i32, E,
3791 DAG.getConstant(12, DL, MVT::i32)));
3792
3793 // B = clamp(1-E, 0, 13);
3794 SDValue OneSubExp = DAG.getNode(ISD::SUB, DL, MVT::i32,
3795 One, E);
3796 SDValue B = DAG.getNode(ISD::SMAX, DL, MVT::i32, OneSubExp, Zero);
3797 B = DAG.getNode(ISD::SMIN, DL, MVT::i32, B,
3798 DAG.getConstant(13, DL, MVT::i32));
3799
3800 SDValue SigSetHigh = DAG.getNode(ISD::OR, DL, MVT::i32, M,
3801 DAG.getConstant(0x1000, DL, MVT::i32));
3802
3803 SDValue D = DAG.getNode(ISD::SRL, DL, MVT::i32, SigSetHigh, B);
3804 SDValue D0 = DAG.getNode(ISD::SHL, DL, MVT::i32, D, B);
3805 SDValue D1 = DAG.getSelectCC(DL, D0, SigSetHigh, One, Zero, ISD::SETNE);
3806 D = DAG.getNode(ISD::OR, DL, MVT::i32, D, D1);
3807
3808 SDValue V = DAG.getSelectCC(DL, E, One, D, N, ISD::SETLT);
3809 SDValue VLow3 = DAG.getNode(ISD::AND, DL, MVT::i32, V,
3810 DAG.getConstant(0x7, DL, MVT::i32));
3811 V = DAG.getNode(ISD::SRL, DL, MVT::i32, V,
3812 DAG.getConstant(2, DL, MVT::i32));
3813 SDValue V0 = DAG.getSelectCC(DL, VLow3, DAG.getConstant(3, DL, MVT::i32),
3814 One, Zero, ISD::SETEQ);
3815 SDValue V1 = DAG.getSelectCC(DL, VLow3, DAG.getConstant(5, DL, MVT::i32),
3816 One, Zero, ISD::SETGT);
3817 V1 = DAG.getNode(ISD::OR, DL, MVT::i32, V0, V1);
3818 V = DAG.getNode(ISD::ADD, DL, MVT::i32, V, V1);
3819
3820 V = DAG.getSelectCC(DL, E, DAG.getConstant(30, DL, MVT::i32),
3821 DAG.getConstant(0x7c00, DL, MVT::i32), V, ISD::SETGT);
3822 V = DAG.getSelectCC(DL, E, DAG.getConstant(1039, DL, MVT::i32),
3823 I, V, ISD::SETEQ);
3824
3825 // Extract the sign bit.
3826 SDValue Sign = DAG.getNode(ISD::SRL, DL, MVT::i32, UH,
3827 DAG.getConstant(16, DL, MVT::i32));
3828 Sign = DAG.getNode(ISD::AND, DL, MVT::i32, Sign,
3829 DAG.getConstant(0x8000, DL, MVT::i32));
3830
3831 return DAG.getNode(ISD::OR, DL, MVT::i32, Sign, V);
3832}
3833
3835 SelectionDAG &DAG) const {
3836 SDValue Src = Op.getOperand(0);
3837 unsigned OpOpcode = Op.getOpcode();
3838 EVT SrcVT = Src.getValueType();
3839 EVT DestVT = Op.getValueType();
3840
3841 // Will be selected natively
3842 if (SrcVT == MVT::f16 && DestVT == MVT::i16)
3843 return Op;
3844
3845 if (SrcVT == MVT::bf16 || (SrcVT == MVT::f16 && DestVT == MVT::i32)) {
3846 SDLoc DL(Op);
3847 SDValue PromotedSrc = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Src);
3848 return DAG.getNode(Op.getOpcode(), DL, DestVT, PromotedSrc);
3849 }
3850
3851 // Promote i16 to i32
3852 if (DestVT == MVT::i16 && (SrcVT == MVT::f32 || SrcVT == MVT::f64)) {
3853 SDLoc DL(Op);
3854
3855 SDValue FpToInt32 = DAG.getNode(OpOpcode, DL, MVT::i32, Src);
3856 return DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FpToInt32);
3857 }
3858
3859 if (DestVT != MVT::i64)
3860 return Op;
3861
3862 if (SrcVT == MVT::f16 ||
3863 (SrcVT == MVT::f32 && Src.getOpcode() == ISD::FP16_TO_FP)) {
3864 SDLoc DL(Op);
3865
3866 SDValue FpToInt32 = DAG.getNode(OpOpcode, DL, MVT::i32, Src);
3867 unsigned Ext =
3869 return DAG.getNode(Ext, DL, MVT::i64, FpToInt32);
3870 }
3871
3872 if (SrcVT == MVT::f32 || SrcVT == MVT::f64)
3873 return LowerFP_TO_INT64(Op, DAG, OpOpcode == ISD::FP_TO_SINT);
3874
3875 return SDValue();
3876}
3877
3879 SelectionDAG &DAG) const {
3880 SDValue Src = Op.getOperand(0);
3881 unsigned OpOpcode = Op.getOpcode();
3882 EVT SrcVT = Src.getValueType();
3883 EVT DstVT = Op.getValueType();
3884 SDValue SatVTOp = Op.getNode()->getOperand(1);
3885 EVT SatVT = cast<VTSDNode>(SatVTOp)->getVT();
3886 SDLoc DL(Op);
3887
3888 uint64_t DstWidth = DstVT.getScalarSizeInBits();
3889 uint64_t SatWidth = SatVT.getScalarSizeInBits();
3890 assert(SatWidth <= DstWidth && "Saturation width cannot exceed result width");
3891
3892 // Scalar cases will be selected natively to v_cvt_/s_cvt_ instructions.
3893 // v2f32 -> v2i16 will be selected natively to v_cvt_pk_[iu]16_f32.
3894 if (SatWidth == DstWidth) {
3895 if ((DstVT == MVT::i32 && (SrcVT == MVT::f32 || SrcVT == MVT::f64)) ||
3896 (DstVT == MVT::i16 && (SrcVT == MVT::f16 || SrcVT == MVT::f32)) ||
3897 (DstVT == MVT::v2i16 && SrcVT == MVT::v2f32))
3898 return Op;
3899 }
3900
3901 // Vectors can only be selected natively.
3902 if (DstVT.isVector())
3903 return SDValue();
3904
3905 // Perform all saturation at selected width (i16 or i32) and truncate
3906 if (SatWidth < DstWidth && SatWidth <= 32) {
3907 // For f16 conversion with sub-i16 saturation perform saturation
3908 // at i16, if available in the target. This removes the need for extra f16
3909 // to f32 conversion. For all the others use i32.
3910 MVT ResultVT =
3911 Subtarget->has16BitInsts() && SrcVT == MVT::f16 && SatWidth < 16
3912 ? MVT::i16
3913 : MVT::i32;
3914
3915 const SDValue ResultVTOp = DAG.getValueType(ResultVT);
3916 const uint64_t ResultWidth = ResultVT.getScalarSizeInBits();
3917
3918 // First, convert input float into selected integer (i16 or i32)
3919 SDValue FpToInt = DAG.getNode(OpOpcode, DL, ResultVT, Src, ResultVTOp);
3920 SDValue IntSatVal;
3921
3922 // Then, clamp at the saturation width using either i16 or i32 instructions
3923 if (OpOpcode == ISD::FP_TO_SINT_SAT) {
3924 SDValue MinConst = DAG.getConstant(
3925 APInt::getSignedMaxValue(SatWidth).sext(ResultWidth), DL, ResultVT);
3926 SDValue MaxConst = DAG.getConstant(
3927 APInt::getSignedMinValue(SatWidth).sext(ResultWidth), DL, ResultVT);
3928 SDValue MinVal = DAG.getNode(ISD::SMIN, DL, ResultVT, FpToInt, MinConst);
3929 IntSatVal = DAG.getNode(ISD::SMAX, DL, ResultVT, MinVal, MaxConst);
3930 } else {
3931 SDValue MinConst = DAG.getConstant(
3932 APInt::getMaxValue(SatWidth).zext(ResultWidth), DL, ResultVT);
3933 IntSatVal = DAG.getNode(ISD::UMIN, DL, ResultVT, FpToInt, MinConst);
3934 }
3935
3936 // Finally, after saturating at i16 or i32 fit into the destination type
3937 return DAG.getExtOrTrunc(OpOpcode == ISD::FP_TO_SINT_SAT, IntSatVal, DL,
3938 DstVT);
3939 }
3940
3941 // SatWidth == DstWidth or SatWidth > 32
3942
3943 // Saturate at i32 for i64 dst and f16/bf16 src (will invoke f16 promotion
3944 // below)
3945 if (DstVT == MVT::i64 &&
3946 (SrcVT == MVT::f16 || SrcVT == MVT::bf16 ||
3947 (SrcVT == MVT::f32 && Src.getOpcode() == ISD::FP16_TO_FP))) {
3948 const SDValue Int32VTOp = DAG.getValueType(MVT::i32);
3949 return DAG.getNode(OpOpcode, DL, DstVT, Src, Int32VTOp);
3950 }
3951
3952 // Promote f16/bf16 src to f32 for i32 conversion
3953 if (DstVT == MVT::i32 && (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
3954 SDValue PromotedSrc = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Src);
3955 return DAG.getNode(Op.getOpcode(), DL, DstVT, PromotedSrc, SatVTOp);
3956 }
3957
3958 // For DstWidth < 16, promote i1 and i8 dst to i16 (if legal) with sub-i16
3959 // saturation. For DstWidth == 16, promote i16 dst to i32 with sub-i32
3960 // saturation; this covers i16.f32 and i16.f64
3961 if (DstWidth < 32) {
3962 // Note: this triggers SatWidth < DstWidth above to generate saturated
3963 // truncate by requesting MVT::i16/i32 destination with SatWidth < 16/32.
3964 MVT PromoteVT =
3965 (DstWidth < 16 && Subtarget->has16BitInsts()) ? MVT::i16 : MVT::i32;
3966 SDValue FpToInt = DAG.getNode(OpOpcode, DL, PromoteVT, Src, SatVTOp);
3967 return DAG.getNode(ISD::TRUNCATE, DL, DstVT, FpToInt);
3968 }
3969
3970 // TODO: can we implement i64 dst for f32/f64?
3971
3972 return SDValue();
3973}
3974
3976 SelectionDAG &DAG) const {
3977 EVT ExtraVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
3978 MVT VT = Op.getSimpleValueType();
3979 MVT ScalarVT = VT.getScalarType();
3980
3981 assert(VT.isVector());
3982
3983 SDValue Src = Op.getOperand(0);
3984 SDLoc DL(Op);
3985
3986 // TODO: Don't scalarize on Evergreen?
3987 unsigned NElts = VT.getVectorNumElements();
3989 DAG.ExtractVectorElements(Src, Args, 0, NElts);
3990
3991 SDValue VTOp = DAG.getValueType(ExtraVT.getScalarType());
3992 for (unsigned I = 0; I < NElts; ++I)
3993 Args[I] = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, ScalarVT, Args[I], VTOp);
3994
3995 return DAG.getBuildVector(VT, DL, Args);
3996}
3997
3998//===----------------------------------------------------------------------===//
3999// Custom DAG optimizations
4000//===----------------------------------------------------------------------===//
4001
4002static bool isU24(SDValue Op, SelectionDAG &DAG) {
4003 return AMDGPUTargetLowering::numBitsUnsigned(Op, DAG) <= 24;
4004}
4005
4006static bool isI24(SDValue Op, SelectionDAG &DAG) {
4007 EVT VT = Op.getValueType();
4008 return VT.getSizeInBits() >= 24 && // Types less than 24-bit should be treated
4009 // as unsigned 24-bit values.
4011}
4012
4015 SelectionDAG &DAG = DCI.DAG;
4016 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
4017 bool IsIntrin = Node24->getOpcode() == ISD::INTRINSIC_WO_CHAIN;
4018
4019 SDValue LHS = IsIntrin ? Node24->getOperand(1) : Node24->getOperand(0);
4020 SDValue RHS = IsIntrin ? Node24->getOperand(2) : Node24->getOperand(1);
4021 unsigned NewOpcode = Node24->getOpcode();
4022 if (IsIntrin) {
4023 unsigned IID = Node24->getConstantOperandVal(0);
4024 switch (IID) {
4025 case Intrinsic::amdgcn_mul_i24:
4026 NewOpcode = AMDGPUISD::MUL_I24;
4027 break;
4028 case Intrinsic::amdgcn_mul_u24:
4029 NewOpcode = AMDGPUISD::MUL_U24;
4030 break;
4031 case Intrinsic::amdgcn_mulhi_i24:
4032 NewOpcode = AMDGPUISD::MULHI_I24;
4033 break;
4034 case Intrinsic::amdgcn_mulhi_u24:
4035 NewOpcode = AMDGPUISD::MULHI_U24;
4036 break;
4037 default:
4038 llvm_unreachable("Expected 24-bit mul intrinsic");
4039 }
4040 }
4041
4042 APInt Demanded = APInt::getLowBitsSet(LHS.getValueSizeInBits(), 24);
4043
4044 // First try to simplify using SimplifyMultipleUseDemandedBits which allows
4045 // the operands to have other uses, but will only perform simplifications that
4046 // involve bypassing some nodes for this user.
4047 SDValue DemandedLHS = TLI.SimplifyMultipleUseDemandedBits(LHS, Demanded, DAG);
4048 SDValue DemandedRHS = TLI.SimplifyMultipleUseDemandedBits(RHS, Demanded, DAG);
4049 if (DemandedLHS || DemandedRHS)
4050 return DAG.getNode(NewOpcode, SDLoc(Node24), Node24->getVTList(),
4051 DemandedLHS ? DemandedLHS : LHS,
4052 DemandedRHS ? DemandedRHS : RHS);
4053
4054 // Now try SimplifyDemandedBits which can simplify the nodes used by our
4055 // operands if this node is the only user.
4056 if (TLI.SimplifyDemandedBits(LHS, Demanded, DCI))
4057 return SDValue(Node24, 0);
4058 if (TLI.SimplifyDemandedBits(RHS, Demanded, DCI))
4059 return SDValue(Node24, 0);
4060
4061 return SDValue();
4062}
4063
4064template <typename IntTy>
4066 uint32_t Width, const SDLoc &DL) {
4067 if (Width + Offset < 32) {
4068 uint32_t Shl = static_cast<uint32_t>(Src0) << (32 - Offset - Width);
4069 IntTy Result = static_cast<IntTy>(Shl) >> (32 - Width);
4070 if constexpr (std::is_signed_v<IntTy>) {
4071 return DAG.getSignedConstant(Result, DL, MVT::i32);
4072 } else {
4073 return DAG.getConstant(Result, DL, MVT::i32);
4074 }
4075 }
4076
4077 return DAG.getConstant(Src0 >> Offset, DL, MVT::i32);
4078}
4079
4080static bool hasVolatileUser(SDNode *Val) {
4081 for (SDNode *U : Val->users()) {
4082 if (MemSDNode *M = dyn_cast<MemSDNode>(U)) {
4083 if (M->isVolatile())
4084 return true;
4085 }
4086 }
4087
4088 return false;
4089}
4090
4092 // i32 vectors are the canonical memory type.
4093 if (VT.getScalarType() == MVT::i32 || isTypeLegal(VT))
4094 return false;
4095
4096 if (!VT.isByteSized())
4097 return false;
4098
4099 unsigned Size = VT.getStoreSize();
4100
4101 if ((Size == 1 || Size == 2 || Size == 4) && !VT.isVector())
4102 return false;
4103
4104 if (Size == 3 || (Size > 4 && (Size % 4 != 0)))
4105 return false;
4106
4107 return true;
4108}
4109
4110// Replace load of an illegal type with a bitcast from a load of a friendlier
4111// type.
4113 DAGCombinerInfo &DCI) const {
4114 if (!DCI.isBeforeLegalize())
4115 return SDValue();
4116
4118 if (!LN->isSimple() || !ISD::isNormalLoad(LN) || hasVolatileUser(LN))
4119 return SDValue();
4120
4121 SDLoc SL(N);
4122 SelectionDAG &DAG = DCI.DAG;
4123 EVT VT = LN->getMemoryVT();
4124
4125 unsigned Size = VT.getStoreSize();
4126 Align Alignment = LN->getAlign();
4127 if (Alignment < Size && isTypeLegal(VT)) {
4128 unsigned IsFast;
4129 unsigned AS = LN->getAddressSpace();
4130
4131 // Expand unaligned loads earlier than legalization. Due to visitation order
4132 // problems during legalization, the emitted instructions to pack and unpack
4133 // the bytes again are not eliminated in the case of an unaligned copy.
4135 VT, AS, Alignment, LN->getMemOperand()->getFlags(), &IsFast)) {
4136 if (VT.isVector())
4137 return SplitVectorLoad(SDValue(LN, 0), DAG);
4138
4139 SDValue Ops[2];
4140 std::tie(Ops[0], Ops[1]) = expandUnalignedLoad(LN, DAG);
4141
4142 return DAG.getMergeValues(Ops, SDLoc(N));
4143 }
4144
4145 if (!IsFast)
4146 return SDValue();
4147 }
4148
4149 if (!shouldCombineMemoryType(VT))
4150 return SDValue();
4151
4152 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VT);
4153
4154 SDValue NewLoad
4155 = DAG.getLoad(NewVT, SL, LN->getChain(),
4156 LN->getBasePtr(), LN->getMemOperand());
4157
4158 SDValue BC = DAG.getNode(ISD::BITCAST, SL, VT, NewLoad);
4159 DCI.CombineTo(N, BC, NewLoad.getValue(1));
4160 return SDValue(N, 0);
4161}
4162
4163// Replace store of an illegal type with a store of a bitcast to a friendlier
4164// type.
4166 DAGCombinerInfo &DCI) const {
4167 if (!DCI.isBeforeLegalize())
4168 return SDValue();
4169
4171 if (!SN->isSimple() || !ISD::isNormalStore(SN))
4172 return SDValue();
4173
4174 EVT VT = SN->getMemoryVT();
4175 unsigned Size = VT.getStoreSize();
4176
4177 SDLoc SL(N);
4178 SelectionDAG &DAG = DCI.DAG;
4179 Align Alignment = SN->getAlign();
4180 if (Alignment < Size && isTypeLegal(VT)) {
4181 unsigned IsFast;
4182 unsigned AS = SN->getAddressSpace();
4183
4184 // Expand unaligned stores earlier than legalization. Due to visitation
4185 // order problems during legalization, the emitted instructions to pack and
4186 // unpack the bytes again are not eliminated in the case of an unaligned
4187 // copy.
4189 VT, AS, Alignment, SN->getMemOperand()->getFlags(), &IsFast)) {
4190 if (VT.isVector())
4191 return SplitVectorStore(SDValue(SN, 0), DAG);
4192
4193 return expandUnalignedStore(SN, DAG);
4194 }
4195
4196 if (!IsFast)
4197 return SDValue();
4198 }
4199
4200 if (!shouldCombineMemoryType(VT))
4201 return SDValue();
4202
4203 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VT);
4204 SDValue Val = SN->getValue();
4205
4206 // DCI.AddToWorklist(Val.getNode());
4207
4208 bool OtherUses = !Val.hasOneUse();
4209 SDValue CastVal = DAG.getBitcast(NewVT, Val);
4210 if (OtherUses) {
4211 SDValue CastBack = DAG.getBitcast(VT, CastVal);
4212 DAG.ReplaceAllUsesOfValueWith(Val, CastBack);
4213 }
4214
4215 return DAG.getStore(SN->getChain(), SL, CastVal,
4216 SN->getBasePtr(), SN->getMemOperand());
4217}
4218
4219// FIXME: This should go in generic DAG combiner with an isTruncateFree check,
4220// but isTruncateFree is inaccurate for i16 now because of SALU vs. VALU
4221// issues.
4223 DAGCombinerInfo &DCI) const {
4224 SelectionDAG &DAG = DCI.DAG;
4225 SDValue N0 = N->getOperand(0);
4226
4227 // (vt2 (assertzext (truncate vt0:x), vt1)) ->
4228 // (vt2 (truncate (assertzext vt0:x, vt1)))
4229 if (N0.getOpcode() == ISD::TRUNCATE) {
4230 SDValue N1 = N->getOperand(1);
4231 EVT ExtVT = cast<VTSDNode>(N1)->getVT();
4232 SDLoc SL(N);
4233
4234 SDValue Src = N0.getOperand(0);
4235 EVT SrcVT = Src.getValueType();
4236 if (SrcVT.bitsGE(ExtVT)) {
4237 SDValue NewInReg = DAG.getNode(N->getOpcode(), SL, SrcVT, Src, N1);
4238 return DAG.getNode(ISD::TRUNCATE, SL, N->getValueType(0), NewInReg);
4239 }
4240 }
4241
4242 return SDValue();
4243}
4244
4246 SDNode *N, DAGCombinerInfo &DCI) const {
4247 unsigned IID = N->getConstantOperandVal(0);
4248 switch (IID) {
4249 case Intrinsic::amdgcn_mul_i24:
4250 case Intrinsic::amdgcn_mul_u24:
4251 case Intrinsic::amdgcn_mulhi_i24:
4252 case Intrinsic::amdgcn_mulhi_u24:
4253 return simplifyMul24(N, DCI);
4254 case Intrinsic::amdgcn_fract:
4255 case Intrinsic::amdgcn_rsq:
4256 case Intrinsic::amdgcn_rcp_legacy:
4257 case Intrinsic::amdgcn_rsq_legacy:
4258 case Intrinsic::amdgcn_rsq_clamp:
4259 case Intrinsic::amdgcn_tanh:
4260 case Intrinsic::amdgcn_prng_b32: {
4261 // FIXME: This is probably wrong. If src is an sNaN, it won't be quieted
4262 SDValue Src = N->getOperand(1);
4263 return Src.isUndef() ? Src : SDValue();
4264 }
4265 case Intrinsic::amdgcn_frexp_exp: {
4266 // frexp_exp (fneg x) -> frexp_exp x
4267 // frexp_exp (fabs x) -> frexp_exp x
4268 // frexp_exp (fneg (fabs x)) -> frexp_exp x
4269 SDValue Src = N->getOperand(1);
4270 SDValue PeekSign = peekFPSignOps(Src);
4271 if (PeekSign == Src)
4272 return SDValue();
4273 return SDValue(DCI.DAG.UpdateNodeOperands(N, N->getOperand(0), PeekSign),
4274 0);
4275 }
4276 default:
4277 return SDValue();
4278 }
4279}
4280
4281/// Split the 64-bit value \p LHS into two 32-bit components, and perform the
4282/// binary operation \p Opc to it with the corresponding constant operands.
4284 DAGCombinerInfo &DCI, const SDLoc &SL,
4285 unsigned Opc, SDValue LHS,
4286 uint32_t ValLo, uint32_t ValHi) const {
4287 SelectionDAG &DAG = DCI.DAG;
4288 SDValue Lo, Hi;
4289 std::tie(Lo, Hi) = split64BitValue(LHS, DAG);
4290
4291 SDValue LoRHS = DAG.getConstant(ValLo, SL, MVT::i32);
4292 SDValue HiRHS = DAG.getConstant(ValHi, SL, MVT::i32);
4293
4294 SDValue LoAnd = DAG.getNode(Opc, SL, MVT::i32, Lo, LoRHS);
4295 SDValue HiAnd = DAG.getNode(Opc, SL, MVT::i32, Hi, HiRHS);
4296
4297 // Re-visit the ands. It's possible we eliminated one of them and it could
4298 // simplify the vector.
4299 DCI.AddToWorklist(Lo.getNode());
4300 DCI.AddToWorklist(Hi.getNode());
4301
4302 SDValue Vec = DAG.getBuildVector(MVT::v2i32, SL, {LoAnd, HiAnd});
4303 return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
4304}
4305
4307 DAGCombinerInfo &DCI) const {
4308 EVT VT = N->getValueType(0);
4309 SDValue LHS = N->getOperand(0);
4310 SDValue RHS = N->getOperand(1);
4312 SDLoc SL(N);
4313 SelectionDAG &DAG = DCI.DAG;
4314
4315 unsigned RHSVal;
4316 if (CRHS) {
4317 RHSVal = CRHS->getZExtValue();
4318 if (!RHSVal)
4319 return LHS;
4320
4321 switch (LHS->getOpcode()) {
4322 default:
4323 break;
4324 case ISD::ZERO_EXTEND:
4325 case ISD::SIGN_EXTEND:
4326 case ISD::ANY_EXTEND: {
4327 SDValue X = LHS->getOperand(0);
4328
4329 if (VT == MVT::i32 && RHSVal == 16 && X.getValueType() == MVT::i16 &&
4330 isOperationLegal(ISD::BUILD_VECTOR, MVT::v2i16)) {
4331 // Prefer build_vector as the canonical form if packed types are legal.
4332 // (shl ([asz]ext i16:x), 16 -> build_vector 0, x
4333 SDValue Vec = DAG.getBuildVector(
4334 MVT::v2i16, SL,
4335 {DAG.getConstant(0, SL, MVT::i16), LHS->getOperand(0)});
4336 return DAG.getNode(ISD::BITCAST, SL, MVT::i32, Vec);
4337 }
4338
4339 // shl (ext x) => zext (shl x), if shift does not overflow int
4340 if (VT != MVT::i64)
4341 break;
4343 unsigned LZ = Known.countMinLeadingZeros();
4344 if (LZ < RHSVal)
4345 break;
4346 EVT XVT = X.getValueType();
4347 SDValue Shl = DAG.getNode(ISD::SHL, SL, XVT, X, SDValue(CRHS, 0));
4348 return DAG.getZExtOrTrunc(Shl, SL, VT);
4349 }
4350 }
4351 }
4352
4353 if (VT.getScalarType() != MVT::i64)
4354 return SDValue();
4355
4356 // On some subtargets, 64-bit shift is a quarter rate instruction. In the
4357 // common case, splitting this into a move and a 32-bit shift is faster and
4358 // the same code size.
4359 KnownBits Known = DAG.computeKnownBits(RHS);
4360
4361 EVT ElementType = VT.getScalarType();
4362 EVT TargetScalarType = ElementType.getHalfSizedIntegerVT(*DAG.getContext());
4363 EVT TargetType = VT.changeElementType(*DAG.getContext(), TargetScalarType);
4364
4365 if (Known.getMinValue().getZExtValue() < TargetScalarType.getSizeInBits())
4366 return SDValue();
4367 SDValue ShiftAmt;
4368
4369 if (CRHS) {
4370 ShiftAmt = DAG.getConstant(RHSVal - TargetScalarType.getSizeInBits(), SL,
4371 TargetType);
4372 } else {
4373 SDValue TruncShiftAmt = DAG.getNode(ISD::TRUNCATE, SL, TargetType, RHS);
4374 const SDValue ShiftMask =
4375 DAG.getConstant(TargetScalarType.getSizeInBits() - 1, SL, TargetType);
4376 // This AND instruction will clamp out of bounds shift values.
4377 // It will also be removed during later instruction selection.
4378 ShiftAmt = DAG.getNode(ISD::AND, SL, TargetType, TruncShiftAmt, ShiftMask);
4379 }
4380
4381 SDValue Lo = DAG.getNode(ISD::TRUNCATE, SL, TargetType, LHS);
4382 SDValue NewShift =
4383 DAG.getNode(ISD::SHL, SL, TargetType, Lo, ShiftAmt, N->getFlags());
4384
4385 const SDValue Zero = DAG.getConstant(0, SL, TargetScalarType);
4386 SDValue Vec;
4387
4388 if (VT.isVector()) {
4389 EVT ConcatType = TargetType.getDoubleNumVectorElementsVT(*DAG.getContext());
4390 unsigned NElts = TargetType.getVectorNumElements();
4392 SmallVector<SDValue, 16> HiAndLoOps(NElts * 2, Zero);
4393
4394 DAG.ExtractVectorElements(NewShift, HiOps, 0, NElts);
4395 for (unsigned I = 0; I != NElts; ++I)
4396 HiAndLoOps[2 * I + 1] = HiOps[I];
4397 Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, ConcatType, HiAndLoOps);
4398 } else {
4399 EVT ConcatType = EVT::getVectorVT(*DAG.getContext(), TargetType, 2);
4400 Vec = DAG.getBuildVector(ConcatType, SL, {Zero, NewShift});
4401 }
4402 return DAG.getNode(ISD::BITCAST, SL, VT, Vec);
4403}
4404
4406 DAGCombinerInfo &DCI) const {
4407 SDValue RHS = N->getOperand(1);
4409 EVT VT = N->getValueType(0);
4410 SDValue LHS = N->getOperand(0);
4411 SelectionDAG &DAG = DCI.DAG;
4412 SDLoc SL(N);
4413
4414 if (VT.getScalarType() != MVT::i64)
4415 return SDValue();
4416
4417 // For C >= 32
4418 // i64 (sra x, C) -> (build_pair (sra hi_32(x), C - 32), sra hi_32(x), 31))
4419
4420 // On some subtargets, 64-bit shift is a quarter rate instruction. In the
4421 // common case, splitting this into a move and a 32-bit shift is faster and
4422 // the same code size.
4423 KnownBits Known = DAG.computeKnownBits(RHS);
4424
4425 EVT ElementType = VT.getScalarType();
4426 EVT TargetScalarType = ElementType.getHalfSizedIntegerVT(*DAG.getContext());
4427 EVT TargetType = VT.changeElementType(*DAG.getContext(), TargetScalarType);
4428
4429 if (Known.getMinValue().getZExtValue() < TargetScalarType.getSizeInBits())
4430 return SDValue();
4431
4432 SDValue ShiftFullAmt =
4433 DAG.getConstant(TargetScalarType.getSizeInBits() - 1, SL, TargetType);
4434 SDValue ShiftAmt;
4435 if (CRHS) {
4436 unsigned RHSVal = CRHS->getZExtValue();
4437 ShiftAmt = DAG.getConstant(RHSVal - TargetScalarType.getSizeInBits(), SL,
4438 TargetType);
4439 } else if (Known.getMinValue().getZExtValue() ==
4440 (ElementType.getSizeInBits() - 1)) {
4441 ShiftAmt = ShiftFullAmt;
4442 } else {
4443 SDValue TruncShiftAmt = DAG.getNode(ISD::TRUNCATE, SL, TargetType, RHS);
4444 const SDValue ShiftMask =
4445 DAG.getConstant(TargetScalarType.getSizeInBits() - 1, SL, TargetType);
4446 // This AND instruction will clamp out of bounds shift values.
4447 // It will also be removed during later instruction selection.
4448 ShiftAmt = DAG.getNode(ISD::AND, SL, TargetType, TruncShiftAmt, ShiftMask);
4449 }
4450
4451 EVT ConcatType;
4452 SDValue Hi;
4453 SDLoc LHSSL(LHS);
4454 // Bitcast LHS into ConcatType so hi-half of source can be extracted into Hi
4455 if (VT.isVector()) {
4456 unsigned NElts = TargetType.getVectorNumElements();
4457 ConcatType = TargetType.getDoubleNumVectorElementsVT(*DAG.getContext());
4458 SDValue SplitLHS = DAG.getNode(ISD::BITCAST, LHSSL, ConcatType, LHS);
4459 SmallVector<SDValue, 8> HiOps(NElts);
4460 SmallVector<SDValue, 16> HiAndLoOps;
4461
4462 DAG.ExtractVectorElements(SplitLHS, HiAndLoOps, 0, NElts * 2);
4463 for (unsigned I = 0; I != NElts; ++I) {
4464 HiOps[I] = HiAndLoOps[2 * I + 1];
4465 }
4466 Hi = DAG.getNode(ISD::BUILD_VECTOR, LHSSL, TargetType, HiOps);
4467 } else {
4468 const SDValue One = DAG.getConstant(1, LHSSL, TargetScalarType);
4469 ConcatType = EVT::getVectorVT(*DAG.getContext(), TargetType, 2);
4470 SDValue SplitLHS = DAG.getNode(ISD::BITCAST, LHSSL, ConcatType, LHS);
4471 Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, LHSSL, TargetType, SplitLHS, One);
4472 }
4473
4474 KnownBits KnownLHS = DAG.computeKnownBits(LHS);
4475 SDValue NewShift, HiShift;
4476 if (KnownLHS.isNegative()) {
4477 HiShift = DAG.getAllOnesConstant(SL, TargetType);
4478 NewShift =
4479 DAG.getNode(ISD::SRA, SL, TargetType, Hi, ShiftAmt, N->getFlags());
4480 } else if (CRHS &&
4481 CRHS->getZExtValue() == (ElementType.getSizeInBits() - 1)) {
4482 NewShift = HiShift =
4483 DAG.getNode(ISD::SRA, SL, TargetType, Hi, ShiftAmt, N->getFlags());
4484 } else {
4485 Hi = DAG.getFreeze(Hi);
4486 HiShift = DAG.getNode(ISD::SRA, SL, TargetType, Hi, ShiftFullAmt);
4487 NewShift =
4488 DAG.getNode(ISD::SRA, SL, TargetType, Hi, ShiftAmt, N->getFlags());
4489 }
4490
4491 SDValue Vec;
4492 if (VT.isVector()) {
4493 unsigned NElts = TargetType.getVectorNumElements();
4496 SmallVector<SDValue, 16> HiAndLoOps(NElts * 2);
4497
4498 DAG.ExtractVectorElements(HiShift, HiOps, 0, NElts);
4499 DAG.ExtractVectorElements(NewShift, LoOps, 0, NElts);
4500 for (unsigned I = 0; I != NElts; ++I) {
4501 HiAndLoOps[2 * I + 1] = HiOps[I];
4502 HiAndLoOps[2 * I] = LoOps[I];
4503 }
4504 Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, ConcatType, HiAndLoOps);
4505 } else {
4506 Vec = DAG.getBuildVector(ConcatType, SL, {NewShift, HiShift});
4507 }
4508 return DAG.getNode(ISD::BITCAST, SL, VT, Vec);
4509}
4510
4512 DAGCombinerInfo &DCI) const {
4513 SDValue RHS = N->getOperand(1);
4515 EVT VT = N->getValueType(0);
4516 SDValue LHS = N->getOperand(0);
4517 SelectionDAG &DAG = DCI.DAG;
4518 SDLoc SL(N);
4519 unsigned RHSVal;
4520
4521 if (CRHS) {
4522 RHSVal = CRHS->getZExtValue();
4523
4524 // fold (srl (and x, c1 << c2), c2) -> (and (srl(x, c2), c1)
4525 // this improves the ability to match BFE patterns in isel.
4526 if (LHS.getOpcode() == ISD::AND) {
4527 if (auto *Mask = dyn_cast<ConstantSDNode>(LHS.getOperand(1))) {
4528 unsigned MaskIdx, MaskLen;
4529 if (Mask->getAPIntValue().isShiftedMask(MaskIdx, MaskLen) &&
4530 MaskIdx == RHSVal) {
4531 return DAG.getNode(ISD::AND, SL, VT,
4532 DAG.getNode(ISD::SRL, SL, VT, LHS.getOperand(0),
4533 N->getOperand(1)),
4534 DAG.getNode(ISD::SRL, SL, VT, LHS.getOperand(1),
4535 N->getOperand(1)));
4536 }
4537 }
4538 }
4539 }
4540
4541 if (VT.getScalarType() != MVT::i64)
4542 return SDValue();
4543
4544 // for C >= 32
4545 // i64 (srl x, C) -> (build_pair (srl hi_32(x), C - 32), 0)
4546
4547 // On some subtargets, 64-bit shift is a quarter rate instruction. In the
4548 // common case, splitting this into a move and a 32-bit shift is faster and
4549 // the same code size.
4550 KnownBits Known = DAG.computeKnownBits(RHS);
4551
4552 EVT ElementType = VT.getScalarType();
4553 EVT TargetScalarType = ElementType.getHalfSizedIntegerVT(*DAG.getContext());
4554 EVT TargetType = VT.changeElementType(*DAG.getContext(), TargetScalarType);
4555
4556 if (Known.getMinValue().getZExtValue() < TargetScalarType.getSizeInBits())
4557 return SDValue();
4558
4559 SDValue ShiftAmt;
4560 if (CRHS) {
4561 ShiftAmt = DAG.getConstant(RHSVal - TargetScalarType.getSizeInBits(), SL,
4562 TargetType);
4563 } else {
4564 SDValue TruncShiftAmt = DAG.getNode(ISD::TRUNCATE, SL, TargetType, RHS);
4565 const SDValue ShiftMask =
4566 DAG.getConstant(TargetScalarType.getSizeInBits() - 1, SL, TargetType);
4567 // This AND instruction will clamp out of bounds shift values.
4568 // It will also be removed during later instruction selection.
4569 ShiftAmt = DAG.getNode(ISD::AND, SL, TargetType, TruncShiftAmt, ShiftMask);
4570 }
4571
4572 const SDValue Zero = DAG.getConstant(0, SL, TargetScalarType);
4573 EVT ConcatType;
4574 SDValue Hi;
4575 SDLoc LHSSL(LHS);
4576 // Bitcast LHS into ConcatType so hi-half of source can be extracted into Hi
4577 if (VT.isVector()) {
4578 unsigned NElts = TargetType.getVectorNumElements();
4579 ConcatType = TargetType.getDoubleNumVectorElementsVT(*DAG.getContext());
4580 SDValue SplitLHS = DAG.getNode(ISD::BITCAST, LHSSL, ConcatType, LHS);
4581 SmallVector<SDValue, 8> HiOps(NElts);
4582 SmallVector<SDValue, 16> HiAndLoOps;
4583
4584 DAG.ExtractVectorElements(SplitLHS, HiAndLoOps, /*Start=*/0, NElts * 2);
4585 for (unsigned I = 0; I != NElts; ++I)
4586 HiOps[I] = HiAndLoOps[2 * I + 1];
4587 Hi = DAG.getNode(ISD::BUILD_VECTOR, LHSSL, TargetType, HiOps);
4588 } else {
4589 const SDValue One = DAG.getConstant(1, LHSSL, TargetScalarType);
4590 ConcatType = EVT::getVectorVT(*DAG.getContext(), TargetType, 2);
4591 SDValue SplitLHS = DAG.getNode(ISD::BITCAST, LHSSL, ConcatType, LHS);
4592 Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, LHSSL, TargetType, SplitLHS, One);
4593 }
4594
4595 SDValue NewShift =
4596 DAG.getNode(ISD::SRL, SL, TargetType, Hi, ShiftAmt, N->getFlags());
4597
4598 SDValue Vec;
4599 if (VT.isVector()) {
4600 unsigned NElts = TargetType.getVectorNumElements();
4602 SmallVector<SDValue, 16> HiAndLoOps(NElts * 2, Zero);
4603
4604 DAG.ExtractVectorElements(NewShift, LoOps, 0, NElts);
4605 for (unsigned I = 0; I != NElts; ++I)
4606 HiAndLoOps[2 * I] = LoOps[I];
4607 Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, ConcatType, HiAndLoOps);
4608 } else {
4609 Vec = DAG.getBuildVector(ConcatType, SL, {NewShift, Zero});
4610 }
4611 return DAG.getNode(ISD::BITCAST, SL, VT, Vec);
4612}
4613
4615 SDNode *N, DAGCombinerInfo &DCI) const {
4616 SDLoc SL(N);
4617 SelectionDAG &DAG = DCI.DAG;
4618 EVT VT = N->getValueType(0);
4619 SDValue Src = N->getOperand(0);
4620
4621 // vt1 (truncate (bitcast (build_vector vt0:x, ...))) -> vt1 (bitcast vt0:x)
4622 if (Src.getOpcode() == ISD::BITCAST && !VT.isVector()) {
4623 SDValue Vec = Src.getOperand(0);
4624 if (Vec.getOpcode() == ISD::BUILD_VECTOR) {
4625 SDValue Elt0 = Vec.getOperand(0);
4626 EVT EltVT = Elt0.getValueType();
4627 if (VT.getFixedSizeInBits() <= EltVT.getFixedSizeInBits()) {
4628 if (EltVT.isFloatingPoint()) {
4629 Elt0 = DAG.getNode(ISD::BITCAST, SL,
4630 EltVT.changeTypeToInteger(), Elt0);
4631 }
4632
4633 return DAG.getNode(ISD::TRUNCATE, SL, VT, Elt0);
4634 }
4635 }
4636 }
4637
4638 // Equivalent of above for accessing the high element of a vector as an
4639 // integer operation.
4640 // trunc (srl (bitcast (build_vector x, y))), 16 -> trunc (bitcast y)
4641 if (Src.getOpcode() == ISD::SRL && !VT.isVector()) {
4642 if (auto *K = isConstOrConstSplat(Src.getOperand(1))) {
4643 SDValue BV = stripBitcast(Src.getOperand(0));
4644 if (BV.getOpcode() == ISD::BUILD_VECTOR) {
4645 EVT SrcEltVT = BV.getOperand(0).getValueType();
4646 unsigned SrcEltSize = SrcEltVT.getSizeInBits();
4647 unsigned BitIndex = K->getZExtValue();
4648 unsigned PartIndex = BitIndex / SrcEltSize;
4649
4650 if (PartIndex * SrcEltSize == BitIndex &&
4651 PartIndex < BV.getNumOperands()) {
4652 if (SrcEltVT.getSizeInBits() == VT.getSizeInBits()) {
4653 SDValue SrcElt =
4654 DAG.getNode(ISD::BITCAST, SL, SrcEltVT.changeTypeToInteger(),
4655 BV.getOperand(PartIndex));
4656 return DAG.getNode(ISD::TRUNCATE, SL, VT, SrcElt);
4657 }
4658 }
4659 }
4660 }
4661 }
4662
4663 // Partially shrink 64-bit shifts to 32-bit if reduced to 16-bit.
4664 //
4665 // i16 (trunc (srl i64:x, K)), K <= 16 ->
4666 // i16 (trunc (srl (i32 (trunc x), K)))
4667 if (VT.getScalarSizeInBits() < 32) {
4668 EVT SrcVT = Src.getValueType();
4669 if (SrcVT.getScalarSizeInBits() > 32 &&
4670 (Src.getOpcode() == ISD::SRL ||
4671 Src.getOpcode() == ISD::SRA ||
4672 Src.getOpcode() == ISD::SHL)) {
4673 SDValue Amt = Src.getOperand(1);
4674 KnownBits Known = DAG.computeKnownBits(Amt);
4675
4676 // - For left shifts, do the transform as long as the shift
4677 // amount is still legal for i32, so when ShiftAmt < 32 (<= 31)
4678 // - For right shift, do it if ShiftAmt <= (32 - Size) to avoid
4679 // losing information stored in the high bits when truncating.
4680 const unsigned MaxCstSize =
4681 (Src.getOpcode() == ISD::SHL) ? 31 : (32 - VT.getScalarSizeInBits());
4682 if (Known.getMaxValue().ule(MaxCstSize)) {
4683 EVT MidVT = VT.isVector() ?
4684 EVT::getVectorVT(*DAG.getContext(), MVT::i32,
4685 VT.getVectorNumElements()) : MVT::i32;
4686
4687 EVT NewShiftVT = getShiftAmountTy(MidVT, DAG.getDataLayout());
4688 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SL, MidVT,
4689 Src.getOperand(0));
4690 DCI.AddToWorklist(Trunc.getNode());
4691
4692 if (Amt.getValueType() != NewShiftVT) {
4693 Amt = DAG.getZExtOrTrunc(Amt, SL, NewShiftVT);
4694 DCI.AddToWorklist(Amt.getNode());
4695 }
4696
4697 SDValue ShrunkShift = DAG.getNode(Src.getOpcode(), SL, MidVT,
4698 Trunc, Amt);
4699 return DAG.getNode(ISD::TRUNCATE, SL, VT, ShrunkShift);
4700 }
4701 }
4702 }
4703
4704 return SDValue();
4705}
4706
4707// We need to specifically handle i64 mul here to avoid unnecessary conversion
4708// instructions. If we only match on the legalized i64 mul expansion,
4709// SimplifyDemandedBits will be unable to remove them because there will be
4710// multiple uses due to the separate mul + mulh[su].
4711static SDValue getMul24(SelectionDAG &DAG, const SDLoc &SL,
4712 SDValue N0, SDValue N1, unsigned Size, bool Signed) {
4713 if (Size <= 32) {
4714 unsigned MulOpc = Signed ? AMDGPUISD::MUL_I24 : AMDGPUISD::MUL_U24;
4715 return DAG.getNode(MulOpc, SL, MVT::i32, N0, N1);
4716 }
4717
4718 unsigned MulLoOpc = Signed ? AMDGPUISD::MUL_I24 : AMDGPUISD::MUL_U24;
4719 unsigned MulHiOpc = Signed ? AMDGPUISD::MULHI_I24 : AMDGPUISD::MULHI_U24;
4720
4721 SDValue MulLo = DAG.getNode(MulLoOpc, SL, MVT::i32, N0, N1);
4722 SDValue MulHi = DAG.getNode(MulHiOpc, SL, MVT::i32, N0, N1);
4723
4724 return DAG.getNode(ISD::BUILD_PAIR, SL, MVT::i64, MulLo, MulHi);
4725}
4726
4727/// If \p V is an add of a constant 1, returns the other operand. Otherwise
4728/// return SDValue().
4729static SDValue getAddOneOp(const SDNode *V) {
4730 if (V->getOpcode() != ISD::ADD)
4731 return SDValue();
4732
4733 return isOneConstant(V->getOperand(1)) ? V->getOperand(0) : SDValue();
4734}
4735
4737 DAGCombinerInfo &DCI) const {
4738 assert(N->getOpcode() == ISD::MUL);
4739 EVT VT = N->getValueType(0);
4740
4741 // Don't generate 24-bit multiplies on values that are in SGPRs, since
4742 // we only have a 32-bit scalar multiply (avoid values being moved to VGPRs
4743 // unnecessarily). isDivergent() is used as an approximation of whether the
4744 // value is in an SGPR.
4745 if (!N->isDivergent())
4746 return SDValue();
4747
4748 unsigned Size = VT.getSizeInBits();
4749 if (VT.isVector() || Size > 64)
4750 return SDValue();
4751
4752 SelectionDAG &DAG = DCI.DAG;
4753 SDLoc DL(N);
4754
4755 SDValue N0 = N->getOperand(0);
4756 SDValue N1 = N->getOperand(1);
4757
4758 // Undo InstCombine canonicalize X * (Y + 1) -> X * Y + X to enable mad
4759 // matching.
4760
4761 // mul x, (add y, 1) -> add (mul x, y), x
4762 auto IsFoldableAdd = [](SDValue V) -> SDValue {
4763 SDValue AddOp = getAddOneOp(V.getNode());
4764 if (!AddOp)
4765 return SDValue();
4766
4767 if (V.hasOneUse() || all_of(V->users(), [](const SDNode *U) -> bool {
4768 return U->getOpcode() == ISD::MUL;
4769 }))
4770 return AddOp;
4771
4772 return SDValue();
4773 };
4774
4775 // FIXME: The selection pattern is not properly checking for commuted
4776 // operands, so we have to place the mul in the LHS
4777 if (SDValue MulOper = IsFoldableAdd(N0)) {
4778 SDValue MulVal = DAG.getNode(N->getOpcode(), DL, VT, N1, MulOper);
4779 return DAG.getNode(ISD::ADD, DL, VT, MulVal, N1);
4780 }
4781
4782 if (SDValue MulOper = IsFoldableAdd(N1)) {
4783 SDValue MulVal = DAG.getNode(N->getOpcode(), DL, VT, N0, MulOper);
4784 return DAG.getNode(ISD::ADD, DL, VT, MulVal, N0);
4785 }
4786
4787 // There are i16 integer mul/mad.
4788 if (isTypeLegal(MVT::i16) && VT.getScalarType().bitsLE(MVT::i16))
4789 return SDValue();
4790
4791 // SimplifyDemandedBits has the annoying habit of turning useful zero_extends
4792 // in the source into any_extends if the result of the mul is truncated. Since
4793 // we can assume the high bits are whatever we want, use the underlying value
4794 // to avoid the unknown high bits from interfering.
4795 if (N0.getOpcode() == ISD::ANY_EXTEND)
4796 N0 = N0.getOperand(0);
4797
4798 if (N1.getOpcode() == ISD::ANY_EXTEND)
4799 N1 = N1.getOperand(0);
4800
4801 SDValue Mul;
4802
4803 if (Subtarget->hasMulU24() && isU24(N0, DAG) && isU24(N1, DAG)) {
4804 N0 = DAG.getZExtOrTrunc(N0, DL, MVT::i32);
4805 N1 = DAG.getZExtOrTrunc(N1, DL, MVT::i32);
4806 Mul = getMul24(DAG, DL, N0, N1, Size, false);
4807 } else if (Subtarget->hasMulI24() && isI24(N0, DAG) && isI24(N1, DAG)) {
4808 N0 = DAG.getSExtOrTrunc(N0, DL, MVT::i32);
4809 N1 = DAG.getSExtOrTrunc(N1, DL, MVT::i32);
4810 Mul = getMul24(DAG, DL, N0, N1, Size, true);
4811 } else {
4812 return SDValue();
4813 }
4814
4815 // We need to use sext even for MUL_U24, because MUL_U24 is used
4816 // for signed multiply of 8 and 16-bit types.
4817 return DAG.getSExtOrTrunc(Mul, DL, VT);
4818}
4819
4820SDValue
4822 DAGCombinerInfo &DCI) const {
4823 if (N->getValueType(0) != MVT::i32)
4824 return SDValue();
4825
4826 SelectionDAG &DAG = DCI.DAG;
4827 SDLoc DL(N);
4828
4829 bool Signed = N->getOpcode() == ISD::SMUL_LOHI;
4830 SDValue N0 = N->getOperand(0);
4831 SDValue N1 = N->getOperand(1);
4832
4833 // SimplifyDemandedBits has the annoying habit of turning useful zero_extends
4834 // in the source into any_extends if the result of the mul is truncated. Since
4835 // we can assume the high bits are whatever we want, use the underlying value
4836 // to avoid the unknown high bits from interfering.
4837 if (N0.getOpcode() == ISD::ANY_EXTEND)
4838 N0 = N0.getOperand(0);
4839 if (N1.getOpcode() == ISD::ANY_EXTEND)
4840 N1 = N1.getOperand(0);
4841
4842 // Try to use two fast 24-bit multiplies (one for each half of the result)
4843 // instead of one slow extending multiply.
4844 unsigned LoOpcode = 0;
4845 unsigned HiOpcode = 0;
4846 if (Signed) {
4847 if (Subtarget->hasMulI24() && isI24(N0, DAG) && isI24(N1, DAG)) {
4848 N0 = DAG.getSExtOrTrunc(N0, DL, MVT::i32);
4849 N1 = DAG.getSExtOrTrunc(N1, DL, MVT::i32);
4850 LoOpcode = AMDGPUISD::MUL_I24;
4851 HiOpcode = AMDGPUISD::MULHI_I24;
4852 }
4853 } else {
4854 if (Subtarget->hasMulU24() && isU24(N0, DAG) && isU24(N1, DAG)) {
4855 N0 = DAG.getZExtOrTrunc(N0, DL, MVT::i32);
4856 N1 = DAG.getZExtOrTrunc(N1, DL, MVT::i32);
4857 LoOpcode = AMDGPUISD::MUL_U24;
4858 HiOpcode = AMDGPUISD::MULHI_U24;
4859 }
4860 }
4861 if (!LoOpcode)
4862 return SDValue();
4863
4864 SDValue Lo = DAG.getNode(LoOpcode, DL, MVT::i32, N0, N1);
4865 SDValue Hi = DAG.getNode(HiOpcode, DL, MVT::i32, N0, N1);
4866 DCI.CombineTo(N, Lo, Hi);
4867 return SDValue(N, 0);
4868}
4869
4871 DAGCombinerInfo &DCI) const {
4872 EVT VT = N->getValueType(0);
4873
4874 if (!Subtarget->hasMulI24() || VT.isVector())
4875 return SDValue();
4876
4877 // Don't generate 24-bit multiplies on values that are in SGPRs, since
4878 // we only have a 32-bit scalar multiply (avoid values being moved to VGPRs
4879 // unnecessarily). isDivergent() is used as an approximation of whether the
4880 // value is in an SGPR.
4881 // This doesn't apply if no s_mul_hi is available (since we'll end up with a
4882 // valu op anyway)
4883 if (Subtarget->hasSMulHi() && !N->isDivergent())
4884 return SDValue();
4885
4886 SelectionDAG &DAG = DCI.DAG;
4887 SDLoc DL(N);
4888
4889 SDValue N0 = N->getOperand(0);
4890 SDValue N1 = N->getOperand(1);
4891
4892 if (!isI24(N0, DAG) || !isI24(N1, DAG))
4893 return SDValue();
4894
4895 N0 = DAG.getSExtOrTrunc(N0, DL, MVT::i32);
4896 N1 = DAG.getSExtOrTrunc(N1, DL, MVT::i32);
4897
4898 SDValue Mulhi = DAG.getNode(AMDGPUISD::MULHI_I24, DL, MVT::i32, N0, N1);
4899 DCI.AddToWorklist(Mulhi.getNode());
4900 return DAG.getSExtOrTrunc(Mulhi, DL, VT);
4901}
4902
4904 DAGCombinerInfo &DCI) const {
4905 EVT VT = N->getValueType(0);
4906
4907 if (VT.isVector() || VT.getSizeInBits() > 32 || !Subtarget->hasMulU24())
4908 return SDValue();
4909
4910 // Don't generate 24-bit multiplies on values that are in SGPRs, since
4911 // we only have a 32-bit scalar multiply (avoid values being moved to VGPRs
4912 // unnecessarily). isDivergent() is used as an approximation of whether the
4913 // value is in an SGPR.
4914 // This doesn't apply if no s_mul_hi is available (since we'll end up with a
4915 // valu op anyway)
4916 if (!N->isDivergent() && Subtarget->hasSMulHi())
4917 return SDValue();
4918
4919 SelectionDAG &DAG = DCI.DAG;
4920 SDLoc DL(N);
4921
4922 SDValue N0 = N->getOperand(0);
4923 SDValue N1 = N->getOperand(1);
4924
4925 if (!isU24(N0, DAG) || !isU24(N1, DAG))
4926 return SDValue();
4927
4928 N0 = DAG.getZExtOrTrunc(N0, DL, MVT::i32);
4929 N1 = DAG.getZExtOrTrunc(N1, DL, MVT::i32);
4930
4931 SDValue Mulhi = DAG.getNode(AMDGPUISD::MULHI_U24, DL, MVT::i32, N0, N1);
4932 DCI.AddToWorklist(Mulhi.getNode());
4933 return DAG.getZExtOrTrunc(Mulhi, DL, VT);
4934}
4935
4936SDValue AMDGPUTargetLowering::getFFBX_U32(SelectionDAG &DAG,
4937 SDValue Op,
4938 const SDLoc &DL,
4939 unsigned Opc) const {
4940 EVT VT = Op.getValueType();
4941 if (VT.bitsGT(MVT::i32))
4942 return SDValue();
4943
4944 if (VT != MVT::i32)
4945 Op = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i32, Op);
4946
4947 SDValue FFBX = DAG.getNode(Opc, DL, MVT::i32, Op);
4948 if (VT != MVT::i32)
4949 FFBX = DAG.getNode(ISD::TRUNCATE, DL, VT, FFBX);
4950
4951 return FFBX;
4952}
4953
4954// The native instructions return -1 on 0 input. Optimize out a select that
4955// produces -1 on 0.
4956//
4957// TODO: If zero is not undef, we could also do this if the output is compared
4958// against the bitwidth.
4959//
4960// TODO: Should probably combine against FFBH_U32 instead of ctlz directly.
4962 SDValue LHS, SDValue RHS,
4963 DAGCombinerInfo &DCI) const {
4964 if (!isNullConstant(Cond.getOperand(1)))
4965 return SDValue();
4966
4967 SelectionDAG &DAG = DCI.DAG;
4968 ISD::CondCode CCOpcode = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
4969 SDValue CmpLHS = Cond.getOperand(0);
4970
4971 // select (setcc x, 0, eq), -1, (ctlz_zero_poison x) -> ffbh_u32 x
4972 // select (setcc x, 0, eq), -1, (cttz_zero_poison x) -> ffbl_u32 x
4973 if (CCOpcode == ISD::SETEQ &&
4974 (isCtlzOpc(RHS.getOpcode()) || isCttzOpc(RHS.getOpcode())) &&
4975 RHS.getOperand(0) == CmpLHS && isAllOnesConstant(LHS)) {
4976 unsigned Opc =
4977 isCttzOpc(RHS.getOpcode()) ? AMDGPUISD::FFBL_B32 : AMDGPUISD::FFBH_U32;
4978 return getFFBX_U32(DAG, CmpLHS, SL, Opc);
4979 }
4980
4981 // select (setcc x, 0, ne), (ctlz_zero_poison x), -1 -> ffbh_u32 x
4982 // select (setcc x, 0, ne), (cttz_zero_poison x), -1 -> ffbl_u32 x
4983 if (CCOpcode == ISD::SETNE &&
4984 (isCtlzOpc(LHS.getOpcode()) || isCttzOpc(LHS.getOpcode())) &&
4985 LHS.getOperand(0) == CmpLHS && isAllOnesConstant(RHS)) {
4986 unsigned Opc =
4987 isCttzOpc(LHS.getOpcode()) ? AMDGPUISD::FFBL_B32 : AMDGPUISD::FFBH_U32;
4988
4989 return getFFBX_U32(DAG, CmpLHS, SL, Opc);
4990 }
4991
4992 return SDValue();
4993}
4994
4996 unsigned Op,
4997 const SDLoc &SL,
4998 SDValue Cond,
4999 SDValue N1,
5000 SDValue N2) {
5001 SelectionDAG &DAG = DCI.DAG;
5002 EVT VT = N1.getValueType();
5003
5004 SDValue NewSelect = DAG.getNode(ISD::SELECT, SL, VT, Cond,
5005 N1.getOperand(0), N2.getOperand(0));
5006 DCI.AddToWorklist(NewSelect.getNode());
5007 return DAG.getNode(Op, SL, VT, NewSelect);
5008}
5009
5010// Pull a free FP operation out of a select so it may fold into uses.
5011//
5012// select c, (fneg x), (fneg y) -> fneg (select c, x, y)
5013// select c, (fneg x), k -> fneg (select c, x, (fneg k))
5014//
5015// select c, (fabs x), (fabs y) -> fabs (select c, x, y)
5016// select c, (fabs x), +k -> fabs (select c, x, k)
5017SDValue
5019 SDValue N) const {
5020 SelectionDAG &DAG = DCI.DAG;
5021 SDValue Cond = N.getOperand(0);
5022 SDValue LHS = N.getOperand(1);
5023 SDValue RHS = N.getOperand(2);
5024
5025 EVT VT = N.getValueType();
5026 if ((LHS.getOpcode() == ISD::FABS && RHS.getOpcode() == ISD::FABS) ||
5027 (LHS.getOpcode() == ISD::FNEG && RHS.getOpcode() == ISD::FNEG)) {
5029 return SDValue();
5030
5031 return distributeOpThroughSelect(DCI, LHS.getOpcode(),
5032 SDLoc(N), Cond, LHS, RHS);
5033 }
5034
5035 bool Inv = false;
5036 if (RHS.getOpcode() == ISD::FABS || RHS.getOpcode() == ISD::FNEG) {
5037 std::swap(LHS, RHS);
5038 Inv = true;
5039 }
5040
5041 // TODO: Support vector constants.
5043 if ((LHS.getOpcode() == ISD::FNEG || LHS.getOpcode() == ISD::FABS) && CRHS &&
5044 !selectSupportsSourceMods(N.getNode())) {
5045 SDLoc SL(N);
5046 // If one side is an fneg/fabs and the other is a constant, we can push the
5047 // fneg/fabs down. If it's an fabs, the constant needs to be non-negative.
5048 SDValue NewLHS = LHS.getOperand(0);
5049 SDValue NewRHS = RHS;
5050
5051 // Careful: if the neg can be folded up, don't try to pull it back down.
5052 bool ShouldFoldNeg = true;
5053
5054 if (NewLHS.hasOneUse()) {
5055 unsigned Opc = NewLHS.getOpcode();
5056 if (LHS.getOpcode() == ISD::FNEG && fnegFoldsIntoOp(NewLHS.getNode()))
5057 ShouldFoldNeg = false;
5058 if (LHS.getOpcode() == ISD::FABS && Opc == ISD::FMUL)
5059 ShouldFoldNeg = false;
5060 }
5061
5062 if (ShouldFoldNeg) {
5063 if (LHS.getOpcode() == ISD::FABS && CRHS->isNegative())
5064 return SDValue();
5065
5066 // We're going to be forced to use a source modifier anyway, there's no
5067 // point to pulling the negate out unless we can get a size reduction by
5068 // negating the constant.
5069 //
5070 // TODO: Generalize to use getCheaperNegatedExpression which doesn't know
5071 // about cheaper constants.
5072 if (NewLHS.getOpcode() == ISD::FABS &&
5074 return SDValue();
5075
5077 return SDValue();
5078
5079 if (LHS.getOpcode() == ISD::FNEG)
5080 NewRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
5081
5082 if (Inv)
5083 std::swap(NewLHS, NewRHS);
5084
5085 SDValue NewSelect = DAG.getNode(ISD::SELECT, SL, VT,
5086 Cond, NewLHS, NewRHS);
5087 DCI.AddToWorklist(NewSelect.getNode());
5088 return DAG.getNode(LHS.getOpcode(), SL, VT, NewSelect);
5089 }
5090 }
5091
5092 return SDValue();
5093}
5094
5096 DAGCombinerInfo &DCI) const {
5097 if (SDValue Folded = foldFreeOpFromSelect(DCI, SDValue(N, 0)))
5098 return Folded;
5099
5100 SDValue Cond = N->getOperand(0);
5101 if (Cond.getOpcode() != ISD::SETCC)
5102 return SDValue();
5103
5104 EVT VT = N->getValueType(0);
5105 SDValue LHS = Cond.getOperand(0);
5106 SDValue RHS = Cond.getOperand(1);
5107 SDValue CC = Cond.getOperand(2);
5108
5109 SDValue True = N->getOperand(1);
5110 SDValue False = N->getOperand(2);
5111
5112 if (Cond.hasOneUse()) { // TODO: Look for multiple select uses.
5113 SelectionDAG &DAG = DCI.DAG;
5114 if (DAG.isConstantValueOfAnyType(True) &&
5115 !DAG.isConstantValueOfAnyType(False)) {
5116 // Swap cmp + select pair to move constant to false input.
5117 // This will allow using VOPC cndmasks more often.
5118 // select (setcc x, y), k, x -> select (setccinv x, y), x, k
5119
5120 SDLoc SL(N);
5121 ISD::CondCode NewCC =
5122 getSetCCInverse(cast<CondCodeSDNode>(CC)->get(), LHS.getValueType());
5123
5124 SDValue NewCond = DAG.getSetCC(SL, Cond.getValueType(), LHS, RHS, NewCC);
5125 return DAG.getNode(ISD::SELECT, SL, VT, NewCond, False, True);
5126 }
5127
5128 if (VT == MVT::f32 && Subtarget->hasFminFmaxLegacy()) {
5129 SDValue MinMax = combineFMinMaxLegacy(SDLoc(N), VT, LHS, RHS, True, False,
5130 CC, N->getFlags(), DCI);
5131 // Revisit this node so we can catch min3/max3/med3 patterns.
5132 //DCI.AddToWorklist(MinMax.getNode());
5133 return MinMax;
5134 }
5135 }
5136
5137 // There's no reason to not do this if the condition has other uses.
5138 return performCtlz_CttzCombine(SDLoc(N), Cond, True, False, DCI);
5139}
5140
5141static bool isInv2Pi(const APFloat &APF) {
5142 static const APFloat KF16(APFloat::IEEEhalf(), APInt(16, 0x3118));
5143 static const APFloat KF32(APFloat::IEEEsingle(), APInt(32, 0x3e22f983));
5144 static const APFloat KF64(APFloat::IEEEdouble(), APInt(64, 0x3fc45f306dc9c882));
5145
5146 return APF.bitwiseIsEqual(KF16) ||
5147 APF.bitwiseIsEqual(KF32) ||
5148 APF.bitwiseIsEqual(KF64);
5149}
5150
5151// 0 and 1.0 / (0.5 * pi) do not have inline immmediates, so there is an
5152// additional cost to negate them.
5155 if (C->isZero())
5156 return C->isNegative() ? NegatibleCost::Cheaper : NegatibleCost::Expensive;
5157
5158 if (Subtarget->hasInv2PiInlineImm() && isInv2Pi(C->getValueAPF()))
5159 return C->isNegative() ? NegatibleCost::Cheaper : NegatibleCost::Expensive;
5160
5162}
5163
5169
5175
5176static unsigned inverseMinMax(unsigned Opc) {
5177 switch (Opc) {
5178 case ISD::FMAXNUM:
5179 return ISD::FMINNUM;
5180 case ISD::FMINNUM:
5181 return ISD::FMAXNUM;
5182 case ISD::FMAXNUM_IEEE:
5183 return ISD::FMINNUM_IEEE;
5184 case ISD::FMINNUM_IEEE:
5185 return ISD::FMAXNUM_IEEE;
5186 case ISD::FMAXIMUM:
5187 return ISD::FMINIMUM;
5188 case ISD::FMINIMUM:
5189 return ISD::FMAXIMUM;
5190 case ISD::FMAXIMUMNUM:
5191 return ISD::FMINIMUMNUM;
5192 case ISD::FMINIMUMNUM:
5193 return ISD::FMAXIMUMNUM;
5194 case AMDGPUISD::FMAX_LEGACY:
5195 return AMDGPUISD::FMIN_LEGACY;
5196 case AMDGPUISD::FMIN_LEGACY:
5197 return AMDGPUISD::FMAX_LEGACY;
5198 default:
5199 llvm_unreachable("invalid min/max opcode");
5200 }
5201}
5202
5203/// \return true if it's profitable to try to push an fneg into its source
5204/// instruction.
5206 // If the input has multiple uses and we can either fold the negate down, or
5207 // the other uses cannot, give up. This both prevents unprofitable
5208 // transformations and infinite loops: we won't repeatedly try to fold around
5209 // a negate that has no 'good' form.
5210 if (N0.hasOneUse()) {
5211 // This may be able to fold into the source, but at a code size cost. Don't
5212 // fold if the fold into the user is free.
5213 if (allUsesHaveSourceMods(N, 0))
5214 return false;
5215 } else {
5216 if (fnegFoldsIntoOp(N0.getNode()) &&
5218 return false;
5219 }
5220
5221 return true;
5222}
5223
5225 DAGCombinerInfo &DCI) const {
5226 SelectionDAG &DAG = DCI.DAG;
5227 SDValue N0 = N->getOperand(0);
5228 EVT VT = N->getValueType(0);
5229
5230 unsigned Opc = N0.getOpcode();
5231
5232 if (!shouldFoldFNegIntoSrc(N, N0))
5233 return SDValue();
5234
5235 SDLoc SL(N);
5236 switch (Opc) {
5237 case ISD::FADD: {
5238 if (!N0->getFlags().hasNoSignedZeros() && !N->getFlags().hasNoSignedZeros())
5239 return SDValue();
5240
5241 // (fneg (fadd x, y)) -> (fadd (fneg x), (fneg y))
5242 SDValue LHS = N0.getOperand(0);
5243 SDValue RHS = N0.getOperand(1);
5244
5245 if (LHS.getOpcode() != ISD::FNEG)
5246 LHS = DAG.getNode(ISD::FNEG, SL, VT, LHS);
5247 else
5248 LHS = LHS.getOperand(0);
5249
5250 if (RHS.getOpcode() != ISD::FNEG)
5251 RHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
5252 else
5253 RHS = RHS.getOperand(0);
5254
5255 SDValue Res = DAG.getNode(ISD::FADD, SL, VT, LHS, RHS, N0->getFlags());
5256 if (Res.getOpcode() != ISD::FADD)
5257 return SDValue(); // Op got folded away.
5258 if (!N0.hasOneUse())
5259 DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Res));
5260 return Res;
5261 }
5262 case ISD::FMUL:
5263 case AMDGPUISD::FMUL_LEGACY: {
5264 // (fneg (fmul x, y)) -> (fmul x, (fneg y))
5265 // (fneg (fmul_legacy x, y)) -> (fmul_legacy x, (fneg y))
5266 SDValue LHS = N0.getOperand(0);
5267 SDValue RHS = N0.getOperand(1);
5268
5269 if (LHS.getOpcode() == ISD::FNEG)
5270 LHS = LHS.getOperand(0);
5271 else if (RHS.getOpcode() == ISD::FNEG)
5272 RHS = RHS.getOperand(0);
5273 else
5274 RHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
5275
5276 SDValue Res = DAG.getNode(Opc, SL, VT, LHS, RHS, N0->getFlags());
5277 if (Res.getOpcode() != Opc)
5278 return SDValue(); // Op got folded away.
5279 if (!N0.hasOneUse())
5280 DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Res));
5281 return Res;
5282 }
5283 case ISD::FMA:
5284 case ISD::FMAD: {
5285 // TODO: handle llvm.amdgcn.fma.legacy
5286 if (!N0->getFlags().hasNoSignedZeros() && !N->getFlags().hasNoSignedZeros())
5287 return SDValue();
5288
5289 // (fneg (fma x, y, z)) -> (fma x, (fneg y), (fneg z))
5290 SDValue LHS = N0.getOperand(0);
5291 SDValue MHS = N0.getOperand(1);
5292 SDValue RHS = N0.getOperand(2);
5293
5294 if (LHS.getOpcode() == ISD::FNEG)
5295 LHS = LHS.getOperand(0);
5296 else if (MHS.getOpcode() == ISD::FNEG)
5297 MHS = MHS.getOperand(0);
5298 else
5299 MHS = DAG.getNode(ISD::FNEG, SL, VT, MHS);
5300
5301 if (RHS.getOpcode() != ISD::FNEG)
5302 RHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
5303 else
5304 RHS = RHS.getOperand(0);
5305
5306 SDValue Res = DAG.getNode(Opc, SL, VT, LHS, MHS, RHS);
5307 if (Res.getOpcode() != Opc)
5308 return SDValue(); // Op got folded away.
5309 if (!N0.hasOneUse())
5310 DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Res));
5311 return Res;
5312 }
5313 case ISD::FMAXNUM:
5314 case ISD::FMINNUM:
5315 case ISD::FMAXNUM_IEEE:
5316 case ISD::FMINNUM_IEEE:
5317 case ISD::FMINIMUM:
5318 case ISD::FMAXIMUM:
5319 case ISD::FMINIMUMNUM:
5320 case ISD::FMAXIMUMNUM:
5321 case AMDGPUISD::FMAX_LEGACY:
5322 case AMDGPUISD::FMIN_LEGACY: {
5323 // fneg (fmaxnum x, y) -> fminnum (fneg x), (fneg y)
5324 // fneg (fminnum x, y) -> fmaxnum (fneg x), (fneg y)
5325 // fneg (fmax_legacy x, y) -> fmin_legacy (fneg x), (fneg y)
5326 // fneg (fmin_legacy x, y) -> fmax_legacy (fneg x), (fneg y)
5327
5328 SDValue LHS = N0.getOperand(0);
5329 SDValue RHS = N0.getOperand(1);
5330
5331 // 0 doesn't have a negated inline immediate.
5332 // TODO: This constant check should be generalized to other operations.
5334 return SDValue();
5335
5336 // Swapping min<->max flips which operand a signed zero tie selects.
5337 if ((Opc == AMDGPUISD::FMIN_LEGACY || Opc == AMDGPUISD::FMAX_LEGACY) &&
5338 !canIgnoreLegacyMinMaxTies(DAG, N0->getFlags(), LHS, RHS))
5339 return SDValue();
5340
5341 SDValue NegLHS = DAG.getNode(ISD::FNEG, SL, VT, LHS);
5342 SDValue NegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
5343 unsigned Opposite = inverseMinMax(Opc);
5344
5345 SDValue Res = DAG.getNode(Opposite, SL, VT, NegLHS, NegRHS, N0->getFlags());
5346 if (Res.getOpcode() != Opposite)
5347 return SDValue(); // Op got folded away.
5348 if (!N0.hasOneUse())
5349 DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Res));
5350 return Res;
5351 }
5352 case AMDGPUISD::FMED3: {
5353 // med3 sorts a NaN input as smaller than everything regardless of its sign,
5354 // so negating all operands does not sign-flip the median when an input may
5355 // be NaN.
5356 if (!N0->getFlags().hasNoNaNs())
5357 return SDValue();
5358
5359 SDValue Ops[3];
5360 for (unsigned I = 0; I < 3; ++I)
5361 Ops[I] = DAG.getNode(ISD::FNEG, SL, VT, N0->getOperand(I), N0->getFlags());
5362
5363 SDValue Res = DAG.getNode(AMDGPUISD::FMED3, SL, VT, Ops, N0->getFlags());
5364 if (Res.getOpcode() != AMDGPUISD::FMED3)
5365 return SDValue(); // Op got folded away.
5366
5367 if (!N0.hasOneUse()) {
5368 SDValue Neg = DAG.getNode(ISD::FNEG, SL, VT, Res);
5369 DAG.ReplaceAllUsesWith(N0, Neg);
5370
5371 for (SDNode *U : Neg->users())
5372 DCI.AddToWorklist(U);
5373 }
5374
5375 return Res;
5376 }
5377 case ISD::FP_EXTEND:
5378 case ISD::FTRUNC:
5379 case ISD::FRINT:
5380 case ISD::FNEARBYINT: // XXX - Should fround be handled?
5381 case ISD::FROUNDEVEN:
5382 case ISD::FSIN:
5383 case ISD::FCANONICALIZE:
5384 case AMDGPUISD::RCP:
5385 case AMDGPUISD::RCP_LEGACY:
5386 case AMDGPUISD::RCP_IFLAG:
5387 case AMDGPUISD::SIN_HW: {
5388 SDValue CvtSrc = N0.getOperand(0);
5389 if (CvtSrc.getOpcode() == ISD::FNEG) {
5390 // (fneg (fp_extend (fneg x))) -> (fp_extend x)
5391 // (fneg (rcp (fneg x))) -> (rcp x)
5392 return DAG.getNode(Opc, SL, VT, CvtSrc.getOperand(0));
5393 }
5394
5395 if (!N0.hasOneUse())
5396 return SDValue();
5397
5398 // (fneg (fp_extend x)) -> (fp_extend (fneg x))
5399 // (fneg (rcp x)) -> (rcp (fneg x))
5400 SDValue Neg = DAG.getNode(ISD::FNEG, SL, CvtSrc.getValueType(), CvtSrc);
5401 return DAG.getNode(Opc, SL, VT, Neg, N0->getFlags());
5402 }
5403 case ISD::FP_ROUND: {
5404 SDValue CvtSrc = N0.getOperand(0);
5405
5406 if (CvtSrc.getOpcode() == ISD::FNEG) {
5407 // (fneg (fp_round (fneg x))) -> (fp_round x)
5408 return DAG.getNode(ISD::FP_ROUND, SL, VT,
5409 CvtSrc.getOperand(0), N0.getOperand(1));
5410 }
5411
5412 if (!N0.hasOneUse())
5413 return SDValue();
5414
5415 // (fneg (fp_round x)) -> (fp_round (fneg x))
5416 SDValue Neg = DAG.getNode(ISD::FNEG, SL, CvtSrc.getValueType(), CvtSrc);
5417 return DAG.getNode(ISD::FP_ROUND, SL, VT, Neg, N0.getOperand(1));
5418 }
5419 case ISD::FP16_TO_FP: {
5420 // v_cvt_f32_f16 supports source modifiers on pre-VI targets without legal
5421 // f16, but legalization of f16 fneg ends up pulling it out of the source.
5422 // Put the fneg back as a legal source operation that can be matched later.
5423 SDLoc SL(N);
5424
5425 SDValue Src = N0.getOperand(0);
5426 EVT SrcVT = Src.getValueType();
5427
5428 // fneg (fp16_to_fp x) -> fp16_to_fp (xor x, 0x8000)
5429 SDValue IntFNeg = DAG.getNode(ISD::XOR, SL, SrcVT, Src,
5430 DAG.getConstant(0x8000, SL, SrcVT));
5431 return DAG.getNode(ISD::FP16_TO_FP, SL, N->getValueType(0), IntFNeg);
5432 }
5433 case ISD::SELECT: {
5434 // fneg (select c, a, b) -> select c, (fneg a), (fneg b)
5435 // TODO: Invert conditions of foldFreeOpFromSelect
5436 return SDValue();
5437 }
5438 case ISD::BITCAST: {
5439 SDLoc SL(N);
5440 SDValue BCSrc = N0.getOperand(0);
5441 if (BCSrc.getOpcode() == ISD::BUILD_VECTOR) {
5442 SDValue HighBits = BCSrc.getOperand(BCSrc.getNumOperands() - 1);
5443 if (VT != MVT::f64 || HighBits.getValueType().getSizeInBits() != 32 ||
5444 !fnegFoldsIntoOp(HighBits.getNode()))
5445 return SDValue();
5446
5447 // f64 fneg only really needs to operate on the high half of of the
5448 // register, so try to force it to an f32 operation to help make use of
5449 // source modifiers.
5450 //
5451 //
5452 // fneg (f64 (bitcast (build_vector x, y))) ->
5453 // f64 (bitcast (build_vector (bitcast i32:x to f32),
5454 // (fneg (bitcast i32:y to f32)))
5455
5456 SDValue CastHi = DAG.getNode(ISD::BITCAST, SL, MVT::f32, HighBits);
5457 SDValue NegHi = DAG.getNode(ISD::FNEG, SL, MVT::f32, CastHi);
5458 SDValue CastBack =
5459 DAG.getNode(ISD::BITCAST, SL, HighBits.getValueType(), NegHi);
5460
5462 Ops.back() = CastBack;
5463 DCI.AddToWorklist(NegHi.getNode());
5464 SDValue Build =
5465 DAG.getNode(ISD::BUILD_VECTOR, SL, BCSrc.getValueType(), Ops);
5466 SDValue Result = DAG.getNode(ISD::BITCAST, SL, VT, Build);
5467
5468 if (!N0.hasOneUse())
5469 DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Result));
5470 return Result;
5471 }
5472
5473 if (BCSrc.getOpcode() == ISD::SELECT && VT == MVT::f32 &&
5474 BCSrc.hasOneUse()) {
5475 // fneg (bitcast (f32 (select cond, i32:lhs, i32:rhs))) ->
5476 // select cond, (bitcast i32:lhs to f32), (bitcast i32:rhs to f32)
5477
5478 // TODO: Cast back result for multiple uses is beneficial in some cases.
5479
5480 SDValue LHS =
5481 DAG.getNode(ISD::BITCAST, SL, MVT::f32, BCSrc.getOperand(1));
5482 SDValue RHS =
5483 DAG.getNode(ISD::BITCAST, SL, MVT::f32, BCSrc.getOperand(2));
5484
5485 SDValue NegLHS = DAG.getNode(ISD::FNEG, SL, MVT::f32, LHS);
5486 SDValue NegRHS = DAG.getNode(ISD::FNEG, SL, MVT::f32, RHS);
5487
5488 return DAG.getNode(ISD::SELECT, SL, MVT::f32, BCSrc.getOperand(0), NegLHS,
5489 NegRHS);
5490 }
5491
5492 return SDValue();
5493 }
5494 default:
5495 return SDValue();
5496 }
5497}
5498
5500 DAGCombinerInfo &DCI) const {
5501 SelectionDAG &DAG = DCI.DAG;
5502 SDValue N0 = N->getOperand(0);
5503
5504 if (!N0.hasOneUse())
5505 return SDValue();
5506
5507 switch (N0.getOpcode()) {
5508 case ISD::FP16_TO_FP: {
5509 assert(!isTypeLegal(MVT::f16) && "should only see if f16 is illegal");
5510 SDLoc SL(N);
5511 SDValue Src = N0.getOperand(0);
5512 EVT SrcVT = Src.getValueType();
5513
5514 // fabs (fp16_to_fp x) -> fp16_to_fp (and x, 0x7fff)
5515 SDValue IntFAbs = DAG.getNode(ISD::AND, SL, SrcVT, Src,
5516 DAG.getConstant(0x7fff, SL, SrcVT));
5517 return DAG.getNode(ISD::FP16_TO_FP, SL, N->getValueType(0), IntFAbs);
5518 }
5519 case ISD::FP_ROUND: {
5520 SDLoc SL(N);
5521 SDValue CvtSrc = N0.getOperand(0);
5522
5523 // fabs (fp_round x) -> fp_round (fabs x)
5524 SDValue Abs = DAG.getNode(ISD::FABS, SL, CvtSrc.getValueType(), CvtSrc,
5525 N->getFlags());
5526 return DAG.getNode(ISD::FP_ROUND, SL, N->getValueType(0), Abs,
5527 N0.getOperand(1), N0->getFlags());
5528 }
5529 default:
5530 return SDValue();
5531 }
5532}
5533
5535 DAGCombinerInfo &DCI) const {
5536 const auto *CFP = dyn_cast<ConstantFPSDNode>(N->getOperand(0));
5537 if (!CFP)
5538 return SDValue();
5539
5540 std::optional<APFloat> Result = AMDGPU::evaluateRcp(CFP->getValueAPF());
5541 if (!Result)
5542 return SDValue();
5543
5544 return DCI.DAG.getConstantFP(*Result, SDLoc(N), N->getValueType(0));
5545}
5546
5548 if (!Subtarget->isGCN())
5549 return false;
5550
5553 auto &ST = DAG.getSubtarget<GCNSubtarget>();
5554 const auto *TII = ST.getInstrInfo();
5555
5556 if (!ST.hasVMovB64Inst() || (!SDConstant && !SDFPConstant))
5557 return false;
5558
5559 if (ST.has64BitLiterals())
5560 return true;
5561
5562 if (SDConstant) {
5563 const APInt &APVal = SDConstant->getAPIntValue();
5564 return isUInt<32>(APVal.getZExtValue()) || TII->isInlineConstant(APVal);
5565 }
5566
5567 APInt Val = SDFPConstant->getValueAPF().bitcastToAPInt();
5568 return isUInt<32>(Val.getZExtValue()) || TII->isInlineConstant(Val);
5569}
5570
5572 DAGCombinerInfo &DCI) const {
5573 SelectionDAG &DAG = DCI.DAG;
5574 SDLoc DL(N);
5575
5576 switch(N->getOpcode()) {
5577 default:
5578 break;
5579 case ISD::BITCAST: {
5580 EVT DestVT = N->getValueType(0);
5581
5582 // Push casts through vector builds. This helps avoid emitting a large
5583 // number of copies when materializing floating point vector constants.
5584 //
5585 // vNt1 bitcast (vNt0 (build_vector t0:x, t0:y)) =>
5586 // vnt1 = build_vector (t1 (bitcast t0:x)), (t1 (bitcast t0:y))
5587 if (DestVT.isVector()) {
5588 SDValue Src = N->getOperand(0);
5589 if (Src.getOpcode() == ISD::BUILD_VECTOR &&
5592 EVT SrcVT = Src.getValueType();
5593 unsigned NElts = DestVT.getVectorNumElements();
5594
5595 if (SrcVT.getVectorNumElements() == NElts) {
5596 EVT DestEltVT = DestVT.getVectorElementType();
5597
5598 SmallVector<SDValue, 8> CastedElts;
5599 SDLoc SL(N);
5600 for (unsigned I = 0, E = SrcVT.getVectorNumElements(); I != E; ++I) {
5601 SDValue Elt = Src.getOperand(I);
5602 CastedElts.push_back(DAG.getNode(ISD::BITCAST, DL, DestEltVT, Elt));
5603 }
5604
5605 return DAG.getBuildVector(DestVT, SL, CastedElts);
5606 }
5607 }
5608 }
5609
5610 if (DestVT.getSizeInBits() != 64 || !DestVT.isVector())
5611 break;
5612
5613 // Fold bitcasts of constants.
5614 //
5615 // v2i32 (bitcast i64:k) -> build_vector lo_32(k), hi_32(k)
5616 // TODO: Generalize and move to DAGCombiner
5617 SDValue Src = N->getOperand(0);
5619 SDLoc SL(N);
5620 if (isInt64ImmLegal(C, DAG))
5621 break;
5622 uint64_t CVal = C->getZExtValue();
5623 SDValue BV = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32,
5624 DAG.getConstant(Lo_32(CVal), SL, MVT::i32),
5625 DAG.getConstant(Hi_32(CVal), SL, MVT::i32));
5626 return DAG.getNode(ISD::BITCAST, SL, DestVT, BV);
5627 }
5628
5630 const APInt &Val = C->getValueAPF().bitcastToAPInt();
5631 SDLoc SL(N);
5632 if (isInt64ImmLegal(C, DAG))
5633 break;
5634 uint64_t CVal = Val.getZExtValue();
5635 SDValue Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32,
5636 DAG.getConstant(Lo_32(CVal), SL, MVT::i32),
5637 DAG.getConstant(Hi_32(CVal), SL, MVT::i32));
5638
5639 return DAG.getNode(ISD::BITCAST, SL, DestVT, Vec);
5640 }
5641
5642 break;
5643 }
5644 case ISD::SHL:
5645 case ISD::SRA:
5646 case ISD::SRL: {
5647 // Range metadata can be invalidated when loads are converted to legal types
5648 // (e.g. v2i64 -> v4i32).
5649 // Try to convert vector shl/sra/srl before type legalization so that range
5650 // metadata can be utilized.
5651 if (!(N->getValueType(0).isVector() &&
5654 break;
5655 if (N->getOpcode() == ISD::SHL)
5656 return performShlCombine(N, DCI);
5657 if (N->getOpcode() == ISD::SRA)
5658 return performSraCombine(N, DCI);
5659 return performSrlCombine(N, DCI);
5660 }
5661 case ISD::TRUNCATE:
5662 return performTruncateCombine(N, DCI);
5663 case ISD::MUL:
5664 return performMulCombine(N, DCI);
5665 case AMDGPUISD::MUL_U24:
5666 case AMDGPUISD::MUL_I24: {
5667 if (SDValue Simplified = simplifyMul24(N, DCI))
5668 return Simplified;
5669 break;
5670 }
5671 case AMDGPUISD::MULHI_I24:
5672 case AMDGPUISD::MULHI_U24:
5673 return simplifyMul24(N, DCI);
5674 case ISD::SMUL_LOHI:
5675 case ISD::UMUL_LOHI:
5676 return performMulLoHiCombine(N, DCI);
5677 case ISD::MULHS:
5678 return performMulhsCombine(N, DCI);
5679 case ISD::MULHU:
5680 return performMulhuCombine(N, DCI);
5681 case ISD::SELECT:
5682 return performSelectCombine(N, DCI);
5683 case ISD::FNEG:
5684 return performFNegCombine(N, DCI);
5685 case ISD::FABS:
5686 return performFAbsCombine(N, DCI);
5687 case AMDGPUISD::BFE_I32:
5688 case AMDGPUISD::BFE_U32: {
5689 assert(N->getValueType(0) == MVT::i32 &&
5690 "BFE_I32/BFE_U32 is a 32-bit operation");
5691 ConstantSDNode *Width = dyn_cast<ConstantSDNode>(N->getOperand(2));
5692 if (!Width)
5693 break;
5694
5695 uint32_t WidthVal = Width->getZExtValue() & 0x1f;
5696 if (WidthVal == 0)
5697 return DAG.getConstant(0, DL, MVT::i32);
5698
5700 if (!Offset)
5701 break;
5702
5703 SDValue BitsFrom = N->getOperand(0);
5704 uint32_t OffsetVal = Offset->getZExtValue() & 0x1f;
5705
5706 bool Signed = N->getOpcode() == AMDGPUISD::BFE_I32;
5707
5708 if (OffsetVal == 0) {
5709 // This is already sign / zero extended, so try to fold away extra BFEs.
5710 EVT SmallVT = EVT::getIntegerVT(*DAG.getContext(), WidthVal);
5711 if (Signed) {
5712 if (DAG.ComputeNumSignBits(BitsFrom) >= 32 - WidthVal + 1)
5713 return BitsFrom;
5714
5715 // This is a sign_extend_inreg. Replace it to take advantage of existing
5716 // DAG Combines. If not eliminated, we will match back to BFE during
5717 // selection.
5718
5719 // TODO: The sext_inreg of extended types ends, although we can could
5720 // handle them in a single BFE.
5721 return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i32, BitsFrom,
5722 DAG.getValueType(SmallVT));
5723 }
5724
5725 if (DAG.MaskedValueIsZero(BitsFrom,
5726 APInt::getHighBitsSet(32, 32 - WidthVal)))
5727 return BitsFrom;
5728
5729 return DAG.getZeroExtendInReg(BitsFrom, DL, SmallVT);
5730 }
5731
5732 if (ConstantSDNode *CVal = dyn_cast<ConstantSDNode>(BitsFrom)) {
5733 if (Signed) {
5734 return constantFoldBFE<int32_t>(DAG,
5735 CVal->getSExtValue(),
5736 OffsetVal,
5737 WidthVal,
5738 DL);
5739 }
5740
5741 return constantFoldBFE<uint32_t>(DAG,
5742 CVal->getZExtValue(),
5743 OffsetVal,
5744 WidthVal,
5745 DL);
5746 }
5747
5748 if ((OffsetVal + WidthVal) >= 32 &&
5749 !(OffsetVal == 16 && WidthVal == 16 && Subtarget->hasSDWA())) {
5750 SDValue ShiftVal = DAG.getConstant(OffsetVal, DL, MVT::i32);
5751 return DAG.getNode(Signed ? ISD::SRA : ISD::SRL, DL, MVT::i32,
5752 BitsFrom, ShiftVal);
5753 }
5754
5755 if (BitsFrom.hasOneUse()) {
5756 APInt Demanded = APInt::getBitsSet(32,
5757 OffsetVal,
5758 OffsetVal + WidthVal);
5759
5762 !DCI.isBeforeLegalizeOps());
5763 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
5764 if (TLI.ShrinkDemandedConstant(BitsFrom, Demanded, TLO) ||
5765 TLI.SimplifyDemandedBits(BitsFrom, Demanded, Known, TLO)) {
5766 DCI.CommitTargetLoweringOpt(TLO);
5767 }
5768 }
5769
5770 break;
5771 }
5772 case ISD::LOAD:
5773 return performLoadCombine(N, DCI);
5774 case ISD::STORE:
5775 return performStoreCombine(N, DCI);
5776 case AMDGPUISD::RCP:
5777 case AMDGPUISD::RCP_IFLAG:
5778 return performRcpCombine(N, DCI);
5779 case ISD::AssertZext:
5780 case ISD::AssertSext:
5781 return performAssertSZExtCombine(N, DCI);
5783 return performIntrinsicWOChainCombine(N, DCI);
5784 case AMDGPUISD::FMAD_FTZ: {
5785 SDValue N0 = N->getOperand(0);
5786 SDValue N1 = N->getOperand(1);
5787 SDValue N2 = N->getOperand(2);
5788 EVT VT = N->getValueType(0);
5789
5790 // FMAD_FTZ is a FMAD + flush denormals to zero.
5791 // We flush the inputs, the intermediate step, and the output.
5795 if (N0CFP && N1CFP && N2CFP) {
5796 const auto FTZ = [](const APFloat &V) {
5797 if (V.isDenormal()) {
5798 APFloat Zero(V.getSemantics(), 0);
5799 return V.isNegative() ? -Zero : Zero;
5800 }
5801 return V;
5802 };
5803
5804 APFloat V0 = FTZ(N0CFP->getValueAPF());
5805 APFloat V1 = FTZ(N1CFP->getValueAPF());
5806 APFloat V2 = FTZ(N2CFP->getValueAPF());
5808 V0 = FTZ(V0);
5810 return DAG.getConstantFP(FTZ(V0), DL, VT);
5811 }
5812 break;
5813 }
5814 }
5815 return SDValue();
5816}
5817
5819 SDValue Op, const APInt &OriginalDemandedBits,
5820 const APInt &OriginalDemandedElts, KnownBits &Known, TargetLoweringOpt &TLO,
5821 unsigned Depth) const {
5822 switch (Op.getOpcode()) {
5824 switch (Op.getConstantOperandVal(0)) {
5825 case Intrinsic::amdgcn_readfirstlane:
5826 case Intrinsic::amdgcn_readlane:
5827 case Intrinsic::amdgcn_wwm: {
5828 if (SimplifyDemandedBits(Op.getOperand(1), OriginalDemandedBits,
5829 OriginalDemandedElts, Known, TLO, Depth + 1))
5830 return true;
5831 break;
5832 }
5833 case Intrinsic::amdgcn_set_inactive:
5834 case Intrinsic::amdgcn_set_inactive_chain_arg: {
5835 // The result is operand 1 in active lanes and operand 2 in inactive
5836 // lanes, so the known bits are the intersection of both operands.
5837 KnownBits KnownValue, KnownInactive;
5838 if (SimplifyDemandedBits(Op.getOperand(1), OriginalDemandedBits,
5839 OriginalDemandedElts, KnownValue, TLO,
5840 Depth + 1))
5841 return true;
5842 if (SimplifyDemandedBits(Op.getOperand(2), OriginalDemandedBits,
5843 OriginalDemandedElts, KnownInactive, TLO,
5844 Depth + 1))
5845 return true;
5846 Known = KnownValue.intersectWith(KnownInactive);
5847 break;
5848 }
5849 default:
5850 break;
5851 }
5852 break;
5853 }
5854 default:
5855 break;
5856 }
5857
5858 return false;
5859}
5860
5861//===----------------------------------------------------------------------===//
5862// Helper functions
5863//===----------------------------------------------------------------------===//
5864
5866 const TargetRegisterClass *RC,
5867 Register Reg, EVT VT,
5868 const SDLoc &SL,
5869 bool RawReg) const {
5871 MachineRegisterInfo &MRI = MF.getRegInfo();
5872 Register VReg;
5873
5874 if (!MRI.isLiveIn(Reg)) {
5875 VReg = MRI.createVirtualRegister(RC);
5876 MRI.addLiveIn(Reg, VReg);
5877 } else {
5878 VReg = MRI.getLiveInVirtReg(Reg);
5879 }
5880
5881 if (RawReg)
5882 return DAG.getRegister(VReg, VT);
5883
5884 return DAG.getCopyFromReg(DAG.getEntryNode(), SL, VReg, VT);
5885}
5886
5887// This may be called multiple times, and nothing prevents creating multiple
5888// objects at the same offset. See if we already defined this object.
5890 int64_t Offset) {
5891 for (int I = MFI.getObjectIndexBegin(); I < 0; ++I) {
5892 if (MFI.getObjectOffset(I) == Offset) {
5893 assert(MFI.getObjectSize(I) == Size);
5894 return I;
5895 }
5896 }
5897
5898 return MFI.CreateFixedObject(Size, Offset, true);
5899}
5900
5902 EVT VT,
5903 const SDLoc &SL,
5904 int64_t Offset) const {
5906 MachineFrameInfo &MFI = MF.getFrameInfo();
5907 int FI = getOrCreateFixedStackObject(MFI, VT.getStoreSize(), Offset);
5908
5909 auto SrcPtrInfo = MachinePointerInfo::getStack(MF, Offset);
5910 SDValue Ptr = DAG.getFrameIndex(FI, MVT::i32);
5911
5912 return DAG.getLoad(VT, SL, DAG.getEntryNode(), Ptr, SrcPtrInfo, Align(4),
5915}
5916
5918 const SDLoc &SL,
5919 SDValue Chain,
5920 SDValue ArgVal,
5921 int64_t Offset) const {
5925
5926 SDValue Ptr = DAG.getConstant(Offset, SL, MVT::i32);
5927 // Stores to the argument stack area are relative to the stack pointer.
5928 SDValue SP =
5929 DAG.getCopyFromReg(Chain, SL, Info->getStackPtrOffsetReg(), MVT::i32);
5930 Ptr = DAG.getNode(ISD::ADD, SL, MVT::i32, SP, Ptr);
5931 SDValue Store = DAG.getStore(Chain, SL, ArgVal, Ptr, DstInfo, Align(4),
5933 return Store;
5934}
5935
5937 const TargetRegisterClass *RC,
5938 EVT VT, const SDLoc &SL,
5939 const ArgDescriptor &Arg) const {
5940 assert(Arg && "Attempting to load missing argument");
5941
5942 SDValue V = Arg.isRegister() ?
5943 CreateLiveInRegister(DAG, RC, Arg.getRegister(), VT, SL) :
5944 loadStackInputValue(DAG, VT, SL, Arg.getStackOffset());
5945
5946 if (!Arg.isMasked())
5947 return V;
5948
5949 unsigned Mask = Arg.getMask();
5950 unsigned Shift = llvm::countr_zero<unsigned>(Mask);
5951 V = DAG.getNode(ISD::SRL, SL, VT, V,
5952 DAG.getShiftAmountConstant(Shift, VT, SL));
5953 return DAG.getNode(ISD::AND, SL, VT, V,
5954 DAG.getConstant(Mask >> Shift, SL, VT));
5955}
5956
5958 uint64_t ExplicitKernArgSize, const ImplicitParameter Param) const {
5959 unsigned ExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();
5960 const Align Alignment = Subtarget->getAlignmentForImplicitArgPtr();
5961 uint64_t ArgOffset =
5962 alignTo(ExplicitKernArgSize, Alignment) + ExplicitArgOffset;
5963 switch (Param) {
5964 case FIRST_IMPLICIT:
5965 return ArgOffset;
5966 case PRIVATE_BASE:
5968 case SHARED_BASE:
5969 return ArgOffset + AMDGPU::ImplicitArg::SHARED_BASE_OFFSET;
5970 case QUEUE_PTR:
5971 return ArgOffset + AMDGPU::ImplicitArg::QUEUE_PTR_OFFSET;
5972 }
5973 llvm_unreachable("unexpected implicit parameter type");
5974}
5975
5982
5984 SelectionDAG &DAG, int Enabled,
5985 int &RefinementSteps,
5986 bool &UseOneConstNR,
5987 bool Reciprocal) const {
5988 EVT VT = Operand.getValueType();
5989
5990 if (VT == MVT::f32) {
5991 RefinementSteps = 0;
5992 return DAG.getNode(AMDGPUISD::RSQ, SDLoc(Operand), VT, Operand);
5993 }
5994
5995 // TODO: There is also f64 rsq instruction, but the documentation is less
5996 // clear on its precision.
5997
5998 return SDValue();
5999}
6000
6002 SelectionDAG &DAG, int Enabled,
6003 int &RefinementSteps) const {
6004 EVT VT = Operand.getValueType();
6005
6006 if (VT == MVT::f32) {
6007 // Reciprocal, < 1 ulp error.
6008 //
6009 // This reciprocal approximation converges to < 0.5 ulp error with one
6010 // newton rhapson performed with two fused multiple adds (FMAs).
6011
6012 RefinementSteps = 0;
6013 return DAG.getNode(AMDGPUISD::RCP, SDLoc(Operand), VT, Operand);
6014 }
6015
6016 // TODO: There is also f64 rcp instruction, but the documentation is less
6017 // clear on its precision.
6018
6019 return SDValue();
6020}
6021
6022static unsigned workitemIntrinsicDim(unsigned ID) {
6023 switch (ID) {
6024 case Intrinsic::amdgcn_workitem_id_x:
6025 return 0;
6026 case Intrinsic::amdgcn_workitem_id_y:
6027 return 1;
6028 case Intrinsic::amdgcn_workitem_id_z:
6029 return 2;
6030 default:
6031 llvm_unreachable("not a workitem intrinsic");
6032 }
6033}
6034
6036 const SDValue Op, KnownBits &Known,
6037 const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const {
6038
6039 Known.resetAll(); // Don't know anything.
6040
6041 unsigned Opc = Op.getOpcode();
6042
6043 switch (Opc) {
6044 default:
6045 break;
6046 case AMDGPUISD::CARRY:
6047 case AMDGPUISD::BORROW: {
6048 Known.Zero = APInt::getHighBitsSet(32, 31);
6049 break;
6050 }
6051
6052 case AMDGPUISD::BFE_I32:
6053 case AMDGPUISD::BFE_U32: {
6054 ConstantSDNode *CWidth = dyn_cast<ConstantSDNode>(Op.getOperand(2));
6055 if (!CWidth)
6056 return;
6057
6058 uint32_t Width = CWidth->getZExtValue() & 0x1f;
6059
6060 if (Opc == AMDGPUISD::BFE_U32)
6061 Known.Zero = APInt::getHighBitsSet(32, 32 - Width);
6062
6063 break;
6064 }
6065 case AMDGPUISD::FP_TO_FP16: {
6066 unsigned BitWidth = Known.getBitWidth();
6067
6068 // High bits are zero.
6070 break;
6071 }
6072 case AMDGPUISD::MUL_U24:
6073 case AMDGPUISD::MUL_I24: {
6074 KnownBits LHSKnown = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
6075 KnownBits RHSKnown = DAG.computeKnownBits(Op.getOperand(1), Depth + 1);
6076 unsigned BitWidth = Op.getScalarValueSizeInBits();
6077
6078 // Sign/Zero extend from 24 bits.
6079 if (Opc == AMDGPUISD::MUL_I24) {
6080 LHSKnown = LHSKnown.trunc(24).sext(BitWidth);
6081 RHSKnown = RHSKnown.trunc(24).sext(BitWidth);
6082 } else {
6083 LHSKnown = LHSKnown.trunc(24).zext(BitWidth);
6084 RHSKnown = RHSKnown.trunc(24).zext(BitWidth);
6085 }
6086
6087 // TODO: SelfMultiply can be poison, but not undef.
6088 bool SelfMultiply = Op.getOperand(0) == Op.getOperand(1);
6089 if (SelfMultiply)
6090 SelfMultiply &= DAG.isGuaranteedNotToBeUndefOrPoison(
6091 Op.getOperand(0), DemandedElts, UndefPoisonKind::UndefOrPoison,
6092 Depth + 1);
6093
6094 Known = KnownBits::mul(LHSKnown, RHSKnown, SelfMultiply);
6095 break;
6096 }
6097 case AMDGPUISD::PERM: {
6098 ConstantSDNode *CMask = dyn_cast<ConstantSDNode>(Op.getOperand(2));
6099 if (!CMask)
6100 return;
6101
6102 KnownBits LHSKnown = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
6103 KnownBits RHSKnown = DAG.computeKnownBits(Op.getOperand(1), Depth + 1);
6104 unsigned Sel = CMask->getZExtValue();
6105
6106 for (unsigned I = 0; I < 32; I += 8) {
6107 unsigned SelBits = Sel & 0xff;
6108 if (SelBits < 4) {
6109 SelBits *= 8;
6110 Known.One |= ((RHSKnown.One.getZExtValue() >> SelBits) & 0xff) << I;
6111 Known.Zero |= ((RHSKnown.Zero.getZExtValue() >> SelBits) & 0xff) << I;
6112 } else if (SelBits < 7) {
6113 SelBits = (SelBits & 3) * 8;
6114 Known.One |= ((LHSKnown.One.getZExtValue() >> SelBits) & 0xff) << I;
6115 Known.Zero |= ((LHSKnown.Zero.getZExtValue() >> SelBits) & 0xff) << I;
6116 } else if (SelBits == 0x0c) {
6117 Known.Zero |= 0xFFull << I;
6118 } else if (SelBits > 0x0c) {
6119 Known.One |= 0xFFull << I;
6120 }
6121 Sel >>= 8;
6122 }
6123 break;
6124 }
6125 case AMDGPUISD::BUFFER_LOAD_UBYTE: {
6126 Known.Zero.setHighBits(24);
6127 break;
6128 }
6129 case AMDGPUISD::BUFFER_LOAD_USHORT: {
6130 Known.Zero.setHighBits(16);
6131 break;
6132 }
6133 case AMDGPUISD::LDS: {
6134 auto *GA = cast<GlobalAddressSDNode>(Op.getOperand(0).getNode());
6135 Align Alignment = GA->getGlobal()->getPointerAlignment(DAG.getDataLayout());
6136
6137 Known.Zero.setHighBits(16);
6138 Known.Zero.setLowBits(Log2(Alignment));
6139 break;
6140 }
6141 case AMDGPUISD::SMIN3:
6142 case AMDGPUISD::SMAX3:
6143 case AMDGPUISD::SMED3:
6144 case AMDGPUISD::UMIN3:
6145 case AMDGPUISD::UMAX3:
6146 case AMDGPUISD::UMED3: {
6147 KnownBits Known2 = DAG.computeKnownBits(Op.getOperand(2), Depth + 1);
6148 if (Known2.isUnknown())
6149 break;
6150
6151 KnownBits Known1 = DAG.computeKnownBits(Op.getOperand(1), Depth + 1);
6152 if (Known1.isUnknown())
6153 break;
6154
6155 KnownBits Known0 = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
6156 if (Known0.isUnknown())
6157 break;
6158
6159 // TODO: Handle LeadZero/LeadOne from UMIN/UMAX handling.
6160 Known.Zero = Known0.Zero & Known1.Zero & Known2.Zero;
6161 Known.One = Known0.One & Known1.One & Known2.One;
6162 break;
6163 }
6165 unsigned IID = Op.getConstantOperandVal(0);
6166 switch (IID) {
6167 case Intrinsic::amdgcn_workitem_id_x:
6168 case Intrinsic::amdgcn_workitem_id_y:
6169 case Intrinsic::amdgcn_workitem_id_z: {
6170 unsigned MaxValue = Subtarget->getMaxWorkitemID(
6172 Known.Zero.setHighBits(llvm::countl_zero(MaxValue));
6173 break;
6174 }
6175 default:
6176 break;
6177 }
6178 }
6179 }
6180}
6181
6183 SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG,
6184 unsigned Depth) const {
6185 switch (Op.getOpcode()) {
6186 case AMDGPUISD::BFE_I32: {
6187 ConstantSDNode *Width = dyn_cast<ConstantSDNode>(Op.getOperand(2));
6188 if (!Width)
6189 return 1;
6190
6191 unsigned SignBits = 32 - (Width->getZExtValue() & 0x1f) + 1;
6192 if (!isNullConstant(Op.getOperand(1)))
6193 return SignBits;
6194
6195 // TODO: Could probably figure something out with non-0 offsets.
6196 unsigned Op0SignBits = DAG.ComputeNumSignBits(Op.getOperand(0), Depth + 1);
6197 return std::max(SignBits, Op0SignBits);
6198 }
6199
6200 case AMDGPUISD::BFE_U32: {
6201 ConstantSDNode *Width = dyn_cast<ConstantSDNode>(Op.getOperand(2));
6202 return Width ? 32 - (Width->getZExtValue() & 0x1f) : 1;
6203 }
6204
6205 case AMDGPUISD::CARRY:
6206 case AMDGPUISD::BORROW:
6207 return 31;
6208 case AMDGPUISD::BUFFER_LOAD_BYTE:
6209 return 25;
6210 case AMDGPUISD::BUFFER_LOAD_SHORT:
6211 return 17;
6212 case AMDGPUISD::BUFFER_LOAD_UBYTE:
6213 return 24;
6214 case AMDGPUISD::BUFFER_LOAD_USHORT:
6215 return 16;
6216 case AMDGPUISD::FP_TO_FP16:
6217 return 16;
6218 case AMDGPUISD::SMIN3:
6219 case AMDGPUISD::SMAX3:
6220 case AMDGPUISD::SMED3:
6221 case AMDGPUISD::UMIN3:
6222 case AMDGPUISD::UMAX3:
6223 case AMDGPUISD::UMED3: {
6224 unsigned Tmp2 = DAG.ComputeNumSignBits(Op.getOperand(2), Depth + 1);
6225 if (Tmp2 == 1)
6226 return 1; // Early out.
6227
6228 unsigned Tmp1 = DAG.ComputeNumSignBits(Op.getOperand(1), Depth + 1);
6229 if (Tmp1 == 1)
6230 return 1; // Early out.
6231
6232 unsigned Tmp0 = DAG.ComputeNumSignBits(Op.getOperand(0), Depth + 1);
6233 if (Tmp0 == 1)
6234 return 1; // Early out.
6235
6236 return std::min({Tmp0, Tmp1, Tmp2});
6237 }
6238 default:
6239 return 1;
6240 }
6241}
6242
6244 GISelValueTracking &Analysis, Register R, const APInt &DemandedElts,
6245 const MachineRegisterInfo &MRI, unsigned Depth) const {
6246 const MachineInstr *MI = MRI.getVRegDef(R);
6247 if (!MI)
6248 return 1;
6249
6250 // TODO: Check range metadata on MMO.
6251 switch (MI->getOpcode()) {
6252 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SBYTE:
6253 return 25;
6254 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SSHORT:
6255 return 17;
6256 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
6257 return 24;
6258 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
6259 return 16;
6260 case AMDGPU::G_AMDGPU_SMED3:
6261 case AMDGPU::G_AMDGPU_UMED3: {
6262 auto [Dst, Src0, Src1, Src2] = MI->getFirst4Regs();
6263 unsigned Tmp2 = Analysis.computeNumSignBits(Src2, DemandedElts, Depth + 1);
6264 if (Tmp2 == 1)
6265 return 1;
6266 unsigned Tmp1 = Analysis.computeNumSignBits(Src1, DemandedElts, Depth + 1);
6267 if (Tmp1 == 1)
6268 return 1;
6269 unsigned Tmp0 = Analysis.computeNumSignBits(Src0, DemandedElts, Depth + 1);
6270 if (Tmp0 == 1)
6271 return 1;
6272 return std::min({Tmp0, Tmp1, Tmp2});
6273 }
6274 default:
6275 return 1;
6276 }
6277}
6278
6280 SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG,
6281 UndefPoisonKind Kind, bool ConsiderFlags, unsigned Depth) const {
6282 unsigned Opcode = Op.getOpcode();
6283 switch (Opcode) {
6284 case AMDGPUISD::BFE_I32:
6285 case AMDGPUISD::BFE_U32:
6286 return false;
6287 }
6289 Op, DemandedElts, DAG, Kind, ConsiderFlags, Depth);
6290}
6291
6293 SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN,
6294 unsigned Depth) const {
6295 unsigned Opcode = Op.getOpcode();
6296 switch (Opcode) {
6297 case AMDGPUISD::FMIN_LEGACY:
6298 case AMDGPUISD::FMAX_LEGACY:
6299 return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1) &&
6300 DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1);
6301 case AMDGPUISD::FMUL_LEGACY:
6302 case AMDGPUISD::CVT_PKRTZ_F16_F32: {
6303 if (SNaN)
6304 return true;
6305 return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1) &&
6306 DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1);
6307 }
6308 case AMDGPUISD::FMED3:
6309 case AMDGPUISD::FMIN3:
6310 case AMDGPUISD::FMAX3:
6311 case AMDGPUISD::FMINIMUM3:
6312 case AMDGPUISD::FMAXIMUM3:
6313 case AMDGPUISD::FMAD_FTZ: {
6314 if (SNaN)
6315 return true;
6316 return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1) &&
6317 DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1) &&
6318 DAG.isKnownNeverNaN(Op.getOperand(2), SNaN, Depth + 1);
6319 }
6320 case AMDGPUISD::CVT_F32_UBYTE0:
6321 case AMDGPUISD::CVT_F32_UBYTE1:
6322 case AMDGPUISD::CVT_F32_UBYTE2:
6323 case AMDGPUISD::CVT_F32_UBYTE3:
6324 return true;
6325
6326 case AMDGPUISD::RCP:
6327 case AMDGPUISD::RSQ:
6328 case AMDGPUISD::RCP_LEGACY:
6329 case AMDGPUISD::RSQ_CLAMP: {
6330 if (SNaN)
6331 return true;
6332
6333 // TODO: Need is known positive check.
6334 return false;
6335 }
6336 case ISD::FLDEXP:
6337 case AMDGPUISD::FRACT: {
6338 if (SNaN)
6339 return true;
6340 return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1);
6341 }
6342 case AMDGPUISD::DIV_SCALE:
6343 case AMDGPUISD::DIV_FMAS:
6344 case AMDGPUISD::DIV_FIXUP:
6345 // TODO: Refine on operands.
6346 return SNaN;
6347 case AMDGPUISD::SIN_HW:
6348 case AMDGPUISD::COS_HW: {
6349 // TODO: Need check for infinity
6350 return SNaN;
6351 }
6353 unsigned IntrinsicID = Op.getConstantOperandVal(0);
6354 // TODO: Handle more intrinsics
6355 switch (IntrinsicID) {
6356 case Intrinsic::amdgcn_cubeid:
6357 case Intrinsic::amdgcn_cvt_off_f32_i4:
6358 return true;
6359
6360 case Intrinsic::amdgcn_frexp_mant: {
6361 if (SNaN)
6362 return true;
6363 return DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1);
6364 }
6365 case Intrinsic::amdgcn_cvt_pkrtz: {
6366 if (SNaN)
6367 return true;
6368 return DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1) &&
6369 DAG.isKnownNeverNaN(Op.getOperand(2), SNaN, Depth + 1);
6370 }
6371 case Intrinsic::amdgcn_rcp:
6372 case Intrinsic::amdgcn_rsq:
6373 case Intrinsic::amdgcn_rcp_legacy:
6374 case Intrinsic::amdgcn_rsq_legacy:
6375 case Intrinsic::amdgcn_rsq_clamp:
6376 case Intrinsic::amdgcn_tanh: {
6377 if (SNaN)
6378 return true;
6379
6380 // TODO: Need is known positive check.
6381 return false;
6382 }
6383 case Intrinsic::amdgcn_trig_preop:
6384 case Intrinsic::amdgcn_fdot2:
6385 // TODO: Refine on operand
6386 return SNaN;
6387 case Intrinsic::amdgcn_fma_legacy:
6388 if (SNaN)
6389 return true;
6390 return DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1) &&
6391 DAG.isKnownNeverNaN(Op.getOperand(2), SNaN, Depth + 1) &&
6392 DAG.isKnownNeverNaN(Op.getOperand(3), SNaN, Depth + 1);
6393 default:
6394 return false;
6395 }
6396 }
6397 default:
6398 return false;
6399 }
6400}
6401
6403 Register N0, Register N1) const {
6404 return MRI.hasOneNonDBGUse(N0); // FIXME: handle regbanks
6405}
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)
unsigned Imm
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 bool canIgnoreLegacyMinMaxTies(const SelectionDAG &DAG, SDNodeFlags Flags, SDValue LHS, SDValue RHS)
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:857
block Block Frequency Analysis
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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:323
#define LLVM_READONLY
Definition Compiler.h:330
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)
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 combineFMinMaxLegacy(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, SDValue True, SDValue False, SDValue CC, SDNodeFlags Flags, DAGCombinerInfo &DCI) const
Flags must be the select flags, not the compare (SELECT_CC flags come from the fcmp and say nothing a...
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 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
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 combineFMinMaxLegacyImpl(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, SDValue True, SDValue False, SDValue CC, SDNodeFlags Flags, 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.
SDValue LowerDIVREMToFloat(SDValue Op, SelectionDAG &DAG, bool sign) const
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
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:304
static const fltSemantics & IEEEdouble()
Definition APFloat.h:305
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:361
static const fltSemantics & IEEEhalf()
Definition APFloat.h:302
bool bitwiseIsEqual(const APFloat &RHS) const
Definition APFloat.h:1548
opStatus add(const APFloat &RHS, roundingMode RM)
Definition APFloat.h:1285
opStatus multiply(const APFloat &RHS, roundingMode RM)
Definition APFloat.h:1303
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
Definition APFloat.h:1262
APInt bitcastToAPInt() const
Definition APFloat.h:1475
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Definition APFloat.h:1202
Class for arbitrary precision integers.
Definition APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1561
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
Definition APInt.h:203
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
Definition APInt.h:255
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
Definition APInt.h:206
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
Definition APInt.h:216
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
Definition APInt.h:303
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
Definition APInt.h:293
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:360
iterator_range< arg_iterator > args()
Definition Function.h:877
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:273
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:356
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 LLVM_READONLY 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 bool isKnownNeverLogicalZero(SDValue Op, const APInt &DemandedElts, unsigned Depth=0) const
Test whether the given floating point SDValue (or all elements of it, if it is a vector) is known to ...
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)
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 getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
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 getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
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 void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
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 MMOMetadata &Metadata=MMOMetadata())
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 SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
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)
std::optional< APFloat > evaluateRcp(const APFloat &Val)
Evaluate the constant-folded result of v_rcp for Val, accounting for the hardware's denormal flushing...
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.
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
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:52
constexpr double log2e
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
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.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
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:380
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:151
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:190
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
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.
@ Fast
Assign the register banks as fast as possible (default).
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:1727
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:880
#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
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 intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
Definition KnownBits.h:325
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
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)
bool hasNoSignedZeros() const
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...