LLVM 24.0.0git
SIISelLowering.cpp
Go to the documentation of this file.
1//===-- SIISelLowering.cpp - SI DAG Lowering Implementation ---------------===//
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/// Custom DAG lowering for SI
11//
12//===----------------------------------------------------------------------===//
13
14#include "SIISelLowering.h"
15#include "AMDGPU.h"
16#include "AMDGPUIGroupLP.h"
17#include "AMDGPUInstrInfo.h"
18#include "AMDGPULaneMaskUtils.h"
19#include "AMDGPUMemoryUtils.h"
21#include "AMDGPUTargetMachine.h"
22#include "GCNSubtarget.h"
25#include "SIRegisterInfo.h"
26#include "llvm/ADT/APFloat.h"
27#include "llvm/ADT/APInt.h"
29#include "llvm/ADT/Statistic.h"
44#include "llvm/IR/IRBuilder.h"
46#include "llvm/IR/IntrinsicsAMDGPU.h"
47#include "llvm/IR/IntrinsicsR600.h"
48#include "llvm/IR/MDBuilder.h"
52#include "llvm/Support/ModRef.h"
55#include <optional>
56
57using namespace llvm;
58using namespace llvm::SDPatternMatch;
59
60#define DEBUG_TYPE "si-lower"
61
62STATISTIC(NumTailCalls, "Number of tail calls");
63
64static cl::opt<bool>
65 DisableLoopAlignment("amdgpu-disable-loop-alignment",
66 cl::desc("Do not align and prefetch loops"),
67 cl::init(false));
68
70 "amdgpu-use-divergent-register-indexing", cl::Hidden,
71 cl::desc("Use indirect register addressing for divergent indexes"),
72 cl::init(false));
73
75 return MF.getInfo<SIMachineFunctionInfo>()->getMode().getDenormalFPEnv();
76}
77
82
87
88static unsigned findFirstFreeSGPR(CCState &CCInfo) {
89 unsigned NumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs();
90 for (unsigned Reg = 0; Reg < NumSGPRs; ++Reg) {
91 if (!CCInfo.isAllocated(AMDGPU::SGPR0 + Reg)) {
92 return AMDGPU::SGPR0 + Reg;
93 }
94 }
95 llvm_unreachable("Cannot allocate sgpr");
96}
97
99 const GCNSubtarget &STI)
100 : AMDGPUTargetLowering(TM, STI, STI), Subtarget(&STI) {
101 addRegisterClass(MVT::i1, &AMDGPU::VReg_1RegClass);
102 addRegisterClass(MVT::i64, &AMDGPU::SReg_64RegClass);
103
104 addRegisterClass(MVT::i32, &AMDGPU::SReg_32RegClass);
105
106 const SIRegisterInfo *TRI = STI.getRegisterInfo();
107 const TargetRegisterClass *V32RegClass =
108 TRI->getDefaultVectorSuperClassForBitWidth(32);
109 addRegisterClass(MVT::f32, V32RegClass);
110
111 addRegisterClass(MVT::v2i32, &AMDGPU::SReg_64RegClass);
112
113 const TargetRegisterClass *V64RegClass =
114 TRI->getDefaultVectorSuperClassForBitWidth(64);
115
116 addRegisterClass(MVT::f64, V64RegClass);
117 addRegisterClass(MVT::v2f32, V64RegClass);
118 addRegisterClass(MVT::Untyped, V64RegClass);
119
120 addRegisterClass(MVT::v3i32, &AMDGPU::SGPR_96RegClass);
121 addRegisterClass(MVT::v3f32, TRI->getDefaultVectorSuperClassForBitWidth(96));
122
123 addRegisterClass(MVT::v2i64, &AMDGPU::SGPR_128RegClass);
124 addRegisterClass(MVT::v2f64, &AMDGPU::SGPR_128RegClass);
125
126 addRegisterClass(MVT::v4i32, &AMDGPU::SGPR_128RegClass);
127 addRegisterClass(MVT::v4f32, TRI->getDefaultVectorSuperClassForBitWidth(128));
128
129 addRegisterClass(MVT::v5i32, &AMDGPU::SGPR_160RegClass);
130 addRegisterClass(MVT::v5f32, TRI->getDefaultVectorSuperClassForBitWidth(160));
131
132 addRegisterClass(MVT::v6i32, &AMDGPU::SGPR_192RegClass);
133 addRegisterClass(MVT::v6f32, TRI->getDefaultVectorSuperClassForBitWidth(192));
134
135 addRegisterClass(MVT::v3i64, &AMDGPU::SGPR_192RegClass);
136 addRegisterClass(MVT::v3f64, TRI->getDefaultVectorSuperClassForBitWidth(192));
137
138 addRegisterClass(MVT::v7i32, &AMDGPU::SGPR_224RegClass);
139 addRegisterClass(MVT::v7f32, TRI->getDefaultVectorSuperClassForBitWidth(224));
140
141 addRegisterClass(MVT::v8i32, &AMDGPU::SGPR_256RegClass);
142 addRegisterClass(MVT::v8f32, TRI->getDefaultVectorSuperClassForBitWidth(256));
143
144 addRegisterClass(MVT::v4i64, &AMDGPU::SGPR_256RegClass);
145 addRegisterClass(MVT::v4f64, TRI->getDefaultVectorSuperClassForBitWidth(256));
146
147 addRegisterClass(MVT::v9i32, &AMDGPU::SGPR_288RegClass);
148 addRegisterClass(MVT::v9f32, TRI->getDefaultVectorSuperClassForBitWidth(288));
149
150 addRegisterClass(MVT::v10i32, &AMDGPU::SGPR_320RegClass);
151 addRegisterClass(MVT::v10f32,
152 TRI->getDefaultVectorSuperClassForBitWidth(320));
153
154 addRegisterClass(MVT::v11i32, &AMDGPU::SGPR_352RegClass);
155 addRegisterClass(MVT::v11f32,
156 TRI->getDefaultVectorSuperClassForBitWidth(352));
157
158 addRegisterClass(MVT::v12i32, &AMDGPU::SGPR_384RegClass);
159 addRegisterClass(MVT::v12f32,
160 TRI->getDefaultVectorSuperClassForBitWidth(384));
161
162 addRegisterClass(MVT::v16i32, &AMDGPU::SGPR_512RegClass);
163 addRegisterClass(MVT::v16f32,
164 TRI->getDefaultVectorSuperClassForBitWidth(512));
165
166 addRegisterClass(MVT::v8i64, &AMDGPU::SGPR_512RegClass);
167 addRegisterClass(MVT::v8f64, TRI->getDefaultVectorSuperClassForBitWidth(512));
168
169 addRegisterClass(MVT::v16i64, &AMDGPU::SGPR_1024RegClass);
170 addRegisterClass(MVT::v16f64,
171 TRI->getDefaultVectorSuperClassForBitWidth(1024));
172
173 if (Subtarget->has16BitInsts()) {
174 if (Subtarget->useRealTrue16Insts()) {
175 addRegisterClass(MVT::i16, &AMDGPU::VGPR_16RegClass);
176 addRegisterClass(MVT::f16, &AMDGPU::VGPR_16RegClass);
177 addRegisterClass(MVT::bf16, &AMDGPU::VGPR_16RegClass);
178 } else {
179 addRegisterClass(MVT::i16, &AMDGPU::SReg_32RegClass);
180 addRegisterClass(MVT::f16, &AMDGPU::SReg_32RegClass);
181 addRegisterClass(MVT::bf16, &AMDGPU::SReg_32RegClass);
182 }
183
184 // Unless there are also VOP3P operations, not operations are really legal.
185 addRegisterClass(MVT::v2i16, &AMDGPU::SReg_32RegClass);
186 addRegisterClass(MVT::v2f16, &AMDGPU::SReg_32RegClass);
187 addRegisterClass(MVT::v2bf16, &AMDGPU::SReg_32RegClass);
188 addRegisterClass(MVT::v4i16, &AMDGPU::SReg_64RegClass);
189 addRegisterClass(MVT::v4f16, &AMDGPU::SReg_64RegClass);
190 addRegisterClass(MVT::v4bf16, &AMDGPU::SReg_64RegClass);
191 addRegisterClass(MVT::v8i16, &AMDGPU::SGPR_128RegClass);
192 addRegisterClass(MVT::v8f16, &AMDGPU::SGPR_128RegClass);
193 addRegisterClass(MVT::v8bf16, &AMDGPU::SGPR_128RegClass);
194 addRegisterClass(MVT::v16i16, &AMDGPU::SGPR_256RegClass);
195 addRegisterClass(MVT::v16f16, &AMDGPU::SGPR_256RegClass);
196 addRegisterClass(MVT::v16bf16, &AMDGPU::SGPR_256RegClass);
197 addRegisterClass(MVT::v32i16, &AMDGPU::SGPR_512RegClass);
198 addRegisterClass(MVT::v32f16, &AMDGPU::SGPR_512RegClass);
199 addRegisterClass(MVT::v32bf16, &AMDGPU::SGPR_512RegClass);
200 }
201
202 addRegisterClass(MVT::v32i32, &AMDGPU::VReg_1024RegClass);
203 addRegisterClass(MVT::v32f32,
204 TRI->getDefaultVectorSuperClassForBitWidth(1024));
205
206 computeRegisterProperties(Subtarget->getRegisterInfo());
207
210
211 // The boolean content concept here is too inflexible. Compares only ever
212 // really produce a 1-bit result. Any copy/extend from these will turn into a
213 // select, and zext/1 or sext/-1 are equally cheap. Arbitrarily choose 0/1, as
214 // it's what most targets use.
217
218 // We need to custom lower vector stores from local memory
220 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
221 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
222 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
223 MVT::i1, MVT::v32i32},
224 Custom);
225
227 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
228 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
229 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
230 MVT::i1, MVT::v32i32},
231 Custom);
232
233 if (isTypeLegal(MVT::bf16)) {
234 for (unsigned Opc :
243 ISD::SETCC}) {
244 setOperationAction(Opc, MVT::bf16, Promote);
245 }
246
247 // Only targets with packed bf16 instructions, e.g. gfx13.
248 if (Subtarget->hasBF16PackedInsts()) {
249 // Don't use Expand for fsub - the DAG combiner will undo fadd+fneg back
250 // to fsub, causing a libcall (which doesn't exist for bf16). Instead,
251 // directly expand to widened v2bf16 operations.
254 Promote);
255 // Promote scalar operations to a v2bf16 operation with an unused high
256 // lane.
257 for (unsigned Opc :
260 AddPromotedToType(Opc, MVT::bf16, MVT::v2bf16);
261 }
262
264
266 AddPromotedToType(ISD::SELECT, MVT::bf16, MVT::i16);
267
271
272 // We only need to custom lower because we can't specify an action for bf16
273 // sources.
276 }
277
278 setTruncStoreAction(MVT::v2i32, MVT::v2i16, Expand);
279 setTruncStoreAction(MVT::v3i32, MVT::v3i16, Expand);
280 setTruncStoreAction(MVT::v4i32, MVT::v4i16, Expand);
281 setTruncStoreAction(MVT::v8i32, MVT::v8i16, Expand);
282 setTruncStoreAction(MVT::v16i32, MVT::v16i16, Expand);
283 setTruncStoreAction(MVT::v32i32, MVT::v32i16, Expand);
284 setTruncStoreAction(MVT::v2i32, MVT::v2i8, Expand);
285 setTruncStoreAction(MVT::v4i32, MVT::v4i8, Expand);
286 setTruncStoreAction(MVT::v8i32, MVT::v8i8, Expand);
287 setTruncStoreAction(MVT::v16i32, MVT::v16i8, Expand);
288 setTruncStoreAction(MVT::v32i32, MVT::v32i8, Expand);
289 setTruncStoreAction(MVT::v2i16, MVT::v2i8, Expand);
290 setTruncStoreAction(MVT::v4i16, MVT::v4i8, Expand);
291 setTruncStoreAction(MVT::v8i16, MVT::v8i8, Expand);
292 setTruncStoreAction(MVT::v16i16, MVT::v16i8, Expand);
293 setTruncStoreAction(MVT::v32i16, MVT::v32i8, Expand);
294
295 setTruncStoreAction(MVT::v3i64, MVT::v3i16, Expand);
296 setTruncStoreAction(MVT::v3i64, MVT::v3i32, Expand);
297 setTruncStoreAction(MVT::v4i64, MVT::v4i8, Expand);
298 setTruncStoreAction(MVT::v8i64, MVT::v8i8, Expand);
299 setTruncStoreAction(MVT::v8i64, MVT::v8i16, Expand);
300 setTruncStoreAction(MVT::v8i64, MVT::v8i32, Expand);
301 setTruncStoreAction(MVT::v16i64, MVT::v16i32, Expand);
302
303 setOperationAction(ISD::GlobalAddress, {MVT::i32, MVT::i64}, Custom);
304 setOperationAction(ISD::BlockAddress, {MVT::i32, MVT::i64}, Custom);
305 setOperationAction(ISD::ExternalSymbol, {MVT::i32, MVT::i64}, Custom);
306
310 AddPromotedToType(ISD::SELECT, MVT::f64, MVT::i64);
311
312 setOperationAction(ISD::FSQRT, {MVT::f32, MVT::f64}, Custom);
313
315 {MVT::f32, MVT::i32, MVT::i64, MVT::f64, MVT::i1}, Expand);
316
318 setOperationAction(ISD::SETCC, {MVT::v2i1, MVT::v4i1}, Expand);
319 AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32);
320
322 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
323 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
324 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32},
325 Expand);
327 {MVT::v2f32, MVT::v3f32, MVT::v4f32, MVT::v5f32,
328 MVT::v6f32, MVT::v7f32, MVT::v8f32, MVT::v9f32,
329 MVT::v10f32, MVT::v11f32, MVT::v12f32, MVT::v16f32},
330 Expand);
331
333 {MVT::v2i1, MVT::v4i1, MVT::v2i8, MVT::v4i8, MVT::v2i16,
334 MVT::v3i16, MVT::v4i16, MVT::Other},
335 Custom);
336
339 {MVT::i1, MVT::i32, MVT::i64, MVT::f32, MVT::f64}, Expand);
340
343
346
348 Expand);
349
351
352 // We only support LOAD/STORE and vector manipulation ops for vectors
353 // with > 4 elements.
354 for (MVT VT :
355 {MVT::v8i32, MVT::v8f32, MVT::v9i32, MVT::v9f32, MVT::v10i32,
356 MVT::v10f32, MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32,
357 MVT::v16i32, MVT::v16f32, MVT::v2i64, MVT::v2f64, MVT::v4i16,
358 MVT::v4f16, MVT::v4bf16, MVT::v3i64, MVT::v3f64, MVT::v6i32,
359 MVT::v6f32, MVT::v4i64, MVT::v4f64, MVT::v8i64, MVT::v8f64,
360 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
361 MVT::v16bf16, MVT::v16i64, MVT::v16f64, MVT::v32i32, MVT::v32f32,
362 MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
363 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) {
364 switch (Op) {
365 case ISD::LOAD:
366 case ISD::STORE:
367 case ISD::ATOMIC_LOAD:
370 case ISD::BITCAST:
371 case ISD::UNDEF:
372 case ISD::POISON:
376 case ISD::IS_FPCLASS:
377 break;
382 break;
383 default:
385 break;
386 }
387 }
388 }
389
391
392 // TODO: For dynamic 64-bit vector inserts/extracts, should emit a pseudo that
393 // is expanded to avoid having two separate loops in case the index is a VGPR.
394
395 // Most operations are naturally 32-bit vector operations. We only support
396 // load and store of i64 vectors, so promote v2i64 vector operations to v4i32.
397 for (MVT Vec64 : {MVT::v2i64, MVT::v2f64}) {
399 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v4i32);
400
402 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v4i32);
403
405 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v4i32);
406
408 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v4i32);
409 }
410
411 for (MVT Vec64 : {MVT::v3i64, MVT::v3f64}) {
413 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v6i32);
414
416 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v6i32);
417
419 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v6i32);
420
422 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v6i32);
423 }
424
425 for (MVT Vec64 : {MVT::v4i64, MVT::v4f64}) {
427 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v8i32);
428
430 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v8i32);
431
433 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v8i32);
434
436 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v8i32);
437 }
438
439 for (MVT Vec64 : {MVT::v8i64, MVT::v8f64}) {
441 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v16i32);
442
444 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v16i32);
445
447 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v16i32);
448
450 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v16i32);
451 }
452
453 for (MVT Vec64 : {MVT::v16i64, MVT::v16f64}) {
455 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v32i32);
456
458 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v32i32);
459
461 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v32i32);
462
464 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v32i32);
465 }
466
468 {MVT::v4i32, MVT::v4f32, MVT::v8i32, MVT::v8f32,
469 MVT::v16i32, MVT::v16f32, MVT::v32i32, MVT::v32f32},
470 Custom);
471
472 if (Subtarget->hasPkMovB32()) {
473 // TODO: 16-bit element vectors should be legal with even aligned elements.
474 // TODO: Can be legal with wider source types than the result with
475 // subregister extracts.
476 setOperationAction(ISD::VECTOR_SHUFFLE, {MVT::v2i32, MVT::v2f32}, Legal);
477 }
478
480 // Prevent SELECT v2i32 from being implemented with the above bitwise ops and
481 // instead lower to cndmask in SITargetLowering::LowerSELECT().
483 // Enable MatchRotate to produce ISD::ROTR, which is later transformed to
484 // alignbit.
485 setOperationAction(ISD::ROTR, MVT::v2i32, Custom);
486
487 setOperationAction(ISD::BUILD_VECTOR, {MVT::v4f16, MVT::v4i16, MVT::v4bf16},
488 Custom);
489
490 // Avoid stack access for these.
491 // TODO: Generalize to more vector types.
493 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v2i8, MVT::v4i8,
494 MVT::v8i8, MVT::v4i16, MVT::v4f16, MVT::v4bf16},
495 Custom);
496
497 // Deal with vec3 vector operations when widened to vec4.
499 {MVT::v3i32, MVT::v3f32, MVT::v4i32, MVT::v4f32}, Custom);
500
501 // Deal with vec5/6/7 vector operations when widened to vec8.
503 {MVT::v5i32, MVT::v5f32, MVT::v6i32, MVT::v6f32,
504 MVT::v7i32, MVT::v7f32, MVT::v8i32, MVT::v8f32,
505 MVT::v9i32, MVT::v9f32, MVT::v10i32, MVT::v10f32,
506 MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32},
507 Custom);
508
509 // BUFFER/FLAT_ATOMIC_CMP_SWAP on GCN GPUs needs input marshalling,
510 // and output demarshalling
511 setOperationAction(ISD::ATOMIC_CMP_SWAP, {MVT::i32, MVT::i64}, Custom);
512
513 // We can't return success/failure, only the old value,
514 // let LLVM add the comparison
516 Expand);
517
518 setOperationAction(ISD::ADDRSPACECAST, {MVT::i32, MVT::i64}, Custom);
519
520 setOperationAction(ISD::BITREVERSE, {MVT::i32, MVT::i64}, Legal);
521
522 // FIXME: This should be narrowed to i32, but that only happens if i64 is
523 // illegal.
524 // FIXME: Should lower sub-i32 bswaps to bit-ops without v_perm_b32.
525 setOperationAction(ISD::BSWAP, {MVT::i64, MVT::i32}, Legal);
526
527 // On SI this is s_memtime and s_memrealtime on VI.
529
530 if (Subtarget->hasSMemRealTime() ||
531 Subtarget->getGeneration() >= AMDGPUSubtarget::GFX11)
534
535 if (Subtarget->has16BitInsts()) {
538 setOperationAction(ISD::IS_FPCLASS, {MVT::f16, MVT::f32, MVT::f64}, Legal);
541 } else {
543 }
544
545 if (Subtarget->hasMadMacF32Insts())
547
551
552 // We only really have 32-bit BFE instructions (and 16-bit on VI).
553 //
554 // On SI+ there are 64-bit BFEs, but they are scalar only and there isn't any
555 // effort to match them now. We want this to be false for i64 cases when the
556 // extraction isn't restricted to the upper or lower half. Ideally we would
557 // have some pass reduce 64-bit extracts to 32-bit if possible. Extracts that
558 // span the midpoint are probably relatively rare, so don't worry about them
559 // for now.
561
562 // Clamp modifier on add/sub
563 if (Subtarget->hasIntClamp())
565
566 if (Subtarget->hasAddNoCarryInsts())
567 setOperationAction({ISD::SADDSAT, ISD::SSUBSAT}, {MVT::i16, MVT::i32},
568 Legal);
569
570 // Do not have s_{min|max}_*f64 instruction f64 will only be lowered to
571 // v_{min|max}_*f64
572 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
575 {MVT::f64, MVT::f32}, Legal);
576 } else {
579 {MVT::f64, MVT::f32}, Custom);
580 // These are really only legal for ieee_mode functions. We should be
581 // avoiding them for functions that don't have ieee_mode enabled, so just
582 // say they are legal.
584 {MVT::f64, MVT::f32}, Legal);
585 }
586
587 if (Subtarget->haveRoundOpsF64())
589 Legal);
590 else
592 MVT::f64, Custom);
593
595 setOperationAction({ISD::FLDEXP, ISD::STRICT_FLDEXP}, {MVT::f32, MVT::f64},
596 Legal);
597 setOperationAction(ISD::FFREXP, {MVT::f32, MVT::f64}, Custom);
598
601
602 setOperationAction(ISD::BF16_TO_FP, {MVT::i16, MVT::f32, MVT::f64}, Expand);
603 setOperationAction(ISD::FP_TO_BF16, {MVT::i16, MVT::f32, MVT::f64}, Expand);
604
606 Custom);
608 Custom);
610 Custom);
611
612 // Custom lower these because we can't specify a rule based on an illegal
613 // source bf16.
616
617 if (Subtarget->has16BitInsts()) {
620 MVT::i16, Legal);
621
622 AddPromotedToType(ISD::SIGN_EXTEND, MVT::i16, MVT::i32);
623
625 MVT::i16, Expand);
626
630 ISD::CTPOP},
631 MVT::i16, Promote);
632
634
635 setTruncStoreAction(MVT::i64, MVT::i16, Expand);
636
638 AddPromotedToType(ISD::FP16_TO_FP, MVT::i16, MVT::i32);
640 AddPromotedToType(ISD::FP_TO_FP16, MVT::i16, MVT::i32);
641
646
648
649 // F16 - Constant Actions.
652
653 // F16 - Load/Store Actions.
655 AddPromotedToType(ISD::LOAD, MVT::f16, MVT::i16);
657 AddPromotedToType(ISD::STORE, MVT::f16, MVT::i16);
658
659 // BF16 - Load/Store Actions.
661 AddPromotedToType(ISD::LOAD, MVT::bf16, MVT::i16);
663 AddPromotedToType(ISD::STORE, MVT::bf16, MVT::i16);
664
665 if (!Subtarget->useRealTrue16Insts() ||
666 !Subtarget->d16PreservesUnusedBits()) {
667 for (MVT VT : {MVT::i16, MVT::f16, MVT::bf16}) {
669 AddPromotedToType(ISD::ATOMIC_LOAD, VT, MVT::i32);
670 }
671 }
672
673 if (!Subtarget->useRealTrue16Insts()) {
674 for (MVT VT : {MVT::i16, MVT::f16, MVT::bf16}) {
677 }
678 }
679
680 // F16 - VOP1 Actions.
683 MVT::f16, Custom);
684
685 // BF16 - VOP1 Actions.
686 if (Subtarget->hasBF16TransInsts())
688
689 // F16 - VOP2 Actions.
690 setOperationAction({ISD::BR_CC, ISD::SELECT_CC}, {MVT::f16, MVT::bf16},
691 Expand);
695
696 // F16 - VOP3 Actions.
698 if (STI.hasMadF16())
700
701 for (MVT VT :
702 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v4i16, MVT::v4f16,
703 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16,
704 MVT::v16f16, MVT::v16bf16, MVT::v32i16, MVT::v32f16}) {
705 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) {
706 switch (Op) {
707 case ISD::LOAD:
708 case ISD::STORE:
709 case ISD::ATOMIC_LOAD:
712 case ISD::BITCAST:
713 case ISD::UNDEF:
714 case ISD::POISON:
719 case ISD::IS_FPCLASS:
720 break;
723 case ISD::FSIN:
724 case ISD::FCOS:
726 break;
727 default:
729 break;
730 }
731 }
732 }
733
734 // v_perm_b32 can handle either of these.
735 setOperationAction(ISD::BSWAP, {MVT::i16, MVT::v2i16}, Legal);
737
738 // Legalize vector types for sat conversions to select v_cvt_pk_[iu]16_f32.
739 if (Subtarget->hasVCvtPkIU16F32())
742 {MVT::v2i16, MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16},
743 Custom);
744
745 // XXX - Do these do anything? Vector constants turn into build_vector.
746 setOperationAction(ISD::Constant, {MVT::v2i16, MVT::v2f16}, Legal);
747
749 {MVT::v2i16, MVT::v2f16, MVT::v2bf16}, Legal);
750
752 AddPromotedToType(ISD::STORE, MVT::v2i16, MVT::i32);
754 AddPromotedToType(ISD::STORE, MVT::v2f16, MVT::i32);
755
757 AddPromotedToType(ISD::LOAD, MVT::v2i16, MVT::i32);
759 AddPromotedToType(ISD::LOAD, MVT::v2f16, MVT::i32);
760
761 setOperationAction(ISD::AND, MVT::v2i16, Promote);
762 AddPromotedToType(ISD::AND, MVT::v2i16, MVT::i32);
763 setOperationAction(ISD::OR, MVT::v2i16, Promote);
764 AddPromotedToType(ISD::OR, MVT::v2i16, MVT::i32);
765 setOperationAction(ISD::XOR, MVT::v2i16, Promote);
766 AddPromotedToType(ISD::XOR, MVT::v2i16, MVT::i32);
767
769 AddPromotedToType(ISD::LOAD, MVT::v4i16, MVT::v2i32);
771 AddPromotedToType(ISD::LOAD, MVT::v4f16, MVT::v2i32);
772 setOperationAction(ISD::LOAD, MVT::v4bf16, Promote);
773 AddPromotedToType(ISD::LOAD, MVT::v4bf16, MVT::v2i32);
774
776 AddPromotedToType(ISD::STORE, MVT::v4i16, MVT::v2i32);
778 AddPromotedToType(ISD::STORE, MVT::v4f16, MVT::v2i32);
780 AddPromotedToType(ISD::STORE, MVT::v4bf16, MVT::v2i32);
781
783 AddPromotedToType(ISD::LOAD, MVT::v8i16, MVT::v4i32);
785 AddPromotedToType(ISD::LOAD, MVT::v8f16, MVT::v4i32);
786 setOperationAction(ISD::LOAD, MVT::v8bf16, Promote);
787 AddPromotedToType(ISD::LOAD, MVT::v8bf16, MVT::v4i32);
788
790 AddPromotedToType(ISD::STORE, MVT::v4i16, MVT::v2i32);
792 AddPromotedToType(ISD::STORE, MVT::v4f16, MVT::v2i32);
793
795 AddPromotedToType(ISD::STORE, MVT::v8i16, MVT::v4i32);
797 AddPromotedToType(ISD::STORE, MVT::v8f16, MVT::v4i32);
799 AddPromotedToType(ISD::STORE, MVT::v8bf16, MVT::v4i32);
800
801 setOperationAction(ISD::LOAD, MVT::v16i16, Promote);
802 AddPromotedToType(ISD::LOAD, MVT::v16i16, MVT::v8i32);
803 setOperationAction(ISD::LOAD, MVT::v16f16, Promote);
804 AddPromotedToType(ISD::LOAD, MVT::v16f16, MVT::v8i32);
805 setOperationAction(ISD::LOAD, MVT::v16bf16, Promote);
806 AddPromotedToType(ISD::LOAD, MVT::v16bf16, MVT::v8i32);
807
809 AddPromotedToType(ISD::STORE, MVT::v16i16, MVT::v8i32);
811 AddPromotedToType(ISD::STORE, MVT::v16f16, MVT::v8i32);
812 setOperationAction(ISD::STORE, MVT::v16bf16, Promote);
813 AddPromotedToType(ISD::STORE, MVT::v16bf16, MVT::v8i32);
814
815 setOperationAction(ISD::LOAD, MVT::v32i16, Promote);
816 AddPromotedToType(ISD::LOAD, MVT::v32i16, MVT::v16i32);
817 setOperationAction(ISD::LOAD, MVT::v32f16, Promote);
818 AddPromotedToType(ISD::LOAD, MVT::v32f16, MVT::v16i32);
819 setOperationAction(ISD::LOAD, MVT::v32bf16, Promote);
820 AddPromotedToType(ISD::LOAD, MVT::v32bf16, MVT::v16i32);
821
823 AddPromotedToType(ISD::STORE, MVT::v32i16, MVT::v16i32);
825 AddPromotedToType(ISD::STORE, MVT::v32f16, MVT::v16i32);
826 setOperationAction(ISD::STORE, MVT::v32bf16, Promote);
827 AddPromotedToType(ISD::STORE, MVT::v32bf16, MVT::v16i32);
828
830 MVT::v2i32, Expand);
832
834 MVT::v4i32, Expand);
835
837 MVT::v8i32, Expand);
838
839 setOperationAction(ISD::BUILD_VECTOR, {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
840 Subtarget->hasVOP3PInsts() ? Legal : Custom);
841
842 setOperationAction(ISD::FNEG, {MVT::v2f16, MVT::v2bf16}, Legal);
843 // This isn't really legal, but this avoids the legalizer unrolling it (and
844 // allows matching fneg (fabs x) patterns)
845 setOperationAction(ISD::FABS, {MVT::v2f16, MVT::v2bf16}, Legal);
846
847 // Can do this in one BFI plus a constant materialize.
849 {MVT::v2f16, MVT::v2bf16, MVT::v4f16, MVT::v4bf16,
850 MVT::v8f16, MVT::v8bf16, MVT::v16f16, MVT::v16bf16,
851 MVT::v32f16, MVT::v32bf16},
852 Custom);
853 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
856 MVT::f16, Legal);
857
860 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16}, Custom);
861 } else {
864 MVT::f16, Custom);
865
867 Legal);
868
871 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
872 Custom);
873
875 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
876 Expand);
877 }
878
879 for (MVT Vec16 :
880 {MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
881 MVT::v16bf16, MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
884 Vec16, Custom);
886 }
887 }
888
889 if (Subtarget->hasVOP3PInsts()) {
893 MVT::v2i16, Legal);
894
897 MVT::v2f16, Legal);
898
900 {MVT::v2i16, MVT::v2f16, MVT::v2bf16}, Custom);
901
903 {MVT::v4f16, MVT::v4i16, MVT::v4bf16, MVT::v8f16,
904 MVT::v8i16, MVT::v8bf16, MVT::v16f16, MVT::v16i16,
905 MVT::v16bf16, MVT::v32f16, MVT::v32i16, MVT::v32bf16},
906 Custom);
907
908 for (MVT VT : {MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16})
909 // Split vector operations.
914 VT, Custom);
915
916 for (MVT VT : {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16})
917 // Split vector operations.
920 VT, Custom);
921
922 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
925 MVT::v2f16, Legal);
926 } else {
928 Legal);
929
932 {MVT::v2f16, MVT::v4f16}, Custom);
933 }
934 setOperationAction(ISD::FEXP, MVT::v2f16, Custom);
935 setOperationAction(ISD::SELECT, {MVT::v4i16, MVT::v4f16, MVT::v4bf16},
936 Custom);
937
938 if (Subtarget->hasBF16PackedInsts()) {
942 MVT::v2bf16, Legal);
943
944 for (MVT VT : {MVT::v4bf16, MVT::v8bf16, MVT::v16bf16, MVT::v32bf16})
945 // Split vector operations.
949 VT, Custom);
950 }
951
952 if (Subtarget->hasAnyPackedFP32Ops()) {
954 MVT::v2f32, Legal);
956 {MVT::v4f32, MVT::v8f32, MVT::v16f32, MVT::v32f32},
957 Custom);
958 }
959 if (Subtarget->hasAnyPackedFP64Ops()) {
962 MVT::v2f64, Legal);
965 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64}, Custom);
966
967 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
970 MVT::v2f64, Legal);
971
974 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64}, Custom);
975 } else {
977 Legal);
980 MVT::v2f64, Custom);
983 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
984 Custom);
985 }
986 }
987
988 if (Subtarget->hasAnyPackedU64Ops()) {
990 MVT::v2i64, Legal);
992 {MVT::v4i64, MVT::v8i64, MVT::v16i64, MVT::v32i64},
993 Custom);
994 }
995 }
996
998
999 if (Subtarget->has16BitInsts()) {
1001 AddPromotedToType(ISD::SELECT, MVT::v2i16, MVT::i32);
1003 AddPromotedToType(ISD::SELECT, MVT::v2f16, MVT::i32);
1004 setOperationAction(ISD::SELECT, MVT::v2bf16, Promote);
1005 AddPromotedToType(ISD::SELECT, MVT::v2bf16, MVT::i32);
1006 } else {
1007 // Legalization hack.
1008 setOperationAction(ISD::SELECT, {MVT::v2i16, MVT::v2f16}, Custom);
1009
1011 }
1012
1014 {MVT::v4i16, MVT::v4f16, MVT::v4bf16, MVT::v2i8, MVT::v4i8,
1015 MVT::v8i8, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1016 MVT::v16i16, MVT::v16f16, MVT::v16bf16, MVT::v32i16,
1017 MVT::v32f16, MVT::v32bf16},
1018 Custom);
1019
1021
1022 if (Subtarget->useVMulU64Inst())
1023 setOperationAction(ISD::MUL, MVT::i64, Legal);
1024 else if (Subtarget->hasScalarSMulU64())
1026
1027 if (Subtarget->hasMad64_32())
1029
1030 if (Subtarget->hasSafeSmemPrefetch() || Subtarget->hasVmemPrefInsts())
1032 // Type legalization cannot expand the i128 pointer of a buffer resource
1033 // prefetch; lowerPREFETCH drops the prefetch instead.
1035
1036 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
1038 {MVT::f16, MVT::f32, MVT::f64, MVT::v2f16}, Legal);
1039 } else {
1040 // FIXME: For nnan fmaximum, emit the fmaximum3 instead of fmaxnum
1041 if (Subtarget->hasMinimum3Maximum3F32())
1043
1044 if (Subtarget->hasMinimum3Maximum3PKF16()) {
1046
1047 // If only the vector form is available, we need to widen to a vector.
1048 if (!Subtarget->hasMinimum3Maximum3F16())
1050 MVT::v2f16);
1051 }
1052 }
1053
1054 if (Subtarget->hasVOP3PInsts()) {
1055 // We want to break these into v2f16 pieces, not scalarize.
1057 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
1058 Custom);
1059 }
1060
1061 if (Subtarget->useMinMaxI64Insts())
1063 Legal);
1064
1066 {MVT::Other, MVT::f32, MVT::v4f32, MVT::i16, MVT::f16,
1067 MVT::bf16, MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::i128,
1068 MVT::i8},
1069 Custom);
1070
1072 {MVT::v2f16, MVT::v2i16, MVT::v2bf16, MVT::v3f16,
1073 MVT::v3i16, MVT::v4f16, MVT::v4i16, MVT::v4bf16,
1074 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::Other, MVT::f16,
1075 MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1076 Custom);
1077
1078 // The s_buffer_load intrinsics accept any result type in IR, but only a few
1079 // of them can be selected. Mark the remaining illegal result types Custom so
1080 // ReplaceNodeResults gets a chance to diagnose them instead of letting the
1081 // type legalizer abort. Its INTRINSIC_WO_CHAIN case dispatches on the
1082 // intrinsic ID, but INTRINSIC_W_CHAIN does not, so remember the types added
1083 // here to keep other chained intrinsics on generic legalization.
1084 for (MVT VT : MVT::all_valuetypes()) {
1085 if (VT.isScalableVector() || isTypeLegal(VT))
1086 continue;
1090 SBufferLoadDiagnosticVTs.set(VT.SimpleTy);
1091 }
1092 }
1093
1095 {MVT::Other, MVT::v2i16, MVT::v2f16, MVT::v2bf16,
1096 MVT::v3i16, MVT::v3f16, MVT::v4f16, MVT::v4i16,
1097 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1098 MVT::f16, MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1099 Custom);
1100
1106
1107 // TODO: Could move this to custom lowering, could benefit from combines on
1108 // extract of relevant bits.
1110
1112
1113 if (Subtarget->hasBF16ConversionInsts()) {
1115 {MVT::bf16, MVT::v2bf16}, Custom);
1117 }
1118
1119 if (Subtarget->hasBF16TransInsts()) {
1121 }
1122
1123 const bool HasE5M3ConversionInsts =
1124 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
1125 if (Subtarget->hasOCPFP8ConversionInsts() || HasE5M3ConversionInsts) {
1126 setOperationAction(ISD::CONVERT_FROM_ARBITRARY_FP, {MVT::f32, MVT::v2f32},
1127 Custom);
1129
1130 // i8 result promotes to i16, wider vectors split down to v2i8, and v2i8 is
1131 // handled in ReplaceNodeResults before the legalizer splits it per lane.
1132 setOperationAction(ISD::CONVERT_TO_ARBITRARY_FP, {MVT::i16, MVT::v2i8},
1133 Custom);
1134 }
1135
1136 if (Subtarget->hasFP8F16ConversionInsts()) {
1137 setOperationAction(ISD::CONVERT_FROM_ARBITRARY_FP, {MVT::f16, MVT::v2f16},
1138 Custom);
1139 }
1140
1141 if (Subtarget->hasCvtPkF16F32Inst()) {
1143 {MVT::v2f16, MVT::v4f16, MVT::v8f16, MVT::v16f16},
1144 Custom);
1145 }
1146
1149 ISD::SUB,
1150 ISD::MUL,
1151 ISD::FADD,
1152 ISD::FSUB,
1153 ISD::FDIV,
1154 ISD::FMUL,
1163 ISD::FMA,
1164 ISD::ABS,
1165 ISD::SMIN,
1166 ISD::SMAX,
1167 ISD::UMIN,
1168 ISD::UMAX,
1169 ISD::SETCC,
1171 ISD::SMIN,
1172 ISD::SMAX,
1173 ISD::UMIN,
1174 ISD::UMAX,
1177 ISD::AND,
1178 ISD::OR,
1179 ISD::XOR,
1180 ISD::SHL,
1181 ISD::SRL,
1182 ISD::SRA,
1183 ISD::FSHR,
1195
1196 if (Subtarget->has16BitInsts() && !Subtarget->hasMed3_16())
1198
1199 // All memory operations. Some folding on the pointer operand is done to help
1200 // matching the constant offsets in the addressing modes.
1202 ISD::STORE,
1227
1228 // FIXME: In other contexts we pretend this is a per-function property.
1230
1232}
1233
1234const GCNSubtarget *SITargetLowering::getSubtarget() const { return Subtarget; }
1235
1237 static const MCPhysReg RCRegs[] = {AMDGPU::MODE};
1238 return RCRegs;
1239}
1240
1241//===----------------------------------------------------------------------===//
1242// TargetLowering queries
1243//===----------------------------------------------------------------------===//
1244
1245// v_mad_mix* support a conversion from f16 to f32.
1246//
1247// There is only one special case when denormals are enabled we don't currently,
1248// where this is OK to use.
1249bool SITargetLowering::isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode,
1250 EVT DestVT, EVT SrcVT) const {
1251 return DestVT.getScalarType() == MVT::f32 &&
1252 ((((Opcode == ISD::FMAD && Subtarget->hasMadMixInsts()) ||
1253 (Opcode == ISD::FMA && Subtarget->hasFmaMixInsts())) &&
1254 SrcVT.getScalarType() == MVT::f16) ||
1255 (Opcode == ISD::FMA && Subtarget->hasFmaMixBF16Insts() &&
1256 SrcVT.getScalarType() == MVT::bf16)) &&
1257 // TODO: This probably only requires no input flushing?
1259}
1260
1262 LLT DestTy, LLT SrcTy) const {
1263 return ((Opcode == TargetOpcode::G_FMAD && Subtarget->hasMadMixInsts()) ||
1264 (Opcode == TargetOpcode::G_FMA && Subtarget->hasFmaMixInsts())) &&
1265 DestTy.getScalarSizeInBits() == 32 &&
1266 SrcTy.getScalarSizeInBits() == 16 &&
1267 // TODO: This probably only requires no input flushing?
1268 denormalModeIsFlushAllF32(*MI.getMF());
1269}
1270
1272 // SI has some legal vector types, but no legal vector operations. Say no
1273 // shuffles are legal in order to prefer scalarizing some vector operations.
1274 return false;
1275}
1276
1278 CallingConv::ID CC,
1279 EVT VT) const {
1281 return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
1282
1283 if (VT.isVector()) {
1284 EVT ScalarVT = VT.getScalarType();
1285 unsigned Size = ScalarVT.getSizeInBits();
1286 if (Size == 16) {
1287 return Subtarget->has16BitInsts()
1288 ? MVT::getVectorVT(ScalarVT.getSimpleVT(), 2)
1289 : MVT::i32;
1290 }
1291
1292 if (Size < 16)
1293 return Subtarget->has16BitInsts() ? MVT::i16 : MVT::i32;
1294 return Size == 32 ? ScalarVT.getSimpleVT() : MVT::i32;
1295 }
1296
1297 if (!Subtarget->has16BitInsts() && VT.getSizeInBits() == 16)
1298 return MVT::i32;
1299
1300 if (VT.getSizeInBits() > 32)
1301 return MVT::i32;
1302
1303 return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
1304}
1305
1307 CallingConv::ID CC,
1308 EVT VT) const {
1310 return TargetLowering::getNumRegistersForCallingConv(Context, CC, VT);
1311
1312 if (VT.isVector()) {
1313 unsigned NumElts = VT.getVectorNumElements();
1314 EVT ScalarVT = VT.getScalarType();
1315 unsigned Size = ScalarVT.getSizeInBits();
1316
1317 // FIXME: Should probably promote 8-bit vectors to i16.
1318 if (Size == 16)
1319 return (NumElts + 1) / 2;
1320
1321 if (Size <= 32)
1322 return NumElts;
1323
1324 if (Size > 32)
1325 return NumElts * ((Size + 31) / 32);
1326 } else if (VT.getSizeInBits() > 32)
1327 return (VT.getSizeInBits() + 31) / 32;
1328
1329 return TargetLowering::getNumRegistersForCallingConv(Context, CC, VT);
1330}
1331
1333 LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT,
1334 unsigned &NumIntermediates, MVT &RegisterVT) const {
1335 if (CC != CallingConv::AMDGPU_KERNEL && VT.isVector()) {
1336 unsigned NumElts = VT.getVectorNumElements();
1337 EVT ScalarVT = VT.getScalarType();
1338 unsigned Size = ScalarVT.getSizeInBits();
1339 // FIXME: We should fix the ABI to be the same on targets without 16-bit
1340 // support, but unless we can properly handle 3-vectors, it will be still be
1341 // inconsistent.
1342 if (Size == 16) {
1343 MVT SimpleIntermediateVT =
1345 IntermediateVT = SimpleIntermediateVT;
1346 RegisterVT = Subtarget->has16BitInsts() ? SimpleIntermediateVT : MVT::i32;
1347 NumIntermediates = (NumElts + 1) / 2;
1348 return (NumElts + 1) / 2;
1349 }
1350
1351 if (Size == 32) {
1352 RegisterVT = ScalarVT.getSimpleVT();
1353 IntermediateVT = RegisterVT;
1354 NumIntermediates = NumElts;
1355 return NumIntermediates;
1356 }
1357
1358 if (Size < 16 && Subtarget->has16BitInsts()) {
1359 // FIXME: Should probably form v2i16 pieces
1360 RegisterVT = MVT::i16;
1361 IntermediateVT = ScalarVT;
1362 NumIntermediates = NumElts;
1363 return NumIntermediates;
1364 }
1365
1366 if (Size != 16 && Size <= 32) {
1367 RegisterVT = MVT::i32;
1368 IntermediateVT = ScalarVT;
1369 NumIntermediates = NumElts;
1370 return NumIntermediates;
1371 }
1372
1373 if (Size > 32) {
1374 RegisterVT = MVT::i32;
1375 IntermediateVT = RegisterVT;
1376 NumIntermediates = NumElts * ((Size + 31) / 32);
1377 return NumIntermediates;
1378 }
1379 }
1380
1382 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
1383}
1384
1386 const DataLayout &DL, Type *Ty,
1387 unsigned MaxNumLanes) {
1388 assert(MaxNumLanes != 0);
1389
1390 LLVMContext &Ctx = Ty->getContext();
1391 if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
1392 unsigned NumElts = std::min(MaxNumLanes, VT->getNumElements());
1393 return EVT::getVectorVT(Ctx, TLI.getValueType(DL, VT->getElementType()),
1394 NumElts);
1395 }
1396
1397 return TLI.getValueType(DL, Ty);
1398}
1399
1400// Peek through TFE struct returns to only use the data size.
1402 const DataLayout &DL, Type *Ty,
1403 unsigned MaxNumLanes) {
1404 auto *ST = dyn_cast<StructType>(Ty);
1405 if (!ST)
1406 return memVTFromLoadIntrData(TLI, DL, Ty, MaxNumLanes);
1407
1408 // TFE intrinsics return an aggregate type.
1409 assert(ST->getNumContainedTypes() == 2 &&
1410 ST->getContainedType(1)->isIntegerTy(32));
1411 return memVTFromLoadIntrData(TLI, DL, ST->getContainedType(0), MaxNumLanes);
1412}
1413
1414/// Map address space 7 to MVT::amdgpuBufferFatPointer because that's its
1415/// in-memory representation. This return value is a custom type because there
1416/// is no MVT::i160 and adding one breaks integer promotion logic. While this
1417/// could cause issues during codegen, these address space 7 pointers will be
1418/// rewritten away by then. Therefore, we can return MVT::amdgpuBufferFatPointer
1419/// in order to allow pre-codegen passes that query TargetTransformInfo, often
1420/// for cost modeling, to work. (This also sets us up decently for doing the
1421/// buffer lowering in GlobalISel if SelectionDAG ever goes away.)
1423 if (AMDGPUAS::BUFFER_FAT_POINTER == AS && DL.getPointerSizeInBits(AS) == 160)
1424 return MVT::amdgpuBufferFatPointer;
1426 DL.getPointerSizeInBits(AS) == 192)
1427 return MVT::amdgpuBufferStridedPointer;
1429}
1430/// Similarly, the in-memory representation of a p7 is {p8, i32}, aka
1431/// v8i32 when padding is added.
1432/// The in-memory representation of a p9 is {p8, i32, i32}, which is
1433/// also v8i32 with padding.
1435 if ((AMDGPUAS::BUFFER_FAT_POINTER == AS &&
1436 DL.getPointerSizeInBits(AS) == 160) ||
1438 DL.getPointerSizeInBits(AS) == 192))
1439 return MVT::v8i32;
1441}
1442
1443static unsigned getIntrMemWidth(unsigned IntrID) {
1444 switch (IntrID) {
1445 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1446 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1447 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1448 return 8;
1449 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1450 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1451 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1452 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1453 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1454 case Intrinsic::amdgcn_flat_load_monitor_b32:
1455 case Intrinsic::amdgcn_global_load_monitor_b32:
1456 return 32;
1457 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1458 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1459 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1460 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1461 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1462 case Intrinsic::amdgcn_flat_load_monitor_b64:
1463 case Intrinsic::amdgcn_global_load_monitor_b64:
1464 return 64;
1465 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1466 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1467 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1468 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
1469 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
1470 case Intrinsic::amdgcn_flat_load_monitor_b128:
1471 case Intrinsic::amdgcn_global_load_monitor_b128:
1472 return 128;
1473 default:
1474 llvm_unreachable("Unknown width");
1475 }
1476}
1477
1479 unsigned ArgIdx) {
1480 Value *OrderingArg = CI.getArgOperand(ArgIdx);
1481 unsigned Ord = cast<ConstantInt>(OrderingArg)->getZExtValue();
1482 switch (AtomicOrderingCABI(Ord)) {
1485 break;
1488 break;
1491 break;
1492 default:
1494 }
1495}
1496
1497static unsigned parseSyncscopeMDArg(const CallBase &CI, unsigned ArgIdx) {
1498 MDNode *ScopeMD = cast<MDNode>(
1499 cast<MetadataAsValue>(CI.getArgOperand(ArgIdx))->getMetadata());
1500 StringRef Scope = cast<MDString>(ScopeMD->getOperand(0))->getString();
1501 return CI.getContext().getOrInsertSyncScopeID(Scope);
1502}
1503
1505 const CallBase &CI,
1506 MachineFunction &MF,
1507 unsigned IntrID) const {
1509 if (CI.hasMetadata(LLVMContext::MD_invariant_load))
1511 if (CI.hasMetadata(LLVMContext::MD_nontemporal))
1513 Flags |= getTargetMMOFlags(CI);
1514
1515 if (const AMDGPU::RsrcIntrinsic *RsrcIntr =
1517 AttributeSet Attr =
1519 MemoryEffects ME = Attr.getMemoryEffects();
1520 if (ME.doesNotAccessMemory())
1521 return;
1522
1523 bool IsSPrefetch = IntrID == Intrinsic::amdgcn_s_buffer_prefetch_data;
1524 if (!IsSPrefetch) {
1525 auto *Aux = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 1));
1526 if (Aux->getZExtValue() & AMDGPU::CPol::VOLATILE)
1528 }
1529
1531
1532 IntrinsicInfo Info;
1533 // TODO: Should images get their own address space?
1535
1536 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode = nullptr;
1537 if (RsrcIntr->IsImage) {
1538 const AMDGPU::ImageDimIntrinsicInfo *Intr =
1540 BaseOpcode = AMDGPU::getMIMGBaseOpcodeInfo(Intr->BaseOpcode);
1541 Info.align.reset();
1542 }
1543
1544 Value *RsrcArg = CI.getArgOperand(RsrcIntr->RsrcArg);
1545 if (auto *RsrcPtrTy = dyn_cast<PointerType>(RsrcArg->getType())) {
1546 if (RsrcPtrTy->getAddressSpace() == AMDGPUAS::BUFFER_RESOURCE)
1547 // We conservatively set the memory operand of a buffer intrinsic to the
1548 // base resource pointer, so that we can access alias information about
1549 // those pointers. Cases like "this points at the same value
1550 // but with a different offset" are handled in
1551 // areMemAccessesTriviallyDisjoint.
1552 Info.ptrVal = RsrcArg;
1553 }
1554
1555 if (ME.onlyReadsMemory()) {
1556 if (RsrcIntr->IsImage) {
1557 unsigned MaxNumLanes = 4;
1558
1559 if (!BaseOpcode->Gather4) {
1560 // If this isn't a gather, we may have excess loaded elements in the
1561 // IR type. Check the dmask for the real number of elements loaded.
1562 unsigned DMask =
1563 cast<ConstantInt>(CI.getArgOperand(0))->getZExtValue();
1564 MaxNumLanes = DMask == 0 ? 1 : llvm::popcount(DMask);
1565 }
1566
1567 Info.memVT = memVTFromLoadIntrReturn(*this, MF.getDataLayout(),
1568 CI.getType(), MaxNumLanes);
1569 } else {
1570 Info.memVT =
1572 std::numeric_limits<unsigned>::max());
1573 }
1574
1575 // FIXME: What does alignment mean for an image?
1576 Info.opc = ISD::INTRINSIC_W_CHAIN;
1577 Info.flags = Flags | MachineMemOperand::MOLoad;
1578 } else if (ME.onlyWritesMemory()) {
1579 Info.opc = ISD::INTRINSIC_VOID;
1580
1581 Type *DataTy = CI.getArgOperand(0)->getType();
1582 if (RsrcIntr->IsImage) {
1583 unsigned DMask = cast<ConstantInt>(CI.getArgOperand(1))->getZExtValue();
1584 unsigned DMaskLanes = DMask == 0 ? 1 : llvm::popcount(DMask);
1585 Info.memVT = memVTFromLoadIntrData(*this, MF.getDataLayout(), DataTy,
1586 DMaskLanes);
1587 } else
1588 Info.memVT = getValueType(MF.getDataLayout(), DataTy);
1589
1590 Info.flags = Flags | MachineMemOperand::MOStore;
1591 } else {
1592 // Atomic, NoReturn Sampler or prefetch
1593 Info.opc = CI.getType()->isVoidTy() ? ISD::INTRINSIC_VOID
1595
1596 switch (IntrID) {
1597 default:
1598 Info.flags = Flags | MachineMemOperand::MOLoad;
1599 if (!IsSPrefetch)
1600 Info.flags |= MachineMemOperand::MOStore;
1601
1602 if ((RsrcIntr->IsImage && BaseOpcode->NoReturn) || IsSPrefetch) {
1603 // Fake memory access type for no return sampler intrinsics
1604 Info.memVT = MVT::i32;
1605 } else {
1606 // XXX - Should this be volatile without known ordering?
1607 Info.flags |= MachineMemOperand::MOVolatile;
1608 Info.memVT = MVT::getVT(CI.getArgOperand(0)->getType());
1609 }
1610 break;
1611 case Intrinsic::amdgcn_raw_buffer_load_lds:
1612 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
1613 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
1614 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
1615 case Intrinsic::amdgcn_struct_buffer_load_lds:
1616 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
1617 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
1618 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
1619 unsigned Width = cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue();
1620
1621 // Entry 0: Load from buffer.
1622 // Don't set an offset, since the pointer value always represents the
1623 // base of the buffer.
1624 Info.memVT = EVT::getIntegerVT(CI.getContext(), Width * 8);
1625 Info.flags = Flags | MachineMemOperand::MOLoad;
1626 Infos.push_back(Info);
1627
1628 // Entry 1: Store to LDS.
1629 // Instruction offset is applied, and an additional per-lane offset
1630 // which we simulate using a larger memory type.
1631 Info.memVT = EVT::getIntegerVT(
1632 CI.getContext(), Width * 8 * Subtarget->getWavefrontSize());
1633 Info.ptrVal = CI.getArgOperand(1); // LDS destination pointer
1634 Info.offset = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 2))
1635 ->getZExtValue();
1636 Info.fallbackAddressSpace = AMDGPUAS::LOCAL_ADDRESS;
1637 Info.flags = Flags | MachineMemOperand::MOStore;
1638 Infos.push_back(Info);
1639 return;
1640 }
1641 case Intrinsic::amdgcn_raw_atomic_buffer_load:
1642 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
1643 case Intrinsic::amdgcn_struct_atomic_buffer_load:
1644 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
1645 Info.memVT =
1647 std::numeric_limits<unsigned>::max());
1648 Info.flags = Flags | MachineMemOperand::MOLoad;
1649 Infos.push_back(Info);
1650 return;
1651 }
1652 }
1653 }
1654 Infos.push_back(Info);
1655 return;
1656 }
1657
1658 IntrinsicInfo Info;
1659 switch (IntrID) {
1660 case Intrinsic::amdgcn_ds_ordered_add:
1661 case Intrinsic::amdgcn_ds_ordered_swap: {
1662 Info.opc = ISD::INTRINSIC_W_CHAIN;
1663 Info.memVT = MVT::getVT(CI.getType());
1664 Info.ptrVal = CI.getOperand(0);
1665 Info.align.reset();
1667
1668 const ConstantInt *Vol = cast<ConstantInt>(CI.getOperand(4));
1669 if (!Vol->isZero())
1670 Info.flags |= MachineMemOperand::MOVolatile;
1671
1672 Infos.push_back(Info);
1673 return;
1674 }
1675 case Intrinsic::amdgcn_ds_add_gs_reg_rtn:
1676 case Intrinsic::amdgcn_ds_sub_gs_reg_rtn: {
1677 Info.opc = ISD::INTRINSIC_W_CHAIN;
1678 Info.memVT = MVT::getVT(CI.getOperand(0)->getType());
1679 Info.ptrVal = nullptr;
1680 Info.fallbackAddressSpace = AMDGPUAS::STREAMOUT_REGISTER;
1682 Infos.push_back(Info);
1683 return;
1684 }
1685 case Intrinsic::amdgcn_ds_append:
1686 case Intrinsic::amdgcn_ds_consume: {
1687 Info.opc = ISD::INTRINSIC_W_CHAIN;
1688 Info.memVT = MVT::getVT(CI.getType());
1689 Info.ptrVal = CI.getOperand(0);
1690 Info.align.reset();
1692
1693 const ConstantInt *Vol = cast<ConstantInt>(CI.getOperand(1));
1694 if (!Vol->isZero())
1695 Info.flags |= MachineMemOperand::MOVolatile;
1696
1697 Infos.push_back(Info);
1698 return;
1699 }
1700 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1701 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64: {
1702 Info.opc = (IntrID == Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64)
1705 Info.memVT = MVT::getVT(CI.getType());
1706 Info.ptrVal = CI.getOperand(0);
1707 Info.memVT = MVT::i64;
1708 Info.size = 8;
1709 Info.align.reset();
1711 Info.order = AtomicOrdering::Monotonic;
1712 Infos.push_back(Info);
1713 return;
1714 }
1715 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
1716 case Intrinsic::amdgcn_image_bvh_intersect_ray:
1717 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
1718 Info.opc = ISD::INTRINSIC_W_CHAIN;
1719 Info.memVT =
1720 MVT::getVT(IntrID == Intrinsic::amdgcn_image_bvh_intersect_ray
1721 ? CI.getType()
1723 ->getElementType(0)); // XXX: what is correct VT?
1724
1725 Info.fallbackAddressSpace = AMDGPUAS::BUFFER_RESOURCE;
1726 Info.align.reset();
1727 Info.flags = Flags | MachineMemOperand::MOLoad |
1729 Infos.push_back(Info);
1730 return;
1731 }
1732 case Intrinsic::amdgcn_global_atomic_fmin_num:
1733 case Intrinsic::amdgcn_global_atomic_fmax_num:
1734 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1735 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1736 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
1737 Info.opc = ISD::INTRINSIC_W_CHAIN;
1738 Info.memVT = MVT::getVT(CI.getType());
1739 Info.ptrVal = CI.getOperand(0);
1740 Info.align.reset();
1741 Info.flags =
1744 Infos.push_back(Info);
1745 return;
1746 }
1747 case Intrinsic::amdgcn_cluster_load_b32:
1748 case Intrinsic::amdgcn_cluster_load_b64:
1749 case Intrinsic::amdgcn_cluster_load_b128:
1750 case Intrinsic::amdgcn_ds_load_tr6_b96:
1751 case Intrinsic::amdgcn_ds_load_tr4_b64:
1752 case Intrinsic::amdgcn_ds_load_tr8_b64:
1753 case Intrinsic::amdgcn_ds_load_tr16_b128:
1754 case Intrinsic::amdgcn_global_load_tr6_b96:
1755 case Intrinsic::amdgcn_global_load_tr4_b64:
1756 case Intrinsic::amdgcn_global_load_tr_b64:
1757 case Intrinsic::amdgcn_global_load_tr_b128:
1758 case Intrinsic::amdgcn_ds_read_tr4_b64:
1759 case Intrinsic::amdgcn_ds_read_tr6_b96:
1760 case Intrinsic::amdgcn_ds_read_tr8_b64:
1761 case Intrinsic::amdgcn_ds_read_tr16_b64: {
1762 Info.opc = ISD::INTRINSIC_W_CHAIN;
1763 Info.memVT = MVT::getVT(CI.getType());
1764 Info.ptrVal = CI.getOperand(0);
1765 Info.align.reset();
1766 Info.flags = Flags | MachineMemOperand::MOLoad;
1767 Infos.push_back(Info);
1768 return;
1769 }
1770 case Intrinsic::amdgcn_flat_load_monitor_b32:
1771 case Intrinsic::amdgcn_flat_load_monitor_b64:
1772 case Intrinsic::amdgcn_flat_load_monitor_b128:
1773 case Intrinsic::amdgcn_global_load_monitor_b32:
1774 case Intrinsic::amdgcn_global_load_monitor_b64:
1775 case Intrinsic::amdgcn_global_load_monitor_b128: {
1776 Info.opc = ISD::INTRINSIC_W_CHAIN;
1777 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1778 Info.ptrVal = CI.getOperand(0);
1779 Info.align.reset();
1780 Info.flags = MachineMemOperand::MOLoad;
1781 Info.order = parseAtomicOrderingCABIArg(CI, 1);
1782 Info.ssid = parseSyncscopeMDArg(CI, 2);
1783 Infos.push_back(Info);
1784 return;
1785 }
1786 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1787 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1788 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
1789 Info.opc = ISD::INTRINSIC_W_CHAIN;
1790 Info.memVT = MVT::getVT(CI.getType());
1791 Info.ptrVal = CI.getOperand(0);
1792 Info.align.reset();
1794 Info.order = parseAtomicOrderingCABIArg(CI, 1);
1795 Info.ssid = parseSyncscopeMDArg(CI, 2);
1796 Infos.push_back(Info);
1797 return;
1798 }
1799 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1800 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1801 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
1802 Info.opc = ISD::INTRINSIC_VOID;
1803 Info.memVT = MVT::getVT(CI.getArgOperand(1)->getType());
1804 Info.ptrVal = CI.getArgOperand(0);
1805 Info.align.reset();
1807 Info.order = parseAtomicOrderingCABIArg(CI, 2);
1808 Info.ssid = parseSyncscopeMDArg(CI, 3);
1809 Infos.push_back(Info);
1810 return;
1811 }
1812 case Intrinsic::amdgcn_ds_gws_init:
1813 case Intrinsic::amdgcn_ds_gws_barrier:
1814 case Intrinsic::amdgcn_ds_gws_sema_v:
1815 case Intrinsic::amdgcn_ds_gws_sema_br:
1816 case Intrinsic::amdgcn_ds_gws_sema_p:
1817 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
1818 Info.opc = ISD::INTRINSIC_VOID;
1819
1820 const GCNTargetMachine &TM =
1821 static_cast<const GCNTargetMachine &>(getTargetMachine());
1822
1824 Info.ptrVal = MFI->getGWSPSV(TM);
1825
1826 // This is an abstract access, but we need to specify a type and size.
1827 Info.memVT = MVT::i32;
1828 Info.size = 4;
1829 Info.align = Align(4);
1830
1831 if (IntrID == Intrinsic::amdgcn_ds_gws_barrier)
1832 Info.flags = Flags | MachineMemOperand::MOLoad;
1833 else
1834 Info.flags = Flags | MachineMemOperand::MOStore;
1835 Infos.push_back(Info);
1836 return;
1837 }
1838 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1839 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1840 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1841 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1842 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1843 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1844 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1845 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
1846 // Entry 0: Load from source (global/flat).
1847 Info.opc = ISD::INTRINSIC_VOID;
1848 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1849 Info.ptrVal = CI.getArgOperand(0); // Global pointer
1850 Info.offset = cast<ConstantInt>(CI.getArgOperand(2))->getSExtValue();
1851 Info.flags = Flags | MachineMemOperand::MOLoad;
1852 Infos.push_back(Info);
1853
1854 // Entry 1: Store to LDS (same offset).
1855 Info.flags = Flags | MachineMemOperand::MOStore;
1856 Info.ptrVal = CI.getArgOperand(1); // LDS pointer
1857 Infos.push_back(Info);
1858 return;
1859 }
1860 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1861 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1862 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1863 case Intrinsic::amdgcn_global_store_async_from_lds_b128: {
1864 // Entry 0: Load from LDS.
1865 Info.opc = ISD::INTRINSIC_VOID;
1866 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1867 Info.ptrVal = CI.getArgOperand(1); // LDS pointer
1868 Info.offset = cast<ConstantInt>(CI.getArgOperand(2))->getSExtValue();
1869 Info.flags = Flags | MachineMemOperand::MOLoad;
1870 Infos.push_back(Info);
1871
1872 // Entry 1: Store to global (same offset).
1873 Info.flags = Flags | MachineMemOperand::MOStore;
1874 Info.ptrVal = CI.getArgOperand(0); // Global pointer
1875 Infos.push_back(Info);
1876 return;
1877 }
1878 case Intrinsic::amdgcn_av_load_b128:
1879 case Intrinsic::amdgcn_av_store_b128: {
1880 bool IsStore = IntrID == Intrinsic::amdgcn_av_store_b128;
1881 Info.opc = IsStore ? ISD::INTRINSIC_VOID : ISD::INTRINSIC_W_CHAIN;
1882 Info.memVT = MVT::v4i32;
1883 Info.ptrVal = CI.getArgOperand(0);
1884 Info.align = Align(16);
1885 Info.flags |=
1887 // Pretend to be atomic so that SIMemoryLegalizer::expandStore sets cache
1888 // flags appropriately.
1889 Info.order = AtomicOrdering::Monotonic;
1890
1891 LLVMContext &Ctx = CI.getContext();
1892 unsigned ScopeIdx = CI.arg_size() - 1;
1893 MDNode *ScopeMD = cast<MDNode>(
1894 cast<MetadataAsValue>(CI.getArgOperand(ScopeIdx))->getMetadata());
1895 StringRef Scope = cast<MDString>(ScopeMD->getOperand(0))->getString();
1896 Info.ssid = Ctx.getOrInsertSyncScopeID(Scope);
1897 Infos.push_back(Info);
1898 return;
1899 }
1900 case Intrinsic::amdgcn_load_to_lds:
1901 case Intrinsic::amdgcn_load_async_to_lds:
1902 case Intrinsic::amdgcn_global_load_lds:
1903 case Intrinsic::amdgcn_global_load_async_lds: {
1904 unsigned Width = cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue();
1905 auto *Aux = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 1));
1906 bool IsVolatile = Aux->getZExtValue() & AMDGPU::CPol::VOLATILE;
1907 if (IsVolatile)
1909
1910 // Entry 0: Load from source (global/flat).
1911 Info.opc = ISD::INTRINSIC_VOID;
1912 Info.memVT = EVT::getIntegerVT(CI.getContext(), Width * 8);
1913 Info.ptrVal = CI.getArgOperand(0); // Source pointer
1914 Info.offset = cast<ConstantInt>(CI.getArgOperand(3))->getSExtValue();
1915 Info.flags = Flags | MachineMemOperand::MOLoad;
1916 Infos.push_back(Info);
1917
1918 // Entry 1: Store to LDS.
1919 // Same offset from the instruction, but an additional per-lane offset is
1920 // added. Represent that using a wider memory type.
1921 Info.memVT = EVT::getIntegerVT(CI.getContext(),
1922 Width * 8 * Subtarget->getWavefrontSize());
1923 Info.ptrVal = CI.getArgOperand(1); // LDS destination pointer
1924 Info.flags = Flags | MachineMemOperand::MOStore;
1925 Infos.push_back(Info);
1926 return;
1927 }
1928 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
1929 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
1930 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
1931 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn: {
1932 Info.opc = ISD::INTRINSIC_W_CHAIN;
1933
1934 const GCNTargetMachine &TM =
1935 static_cast<const GCNTargetMachine &>(getTargetMachine());
1936
1938 Info.ptrVal = MFI->getGWSPSV(TM);
1939
1940 // This is an abstract access, but we need to specify a type and size.
1941 Info.memVT = MVT::i32;
1942 Info.size = 4;
1943 Info.align = Align(4);
1944
1946 Infos.push_back(Info);
1947 return;
1948 }
1949 case Intrinsic::amdgcn_s_prefetch_data:
1950 case Intrinsic::amdgcn_s_prefetch_inst:
1951 case Intrinsic::amdgcn_flat_prefetch:
1952 case Intrinsic::amdgcn_global_prefetch: {
1953 Info.opc = ISD::INTRINSIC_VOID;
1954 Info.memVT = EVT::getIntegerVT(CI.getContext(), 8);
1955 Info.ptrVal = CI.getArgOperand(0);
1956 Info.flags = Flags | MachineMemOperand::MOLoad;
1957 Infos.push_back(Info);
1958 return;
1959 }
1960 default:
1961 return;
1962 }
1963}
1964
1967 Type *&AccessTy) const {
1968 Value *Ptr = nullptr;
1969 switch (II->getIntrinsicID()) {
1970 case Intrinsic::amdgcn_cluster_load_b128:
1971 case Intrinsic::amdgcn_cluster_load_b64:
1972 case Intrinsic::amdgcn_cluster_load_b32:
1973 case Intrinsic::amdgcn_ds_append:
1974 case Intrinsic::amdgcn_ds_consume:
1975 case Intrinsic::amdgcn_ds_load_tr8_b64:
1976 case Intrinsic::amdgcn_ds_load_tr16_b128:
1977 case Intrinsic::amdgcn_ds_load_tr4_b64:
1978 case Intrinsic::amdgcn_ds_load_tr6_b96:
1979 case Intrinsic::amdgcn_ds_read_tr4_b64:
1980 case Intrinsic::amdgcn_ds_read_tr6_b96:
1981 case Intrinsic::amdgcn_ds_read_tr8_b64:
1982 case Intrinsic::amdgcn_ds_read_tr16_b64:
1983 case Intrinsic::amdgcn_ds_ordered_add:
1984 case Intrinsic::amdgcn_ds_ordered_swap:
1985 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1986 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64:
1987 case Intrinsic::amdgcn_flat_atomic_fmax_num:
1988 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1989 case Intrinsic::amdgcn_global_atomic_fmax_num:
1990 case Intrinsic::amdgcn_global_atomic_fmin_num:
1991 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1992 case Intrinsic::amdgcn_global_load_tr_b64:
1993 case Intrinsic::amdgcn_global_load_tr_b128:
1994 case Intrinsic::amdgcn_global_load_tr4_b64:
1995 case Intrinsic::amdgcn_global_load_tr6_b96:
1996 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1997 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1998 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1999 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
2000 case Intrinsic::amdgcn_av_load_b128:
2001 case Intrinsic::amdgcn_av_store_b128:
2002 Ptr = II->getArgOperand(0);
2003 break;
2004 case Intrinsic::amdgcn_load_to_lds:
2005 case Intrinsic::amdgcn_load_async_to_lds:
2006 case Intrinsic::amdgcn_global_load_lds:
2007 case Intrinsic::amdgcn_global_load_async_lds:
2008 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
2009 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
2010 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
2011 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
2012 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
2013 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
2014 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
2015 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
2016 Ptr = II->getArgOperand(1);
2017 break;
2018 default:
2019 return false;
2020 }
2021 AccessTy = II->getType();
2022 Ops.push_back(Ptr);
2023 return true;
2024}
2025
2027 unsigned AddrSpace) const {
2028 if (!Subtarget->hasFlatInstOffsets()) {
2029 // Flat instructions do not have offsets, and only have the register
2030 // address.
2031 return AM.BaseOffs == 0 && AM.Scale == 0;
2032 }
2033
2035 FlatAddrSpace FlatVariant =
2036 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS ? FlatAddrSpace::FlatGlobal
2037 : AddrSpace == AMDGPUAS::PRIVATE_ADDRESS ? FlatAddrSpace::FlatScratch
2038 : FlatAddrSpace::FLAT;
2039
2040 return AM.Scale == 0 &&
2041 (AM.BaseOffs == 0 || Subtarget->getInstrInfo()->isLegalFLATOffset(
2042 AM.BaseOffs, AddrSpace, FlatVariant));
2043}
2044
2046 if (Subtarget->hasFlatGlobalInsts())
2048
2049 if (!Subtarget->hasAddr64() || Subtarget->useFlatForGlobal()) {
2050 // Assume the we will use FLAT for all global memory accesses
2051 // on VI.
2052 // FIXME: This assumption is currently wrong. On VI we still use
2053 // MUBUF instructions for the r + i addressing mode. As currently
2054 // implemented, the MUBUF instructions only work on buffer < 4GB.
2055 // It may be possible to support > 4GB buffers with MUBUF instructions,
2056 // by setting the stride value in the resource descriptor which would
2057 // increase the size limit to (stride * 4GB). However, this is risky,
2058 // because it has never been validated.
2060 }
2061
2062 return isLegalMUBUFAddressingMode(AM);
2063}
2064
2065bool SITargetLowering::isLegalMUBUFAddressingMode(const AddrMode &AM) const {
2066 // MUBUF / MTBUF instructions have a 12-bit unsigned byte offset, and
2067 // additionally can do r + r + i with addr64. 32-bit has more addressing
2068 // mode options. Depending on the resource constant, it can also do
2069 // (i64 r0) + (i32 r1) * (i14 i).
2070 //
2071 // Private arrays end up using a scratch buffer most of the time, so also
2072 // assume those use MUBUF instructions. Scratch loads / stores are currently
2073 // implemented as mubuf instructions with offen bit set, so slightly
2074 // different than the normal addr64.
2075 const SIInstrInfo *TII = Subtarget->getInstrInfo();
2076 if (!TII->isLegalMUBUFImmOffset(AM.BaseOffs))
2077 return false;
2078
2079 // FIXME: Since we can split immediate into soffset and immediate offset,
2080 // would it make sense to allow any immediate?
2081
2082 switch (AM.Scale) {
2083 case 0: // r + i or just i, depending on HasBaseReg.
2084 return true;
2085 case 1:
2086 return true; // We have r + r or r + i.
2087 case 2:
2088 if (AM.HasBaseReg) {
2089 // Reject 2 * r + r.
2090 return false;
2091 }
2092
2093 // Allow 2 * r as r + r
2094 // Or 2 * r + i is allowed as r + r + i.
2095 return true;
2096 default: // Don't allow n * r
2097 return false;
2098 }
2099}
2100
2102 const AddrMode &AM, Type *Ty,
2103 unsigned AS,
2104 Instruction *I) const {
2105 // No global is ever allowed as a base.
2106 if (AM.BaseGV)
2107 return false;
2108
2109 if (AS == AMDGPUAS::GLOBAL_ADDRESS)
2110 return isLegalGlobalAddressingMode(AM);
2111
2112 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
2116 // If the offset isn't a multiple of 4, it probably isn't going to be
2117 // correctly aligned.
2118 // FIXME: Can we get the real alignment here?
2119 if (AM.BaseOffs % 4 != 0)
2120 return isLegalMUBUFAddressingMode(AM);
2121
2122 if (!Subtarget->hasScalarSubwordLoads()) {
2123 // There are no SMRD extloads, so if we have to do a small type access we
2124 // will use a MUBUF load.
2125 // FIXME?: We also need to do this if unaligned, but we don't know the
2126 // alignment here.
2127 if (Ty->isSized() && DL.getTypeStoreSize(Ty) < 4)
2128 return isLegalGlobalAddressingMode(AM);
2129 }
2130
2131 if (Subtarget->getGeneration() == AMDGPUSubtarget::SOUTHERN_ISLANDS) {
2132 // SMRD instructions have an 8-bit, dword offset on SI.
2133 if (!isUInt<8>(AM.BaseOffs / 4))
2134 return false;
2135 } else if (Subtarget->getGeneration() == AMDGPUSubtarget::SEA_ISLANDS) {
2136 // On CI+, this can also be a 32-bit literal constant offset. If it fits
2137 // in 8-bits, it can use a smaller encoding.
2138 if (!isUInt<32>(AM.BaseOffs / 4))
2139 return false;
2140 } else if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX9) {
2141 // On VI, these use the SMEM format and the offset is 20-bit in bytes.
2142 if (!isUInt<20>(AM.BaseOffs))
2143 return false;
2144 } else if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX12) {
2145 // On GFX9 the offset is signed 21-bit in bytes (but must not be negative
2146 // for S_BUFFER_* instructions).
2147 if (!isInt<21>(AM.BaseOffs))
2148 return false;
2149 } else {
2150 // On GFX12, all offsets are signed 24-bit in bytes.
2151 if (!isInt<24>(AM.BaseOffs))
2152 return false;
2153 }
2154
2155 if ((AS == AMDGPUAS::CONSTANT_ADDRESS ||
2157 AM.BaseOffs < 0) {
2158 // Scalar (non-buffer) loads can only use a negative offset if
2159 // soffset+offset is non-negative. Since the compiler can only prove that
2160 // in a few special cases, it is safer to claim that negative offsets are
2161 // not supported.
2162 return false;
2163 }
2164
2165 if (AM.Scale == 0) // r + i or just i, depending on HasBaseReg.
2166 return true;
2167
2168 if (AM.Scale == 1 && AM.HasBaseReg)
2169 return true;
2170
2171 return false;
2172 }
2173
2174 if (AS == AMDGPUAS::PRIVATE_ADDRESS)
2175 return Subtarget->hasFlatScratchEnabled()
2177 : isLegalMUBUFAddressingMode(AM);
2178
2179 if (AS == AMDGPUAS::LOCAL_ADDRESS ||
2180 (AS == AMDGPUAS::REGION_ADDRESS && Subtarget->hasGDS())) {
2181 // Basic, single offset DS instructions allow a 16-bit unsigned immediate
2182 // field.
2183 // XXX - If doing a 4-byte aligned 8-byte type access, we effectively have
2184 // an 8-bit dword offset but we don't know the alignment here.
2185 if (!isUInt<16>(AM.BaseOffs))
2186 return false;
2187
2188 if (AM.Scale == 0) // r + i or just i, depending on HasBaseReg.
2189 return true;
2190
2191 if (AM.Scale == 1 && AM.HasBaseReg)
2192 return true;
2193
2194 return false;
2195 }
2196
2198 // For an unknown address space, this usually means that this is for some
2199 // reason being used for pure arithmetic, and not based on some addressing
2200 // computation. We don't have instructions that compute pointers with any
2201 // addressing modes, so treat them as having no offset like flat
2202 // instructions.
2204 }
2205
2206 // Assume a user alias of global for unknown address spaces.
2207 return isLegalGlobalAddressingMode(AM);
2208}
2209
2211 const MachineFunction &MF) const {
2213 return (MemVT.getSizeInBits() <= 4 * 32);
2214 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
2215 unsigned MaxPrivateBits = 8 * getSubtarget()->getMaxPrivateElementSize();
2216 return (MemVT.getSizeInBits() <= MaxPrivateBits);
2217 }
2219 return (MemVT.getSizeInBits() <= 2 * 32);
2220 return true;
2221}
2222
2224 unsigned Size, unsigned AddrSpace, Align Alignment,
2225 MachineMemOperand::Flags Flags, unsigned *IsFast) const {
2226 if (IsFast)
2227 *IsFast = 0;
2228
2229 if (AddrSpace == AMDGPUAS::LOCAL_ADDRESS ||
2230 AddrSpace == AMDGPUAS::REGION_ADDRESS) {
2231 // Check if alignment requirements for ds_read/write instructions are
2232 // disabled.
2233 if (!Subtarget->hasUnalignedDSAccessEnabled() && Alignment < Align(4))
2234 return false;
2235
2236 Align RequiredAlignment(
2237 PowerOf2Ceil(divideCeil(Size, 8))); // Natural alignment.
2238 if (Subtarget->hasLDSMisalignedBugInWGPMode() && Size > 32 &&
2239 Alignment < RequiredAlignment)
2240 return false;
2241
2242 // Either, the alignment requirements are "enabled", or there is an
2243 // unaligned LDS access related hardware bug though alignment requirements
2244 // are "disabled". In either case, we need to check for proper alignment
2245 // requirements.
2246 //
2247 switch (Size) {
2248 case 64:
2249 // SI has a hardware bug in the LDS / GDS bounds checking: if the base
2250 // address is negative, then the instruction is incorrectly treated as
2251 // out-of-bounds even if base + offsets is in bounds. Split vectorized
2252 // loads here to avoid emitting ds_read2_b32. We may re-combine the
2253 // load later in the SILoadStoreOptimizer.
2254 if (!Subtarget->hasUsableDSOffset() && Alignment < Align(8))
2255 return false;
2256
2257 // 8 byte accessing via ds_read/write_b64 require 8-byte alignment, but we
2258 // can do a 4 byte aligned, 8 byte access in a single operation using
2259 // ds_read2/write2_b32 with adjacent offsets.
2260 RequiredAlignment = Align(4);
2261
2262 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2263 // We will either select ds_read_b64/ds_write_b64 or ds_read2_b32/
2264 // ds_write2_b32 depending on the alignment. In either case with either
2265 // alignment there is no faster way of doing this.
2266
2267 // The numbers returned here and below are not additive, it is a 'speed
2268 // rank'. They are just meant to be compared to decide if a certain way
2269 // of lowering an operation is faster than another. For that purpose
2270 // naturally aligned operation gets it bitsize to indicate that "it
2271 // operates with a speed comparable to N-bit wide load". With the full
2272 // alignment ds128 is slower than ds96 for example. If underaligned it
2273 // is comparable to a speed of a single dword access, which would then
2274 // mean 32 < 128 and it is faster to issue a wide load regardless.
2275 // 1 is simply "slow, don't do it". I.e. comparing an aligned load to a
2276 // wider load which will not be aligned anymore the latter is slower.
2277 if (IsFast)
2278 *IsFast = (Alignment >= RequiredAlignment) ? 64
2279 : (Alignment < Align(4)) ? 32
2280 : 1;
2281 return true;
2282 }
2283
2284 break;
2285 case 96:
2286 if (!Subtarget->hasDS96AndDS128())
2287 return false;
2288
2289 // 12 byte accessing via ds_read/write_b96 require 16-byte alignment on
2290 // gfx8 and older.
2291
2292 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2293 // Naturally aligned access is fastest. However, also report it is Fast
2294 // if memory is aligned less than DWORD. A narrow load or store will be
2295 // be equally slow as a single ds_read_b96/ds_write_b96, but there will
2296 // be more of them, so overall we will pay less penalty issuing a single
2297 // instruction.
2298
2299 // See comment on the values above.
2300 if (IsFast)
2301 *IsFast = (Alignment >= RequiredAlignment) ? 96
2302 : (Alignment < Align(4)) ? 32
2303 : 1;
2304 return true;
2305 }
2306
2307 break;
2308 case 128:
2309 if (!Subtarget->hasDS96AndDS128() || !Subtarget->useDS128())
2310 return false;
2311
2312 // 16 byte accessing via ds_read/write_b128 require 16-byte alignment on
2313 // gfx8 and older, but we can do a 8 byte aligned, 16 byte access in a
2314 // single operation using ds_read2/write2_b64.
2315 RequiredAlignment = Align(8);
2316
2317 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2318 // Naturally aligned access is fastest. However, also report it is Fast
2319 // if memory is aligned less than DWORD. A narrow load or store will be
2320 // be equally slow as a single ds_read_b128/ds_write_b128, but there
2321 // will be more of them, so overall we will pay less penalty issuing a
2322 // single instruction.
2323
2324 // See comment on the values above.
2325 if (IsFast)
2326 *IsFast = (Alignment >= RequiredAlignment) ? 128
2327 : (Alignment < Align(4)) ? 32
2328 : 1;
2329 return true;
2330 }
2331
2332 break;
2333 default:
2334 if (Size > 32)
2335 return false;
2336
2337 break;
2338 }
2339
2340 // See comment on the values above.
2341 // Note that we have a single-dword or sub-dword here, so if underaligned
2342 // it is a slowest possible access, hence returned value is 0.
2343 if (IsFast)
2344 *IsFast = (Alignment >= RequiredAlignment) ? Size : 0;
2345
2346 return Alignment >= RequiredAlignment ||
2347 Subtarget->hasUnalignedDSAccessEnabled();
2348 }
2349
2350 // FIXME: We have to be conservative here and assume that flat operations
2351 // will access scratch. If we had access to the IR function, then we
2352 // could determine if any private memory was used in the function.
2353 if (AddrSpace == AMDGPUAS::PRIVATE_ADDRESS ||
2354 AddrSpace == AMDGPUAS::FLAT_ADDRESS) {
2355 bool AlignedBy4 = Alignment >= Align(4);
2356 if (Subtarget->hasUnalignedScratchAccessEnabled()) {
2357 if (IsFast)
2358 *IsFast = AlignedBy4 ? Size : 1;
2359 return true;
2360 }
2361
2362 if (IsFast)
2363 *IsFast = AlignedBy4;
2364
2365 return AlignedBy4;
2366 }
2367
2368 // So long as they are correct, wide global memory operations perform better
2369 // than multiple smaller memory ops -- even when misaligned
2370 if (AMDGPU::isExtendedGlobalAddrSpace(AddrSpace)) {
2371 if (IsFast)
2372 *IsFast = Size;
2373
2374 return Alignment >= Align(4) ||
2375 Subtarget->hasUnalignedBufferAccessEnabled();
2376 }
2377
2378 // Ensure robust out-of-bounds guarantees for buffer accesses are met when the
2379 // "amdgpu.buffer.oob.mode" module flag has not enabled relaxed untyped-buffer
2380 // OOB semantics. Normally hardware will ensure proper
2381 // out-of-bounds behavior, but in the edge case where an access starts
2382 // out-of-bounds and then enters in-bounds, the entire access would be treated
2383 // as out-of-bounds. Prevent misaligned memory accesses by requiring the
2384 // natural alignment of buffer accesses.
2385 if (AddrSpace == AMDGPUAS::BUFFER_FAT_POINTER ||
2386 AddrSpace == AMDGPUAS::BUFFER_RESOURCE ||
2387 AddrSpace == AMDGPUAS::BUFFER_STRIDED_POINTER) {
2388 if (!Subtarget->hasRelaxedBufferOOBMode() &&
2389 Alignment < Align(PowerOf2Ceil(divideCeil(Size, 8))))
2390 return false;
2391 }
2392
2393 // Smaller than dword value must be aligned.
2394 if (Size < 32)
2395 return false;
2396
2397 // 8.1.6 - For Dword or larger reads or writes, the two LSBs of the
2398 // byte-address are ignored, thus forcing Dword alignment.
2399 // This applies to private, global, and constant memory.
2400 if (IsFast)
2401 *IsFast = 1;
2402
2403 return Size >= 32 && Alignment >= Align(4);
2404}
2405
2407 EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags,
2408 unsigned *IsFast) const {
2410 Alignment, Flags, IsFast);
2411}
2412
2414 LLVMContext &Context, const MemOp &Op,
2415 const AttributeList &FuncAttributes) const {
2416 // FIXME: Should account for address space here.
2417
2418 // The default fallback uses the private pointer size as a guess for a type to
2419 // use. Make sure we switch these to 64-bit accesses.
2420
2421 if (Op.size() >= 16 &&
2422 Op.isDstAligned(Align(4))) // XXX: Should only do for global
2423 return MVT::v4i32;
2424
2425 if (Op.size() >= 8 && Op.isDstAligned(Align(4)))
2426 return MVT::v2i32;
2427
2428 // Use the default.
2429 return MVT::Other;
2430}
2431
2433 const MemSDNode *MemNode = cast<MemSDNode>(N);
2434 return MemNode->getMemOperand()->getFlags() & MONoClobber;
2435}
2436
2441
2443 unsigned DestAS) const {
2444 if (SrcAS == AMDGPUAS::FLAT_ADDRESS) {
2445 if (DestAS == AMDGPUAS::PRIVATE_ADDRESS &&
2446 Subtarget->hasGloballyAddressableScratch()) {
2447 // Flat -> private requires subtracting src_flat_scratch_base_lo.
2448 return false;
2449 }
2450
2451 // Flat -> private/local is a simple truncate.
2452 // Flat -> global is no-op
2453 return true;
2454 }
2455
2456 const GCNTargetMachine &TM =
2457 static_cast<const GCNTargetMachine &>(getTargetMachine());
2458 return TM.isNoopAddrSpaceCast(DL, SrcAS, DestAS);
2459}
2460
2468
2470 Type *Ty) const {
2471 // FIXME: Could be smarter if called for vector constants.
2472 return true;
2473}
2474
2477 unsigned Index) const {
2480
2481 // TODO: Add more cases that are cheap.
2482 if (Index == 0)
2485}
2486
2487bool SITargetLowering::isExtractVecEltCheap(EVT VT, unsigned Index) const {
2488 // TODO: This should be more aggressive, particular for 16-bit element
2489 // vectors. However there are some mixed improvements and regressions.
2490 EVT EltTy = VT.getVectorElementType();
2491 unsigned MinAlign = Subtarget->useRealTrue16Insts() ? 16 : 32;
2492 return EltTy.getSizeInBits() % MinAlign == 0;
2493}
2494
2496 if (Subtarget->has16BitInsts() && VT == MVT::i16) {
2497 switch (Op) {
2498 case ISD::LOAD:
2499 case ISD::STORE:
2500 return true;
2501 default:
2502 return false;
2503 }
2504 }
2505
2506 // SimplifySetCC uses this function to determine whether or not it should
2507 // create setcc with i1 operands. We don't have instructions for i1 setcc.
2508 if (VT == MVT::i1 && Op == ISD::SETCC)
2509 return false;
2510
2511 if (VT.getScalarType() == MVT::i64 &&
2513 return false;
2514
2516}
2517
2519 // Do not convert uniform loads to 16-bit.
2520 // Uniform 16-bit loads are legalized to i16 = trunc (zextload i16->i32)
2521 // to match subword load patterns. Allowing conversion back to a 16-bit
2522 // load would create an infinite loop.
2523 if (Subtarget->hasScalarSubwordLoads() && N->getOpcode() == ISD::LOAD &&
2524 !VT.isVector() && VT.getSizeInBits() == 16) {
2525 auto *Load = dyn_cast<LoadSDNode>(N);
2526 if (Load && isUniformLoad(Load)) {
2527 return false;
2528 }
2529 }
2530
2531 return isTypeDesirableForOp(N->getOpcode(), VT);
2532}
2533
2535 const MachineMemOperand *MMO = Load->getMemOperand();
2536
2537 // FIXME: We ought to able able to take the direct isDivergent result. We
2538 // cannot rely on the MMO for a uniformity check, and should stop using
2539 // it. This is a hack for 2 ways that the IR divergence analysis is superior
2540 // to the DAG divergence: Recognizing shift-of-workitem-id as always
2541 // uniform, and isSingleLaneExecution. These should be handled in the DAG
2542 // version, and then this can be dropped.
2543 if (Load->isDivergent() && !AMDGPU::isUniformMMO(MMO))
2544 return false;
2545
2546 return MMO->getSize().hasValue() &&
2547 Load->getAlign() >=
2548 Align(std::min(MMO->getSize().getValue().getKnownMinValue(),
2549 uint64_t(4))) &&
2550 (MMO->isInvariant() ||
2551 (Load->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS ||
2552 Load->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT) ||
2553 (Load->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS &&
2554 Load->isSimple() && isMemOpHasNoClobberedMemOperand(Load)));
2555}
2556
2559 // This isn't really a constant pool but close enough.
2562 return PtrInfo;
2563}
2564
2565SDValue SITargetLowering::lowerKernArgParameterPtr(SelectionDAG &DAG,
2566 const SDLoc &SL,
2567 SDValue Chain,
2568 uint64_t Offset) const {
2569 const DataLayout &DL = DAG.getDataLayout();
2573
2574 auto [InputPtrReg, RC, ArgTy] =
2575 Info->getPreloadedValue(AMDGPUFunctionArgInfo::KERNARG_SEGMENT_PTR);
2576
2577 // We may not have the kernarg segment argument if we have no kernel
2578 // arguments.
2579 if (!InputPtrReg)
2580 return DAG.getConstant(Offset, SL, PtrVT);
2581
2583 SDValue BasePtr = DAG.getCopyFromReg(
2584 Chain, SL, MRI.getLiveInVirtReg(InputPtrReg->getRegister()), PtrVT);
2585
2586 return DAG.getObjectPtrOffset(SL, BasePtr, TypeSize::getFixed(Offset));
2587}
2588
2589SDValue SITargetLowering::getImplicitArgPtr(SelectionDAG &DAG,
2590 const SDLoc &SL) const {
2593 return lowerKernArgParameterPtr(DAG, SL, DAG.getEntryNode(), Offset);
2594}
2595
2596SDValue SITargetLowering::getLDSKernelId(SelectionDAG &DAG,
2597 const SDLoc &SL) const {
2598
2600 std::optional<uint32_t> KnownSize =
2602 if (KnownSize.has_value())
2603 return DAG.getConstant(*KnownSize, SL, MVT::i32);
2604 return SDValue();
2605}
2606
2607SDValue SITargetLowering::convertArgType(SelectionDAG &DAG, EVT VT, EVT MemVT,
2608 const SDLoc &SL, SDValue Val,
2609 bool Signed,
2610 const ISD::InputArg *Arg) const {
2611 // First, if it is a widened vector, narrow it.
2612 if (VT.isVector() &&
2614 EVT NarrowedVT =
2617 Val = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, NarrowedVT, Val,
2618 DAG.getConstant(0, SL, MVT::i32));
2619 }
2620
2621 // Then convert the vector elements or scalar value.
2622 if (Arg && (Arg->Flags.isSExt() || Arg->Flags.isZExt()) && VT.bitsLT(MemVT)) {
2623 unsigned Opc = Arg->Flags.isZExt() ? ISD::AssertZext : ISD::AssertSext;
2624 Val = DAG.getNode(Opc, SL, MemVT, Val, DAG.getValueType(VT));
2625 }
2626
2627 if (MemVT.isFloatingPoint()) {
2628 if (VT.isFloatingPoint()) {
2629 Val = getFPExtOrFPRound(DAG, Val, SL, VT);
2630 } else {
2631 assert(!MemVT.isVector());
2632 EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits());
2633 SDValue Cast = DAG.getBitcast(IntVT, Val);
2634 Val = DAG.getAnyExtOrTrunc(Cast, SL, VT);
2635 }
2636 } else if (Signed)
2637 Val = DAG.getSExtOrTrunc(Val, SL, VT);
2638 else
2639 Val = DAG.getZExtOrTrunc(Val, SL, VT);
2640
2641 return Val;
2642}
2643
2644SDValue SITargetLowering::lowerKernargMemParameter(
2645 SelectionDAG &DAG, EVT VT, EVT MemVT, const SDLoc &SL, SDValue Chain,
2646 uint64_t Offset, Align Alignment, bool Signed,
2647 const ISD::InputArg *Arg) const {
2648
2649 MachinePointerInfo PtrInfo =
2651
2652 // Try to avoid using an extload by loading earlier than the argument address,
2653 // and extracting the relevant bits. The load should hopefully be merged with
2654 // the previous argument.
2655 if (MemVT.getStoreSize() < 4 && Alignment < 4) {
2656 // TODO: Handle align < 4 and size >= 4 (can happen with packed structs).
2657 int64_t AlignDownOffset = alignDown(Offset, 4);
2658 int64_t OffsetDiff = Offset - AlignDownOffset;
2659
2660 EVT IntVT = MemVT.changeTypeToInteger();
2661
2662 // TODO: If we passed in the base kernel offset we could have a better
2663 // alignment than 4, but we don't really need it.
2664 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, AlignDownOffset);
2665 SDValue Load = DAG.getLoad(MVT::i32, SL, Chain, Ptr,
2666 PtrInfo.getWithOffset(AlignDownOffset), Align(4),
2669
2670 SDValue ShiftAmt = DAG.getConstant(OffsetDiff * 8, SL, MVT::i32);
2671 SDValue Extract = DAG.getNode(ISD::SRL, SL, MVT::i32, Load, ShiftAmt);
2672
2673 SDValue ArgVal = DAG.getNode(ISD::TRUNCATE, SL, IntVT, Extract);
2674 ArgVal = DAG.getNode(ISD::BITCAST, SL, MemVT, ArgVal);
2675 ArgVal = convertArgType(DAG, VT, MemVT, SL, ArgVal, Signed, Arg);
2676
2677 return DAG.getMergeValues({ArgVal, Load.getValue(1)}, SL);
2678 }
2679
2680 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, Offset);
2681 SDValue Load = DAG.getLoad(
2682 MemVT, SL, Chain, Ptr, PtrInfo.getWithOffset(Offset), Alignment,
2684
2685 SDValue Val = convertArgType(DAG, VT, MemVT, SL, Load, Signed, Arg);
2686 return DAG.getMergeValues({Val, Load.getValue(1)}, SL);
2687}
2688
2689/// Coerce an argument which was passed in a different ABI type to the original
2690/// expected value type.
2691SDValue SITargetLowering::convertABITypeToValueType(SelectionDAG &DAG,
2692 SDValue Val,
2693 CCValAssign &VA,
2694 const SDLoc &SL) const {
2695 EVT ValVT = VA.getValVT();
2696
2697 // If this is an 8 or 16-bit value, it is really passed promoted
2698 // to 32 bits. Insert an assert[sz]ext to capture this, then
2699 // truncate to the right size.
2700 switch (VA.getLocInfo()) {
2701 case CCValAssign::Full:
2702 return Val;
2703 case CCValAssign::BCvt:
2704 return DAG.getNode(ISD::BITCAST, SL, ValVT, Val);
2705 case CCValAssign::SExt:
2706 Val = DAG.getNode(ISD::AssertSext, SL, VA.getLocVT(), Val,
2707 DAG.getValueType(ValVT));
2708 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2709 case CCValAssign::ZExt:
2710 Val = DAG.getNode(ISD::AssertZext, SL, VA.getLocVT(), Val,
2711 DAG.getValueType(ValVT));
2712 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2713 case CCValAssign::AExt:
2714 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2715 default:
2716 llvm_unreachable("Unknown loc info!");
2717 }
2718}
2719
2720SDValue SITargetLowering::lowerStackParameter(SelectionDAG &DAG,
2721 CCValAssign &VA, const SDLoc &SL,
2722 SDValue Chain,
2723 const ISD::InputArg &Arg) const {
2725 MachineFrameInfo &MFI = MF.getFrameInfo();
2726
2727 if (Arg.Flags.isByVal()) {
2728 unsigned Size = Arg.Flags.getByValSize();
2729 int FrameIdx = MFI.CreateFixedObject(Size, VA.getLocMemOffset(), false);
2730 return DAG.getFrameIndex(FrameIdx, MVT::i32);
2731 }
2732
2733 unsigned ArgOffset = VA.getLocMemOffset();
2734 unsigned ArgSize = VA.getValVT().getStoreSize();
2735
2736 int FI = MFI.CreateFixedObject(ArgSize, ArgOffset, true);
2737
2738 // Create load nodes to retrieve arguments from the stack.
2739 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
2740
2741 // For NON_EXTLOAD, generic code in getLoad assert(ValVT == MemVT)
2743 MVT MemVT = VA.getValVT();
2744
2745 switch (VA.getLocInfo()) {
2746 default:
2747 break;
2748 case CCValAssign::BCvt:
2749 MemVT = VA.getLocVT();
2750 break;
2751 case CCValAssign::SExt:
2752 ExtType = ISD::SEXTLOAD;
2753 break;
2754 case CCValAssign::ZExt:
2755 ExtType = ISD::ZEXTLOAD;
2756 break;
2757 case CCValAssign::AExt:
2758 ExtType = ISD::EXTLOAD;
2759 break;
2760 }
2761
2762 SDValue ArgValue = DAG.getExtLoad(
2763 ExtType, SL, VA.getLocVT(), Chain, FIN,
2765
2766 SDValue ConvertedVal = convertABITypeToValueType(DAG, ArgValue, VA, SL);
2767 if (ConvertedVal == ArgValue)
2768 return ConvertedVal;
2769
2770 return DAG.getMergeValues({ConvertedVal, ArgValue.getValue(1)}, SL);
2771}
2772
2773SDValue SITargetLowering::lowerWorkGroupId(
2774 SelectionDAG &DAG, const SIMachineFunctionInfo &MFI, EVT VT,
2777 AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const {
2778 if (!Subtarget->hasClusters())
2779 return getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2780
2781 // Clusters are supported. Return the global position in the grid. If clusters
2782 // are enabled, WorkGroupIdPV returns the cluster ID not the workgroup ID.
2783
2784 // WorkGroupIdXYZ = ClusterId == 0 ?
2785 // ClusterIdXYZ :
2786 // ClusterIdXYZ * (ClusterMaxIdXYZ + 1) + ClusterWorkGroupIdXYZ
2787 SDValue ClusterIdXYZ = getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2788 SDLoc SL(ClusterIdXYZ);
2789 SDValue ClusterMaxIdXYZ = getPreloadedValue(DAG, MFI, VT, ClusterMaxIdPV);
2790 SDValue One = DAG.getConstant(1, SL, VT);
2791 SDValue ClusterSizeXYZ = DAG.getNode(ISD::ADD, SL, VT, ClusterMaxIdXYZ, One);
2792 SDValue ClusterWorkGroupIdXYZ =
2793 getPreloadedValue(DAG, MFI, VT, ClusterWorkGroupIdPV);
2794 SDValue GlobalIdXYZ =
2795 DAG.getNode(ISD::ADD, SL, VT, ClusterWorkGroupIdXYZ,
2796 DAG.getNode(ISD::MUL, SL, VT, ClusterIdXYZ, ClusterSizeXYZ));
2797
2798 switch (MFI.getClusterDims().getKind()) {
2801 return GlobalIdXYZ;
2803 return ClusterIdXYZ;
2805 using namespace AMDGPU::Hwreg;
2806 SDValue ClusterIdField =
2807 DAG.getTargetConstant(HwregEncoding::encode(ID_IB_STS2, 6, 4), SL, VT);
2808 SDNode *GetReg =
2809 DAG.getMachineNode(AMDGPU::S_GETREG_B32_const, SL, VT, ClusterIdField);
2810 SDValue ClusterId(GetReg, 0);
2811 SDValue Zero = DAG.getConstant(0, SL, VT);
2812 return DAG.getNode(ISD::SELECT_CC, SL, VT, ClusterId, Zero, ClusterIdXYZ,
2813 GlobalIdXYZ, DAG.getCondCode(ISD::SETEQ));
2814 }
2815 }
2816
2817 llvm_unreachable("nothing should reach here");
2818}
2819
2820SDValue SITargetLowering::getPreloadedValue(
2821 SelectionDAG &DAG, const SIMachineFunctionInfo &MFI, EVT VT,
2823 const ArgDescriptor *Reg = nullptr;
2824 const TargetRegisterClass *RC = nullptr;
2825 LLT Ty;
2826
2828 const ArgDescriptor WorkGroupIDX =
2829 ArgDescriptor::createRegister(AMDGPU::TTMP9);
2830 // If GridZ is not programmed in an entry function then the hardware will set
2831 // it to all zeros, so there is no need to mask the GridY value in the low
2832 // order bits.
2833 const ArgDescriptor WorkGroupIDY = ArgDescriptor::createRegister(
2834 AMDGPU::TTMP7,
2835 AMDGPU::isEntryFunctionCC(CC) && !MFI.hasWorkGroupIDZ() ? ~0u : 0xFFFFu);
2836 const ArgDescriptor WorkGroupIDZ =
2837 ArgDescriptor::createRegister(AMDGPU::TTMP7, 0xFFFF0000u);
2838 const ArgDescriptor ClusterWorkGroupIDX =
2839 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0000000Fu);
2840 const ArgDescriptor ClusterWorkGroupIDY =
2841 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x000000F0u);
2842 const ArgDescriptor ClusterWorkGroupIDZ =
2843 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x00000F00u);
2844 const ArgDescriptor ClusterWorkGroupMaxIDX =
2845 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0000F000u);
2846 const ArgDescriptor ClusterWorkGroupMaxIDY =
2847 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x000F0000u);
2848 const ArgDescriptor ClusterWorkGroupMaxIDZ =
2849 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x00F00000u);
2850 const ArgDescriptor ClusterWorkGroupMaxFlatID =
2851 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0F000000u);
2852
2853 auto LoadConstant = [&](unsigned N) {
2854 return DAG.getConstant(N, SDLoc(), VT);
2855 };
2856
2857 if (Subtarget->hasArchitectedSGPRs() &&
2859 AMDGPU::ClusterDimsAttr ClusterDims = MFI.getClusterDims();
2860 bool HasFixedDims = ClusterDims.isFixedDims();
2861
2862 switch (PVID) {
2864 Reg = &WorkGroupIDX;
2865 RC = &AMDGPU::SReg_32RegClass;
2866 Ty = LLT::scalar(32);
2867 break;
2869 Reg = &WorkGroupIDY;
2870 RC = &AMDGPU::SReg_32RegClass;
2871 Ty = LLT::scalar(32);
2872 break;
2874 Reg = &WorkGroupIDZ;
2875 RC = &AMDGPU::SReg_32RegClass;
2876 Ty = LLT::scalar(32);
2877 break;
2879 if (HasFixedDims && ClusterDims.getDims()[0] == 1)
2880 return LoadConstant(0);
2881 Reg = &ClusterWorkGroupIDX;
2882 RC = &AMDGPU::SReg_32RegClass;
2883 Ty = LLT::scalar(32);
2884 break;
2886 if (HasFixedDims && ClusterDims.getDims()[1] == 1)
2887 return LoadConstant(0);
2888 Reg = &ClusterWorkGroupIDY;
2889 RC = &AMDGPU::SReg_32RegClass;
2890 Ty = LLT::scalar(32);
2891 break;
2893 if (HasFixedDims && ClusterDims.getDims()[2] == 1)
2894 return LoadConstant(0);
2895 Reg = &ClusterWorkGroupIDZ;
2896 RC = &AMDGPU::SReg_32RegClass;
2897 Ty = LLT::scalar(32);
2898 break;
2900 if (HasFixedDims)
2901 return LoadConstant(ClusterDims.getDims()[0] - 1);
2902 Reg = &ClusterWorkGroupMaxIDX;
2903 RC = &AMDGPU::SReg_32RegClass;
2904 Ty = LLT::scalar(32);
2905 break;
2907 if (HasFixedDims)
2908 return LoadConstant(ClusterDims.getDims()[1] - 1);
2909 Reg = &ClusterWorkGroupMaxIDY;
2910 RC = &AMDGPU::SReg_32RegClass;
2911 Ty = LLT::scalar(32);
2912 break;
2914 if (HasFixedDims)
2915 return LoadConstant(ClusterDims.getDims()[2] - 1);
2916 Reg = &ClusterWorkGroupMaxIDZ;
2917 RC = &AMDGPU::SReg_32RegClass;
2918 Ty = LLT::scalar(32);
2919 break;
2921 Reg = &ClusterWorkGroupMaxFlatID;
2922 RC = &AMDGPU::SReg_32RegClass;
2923 Ty = LLT::scalar(32);
2924 break;
2925 default:
2926 break;
2927 }
2928 }
2929
2930 if (!Reg)
2931 std::tie(Reg, RC, Ty) = MFI.getPreloadedValue(PVID);
2932 if (!Reg) {
2934 // It's possible for a kernarg intrinsic call to appear in a kernel with
2935 // no allocated segment, in which case we do not add the user sgpr
2936 // argument, so just return null.
2937 return DAG.getConstant(0, SDLoc(), VT);
2938 }
2939
2940 // It's undefined behavior if a function marked with the amdgpu-no-*
2941 // attributes uses the corresponding intrinsic.
2942 return DAG.getPOISON(VT);
2943 }
2944
2945 return loadInputValue(DAG, RC, VT, SDLoc(DAG.getEntryNode()), *Reg);
2946}
2947
2949 CallingConv::ID CallConv,
2950 ArrayRef<ISD::InputArg> Ins, BitVector &Skipped,
2951 FunctionType *FType,
2952 SIMachineFunctionInfo *Info) {
2953 for (unsigned I = 0, E = Ins.size(), PSInputNum = 0; I != E; ++I) {
2954 const ISD::InputArg *Arg = &Ins[I];
2955
2956 assert((!Arg->VT.isVector() || Arg->VT.getScalarSizeInBits() == 16) &&
2957 "vector type argument should have been split");
2958
2959 // First check if it's a PS input addr.
2960 if (CallConv == CallingConv::AMDGPU_PS && !Arg->Flags.isInReg() &&
2961 PSInputNum <= 15) {
2962 bool SkipArg = !Arg->Used && !Info->isPSInputAllocated(PSInputNum);
2963
2964 // Inconveniently only the first part of the split is marked as isSplit,
2965 // so skip to the end. We only want to increment PSInputNum once for the
2966 // entire split argument.
2967 if (Arg->Flags.isSplit()) {
2968 while (!Arg->Flags.isSplitEnd()) {
2969 assert((!Arg->VT.isVector() || Arg->VT.getScalarSizeInBits() == 16) &&
2970 "unexpected vector split in ps argument type");
2971 if (!SkipArg)
2972 Splits.push_back(*Arg);
2973 Arg = &Ins[++I];
2974 }
2975 }
2976
2977 if (SkipArg) {
2978 // We can safely skip PS inputs.
2979 Skipped.set(Arg->getOrigArgIndex());
2980 ++PSInputNum;
2981 continue;
2982 }
2983
2984 Info->markPSInputAllocated(PSInputNum);
2985 if (Arg->Used)
2986 Info->markPSInputEnabled(PSInputNum);
2987
2988 ++PSInputNum;
2989 }
2990
2991 Splits.push_back(*Arg);
2992 }
2993}
2994
2995// Allocate special inputs passed in VGPRs.
2997 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
2998 SIMachineFunctionInfo &Info) const {
2999 const LLT I32 = LLT::integer(32);
3000 MachineRegisterInfo &MRI = MF.getRegInfo();
3001
3002 if (Info.hasWorkItemIDX()) {
3003 Register Reg = AMDGPU::VGPR0;
3004 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
3005
3006 CCInfo.AllocateReg(Reg);
3007 unsigned Mask =
3008 (Subtarget->hasPackedTID() && Info.hasWorkItemIDY()) ? 0x3ff : ~0u;
3009 Info.setWorkItemIDX(ArgDescriptor::createRegister(Reg, Mask));
3010 }
3011
3012 if (Info.hasWorkItemIDY()) {
3013 assert(Info.hasWorkItemIDX());
3014 if (Subtarget->hasPackedTID()) {
3015 Info.setWorkItemIDY(
3016 ArgDescriptor::createRegister(AMDGPU::VGPR0, 0x3ff << 10));
3017 } else {
3018 unsigned Reg = AMDGPU::VGPR1;
3019 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
3020
3021 CCInfo.AllocateReg(Reg);
3022 Info.setWorkItemIDY(ArgDescriptor::createRegister(Reg));
3023 }
3024 }
3025
3026 if (Info.hasWorkItemIDZ()) {
3027 assert(Info.hasWorkItemIDX() && Info.hasWorkItemIDY());
3028 if (Subtarget->hasPackedTID()) {
3029 Info.setWorkItemIDZ(
3030 ArgDescriptor::createRegister(AMDGPU::VGPR0, 0x3ff << 20));
3031 } else {
3032 unsigned Reg = AMDGPU::VGPR2;
3033 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
3034
3035 CCInfo.AllocateReg(Reg);
3036 Info.setWorkItemIDZ(ArgDescriptor::createRegister(Reg));
3037 }
3038 }
3039}
3040
3042 const TargetRegisterClass *RC,
3043 unsigned NumArgRegs) {
3044 ArrayRef<MCPhysReg> ArgSGPRs = ArrayRef(RC->begin(), 32);
3045 unsigned RegIdx = CCInfo.getFirstUnallocated(ArgSGPRs);
3046 if (RegIdx == ArgSGPRs.size())
3047 report_fatal_error("ran out of SGPRs for arguments");
3048
3049 unsigned Reg = ArgSGPRs[RegIdx];
3050 Reg = CCInfo.AllocateReg(Reg);
3051 assert(Reg != AMDGPU::NoRegister);
3052
3053 MachineFunction &MF = CCInfo.getMachineFunction();
3054 MF.addLiveIn(Reg, RC);
3056}
3057
3058// If this has a fixed position, we still should allocate the register in the
3059// CCInfo state. Technically we could get away with this for values passed
3060// outside of the normal argument range.
3062 const TargetRegisterClass *RC,
3063 MCRegister Reg) {
3064 Reg = CCInfo.AllocateReg(Reg);
3065 assert(Reg != AMDGPU::NoRegister);
3066 MachineFunction &MF = CCInfo.getMachineFunction();
3067 MF.addLiveIn(Reg, RC);
3068}
3069
3070static void allocateSGPR32Input(CCState &CCInfo, ArgDescriptor &Arg) {
3071 if (Arg) {
3072 allocateFixedSGPRInputImpl(CCInfo, &AMDGPU::SGPR_32RegClass,
3073 Arg.getRegister());
3074 } else
3075 Arg = allocateSGPR32InputImpl(CCInfo, &AMDGPU::SGPR_32RegClass, 32);
3076}
3077
3078static void allocateSGPR64Input(CCState &CCInfo, ArgDescriptor &Arg) {
3079 if (Arg) {
3080 allocateFixedSGPRInputImpl(CCInfo, &AMDGPU::SGPR_64RegClass,
3081 Arg.getRegister());
3082 } else
3083 Arg = allocateSGPR32InputImpl(CCInfo, &AMDGPU::SGPR_64RegClass, 16);
3084}
3085
3086/// Allocate implicit function VGPR arguments in fixed registers.
3088 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3089 SIMachineFunctionInfo &Info) const {
3090 Register Reg = CCInfo.AllocateReg(AMDGPU::VGPR31);
3091 if (!Reg)
3092 report_fatal_error("failed to allocate VGPR for implicit arguments");
3093
3094 const unsigned Mask = 0x3ff;
3095 Info.setWorkItemIDX(ArgDescriptor::createRegister(Reg, Mask));
3096 Info.setWorkItemIDY(ArgDescriptor::createRegister(Reg, Mask << 10));
3097 Info.setWorkItemIDZ(ArgDescriptor::createRegister(Reg, Mask << 20));
3098}
3099
3101 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3102 SIMachineFunctionInfo &Info) const {
3103 auto &ArgInfo = Info.getArgInfo();
3104 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info.getUserSGPRInfo();
3105
3106 // TODO: Unify handling with private memory pointers.
3107 if (UserSGPRInfo.hasDispatchPtr())
3108 allocateSGPR64Input(CCInfo, ArgInfo.DispatchPtr);
3109
3110 if (UserSGPRInfo.hasQueuePtr())
3111 allocateSGPR64Input(CCInfo, ArgInfo.QueuePtr);
3112
3113 // Implicit arg ptr takes the place of the kernarg segment pointer. This is a
3114 // constant offset from the kernarg segment.
3115 if (Info.hasImplicitArgPtr())
3116 allocateSGPR64Input(CCInfo, ArgInfo.ImplicitArgPtr);
3117
3118 if (UserSGPRInfo.hasDispatchID())
3119 allocateSGPR64Input(CCInfo, ArgInfo.DispatchID);
3120
3121 // flat_scratch_init is not applicable for non-kernel functions.
3122
3123 if (Info.hasWorkGroupIDX())
3124 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDX);
3125
3126 if (Info.hasWorkGroupIDY())
3127 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDY);
3128
3129 if (Info.hasWorkGroupIDZ())
3130 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDZ);
3131
3132 if (Info.hasLDSKernelId())
3133 allocateSGPR32Input(CCInfo, ArgInfo.LDSKernelId);
3134}
3135
3136// Allocate special inputs passed in user SGPRs.
3138 MachineFunction &MF,
3139 const SIRegisterInfo &TRI,
3140 SIMachineFunctionInfo &Info) const {
3141 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info.getUserSGPRInfo();
3142 if (UserSGPRInfo.hasImplicitBufferPtr()) {
3143 Register ImplicitBufferPtrReg = Info.addImplicitBufferPtr(TRI);
3144 MF.addLiveIn(ImplicitBufferPtrReg, &AMDGPU::SGPR_64RegClass);
3145 CCInfo.AllocateReg(ImplicitBufferPtrReg);
3146 }
3147
3148 // FIXME: How should these inputs interact with inreg / custom SGPR inputs?
3149 if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
3150 Register PrivateSegmentBufferReg = Info.addPrivateSegmentBuffer(TRI);
3151 MF.addLiveIn(PrivateSegmentBufferReg, &AMDGPU::SGPR_128RegClass);
3152 CCInfo.AllocateReg(PrivateSegmentBufferReg);
3153 }
3154
3155 if (UserSGPRInfo.hasDispatchPtr()) {
3156 Register DispatchPtrReg = Info.addDispatchPtr(TRI);
3157 MF.addLiveIn(DispatchPtrReg, &AMDGPU::SGPR_64RegClass);
3158 CCInfo.AllocateReg(DispatchPtrReg);
3159 }
3160
3161 if (UserSGPRInfo.hasQueuePtr()) {
3162 Register QueuePtrReg = Info.addQueuePtr(TRI);
3163 MF.addLiveIn(QueuePtrReg, &AMDGPU::SGPR_64RegClass);
3164 CCInfo.AllocateReg(QueuePtrReg);
3165 }
3166
3167 if (UserSGPRInfo.hasKernargSegmentPtr()) {
3168 MachineRegisterInfo &MRI = MF.getRegInfo();
3169 Register InputPtrReg = Info.addKernargSegmentPtr(TRI);
3170 CCInfo.AllocateReg(InputPtrReg);
3171
3172 Register VReg = MF.addLiveIn(InputPtrReg, &AMDGPU::SGPR_64RegClass);
3174 }
3175
3176 if (UserSGPRInfo.hasDispatchID()) {
3177 Register DispatchIDReg = Info.addDispatchID(TRI);
3178 MF.addLiveIn(DispatchIDReg, &AMDGPU::SGPR_64RegClass);
3179 CCInfo.AllocateReg(DispatchIDReg);
3180 }
3181
3182 if (UserSGPRInfo.hasFlatScratchInit() && !getSubtarget()->isAmdPalOS()) {
3183 Register FlatScratchInitReg = Info.addFlatScratchInit(TRI);
3184 MF.addLiveIn(FlatScratchInitReg, &AMDGPU::SGPR_64RegClass);
3185 CCInfo.AllocateReg(FlatScratchInitReg);
3186 }
3187
3188 if (UserSGPRInfo.hasPrivateSegmentSize()) {
3189 Register PrivateSegmentSizeReg = Info.addPrivateSegmentSize(TRI);
3190 MF.addLiveIn(PrivateSegmentSizeReg, &AMDGPU::SGPR_32RegClass);
3191 CCInfo.AllocateReg(PrivateSegmentSizeReg);
3192 }
3193
3194 // TODO: Add GridWorkGroupCount user SGPRs when used. For now with HSA we read
3195 // these from the dispatch pointer.
3196}
3197
3198// Allocate pre-loaded kernel arguemtns. Arguments to be preloading must be
3199// sequential starting from the first argument.
3201 CCState &CCInfo, SmallVectorImpl<CCValAssign> &ArgLocs,
3203 const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const {
3204 Function &F = MF.getFunction();
3205 unsigned LastExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();
3206 GCNUserSGPRUsageInfo &SGPRInfo = Info.getUserSGPRInfo();
3207 bool InPreloadSequence = true;
3208 unsigned InIdx = 0;
3209 bool AlignedForImplictArgs = false;
3210 unsigned ImplicitArgOffset = 0;
3211 for (auto &Arg : F.args()) {
3212 if (!InPreloadSequence || !Arg.hasInRegAttr())
3213 break;
3214
3215 unsigned ArgIdx = Arg.getArgNo();
3216 // Don't preload non-original args or parts not in the current preload
3217 // sequence.
3218 if (InIdx < Ins.size() &&
3219 (!Ins[InIdx].isOrigArg() || Ins[InIdx].getOrigArgIndex() != ArgIdx))
3220 break;
3221
3222 for (; InIdx < Ins.size() && Ins[InIdx].isOrigArg() &&
3223 Ins[InIdx].getOrigArgIndex() == ArgIdx;
3224 InIdx++) {
3225 assert(ArgLocs[ArgIdx].isMemLoc());
3226 auto &ArgLoc = ArgLocs[InIdx];
3227 const Align KernelArgBaseAlign = Align(16);
3228 unsigned ArgOffset = ArgLoc.getLocMemOffset();
3229 Align Alignment = commonAlignment(KernelArgBaseAlign, ArgOffset);
3230 unsigned NumAllocSGPRs =
3231 alignTo(ArgLoc.getLocVT().getFixedSizeInBits(), 32) / 32;
3232
3233 // Fix alignment for hidden arguments.
3234 if (Arg.hasAttribute("amdgpu-hidden-argument")) {
3235 if (!AlignedForImplictArgs) {
3236 ImplicitArgOffset =
3237 alignTo(LastExplicitArgOffset,
3238 Subtarget->getAlignmentForImplicitArgPtr()) -
3239 LastExplicitArgOffset;
3240 AlignedForImplictArgs = true;
3241 }
3242 ArgOffset += ImplicitArgOffset;
3243 }
3244
3245 // Arg is preloaded into the previous SGPR.
3246 if (ArgLoc.getLocVT().getStoreSize() < 4 && Alignment < 4) {
3247 assert(InIdx >= 1 && "No previous SGPR");
3248 Info.getArgInfo().PreloadKernArgs[InIdx].Regs.push_back(
3249 Info.getArgInfo().PreloadKernArgs[InIdx - 1].Regs[0]);
3250 continue;
3251 }
3252
3253 unsigned Padding = ArgOffset - LastExplicitArgOffset;
3254 unsigned PaddingSGPRs = alignTo(Padding, 4) / 4;
3255 // Check for free user SGPRs for preloading.
3256 if (PaddingSGPRs + NumAllocSGPRs > SGPRInfo.getNumFreeUserSGPRs()) {
3257 InPreloadSequence = false;
3258 break;
3259 }
3260
3261 // Preload this argument.
3262 const TargetRegisterClass *RC =
3263 TRI.getSGPRClassForBitWidth(NumAllocSGPRs * 32);
3264 SmallVectorImpl<MCRegister> *PreloadRegs =
3265 Info.addPreloadedKernArg(TRI, RC, NumAllocSGPRs, InIdx, PaddingSGPRs);
3266
3267 if (PreloadRegs->size() > 1)
3268 RC = &AMDGPU::SGPR_32RegClass;
3269 for (auto &Reg : *PreloadRegs) {
3270 assert(Reg);
3271 MF.addLiveIn(Reg, RC);
3272 CCInfo.AllocateReg(Reg);
3273 }
3274
3275 LastExplicitArgOffset = NumAllocSGPRs * 4 + ArgOffset;
3276 }
3277 }
3278}
3279
3281 const SIRegisterInfo &TRI,
3282 SIMachineFunctionInfo &Info) const {
3283 // Always allocate this last since it is a synthetic preload.
3284 if (Info.hasLDSKernelId()) {
3285 Register Reg = Info.addLDSKernelId();
3286 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3287 CCInfo.AllocateReg(Reg);
3288 }
3289}
3290
3291// Allocate special input registers that are initialized per-wave.
3294 CallingConv::ID CallConv,
3295 bool IsShader) const {
3296 bool HasArchitectedSGPRs = Subtarget->hasArchitectedSGPRs();
3297 if (Subtarget->hasUserSGPRInit16BugInWave32() && !IsShader) {
3298 // Note: user SGPRs are handled by the front-end for graphics shaders
3299 // Pad up the used user SGPRs with dead inputs.
3300
3301 // TODO: NumRequiredSystemSGPRs computation should be adjusted appropriately
3302 // before enabling architected SGPRs for workgroup IDs.
3303 assert(!HasArchitectedSGPRs && "Unhandled feature for the subtarget");
3304
3305 unsigned CurrentUserSGPRs = Info.getNumUserSGPRs();
3306 // Note we do not count the PrivateSegmentWaveByteOffset. We do not want to
3307 // rely on it to reach 16 since if we end up having no stack usage, it will
3308 // not really be added.
3309 unsigned NumRequiredSystemSGPRs =
3310 Info.hasWorkGroupIDX() + Info.hasWorkGroupIDY() +
3311 Info.hasWorkGroupIDZ() + Info.hasWorkGroupInfo();
3312 for (unsigned i = NumRequiredSystemSGPRs + CurrentUserSGPRs; i < 16; ++i) {
3313 Register Reg = Info.addReservedUserSGPR();
3314 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3315 CCInfo.AllocateReg(Reg);
3316 }
3317 }
3318
3319 if (!HasArchitectedSGPRs) {
3320 if (Info.hasWorkGroupIDX()) {
3321 Register Reg = Info.addWorkGroupIDX();
3322 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3323 CCInfo.AllocateReg(Reg);
3324 }
3325
3326 if (Info.hasWorkGroupIDY()) {
3327 Register Reg = Info.addWorkGroupIDY();
3328 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3329 CCInfo.AllocateReg(Reg);
3330 }
3331
3332 if (Info.hasWorkGroupIDZ()) {
3333 Register Reg = Info.addWorkGroupIDZ();
3334 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3335 CCInfo.AllocateReg(Reg);
3336 }
3337 }
3338
3339 if (Info.hasWorkGroupInfo()) {
3340 Register Reg = Info.addWorkGroupInfo();
3341 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3342 CCInfo.AllocateReg(Reg);
3343 }
3344
3345 if (Info.hasPrivateSegmentWaveByteOffset()) {
3346 // Scratch wave offset passed in system SGPR.
3347 unsigned PrivateSegmentWaveByteOffsetReg;
3348
3349 if (IsShader) {
3350 PrivateSegmentWaveByteOffsetReg =
3351 Info.getPrivateSegmentWaveByteOffsetSystemSGPR();
3352
3353 // This is true if the scratch wave byte offset doesn't have a fixed
3354 // location.
3355 if (PrivateSegmentWaveByteOffsetReg == AMDGPU::NoRegister) {
3356 PrivateSegmentWaveByteOffsetReg = findFirstFreeSGPR(CCInfo);
3357 Info.setPrivateSegmentWaveByteOffset(PrivateSegmentWaveByteOffsetReg);
3358 }
3359 } else
3360 PrivateSegmentWaveByteOffsetReg = Info.addPrivateSegmentWaveByteOffset();
3361
3362 MF.addLiveIn(PrivateSegmentWaveByteOffsetReg, &AMDGPU::SGPR_32RegClass);
3363 CCInfo.AllocateReg(PrivateSegmentWaveByteOffsetReg);
3364 }
3365
3366 assert(!Subtarget->hasUserSGPRInit16BugInWave32() || IsShader ||
3367 Info.getNumPreloadedSGPRs() >= 16);
3368}
3369
3371 MachineFunction &MF,
3372 const SIRegisterInfo &TRI,
3373 SIMachineFunctionInfo &Info) {
3374 // Now that we've figured out where the scratch register inputs are, see if
3375 // should reserve the arguments and use them directly.
3376 MachineFrameInfo &MFI = MF.getFrameInfo();
3377 bool HasStackObjects = MFI.hasStackObjects();
3378 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
3379
3380 // Record that we know we have non-spill stack objects so we don't need to
3381 // check all stack objects later.
3382 if (HasStackObjects)
3383 Info.setHasNonSpillStackObjects(true);
3384
3385 // Everything live out of a block is spilled with fast regalloc, so it's
3386 // almost certain that spilling will be required.
3388 HasStackObjects = true;
3389
3390 // For now assume stack access is needed in any callee functions, so we need
3391 // the scratch registers to pass in.
3392 bool RequiresStackAccess = HasStackObjects || MFI.hasCalls();
3393
3394 if (!ST.hasFlatScratchEnabled()) {
3395 if (RequiresStackAccess && ST.isAmdHsaOrMesa(MF.getFunction())) {
3396 // If we have stack objects, we unquestionably need the private buffer
3397 // resource. For the Code Object V2 ABI, this will be the first 4 user
3398 // SGPR inputs. We can reserve those and use them directly.
3399
3400 Register PrivateSegmentBufferReg =
3402 Info.setScratchRSrcReg(PrivateSegmentBufferReg);
3403 } else {
3404 unsigned ReservedBufferReg = TRI.reservedPrivateSegmentBufferReg(MF);
3405 // We tentatively reserve the last registers (skipping the last registers
3406 // which may contain VCC, FLAT_SCR, and XNACK). After register allocation,
3407 // we'll replace these with the ones immediately after those which were
3408 // really allocated. In the prologue copies will be inserted from the
3409 // argument to these reserved registers.
3410
3411 // Without HSA, relocations are used for the scratch pointer and the
3412 // buffer resource setup is always inserted in the prologue. Scratch wave
3413 // offset is still in an input SGPR.
3414 Info.setScratchRSrcReg(ReservedBufferReg);
3415 }
3416 }
3417
3418 MachineRegisterInfo &MRI = MF.getRegInfo();
3419
3420 // For entry functions we have to set up the stack pointer if we use it,
3421 // whereas non-entry functions get this "for free". This means there is no
3422 // intrinsic advantage to using S32 over S34 in cases where we do not have
3423 // calls but do need a frame pointer (i.e. if we are requested to have one
3424 // because frame pointer elimination is disabled). To keep things simple we
3425 // only ever use S32 as the call ABI stack pointer, and so using it does not
3426 // imply we need a separate frame pointer.
3427 //
3428 // Try to use s32 as the SP, but move it if it would interfere with input
3429 // arguments. This won't work with calls though.
3430 //
3431 // FIXME: Move SP to avoid any possible inputs, or find a way to spill input
3432 // registers.
3433 if (!MRI.isLiveIn(AMDGPU::SGPR32)) {
3434 Info.setStackPtrOffsetReg(AMDGPU::SGPR32);
3435 } else {
3437
3438 if (MFI.hasCalls())
3439 report_fatal_error("call in graphics shader with too many input SGPRs");
3440
3441 for (unsigned Reg : AMDGPU::SGPR_32RegClass) {
3442 if (!MRI.isLiveIn(Reg)) {
3443 Info.setStackPtrOffsetReg(Reg);
3444 break;
3445 }
3446 }
3447
3448 if (Info.getStackPtrOffsetReg() == AMDGPU::SP_REG)
3449 report_fatal_error("failed to find register for SP");
3450 }
3451
3452 // hasFP should be accurate for entry functions even before the frame is
3453 // finalized, because it does not rely on the known stack size, only
3454 // properties like whether variable sized objects are present.
3455 if (ST.getFrameLowering()->hasFP(MF)) {
3456 Info.setFrameOffsetReg(AMDGPU::SGPR33);
3457 }
3458}
3459
3462 return !Info->isEntryFunction();
3463}
3464
3466
3468 MachineBasicBlock *Entry,
3469 const SmallVectorImpl<MachineBasicBlock *> &Exits) const {
3471
3472 const MCPhysReg *IStart = TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
3473 if (!IStart)
3474 return;
3475
3476 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3477 MachineRegisterInfo *MRI = &Entry->getParent()->getRegInfo();
3478 MachineBasicBlock::iterator MBBI = Entry->begin();
3479 for (const MCPhysReg *I = IStart; *I; ++I) {
3480 const TargetRegisterClass *RC = nullptr;
3481 if (AMDGPU::SReg_64RegClass.contains(*I))
3482 RC = &AMDGPU::SGPR_64RegClass;
3483 else if (AMDGPU::SReg_32RegClass.contains(*I))
3484 RC = &AMDGPU::SGPR_32RegClass;
3485 else
3486 llvm_unreachable("Unexpected register class in CSRsViaCopy!");
3487
3488 Register NewVR = MRI->createVirtualRegister(RC);
3489 // Create copy from CSR to a virtual register.
3490 Entry->addLiveIn(*I);
3491 BuildMI(*Entry, MBBI, DebugLoc(), TII->get(TargetOpcode::COPY), NewVR)
3492 .addReg(*I);
3493
3494 // Insert the copy-back instructions right before the terminator.
3495 for (auto *Exit : Exits)
3496 BuildMI(*Exit, Exit->getFirstTerminator(), DebugLoc(),
3497 TII->get(TargetOpcode::COPY), *I)
3498 .addReg(NewVR);
3499 }
3500}
3501
3503 SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
3504 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
3505 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
3507
3509 const Function &Fn = MF.getFunction();
3512 bool IsError = false;
3513
3514 if (Subtarget->isAmdHsaOS() && AMDGPU::isGraphics(CallConv)) {
3516 Fn, "unsupported non-compute shaders with HSA", DL.getDebugLoc()));
3517 IsError = true;
3518 }
3519
3522 BitVector Skipped(Fn.arg_size());
3523 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
3524 *DAG.getContext());
3525
3526 bool IsGraphics = AMDGPU::isGraphics(CallConv);
3527 bool IsKernel = AMDGPU::isKernel(CallConv);
3528 bool IsEntryFunc = AMDGPU::isEntryFunctionCC(CallConv);
3529
3530 if (IsGraphics) {
3531 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info->getUserSGPRInfo();
3532 assert(!UserSGPRInfo.hasDispatchPtr() &&
3533 !UserSGPRInfo.hasKernargSegmentPtr() && !Info->hasWorkGroupInfo() &&
3534 !Info->hasLDSKernelId() && !Info->hasWorkItemIDX() &&
3535 !Info->hasWorkItemIDY() && !Info->hasWorkItemIDZ());
3536 (void)UserSGPRInfo;
3537 if (!Subtarget->hasFlatScratchEnabled())
3538 assert(!UserSGPRInfo.hasFlatScratchInit());
3539 if ((CallConv != CallingConv::AMDGPU_CS &&
3540 CallConv != CallingConv::AMDGPU_Gfx &&
3541 CallConv != CallingConv::AMDGPU_Gfx_WholeWave) ||
3542 !Subtarget->hasArchitectedSGPRs())
3543 assert(!Info->hasWorkGroupIDX() && !Info->hasWorkGroupIDY() &&
3544 !Info->hasWorkGroupIDZ());
3545 }
3546
3547 bool IsWholeWaveFunc = Info->isWholeWaveFunction();
3548
3549 if (CallConv == CallingConv::AMDGPU_PS) {
3550 processPSInputArgs(Splits, CallConv, Ins, Skipped, FType, Info);
3551
3552 // At least one interpolation mode must be enabled or else the GPU will
3553 // hang.
3554 //
3555 // Check PSInputAddr instead of PSInputEnable. The idea is that if the user
3556 // set PSInputAddr, the user wants to enable some bits after the compilation
3557 // based on run-time states. Since we can't know what the final PSInputEna
3558 // will look like, so we shouldn't do anything here and the user should take
3559 // responsibility for the correct programming.
3560 //
3561 // Otherwise, the following restrictions apply:
3562 // - At least one of PERSP_* (0xF) or LINEAR_* (0x70) must be enabled.
3563 // - If POS_W_FLOAT (11) is enabled, at least one of PERSP_* must be
3564 // enabled too.
3565 if ((Info->getPSInputAddr() & 0x7F) == 0 ||
3566 ((Info->getPSInputAddr() & 0xF) == 0 && Info->isPSInputAllocated(11))) {
3567 CCInfo.AllocateReg(AMDGPU::VGPR0);
3568 CCInfo.AllocateReg(AMDGPU::VGPR1);
3569 Info->markPSInputAllocated(0);
3570 Info->markPSInputEnabled(0);
3571 }
3572 if (Subtarget->isAmdPalOS()) {
3573 // For isAmdPalOS, the user does not enable some bits after compilation
3574 // based on run-time states; the register values being generated here are
3575 // the final ones set in hardware. Therefore we need to apply the
3576 // workaround to PSInputAddr and PSInputEnable together. (The case where
3577 // a bit is set in PSInputAddr but not PSInputEnable is where the
3578 // frontend set up an input arg for a particular interpolation mode, but
3579 // nothing uses that input arg. Really we should have an earlier pass
3580 // that removes such an arg.)
3581 unsigned PsInputBits = Info->getPSInputAddr() & Info->getPSInputEnable();
3582 if ((PsInputBits & 0x7F) == 0 ||
3583 ((PsInputBits & 0xF) == 0 && (PsInputBits >> 11 & 1)))
3584 Info->markPSInputEnabled(llvm::countr_zero(Info->getPSInputAddr()));
3585 }
3586 } else if (IsKernel) {
3587 assert(Info->hasWorkGroupIDX() && Info->hasWorkItemIDX());
3588 } else {
3589 Splits.append(IsWholeWaveFunc ? std::next(Ins.begin()) : Ins.begin(),
3590 Ins.end());
3591 }
3592
3593 if (IsKernel)
3594 analyzeFormalArgumentsCompute(CCInfo, Ins);
3595
3596 if (IsEntryFunc) {
3597 allocateSpecialEntryInputVGPRs(CCInfo, MF, *TRI, *Info);
3598 allocateHSAUserSGPRs(CCInfo, MF, *TRI, *Info);
3599 if (IsKernel && Subtarget->hasKernargPreload())
3600 allocatePreloadKernArgSGPRs(CCInfo, ArgLocs, Ins, MF, *TRI, *Info);
3601
3602 allocateLDSKernelId(CCInfo, MF, *TRI, *Info);
3603 } else if (!IsGraphics) {
3604 // For the fixed ABI, pass workitem IDs in the last argument register.
3605 allocateSpecialInputVGPRsFixed(CCInfo, MF, *TRI, *Info);
3606
3607 // FIXME: Sink this into allocateSpecialInputSGPRs
3608 if (!Subtarget->hasFlatScratchEnabled())
3609 CCInfo.AllocateReg(Info->getScratchRSrcReg());
3610
3611 allocateSpecialInputSGPRs(CCInfo, MF, *TRI, *Info);
3612 }
3613
3614 if (!IsKernel) {
3615 CCAssignFn *AssignFn = CCAssignFnForCall(CallConv, isVarArg);
3616 CCInfo.AnalyzeFormalArguments(Splits, AssignFn);
3617
3618 // This assumes the registers are allocated by CCInfo in ascending order
3619 // with no gaps.
3620 Info->setNumWaveDispatchSGPRs(
3621 CCInfo.getFirstUnallocated(AMDGPU::SGPR_32RegClass.getRegisters()));
3622 Info->setNumWaveDispatchVGPRs(
3623 CCInfo.getFirstUnallocated(AMDGPU::VGPR_32RegClass.getRegisters()));
3624 } else if (Info->getNumKernargPreloadedSGPRs()) {
3625 Info->setNumWaveDispatchSGPRs(Info->getNumUserSGPRs());
3626 }
3627
3629
3630 if (IsWholeWaveFunc) {
3631 SDValue Setup = DAG.getNode(AMDGPUISD::WHOLE_WAVE_SETUP, DL,
3632 {MVT::i1, MVT::Other}, Chain);
3633 InVals.push_back(Setup.getValue(0));
3634 Chains.push_back(Setup.getValue(1));
3635 }
3636
3637 // FIXME: This is the minimum kernel argument alignment. We should improve
3638 // this to the maximum alignment of the arguments.
3639 //
3640 // FIXME: Alignment of explicit arguments totally broken with non-0 explicit
3641 // kern arg offset.
3642 const Align KernelArgBaseAlign = Align(16);
3643
3644 for (unsigned i = IsWholeWaveFunc ? 1 : 0, e = Ins.size(), ArgIdx = 0; i != e;
3645 ++i) {
3646 const ISD::InputArg &Arg = Ins[i];
3647 if ((Arg.isOrigArg() && Skipped[Arg.getOrigArgIndex()]) || IsError) {
3648 InVals.push_back(DAG.getPOISON(Arg.VT));
3649 continue;
3650 }
3651
3652 CCValAssign &VA = ArgLocs[ArgIdx++];
3653 MVT VT = VA.getLocVT();
3654
3655 if (IsEntryFunc && VA.isMemLoc()) {
3656 VT = Ins[i].VT;
3657 EVT MemVT = VA.getLocVT();
3658
3659 const uint64_t Offset = VA.getLocMemOffset();
3660 Align Alignment = commonAlignment(KernelArgBaseAlign, Offset);
3661
3662 if (Arg.Flags.isByRef()) {
3663 SDValue Ptr = lowerKernArgParameterPtr(DAG, DL, Chain, Offset);
3664
3665 const GCNTargetMachine &TM =
3666 static_cast<const GCNTargetMachine &>(getTargetMachine());
3667 if (!TM.isNoopAddrSpaceCast(DAG.getDataLayout(),
3669 Arg.Flags.getPointerAddrSpace())) {
3672 }
3673
3674 InVals.push_back(Ptr);
3675 continue;
3676 }
3677
3678 SDValue NewArg;
3679 if (Arg.isOrigArg() && Info->getArgInfo().PreloadKernArgs.count(i)) {
3680 if (MemVT.getStoreSize() < 4 && Alignment < 4) {
3681 // In this case the argument is packed into the previous preload SGPR.
3682 int64_t AlignDownOffset = alignDown(Offset, 4);
3683 int64_t OffsetDiff = Offset - AlignDownOffset;
3684 EVT IntVT = MemVT.changeTypeToInteger();
3685
3686 const SIMachineFunctionInfo *Info =
3689 Register Reg =
3690 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs[0];
3691
3692 assert(Reg);
3693 Register VReg = MRI.getLiveInVirtReg(Reg);
3694 SDValue Copy = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i32);
3695
3696 SDValue ShiftAmt = DAG.getConstant(OffsetDiff * 8, DL, MVT::i32);
3697 SDValue Extract = DAG.getNode(ISD::SRL, DL, MVT::i32, Copy, ShiftAmt);
3698
3699 SDValue ArgVal = DAG.getNode(ISD::TRUNCATE, DL, IntVT, Extract);
3700 ArgVal = DAG.getNode(ISD::BITCAST, DL, MemVT, ArgVal);
3701 NewArg = convertArgType(DAG, VT, MemVT, DL, ArgVal,
3702 Ins[i].Flags.isSExt(), &Ins[i]);
3703
3704 NewArg = DAG.getMergeValues({NewArg, Copy.getValue(1)}, DL);
3705 } else {
3706 const SIMachineFunctionInfo *Info =
3709 const SmallVectorImpl<MCRegister> &PreloadRegs =
3710 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs;
3711
3712 SDValue Copy;
3713 if (PreloadRegs.size() == 1) {
3714 Register VReg = MRI.getLiveInVirtReg(PreloadRegs[0]);
3715 const TargetRegisterClass *RC = MRI.getRegClass(VReg);
3716 NewArg = DAG.getCopyFromReg(
3717 Chain, DL, VReg,
3719 TRI->getRegSizeInBits(*RC)));
3720
3721 } else {
3722 // If the kernarg alignment does not match the alignment of the SGPR
3723 // tuple RC that can accommodate this argument, it will be built up
3724 // via copies from from the individual SGPRs that the argument was
3725 // preloaded to.
3727 for (auto Reg : PreloadRegs) {
3728 Register VReg = MRI.getLiveInVirtReg(Reg);
3729 Copy = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i32);
3730 Elts.push_back(Copy);
3731 }
3732 NewArg =
3733 DAG.getBuildVector(EVT::getVectorVT(*DAG.getContext(), MVT::i32,
3734 PreloadRegs.size()),
3735 DL, Elts);
3736 }
3737
3738 // If the argument was preloaded to multiple consecutive 32-bit
3739 // registers because of misalignment between addressable SGPR tuples
3740 // and the argument size, we can still assume that because of kernarg
3741 // segment alignment restrictions that NewArg's size is the same as
3742 // MemVT and just do a bitcast. If MemVT is less than 32-bits we add a
3743 // truncate since we cannot preload to less than a single SGPR and the
3744 // MemVT may be smaller.
3745 EVT MemVTInt =
3747 if (MemVT.bitsLT(NewArg.getSimpleValueType()))
3748 NewArg = DAG.getNode(ISD::TRUNCATE, DL, MemVTInt, NewArg);
3749
3750 NewArg = DAG.getBitcast(MemVT, NewArg);
3751 NewArg = convertArgType(DAG, VT, MemVT, DL, NewArg,
3752 Ins[i].Flags.isSExt(), &Ins[i]);
3753 NewArg = DAG.getMergeValues({NewArg, Chain}, DL);
3754 }
3755 } else {
3756 // Hidden arguments that are in the kernel signature must be preloaded
3757 // to user SGPRs. Print a diagnostic error if a hidden argument is in
3758 // the argument list and is not preloaded.
3759 if (Arg.isOrigArg()) {
3760 Argument *OrigArg = Fn.getArg(Arg.getOrigArgIndex());
3761 if (OrigArg->hasAttribute("amdgpu-hidden-argument")) {
3763 *OrigArg->getParent(),
3764 "hidden argument in kernel signature was not preloaded",
3765 DL.getDebugLoc()));
3766 }
3767 }
3768
3769 NewArg =
3770 lowerKernargMemParameter(DAG, VT, MemVT, DL, Chain, Offset,
3771 Alignment, Ins[i].Flags.isSExt(), &Ins[i]);
3772 }
3773 Chains.push_back(NewArg.getValue(1));
3774
3775 auto *ParamTy =
3776 dyn_cast<PointerType>(FType->getParamType(Ins[i].getOrigArgIndex()));
3777 if (Subtarget->getGeneration() == AMDGPUSubtarget::SOUTHERN_ISLANDS &&
3778 ParamTy &&
3779 (ParamTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS ||
3780 ParamTy->getAddressSpace() == AMDGPUAS::REGION_ADDRESS)) {
3781 // On SI local pointers are just offsets into LDS, so they are always
3782 // less than 16-bits. On CI and newer they could potentially be
3783 // real pointers, so we can't guarantee their size.
3784 NewArg = DAG.getNode(ISD::AssertZext, DL, NewArg.getValueType(), NewArg,
3785 DAG.getValueType(MVT::i16));
3786 }
3787
3788 InVals.push_back(NewArg);
3789 continue;
3790 }
3791 if (!IsEntryFunc && VA.isMemLoc()) {
3792 SDValue Val = lowerStackParameter(DAG, VA, DL, Chain, Arg);
3793 InVals.push_back(Val);
3794 if (!Arg.Flags.isByVal())
3795 Chains.push_back(Val.getValue(1));
3796 continue;
3797 }
3798
3799 assert(VA.isRegLoc() && "Parameter must be in a register!");
3800
3801 Register Reg = VA.getLocReg();
3802 const TargetRegisterClass *RC = nullptr;
3803 if (AMDGPU::VGPR_32RegClass.contains(Reg))
3804 RC = &AMDGPU::VGPR_32RegClass;
3805 else if (AMDGPU::SGPR_32RegClass.contains(Reg))
3806 RC = &AMDGPU::SGPR_32RegClass;
3807 else
3808 llvm_unreachable("Unexpected register class in LowerFormalArguments!");
3809
3810 Reg = MF.addLiveIn(Reg, RC);
3811 SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, VT);
3812 if (Arg.Flags.isInReg() && RC == &AMDGPU::VGPR_32RegClass) {
3813 // FIXME: Need to forward the chains created by `CopyFromReg`s, make sure
3814 // they will read physical regs before any side effect instructions.
3815 SDValue ReadFirstLane =
3816 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
3818 ReadFirstLane, Val);
3819 }
3820
3821 if (Arg.Flags.isSRet()) {
3822 // The return object should be reasonably addressable.
3823 Val = annotateStackObjectPointer(Val, DAG, DL,
3825 }
3826
3827 Val = convertABITypeToValueType(DAG, Val, VA, DL);
3828 InVals.push_back(Val);
3829 }
3830
3831 // Start adding system SGPRs.
3832 if (IsEntryFunc)
3833 allocateSystemSGPRs(CCInfo, MF, *Info, CallConv, IsGraphics);
3834
3835 unsigned StackArgSize = CCInfo.getStackSize();
3836 Info->setBytesInStackArgArea(StackArgSize);
3837
3838 return Chains.empty() ? Chain
3839 : DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
3840}
3841
3842// TODO: If return values can't fit in registers, we should return as many as
3843// possible in registers before passing on stack.
3845 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
3846 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
3847 const Type *RetTy) const {
3848 // Replacing returns with sret/stack usage doesn't make sense for shaders.
3849 // FIXME: Also sort of a workaround for custom vector splitting in LowerReturn
3850 // for shaders. Vector types should be explicitly handled by CC.
3851 if (AMDGPU::isEntryFunctionCC(CallConv))
3852 return true;
3853
3855 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
3856 if (!CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg)))
3857 return false;
3858
3859 // We must use the stack if return would require unavailable registers.
3860 unsigned MaxNumVGPRs = Subtarget->getMaxNumVGPRs(MF);
3861 unsigned TotalNumVGPRs = Subtarget->getAddressableNumArchVGPRs();
3862 for (unsigned i = MaxNumVGPRs; i < TotalNumVGPRs; ++i)
3863 if (CCInfo.isAllocated(AMDGPU::VGPR_32RegClass.getRegister(i)))
3864 return false;
3865
3866 return true;
3867}
3868
3869SDValue
3871 bool isVarArg,
3873 const SmallVectorImpl<SDValue> &OutVals,
3874 const SDLoc &DL, SelectionDAG &DAG) const {
3878
3879 if (AMDGPU::isKernel(CallConv)) {
3880 return AMDGPUTargetLowering::LowerReturn(Chain, CallConv, isVarArg, Outs,
3881 OutVals, DL, DAG);
3882 }
3883
3884 bool IsShader = AMDGPU::isShader(CallConv);
3885
3886 Info->setIfReturnsVoid(Outs.empty());
3887 bool IsWaveEnd = Info->returnsVoid() && IsShader;
3888
3889 // CCValAssign - represent the assignment of the return value to a location.
3891
3892 // CCState - Info about the registers and stack slots.
3893 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
3894 *DAG.getContext());
3895
3896 // Analyze outgoing return values.
3897 CCInfo.AnalyzeReturn(Outs, CCAssignFnForReturn(CallConv, isVarArg));
3898
3899 SDValue Glue;
3901 RetOps.push_back(Chain); // Operand #0 = Chain (updated below)
3902
3903 SDValue ReadFirstLane =
3904 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
3905 // Copy the result values into the output registers.
3906 for (unsigned I = 0, RealRVLocIdx = 0, E = RVLocs.size(); I != E;
3907 ++I, ++RealRVLocIdx) {
3908 CCValAssign &VA = RVLocs[I];
3909 assert(VA.isRegLoc() && "Can only return in registers!");
3910 // TODO: Partially return in registers if return values don't fit.
3911 SDValue Arg = OutVals[RealRVLocIdx];
3912
3913 // Copied from other backends.
3914 switch (VA.getLocInfo()) {
3915 case CCValAssign::Full:
3916 break;
3917 case CCValAssign::BCvt:
3918 Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
3919 break;
3920 case CCValAssign::SExt:
3921 Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
3922 break;
3923 case CCValAssign::ZExt:
3924 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
3925 break;
3926 case CCValAssign::AExt:
3927 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
3928 break;
3929 default:
3930 llvm_unreachable("Unknown loc info!");
3931 }
3932 if (TRI->isSGPRPhysReg(VA.getLocReg()))
3934 ReadFirstLane, Arg);
3935 Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Arg, Glue);
3936 Glue = Chain.getValue(1);
3937 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
3938 }
3939
3940 // FIXME: Does sret work properly?
3941 if (!Info->isEntryFunction()) {
3942 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
3943 const MCPhysReg *I =
3944 TRI->getCalleeSavedRegsViaCopy(&DAG.getMachineFunction());
3945 if (I) {
3946 for (; *I; ++I) {
3947 if (AMDGPU::SReg_64RegClass.contains(*I))
3948 RetOps.push_back(DAG.getRegister(*I, MVT::i64));
3949 else if (AMDGPU::SReg_32RegClass.contains(*I))
3950 RetOps.push_back(DAG.getRegister(*I, MVT::i32));
3951 else
3952 llvm_unreachable("Unexpected register class in CSRsViaCopy!");
3953 }
3954 }
3955 }
3956
3957 // Update chain and glue.
3958 RetOps[0] = Chain;
3959 if (Glue.getNode())
3960 RetOps.push_back(Glue);
3961
3962 unsigned Opc = AMDGPUISD::ENDPGM;
3963 if (!IsWaveEnd)
3964 Opc = Info->isWholeWaveFunction() ? AMDGPUISD::WHOLE_WAVE_RETURN
3965 : IsShader ? AMDGPUISD::RETURN_TO_EPILOG
3966 : AMDGPUISD::RET_GLUE;
3967 return DAG.getNode(Opc, DL, MVT::Other, RetOps);
3968}
3969
3971 SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,
3972 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
3973 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals, bool IsThisReturn,
3974 SDValue ThisVal) const {
3975 CCAssignFn *RetCC = CCAssignFnForReturn(CallConv, IsVarArg);
3976
3977 // Assign locations to each value returned by this call.
3979 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
3980 *DAG.getContext());
3981 CCInfo.AnalyzeCallResult(Ins, RetCC);
3982
3983 // Copy all of the result registers out of their specified physreg.
3984 for (CCValAssign VA : RVLocs) {
3985 SDValue Val;
3986
3987 if (VA.isRegLoc()) {
3988 Val =
3989 DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), InGlue);
3990 Chain = Val.getValue(1);
3991 InGlue = Val.getValue(2);
3992 } else if (VA.isMemLoc()) {
3993 report_fatal_error("TODO: return values in memory");
3994 } else
3995 llvm_unreachable("unknown argument location type");
3996
3997 switch (VA.getLocInfo()) {
3998 case CCValAssign::Full:
3999 break;
4000 case CCValAssign::BCvt:
4001 Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);
4002 break;
4003 case CCValAssign::ZExt:
4004 Val = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Val,
4005 DAG.getValueType(VA.getValVT()));
4006 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
4007 break;
4008 case CCValAssign::SExt:
4009 Val = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Val,
4010 DAG.getValueType(VA.getValVT()));
4011 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
4012 break;
4013 case CCValAssign::AExt:
4014 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
4015 break;
4016 default:
4017 llvm_unreachable("Unknown loc info!");
4018 }
4019
4020 InVals.push_back(Val);
4021 }
4022
4023 return Chain;
4024}
4025
4026// Add code to pass special inputs required depending on used features separate
4027// from the explicit user arguments present in the IR.
4029 CallLoweringInfo &CLI, CCState &CCInfo, const SIMachineFunctionInfo &Info,
4030 SmallVectorImpl<std::pair<unsigned, SDValue>> &RegsToPass,
4031 SmallVectorImpl<SDValue> &MemOpChains, SDValue Chain) const {
4032 // If we don't have a call site, this was a call inserted by
4033 // legalization. These can never use special inputs.
4034 if (!CLI.CB)
4035 return;
4036
4037 SelectionDAG &DAG = CLI.DAG;
4038 const SDLoc &DL = CLI.DL;
4039 const Function &F = DAG.getMachineFunction().getFunction();
4040
4041 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
4042 const AMDGPUFunctionArgInfo &CallerArgInfo = Info.getArgInfo();
4043
4044 const AMDGPUFunctionArgInfo &CalleeArgInfo =
4046
4047 // TODO: Unify with private memory register handling. This is complicated by
4048 // the fact that at least in kernels, the input argument is not necessarily
4049 // in the same location as the input.
4050 // clang-format off
4051 static constexpr std::pair<AMDGPUFunctionArgInfo::PreloadedValue,
4052 std::array<StringLiteral, 2>> ImplicitAttrs[] = {
4053 {AMDGPUFunctionArgInfo::DISPATCH_PTR, {"amdgpu-no-dispatch-ptr", ""}},
4054 {AMDGPUFunctionArgInfo::QUEUE_PTR, {"amdgpu-no-queue-ptr", ""}},
4055 {AMDGPUFunctionArgInfo::IMPLICIT_ARG_PTR, {"amdgpu-no-implicitarg-ptr", ""}},
4056 {AMDGPUFunctionArgInfo::DISPATCH_ID, {"amdgpu-no-dispatch-id", ""}},
4057 {AMDGPUFunctionArgInfo::WORKGROUP_ID_X, {"amdgpu-no-workgroup-id-x", "amdgpu-no-cluster-id-x"}},
4058 {AMDGPUFunctionArgInfo::WORKGROUP_ID_Y, {"amdgpu-no-workgroup-id-y", "amdgpu-no-cluster-id-y"}},
4059 {AMDGPUFunctionArgInfo::WORKGROUP_ID_Z, {"amdgpu-no-workgroup-id-z", "amdgpu-no-cluster-id-z"}},
4060 {AMDGPUFunctionArgInfo::LDS_KERNEL_ID, {"amdgpu-no-lds-kernel-id", ""}},
4061 };
4062 // clang-format on
4063
4064 for (auto [InputID, Attrs] : ImplicitAttrs) {
4065 // If the callee does not use the attribute value, skip copying the value.
4066 if (all_of(Attrs, [&](StringRef Attr) {
4067 return Attr.empty() || CLI.CB->hasFnAttr(Attr);
4068 }))
4069 continue;
4070
4071 const auto [OutgoingArg, ArgRC, ArgTy] =
4072 CalleeArgInfo.getPreloadedValue(InputID);
4073 if (!OutgoingArg)
4074 continue;
4075
4076 const auto [IncomingArg, IncomingArgRC, Ty] =
4077 CallerArgInfo.getPreloadedValue(InputID);
4078 assert(IncomingArgRC == ArgRC);
4079
4080 // All special arguments are ints for now.
4081 EVT ArgVT = TRI->getSpillSize(*ArgRC) == 8 ? MVT::i64 : MVT::i32;
4082 SDValue InputReg;
4083
4084 if (IncomingArg) {
4085 InputReg = loadInputValue(DAG, ArgRC, ArgVT, DL, *IncomingArg);
4086 } else if (InputID == AMDGPUFunctionArgInfo::IMPLICIT_ARG_PTR) {
4087 // The implicit arg ptr is special because it doesn't have a corresponding
4088 // input for kernels, and is computed from the kernarg segment pointer.
4089 InputReg = getImplicitArgPtr(DAG, DL);
4090 } else if (InputID == AMDGPUFunctionArgInfo::LDS_KERNEL_ID) {
4091 std::optional<uint32_t> Id =
4093 if (Id.has_value()) {
4094 InputReg = DAG.getConstant(*Id, DL, ArgVT);
4095 } else {
4096 InputReg = DAG.getPOISON(ArgVT);
4097 }
4098 } else {
4099 // We may have proven the input wasn't needed, although the ABI is
4100 // requiring it. We just need to allocate the register appropriately.
4101 InputReg = DAG.getPOISON(ArgVT);
4102 }
4103
4104 if (OutgoingArg->isRegister()) {
4105 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4106 if (!CCInfo.AllocateReg(OutgoingArg->getRegister()))
4107 report_fatal_error("failed to allocate implicit input argument");
4108 } else {
4109 unsigned SpecialArgOffset =
4110 CCInfo.AllocateStack(ArgVT.getStoreSize(), Align(4));
4111 SDValue ArgStore =
4112 storeStackInputValue(DAG, DL, Chain, InputReg, SpecialArgOffset);
4113 MemOpChains.push_back(ArgStore);
4114 }
4115 }
4116
4117 // Pack workitem IDs into a single register or pass it as is if already
4118 // packed.
4119
4120 auto [OutgoingArg, ArgRC, Ty] =
4122 if (!OutgoingArg)
4123 std::tie(OutgoingArg, ArgRC, Ty) =
4125 if (!OutgoingArg)
4126 std::tie(OutgoingArg, ArgRC, Ty) =
4128 if (!OutgoingArg)
4129 return;
4130
4131 const ArgDescriptor *IncomingArgX = std::get<0>(
4133 const ArgDescriptor *IncomingArgY = std::get<0>(
4135 const ArgDescriptor *IncomingArgZ = std::get<0>(
4137
4138 SDValue InputReg;
4139 SDLoc SL;
4140
4141 const bool NeedWorkItemIDX = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-x");
4142 const bool NeedWorkItemIDY = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-y");
4143 const bool NeedWorkItemIDZ = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-z");
4144
4145 // If incoming ids are not packed we need to pack them.
4146 if (IncomingArgX && !IncomingArgX->isMasked() && CalleeArgInfo.WorkItemIDX &&
4147 NeedWorkItemIDX) {
4148 if (Subtarget->getMaxWorkitemID(F, 0) != 0) {
4149 InputReg = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgX);
4150 } else {
4151 InputReg = DAG.getConstant(0, DL, MVT::i32);
4152 }
4153 }
4154
4155 if (IncomingArgY && !IncomingArgY->isMasked() && CalleeArgInfo.WorkItemIDY &&
4156 NeedWorkItemIDY && Subtarget->getMaxWorkitemID(F, 1) != 0) {
4157 SDValue Y = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgY);
4158 Y = DAG.getNode(ISD::SHL, SL, MVT::i32, Y,
4159 DAG.getShiftAmountConstant(10, MVT::i32, SL));
4160 InputReg = InputReg.getNode()
4161 ? DAG.getNode(ISD::OR, SL, MVT::i32, InputReg, Y)
4162 : Y;
4163 }
4164
4165 if (IncomingArgZ && !IncomingArgZ->isMasked() && CalleeArgInfo.WorkItemIDZ &&
4166 NeedWorkItemIDZ && Subtarget->getMaxWorkitemID(F, 2) != 0) {
4167 SDValue Z = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgZ);
4168 Z = DAG.getNode(ISD::SHL, SL, MVT::i32, Z,
4169 DAG.getShiftAmountConstant(20, MVT::i32, SL));
4170 InputReg = InputReg.getNode()
4171 ? DAG.getNode(ISD::OR, SL, MVT::i32, InputReg, Z)
4172 : Z;
4173 }
4174
4175 if (!InputReg && (NeedWorkItemIDX || NeedWorkItemIDY || NeedWorkItemIDZ)) {
4176 if (!IncomingArgX && !IncomingArgY && !IncomingArgZ) {
4177 // We're in a situation where the outgoing function requires the workitem
4178 // ID, but the calling function does not have it (e.g a graphics function
4179 // calling a C calling convention function). This is illegal, but we need
4180 // to produce something.
4181 InputReg = DAG.getPOISON(MVT::i32);
4182 } else {
4183 // Workitem ids are already packed, any of present incoming arguments
4184 // will carry all required fields.
4185 ArgDescriptor IncomingArg =
4186 ArgDescriptor::createArg(IncomingArgX ? *IncomingArgX
4187 : IncomingArgY ? *IncomingArgY
4188 : *IncomingArgZ,
4189 ~0u);
4190 InputReg = loadInputValue(DAG, ArgRC, MVT::i32, DL, IncomingArg);
4191 }
4192 }
4193
4194 if (OutgoingArg->isRegister()) {
4195 if (InputReg)
4196 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4197
4198 CCInfo.AllocateReg(OutgoingArg->getRegister());
4199 } else {
4200 unsigned SpecialArgOffset = CCInfo.AllocateStack(4, Align(4));
4201 if (InputReg) {
4202 SDValue ArgStore =
4203 storeStackInputValue(DAG, DL, Chain, InputReg, SpecialArgOffset);
4204 MemOpChains.push_back(ArgStore);
4205 }
4206 }
4207}
4208
4210 SDValue Callee, CallingConv::ID CalleeCC, bool IsVarArg,
4212 const SmallVectorImpl<SDValue> &OutVals,
4213 const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG) const {
4214 if (AMDGPU::isChainCC(CalleeCC))
4215 return true;
4216
4217 if (!AMDGPU::mayTailCallThisCC(CalleeCC))
4218 return false;
4219
4220 // For a divergent call target, we need to do a waterfall loop over the
4221 // possible callees which precludes us from using a simple jump.
4222 if (Callee->isDivergent())
4223 return false;
4224
4226 const Function &CallerF = MF.getFunction();
4227 CallingConv::ID CallerCC = CallerF.getCallingConv();
4229 const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC);
4230
4231 // Kernels aren't callable, and don't have a live in return address so it
4232 // doesn't make sense to do a tail call with entry functions.
4233 if (!CallerPreserved)
4234 return false;
4235
4236 bool CCMatch = CallerCC == CalleeCC;
4237
4239 if (AMDGPU::canGuaranteeTCO(CalleeCC) && CCMatch)
4240 return true;
4241 return false;
4242 }
4243
4244 // TODO: Can we handle var args?
4245 if (IsVarArg)
4246 return false;
4247
4248 for (const Argument &Arg : CallerF.args()) {
4249 if (Arg.hasByValAttr())
4250 return false;
4251 }
4252
4253 LLVMContext &Ctx = *DAG.getContext();
4254
4255 // Check that the call results are passed in the same way.
4256 if (!CCState::resultsCompatible(CalleeCC, CallerCC, MF, Ctx, Ins,
4257 CCAssignFnForCall(CalleeCC, IsVarArg),
4258 CCAssignFnForCall(CallerCC, IsVarArg)))
4259 return false;
4260
4261 // The callee has to preserve all registers the caller needs to preserve.
4262 if (!CCMatch) {
4263 const uint32_t *CalleePreserved = TRI->getCallPreservedMask(MF, CalleeCC);
4264 if (!TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
4265 return false;
4266 }
4267
4268 // Nothing more to check if the callee is taking no arguments.
4269 if (Outs.empty())
4270 return true;
4271
4273 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, Ctx);
4274
4275 // FIXME: We are not allocating special input registers, so we will be
4276 // deciding based on incorrect register assignments.
4277 CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CalleeCC, IsVarArg));
4278
4279 const SIMachineFunctionInfo *FuncInfo = MF.getInfo<SIMachineFunctionInfo>();
4280 // If the stack arguments for this call do not fit into our own save area then
4281 // the call cannot be made tail.
4282 // TODO: Is this really necessary?
4283 if (CCInfo.getStackSize() > FuncInfo->getBytesInStackArgArea())
4284 return false;
4285
4286 for (const auto &[CCVA, ArgVal] : zip_equal(ArgLocs, OutVals)) {
4287 // FIXME: What about inreg arguments that end up passed in memory?
4288 if (!CCVA.isRegLoc())
4289 continue;
4290
4291 // If we are passing an argument in an SGPR, and the value is divergent,
4292 // this call requires a waterfall loop.
4293 if (ArgVal->isDivergent() && TRI->isSGPRPhysReg(CCVA.getLocReg())) {
4294 LLVM_DEBUG(
4295 dbgs() << "Cannot tail call due to divergent outgoing argument in "
4296 << printReg(CCVA.getLocReg(), TRI) << '\n');
4297 return false;
4298 }
4299 }
4300
4301 const MachineRegisterInfo &MRI = MF.getRegInfo();
4302 return parametersInCSRMatch(MRI, CallerPreserved, ArgLocs, OutVals);
4303}
4304
4306 if (!CI->isTailCall())
4307 return false;
4308
4309 const Function *ParentFn = CI->getFunction();
4311 return false;
4312 return true;
4313}
4314
4315namespace {
4316// Chain calls have special arguments that we need to handle. These are
4317// tagging along at the end of the arguments list(s), after the SGPR and VGPR
4318// arguments (index 0 and 1 respectively).
4319enum ChainCallArgIdx {
4320 Exec = 2,
4321 Flags,
4322 NumVGPRs,
4323 FallbackExec,
4324 FallbackCallee
4325};
4326} // anonymous namespace
4327
4328// The wave scratch offset register is used as the global base pointer.
4330 SmallVectorImpl<SDValue> &InVals) const {
4331 CallingConv::ID CallConv = CLI.CallConv;
4332 bool IsChainCallConv = AMDGPU::isChainCC(CallConv);
4333
4334 SelectionDAG &DAG = CLI.DAG;
4335
4336 const SDLoc &DL = CLI.DL;
4337 SDValue Chain = CLI.Chain;
4338 SDValue Callee = CLI.Callee;
4339
4340 llvm::SmallVector<SDValue, 6> ChainCallSpecialArgs;
4341 bool UsesDynamicVGPRs = false;
4342 if (IsChainCallConv) {
4343 // The last arguments should be the value that we need to put in EXEC,
4344 // followed by the flags and any other arguments with special meanings.
4345 // Pop them out of CLI.Outs and CLI.OutVals before we do any processing so
4346 // we don't treat them like the "real" arguments.
4347 auto RequestedExecIt =
4348 llvm::find_if(CLI.Outs, [](const ISD::OutputArg &Arg) {
4349 return Arg.OrigArgIndex == 2;
4350 });
4351 assert(RequestedExecIt != CLI.Outs.end() && "No node for EXEC");
4352
4353 size_t SpecialArgsBeginIdx = RequestedExecIt - CLI.Outs.begin();
4354 CLI.OutVals.erase(CLI.OutVals.begin() + SpecialArgsBeginIdx,
4355 CLI.OutVals.end());
4356 CLI.Outs.erase(RequestedExecIt, CLI.Outs.end());
4357
4358 assert(CLI.Outs.back().OrigArgIndex < 2 &&
4359 "Haven't popped all the special args");
4360
4361 TargetLowering::ArgListEntry RequestedExecArg =
4362 CLI.Args[ChainCallArgIdx::Exec];
4363 if (!RequestedExecArg.Ty->isIntegerTy(Subtarget->getWavefrontSize()))
4364 return lowerUnhandledCall(CLI, InVals, "Invalid value for EXEC");
4365
4366 // Convert constants into TargetConstants, so they become immediate operands
4367 // instead of being selected into S_MOV.
4368 auto PushNodeOrTargetConstant = [&](TargetLowering::ArgListEntry Arg) {
4369 if (const auto *ArgNode = dyn_cast<ConstantSDNode>(Arg.Node)) {
4370 ChainCallSpecialArgs.push_back(DAG.getTargetConstant(
4371 ArgNode->getAPIntValue(), DL, ArgNode->getValueType(0)));
4372 } else
4373 ChainCallSpecialArgs.push_back(Arg.Node);
4374 };
4375
4376 PushNodeOrTargetConstant(RequestedExecArg);
4377
4378 // Process any other special arguments depending on the value of the flags.
4379 TargetLowering::ArgListEntry Flags = CLI.Args[ChainCallArgIdx::Flags];
4380
4381 const APInt &FlagsValue = cast<ConstantSDNode>(Flags.Node)->getAPIntValue();
4382 if (FlagsValue.isZero()) {
4383 if (CLI.Args.size() > ChainCallArgIdx::Flags + 1)
4384 return lowerUnhandledCall(CLI, InVals,
4385 "no additional args allowed if flags == 0");
4386 } else if (FlagsValue.isOneBitSet(0)) {
4387 if (CLI.Args.size() != ChainCallArgIdx::FallbackCallee + 1) {
4388 return lowerUnhandledCall(CLI, InVals, "expected 3 additional args");
4389 }
4390
4391 if (!Subtarget->isWave32()) {
4392 return lowerUnhandledCall(
4393 CLI, InVals, "dynamic VGPR mode is only supported for wave32");
4394 }
4395
4396 UsesDynamicVGPRs = true;
4397 std::for_each(CLI.Args.begin() + ChainCallArgIdx::NumVGPRs,
4398 CLI.Args.end(), PushNodeOrTargetConstant);
4399 }
4400 }
4401
4403 SmallVector<SDValue, 32> &OutVals = CLI.OutVals;
4405 bool &IsTailCall = CLI.IsTailCall;
4406 bool IsVarArg = CLI.IsVarArg;
4407 bool IsSibCall = false;
4409
4410 if (Callee.isUndef() || isNullConstant(Callee)) {
4411 if (!CLI.IsTailCall) {
4412 for (ISD::InputArg &Arg : CLI.Ins)
4413 InVals.push_back(DAG.getPOISON(Arg.VT));
4414 }
4415
4416 return Chain;
4417 }
4418
4419 if (IsVarArg) {
4420 return lowerUnhandledCall(CLI, InVals,
4421 "unsupported call to variadic function ");
4422 }
4423
4424 if (!CLI.CB)
4425 return lowerUnhandledCall(CLI, InVals, "unsupported libcall legalization");
4426
4427 if (IsTailCall && MF.getTarget().Options.GuaranteedTailCallOpt) {
4428 return lowerUnhandledCall(CLI, InVals,
4429 "unsupported required tail call to function ");
4430 }
4431
4432 if (IsTailCall) {
4433 IsTailCall = isEligibleForTailCallOptimization(Callee, CallConv, IsVarArg,
4434 Outs, OutVals, Ins, DAG);
4435 if (!IsTailCall &&
4436 ((CLI.CB && CLI.CB->isMustTailCall()) || IsChainCallConv)) {
4437 report_fatal_error("failed to perform tail call elimination on a call "
4438 "site marked musttail or on llvm.amdgcn.cs.chain");
4439 }
4440
4441 bool TailCallOpt = MF.getTarget().Options.GuaranteedTailCallOpt;
4442
4443 // A sibling call is one where we're under the usual C ABI and not planning
4444 // to change that but can still do a tail call:
4445 if (!TailCallOpt && IsTailCall)
4446 IsSibCall = true;
4447
4448 if (IsTailCall)
4449 ++NumTailCalls;
4450 }
4451
4454 SmallVector<SDValue, 8> MemOpChains;
4455
4456 // Analyze operands of the call, assigning locations to each operand.
4458 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
4459 CCAssignFn *AssignFn = CCAssignFnForCall(CallConv, IsVarArg);
4460
4461 if (CallConv != CallingConv::AMDGPU_Gfx && !AMDGPU::isChainCC(CallConv) &&
4463 // With a fixed ABI, allocate fixed registers before user arguments.
4464 passSpecialInputs(CLI, CCInfo, *Info, RegsToPass, MemOpChains, Chain);
4465 }
4466
4467 // Mark the scratch resource descriptor as allocated so the CC analysis
4468 // does not assign user arguments to these registers, matching the callee.
4469 if (!Subtarget->hasFlatScratchEnabled())
4470 CCInfo.AllocateReg(Info->getScratchRSrcReg());
4471
4472 CCInfo.AnalyzeCallOperands(Outs, AssignFn);
4473
4474 // Get a count of how many bytes are to be pushed on the stack.
4475 unsigned NumBytes = CCInfo.getStackSize();
4476
4477 if (IsSibCall) {
4478 // Since we're not changing the ABI to make this a tail call, the memory
4479 // operands are already available in the caller's incoming argument space.
4480 NumBytes = 0;
4481 }
4482
4483 // FPDiff is the byte offset of the call's argument area from the callee's.
4484 // Stores to callee stack arguments will be placed in FixedStackSlots offset
4485 // by this amount for a tail call. In a sibling call it must be 0 because the
4486 // caller will deallocate the entire stack and the callee still expects its
4487 // arguments to begin at SP+0. Completely unused for non-tail calls.
4488 int32_t FPDiff = 0;
4489 MachineFrameInfo &MFI = MF.getFrameInfo();
4490 auto *TRI = Subtarget->getRegisterInfo();
4491
4492 // Adjust the stack pointer for the new arguments...
4493 // These operations are automatically eliminated by the prolog/epilog pass
4494 if (!IsSibCall)
4495 Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL);
4496
4497 if (!IsSibCall || IsChainCallConv) {
4498 if (!Subtarget->hasFlatScratchEnabled()) {
4499 SmallVector<SDValue, 4> CopyFromChains;
4500
4501 // In the HSA case, this should be an identity copy.
4502 SDValue ScratchRSrcReg =
4503 DAG.getCopyFromReg(Chain, DL, Info->getScratchRSrcReg(), MVT::v4i32);
4504 RegsToPass.emplace_back(IsChainCallConv
4505 ? AMDGPU::SGPR48_SGPR49_SGPR50_SGPR51
4506 : AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3,
4507 ScratchRSrcReg);
4508 CopyFromChains.push_back(ScratchRSrcReg.getValue(1));
4509 Chain = DAG.getTokenFactor(DL, CopyFromChains);
4510 }
4511 }
4512
4513 const unsigned NumSpecialInputs = RegsToPass.size();
4514
4515 MVT PtrVT = MVT::i32;
4516
4517 // Walk the register/memloc assignments, inserting copies/loads.
4518 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4519 CCValAssign &VA = ArgLocs[i];
4520 SDValue Arg = OutVals[i];
4521
4522 // Promote the value if needed.
4523 switch (VA.getLocInfo()) {
4524 case CCValAssign::Full:
4525 break;
4526 case CCValAssign::BCvt:
4527 Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
4528 break;
4529 case CCValAssign::ZExt:
4530 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
4531 break;
4532 case CCValAssign::SExt:
4533 Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
4534 break;
4535 case CCValAssign::AExt:
4536 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
4537 break;
4538 case CCValAssign::FPExt:
4539 Arg = DAG.getNode(ISD::FP_EXTEND, DL, VA.getLocVT(), Arg);
4540 break;
4541 default:
4542 llvm_unreachable("Unknown loc info!");
4543 }
4544
4545 if (VA.isRegLoc()) {
4546 RegsToPass.push_back(std::pair(VA.getLocReg(), Arg));
4547 } else {
4548 assert(VA.isMemLoc());
4549
4550 SDValue DstAddr;
4551 MachinePointerInfo DstInfo;
4552
4553 unsigned LocMemOffset = VA.getLocMemOffset();
4554 int32_t Offset = LocMemOffset;
4555
4556 SDValue PtrOff = DAG.getConstant(Offset, DL, PtrVT);
4557 MaybeAlign Alignment;
4558
4559 if (IsTailCall) {
4560 ISD::ArgFlagsTy Flags = Outs[i].Flags;
4561 unsigned OpSize = Flags.isByVal() ? Flags.getByValSize()
4562 : VA.getValVT().getStoreSize();
4563
4564 // FIXME: We can have better than the minimum byval required alignment.
4565 Alignment =
4566 Flags.isByVal()
4567 ? Flags.getNonZeroByValAlign()
4568 : commonAlignment(Subtarget->getStackAlignment(), Offset);
4569
4570 Offset = Offset + FPDiff;
4571 int FI = MFI.CreateFixedObject(OpSize, Offset, true);
4572
4573 DstAddr = DAG.getFrameIndex(FI, PtrVT);
4574 DstInfo = MachinePointerInfo::getFixedStack(MF, FI);
4575
4576 // Make sure any stack arguments overlapping with where we're storing
4577 // are loaded before this eventual operation. Otherwise they'll be
4578 // clobbered.
4579
4580 // FIXME: Why is this really necessary? This seems to just result in a
4581 // lot of code to copy the stack and write them back to the same
4582 // locations, which are supposed to be immutable?
4583 Chain = addTokenForArgument(Chain, DAG, MFI, FI);
4584 } else {
4585 // Stores to the argument stack area are relative to the stack pointer.
4586 SDValue SP = DAG.getCopyFromReg(Chain, DL, Info->getStackPtrOffsetReg(),
4587 MVT::i32);
4588 DstAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, SP, PtrOff);
4589 DstInfo = MachinePointerInfo::getStack(MF, LocMemOffset);
4590 Alignment =
4591 commonAlignment(Subtarget->getStackAlignment(), LocMemOffset);
4592 }
4593
4594 if (Outs[i].Flags.isByVal()) {
4595 SDValue SizeNode =
4596 DAG.getConstant(Outs[i].Flags.getByValSize(), DL, MVT::i32);
4597 SDValue Cpy =
4598 DAG.getMemcpy(Chain, DL, DstAddr, Arg, SizeNode,
4599 Outs[i].Flags.getNonZeroByValAlign(),
4600 Outs[i].Flags.getNonZeroByValAlign(),
4601 /*isVol = */ false, /*AlwaysInline = */ true,
4602 /*CI=*/nullptr, std::nullopt, DstInfo,
4604
4605 MemOpChains.push_back(Cpy);
4606 } else {
4607 SDValue Store =
4608 DAG.getStore(Chain, DL, Arg, DstAddr, DstInfo, Alignment);
4609 MemOpChains.push_back(Store);
4610 }
4611 }
4612 }
4613
4614 if (!MemOpChains.empty())
4615 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
4616
4617 SDValue ReadFirstLaneID =
4618 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
4619
4620 SDValue TokenGlue;
4621 if (CLI.ConvergenceControlToken) {
4622 TokenGlue = DAG.getNode(ISD::CONVERGENCECTRL_GLUE, DL, MVT::Glue,
4624 }
4625
4626 // Build a sequence of copy-to-reg nodes chained together with token chain
4627 // and flag operands which copy the outgoing args into the appropriate regs.
4628 SDValue InGlue;
4629
4630 unsigned ArgIdx = 0;
4631 for (auto [Reg, Val] : RegsToPass) {
4632 if (ArgIdx++ >= NumSpecialInputs &&
4633 (IsChainCallConv || !Val->isDivergent()) && TRI->isSGPRPhysReg(Reg)) {
4634 // For chain calls, the inreg arguments are required to be
4635 // uniform. Speculatively Insert a readfirstlane in case we cannot prove
4636 // they are uniform.
4637 //
4638 // For other calls, if an inreg arguments is known to be uniform,
4639 // speculatively insert a readfirstlane in case it is in a VGPR.
4640 //
4641 // FIXME: We need to execute this in a waterfall loop if it is a divergent
4642 // value, so let that continue to produce invalid code.
4643
4644 SmallVector<SDValue, 3> ReadfirstlaneArgs({ReadFirstLaneID, Val});
4645 if (TokenGlue)
4646 ReadfirstlaneArgs.push_back(TokenGlue);
4648 ReadfirstlaneArgs);
4649 }
4650
4651 Chain = DAG.getCopyToReg(Chain, DL, Reg, Val, InGlue);
4652 InGlue = Chain.getValue(1);
4653 }
4654
4655 // We don't usually want to end the call-sequence here because we would tidy
4656 // the frame up *after* the call, however in the ABI-changing tail-call case
4657 // we've carefully laid out the parameters so that when sp is reset they'll be
4658 // in the correct location.
4659 if (IsTailCall && !IsSibCall) {
4660 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
4661 InGlue = Chain.getValue(1);
4662 }
4663
4664 std::vector<SDValue> Ops({Chain});
4665
4666 // Add a redundant copy of the callee global which will not be legalized, as
4667 // we need direct access to the callee later.
4669 const GlobalValue *GV = GSD->getGlobal();
4670 Ops.push_back(Callee);
4671 Ops.push_back(DAG.getTargetGlobalAddress(GV, DL, MVT::i64));
4672 } else {
4673 if (IsTailCall) {
4674 // isEligibleForTailCallOptimization considered whether the call target is
4675 // divergent, but we may still end up with a uniform value in a VGPR.
4676 // Insert a readfirstlane just in case.
4677 SDValue ReadFirstLaneID =
4678 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
4679
4680 SmallVector<SDValue, 3> ReadfirstlaneArgs({ReadFirstLaneID, Callee});
4681 if (TokenGlue)
4682 ReadfirstlaneArgs.push_back(TokenGlue); // Wire up convergence token.
4683 Callee = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, Callee.getValueType(),
4684 ReadfirstlaneArgs);
4685 }
4686
4687 Ops.push_back(Callee);
4688 Ops.push_back(DAG.getTargetConstant(0, DL, MVT::i64));
4689 }
4690
4691 if (IsTailCall) {
4692 // Each tail call may have to adjust the stack by a different amount, so
4693 // this information must travel along with the operation for eventual
4694 // consumption by emitEpilogue.
4695 Ops.push_back(DAG.getTargetConstant(FPDiff, DL, MVT::i32));
4696 }
4697
4698 if (IsChainCallConv)
4699 llvm::append_range(Ops, ChainCallSpecialArgs);
4700
4701 // Add argument registers to the end of the list so that they are known live
4702 // into the call.
4703 for (auto &[Reg, Val] : RegsToPass)
4704 Ops.push_back(DAG.getRegister(Reg, Val.getValueType()));
4705
4706 // Add a register mask operand representing the call-preserved registers.
4707 const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
4708 assert(Mask && "Missing call preserved mask for calling convention");
4709 Ops.push_back(DAG.getRegisterMask(Mask));
4710
4711 if (SDValue Token = CLI.ConvergenceControlToken) {
4713 GlueOps.push_back(Token);
4714 if (InGlue)
4715 GlueOps.push_back(InGlue);
4716
4717 InGlue = SDValue(DAG.getMachineNode(TargetOpcode::CONVERGENCECTRL_GLUE, DL,
4718 MVT::Glue, GlueOps),
4719 0);
4720 }
4721
4722 if (InGlue)
4723 Ops.push_back(InGlue);
4724
4725 // If we're doing a tall call, use a TC_RETURN here rather than an
4726 // actual call instruction.
4727 if (IsTailCall) {
4728 MFI.setHasTailCall();
4729 unsigned OPC = AMDGPUISD::TC_RETURN;
4730 switch (CallConv) {
4732 OPC = AMDGPUISD::TC_RETURN_GFX;
4733 break;
4736 OPC = UsesDynamicVGPRs ? AMDGPUISD::TC_RETURN_CHAIN_DVGPR
4737 : AMDGPUISD::TC_RETURN_CHAIN;
4738 break;
4739 }
4740
4741 // If the caller is a whole wave function, we need to use a special opcode
4742 // so we can patch up EXEC.
4743 if (Info->isWholeWaveFunction())
4744 OPC = AMDGPUISD::TC_RETURN_GFX_WholeWave;
4745
4746 SDValue Ret = DAG.getNode(OPC, DL, MVT::Other, Ops);
4747 DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge);
4748 return Ret;
4749 }
4750
4751 // Returns a chain and a flag for retval copy to use.
4752 SDValue Call = DAG.getNode(AMDGPUISD::CALL, DL, {MVT::Other, MVT::Glue}, Ops);
4753 DAG.addNoMergeSiteInfo(Call.getNode(), CLI.NoMerge);
4754 Chain = Call.getValue(0);
4755 InGlue = Call.getValue(1);
4756
4757 uint64_t CalleePopBytes = NumBytes;
4758 Chain = DAG.getCALLSEQ_END(Chain, 0, CalleePopBytes, InGlue, DL);
4759 if (!Ins.empty())
4760 InGlue = Chain.getValue(1);
4761
4762 // Handle result values, copying them out of physregs into vregs that we
4763 // return.
4764 return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG,
4765 InVals, /*IsThisReturn=*/false, SDValue());
4766}
4767
4768// This is similar to the default implementation in ExpandDYNAMIC_STACKALLOC,
4769// except for:
4770// 1. Stack growth direction(default: downwards, AMDGPU: upwards), and
4771// 2. Scale size where, scale = wave-reduction(alloca-size) * wave-size
4773 SelectionDAG &DAG) const {
4774 const MachineFunction &MF = DAG.getMachineFunction();
4776
4777 SDLoc dl(Op);
4778 EVT VT = Op.getValueType();
4779 SDValue Chain = Op.getOperand(0);
4780 Register SPReg = Info->getStackPtrOffsetReg();
4781
4782 // Chain the dynamic stack allocation so that it doesn't modify the stack
4783 // pointer when other instructions are using the stack.
4784 Chain = DAG.getCALLSEQ_START(Chain, 0, 0, dl);
4785
4786 SDValue Size = Op.getOperand(1);
4787 SDValue BaseAddr = DAG.getCopyFromReg(Chain, dl, SPReg, VT);
4788 Align Alignment = cast<ConstantSDNode>(Op.getOperand(2))->getAlignValue();
4789
4790 const TargetFrameLowering *TFL = Subtarget->getFrameLowering();
4792 "Stack grows upwards for AMDGPU");
4793
4794 Chain = BaseAddr.getValue(1);
4795 // When using flat-scratch, the stack offset is unscaled.
4796 const bool HasFlatScratch = Subtarget->hasFlatScratchEnabled();
4797 const unsigned WavefrontSizeLog2 = Subtarget->getWavefrontSizeLog2();
4798
4799 Align StackAlign = TFL->getStackAlign();
4800 if (Alignment > StackAlign) {
4801 uint64_t ScaledAlignment = Alignment.value()
4802 << (HasFlatScratch ? 0 : WavefrontSizeLog2);
4803 uint64_t StackAlignMask = ScaledAlignment - 1;
4804 SDValue TmpAddr = DAG.getNode(ISD::ADD, dl, VT, BaseAddr,
4805 DAG.getConstant(StackAlignMask, dl, VT));
4806 BaseAddr = DAG.getNode(ISD::AND, dl, VT, TmpAddr,
4807 DAG.getSignedConstant(-ScaledAlignment, dl, VT));
4808 }
4809
4810 assert(Size.getValueType() == MVT::i32 && "Size must be 32-bit");
4811 SDValue NewSP;
4813 // Increase the stack pointer by the size of the alloca.
4814 // If not using flat-scratch, we have to scale the size by the wave-size.
4815 SDValue ScaledSize =
4816 HasFlatScratch
4817 ? Size
4818 : DAG.getNode(ISD::SHL, dl, VT, Size,
4819 DAG.getConstant(WavefrontSizeLog2, dl, MVT::i32));
4820 NewSP = DAG.getNode(ISD::ADD, dl, VT, BaseAddr, ScaledSize); // Value
4821 } else {
4822 // For dynamic sized alloca, perform wave-wide reduction to get max of
4823 // alloca size(divergent), and then scale it (when not using flat-scratch)
4824 // by wave-size.
4825 SDValue WaveReduction =
4826 DAG.getTargetConstant(Intrinsic::amdgcn_wave_reduce_umax, dl, MVT::i32);
4827 Size = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, WaveReduction,
4828 Size, DAG.getTargetConstant(0, dl, MVT::i32));
4829 SDValue ScaledSize = Size;
4830 if (!HasFlatScratch) {
4831 ScaledSize =
4832 DAG.getNode(ISD::SHL, dl, VT, Size,
4833 DAG.getConstant(WavefrontSizeLog2, dl, MVT::i32));
4834 }
4835 NewSP =
4836 DAG.getNode(ISD::ADD, dl, VT, BaseAddr, ScaledSize); // Value in vgpr.
4837 SDValue ReadFirstLaneID =
4838 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, dl, MVT::i32);
4839 NewSP = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, ReadFirstLaneID,
4840 NewSP);
4841 }
4842
4843 Chain = DAG.getCopyToReg(Chain, dl, SPReg, NewSP); // Output chain
4844 SDValue CallSeqEnd = DAG.getCALLSEQ_END(Chain, 0, 0, SDValue(), dl);
4845
4846 return DAG.getMergeValues({BaseAddr, CallSeqEnd}, dl);
4847}
4848
4850 if (Op.getValueType() != MVT::i32)
4851 return Op; // Defer to cannot select error.
4852
4854 SDLoc SL(Op);
4855
4856 SDValue CopyFromSP = DAG.getCopyFromReg(Op->getOperand(0), SL, SP, MVT::i32);
4857
4858 // Convert from wave uniform to swizzled vector address. This should protect
4859 // from any edge cases where the stacksave result isn't directly used with
4860 // stackrestore.
4861 SDValue VectorAddress =
4862 DAG.getNode(AMDGPUISD::WAVE_ADDRESS, SL, MVT::i32, CopyFromSP);
4863 return DAG.getMergeValues({VectorAddress, CopyFromSP.getValue(1)}, SL);
4864}
4865
4867 SelectionDAG &DAG) const {
4868 SDLoc SL(Op);
4869 assert(Op.getValueType() == MVT::i32);
4870
4871 uint32_t BothRoundHwReg =
4873 SDValue GetRoundBothImm = DAG.getTargetConstant(BothRoundHwReg, SL, MVT::i32);
4874
4875 SDValue IntrinID =
4876 DAG.getTargetConstant(Intrinsic::amdgcn_s_getreg, SL, MVT::i32);
4877 SDValue GetReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, Op->getVTList(),
4878 Op.getOperand(0), IntrinID, GetRoundBothImm);
4879
4880 // There are two rounding modes, one for f32 and one for f64/f16. We only
4881 // report in the standard value range if both are the same.
4882 //
4883 // The raw values also differ from the expected FLT_ROUNDS values. Nearest
4884 // ties away from zero is not supported, and the other values are rotated by
4885 // 1.
4886 //
4887 // If the two rounding modes are not the same, report a target defined value.
4888
4889 // Mode register rounding mode fields:
4890 //
4891 // [1:0] Single-precision round mode.
4892 // [3:2] Double/Half-precision round mode.
4893 //
4894 // 0=nearest even; 1= +infinity; 2= -infinity, 3= toward zero.
4895 //
4896 // Hardware Spec
4897 // Toward-0 3 0
4898 // Nearest Even 0 1
4899 // +Inf 1 2
4900 // -Inf 2 3
4901 // NearestAway0 N/A 4
4902 //
4903 // We have to handle 16 permutations of a 4-bit value, so we create a 64-bit
4904 // table we can index by the raw hardware mode.
4905 //
4906 // (trunc (FltRoundConversionTable >> MODE.fp_round)) & 0xf
4907
4908 SDValue BitTable =
4910
4911 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4912 SDValue RoundModeTimesNumBits =
4913 DAG.getNode(ISD::SHL, SL, MVT::i32, GetReg, Two);
4914
4915 // TODO: We could possibly avoid a 64-bit shift and use a simpler table if we
4916 // knew only one mode was demanded.
4917 SDValue TableValue =
4918 DAG.getNode(ISD::SRL, SL, MVT::i64, BitTable, RoundModeTimesNumBits);
4919 SDValue TruncTable = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, TableValue);
4920
4921 SDValue EntryMask = DAG.getConstant(0xf, SL, MVT::i32);
4922 SDValue TableEntry =
4923 DAG.getNode(ISD::AND, SL, MVT::i32, TruncTable, EntryMask);
4924
4925 // There's a gap in the 4-bit encoded table and actual enum values, so offset
4926 // if it's an extended value.
4927 SDValue Four = DAG.getConstant(4, SL, MVT::i32);
4928 SDValue IsStandardValue =
4929 DAG.getSetCC(SL, MVT::i1, TableEntry, Four, ISD::SETULT);
4930 SDValue EnumOffset = DAG.getNode(ISD::ADD, SL, MVT::i32, TableEntry, Four);
4931 SDValue Result = DAG.getNode(ISD::SELECT, SL, MVT::i32, IsStandardValue,
4932 TableEntry, EnumOffset);
4933
4934 return DAG.getMergeValues({Result, GetReg.getValue(1)}, SL);
4935}
4936
4938 SelectionDAG &DAG) const {
4939 SDLoc SL(Op);
4940
4941 SDValue NewMode = Op.getOperand(1);
4942 assert(NewMode.getValueType() == MVT::i32);
4943
4944 // Index a table of 4-bit entries mapping from the C FLT_ROUNDS values to the
4945 // hardware MODE.fp_round values.
4946 if (auto *ConstMode = dyn_cast<ConstantSDNode>(NewMode)) {
4947 uint32_t ClampedVal = std::min(
4948 static_cast<uint32_t>(ConstMode->getZExtValue()),
4950 NewMode = DAG.getConstant(
4951 AMDGPU::decodeFltRoundToHWConversionTable(ClampedVal), SL, MVT::i32);
4952 } else {
4953 // If we know the input can only be one of the supported standard modes in
4954 // the range 0-3, we can use a simplified mapping to hardware values.
4955 KnownBits KB = DAG.computeKnownBits(NewMode);
4956 const bool UseReducedTable = KB.countMinLeadingZeros() >= 30;
4957 // The supported standard values are 0-3. The extended values start at 8. We
4958 // need to offset by 4 if the value is in the extended range.
4959
4960 if (UseReducedTable) {
4961 // Truncate to the low 32-bits.
4962 SDValue BitTable = DAG.getConstant(
4963 AMDGPU::FltRoundToHWConversionTable & 0xffff, SL, MVT::i32);
4964
4965 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4966 SDValue RoundModeTimesNumBits =
4967 DAG.getNode(ISD::SHL, SL, MVT::i32, NewMode, Two);
4968
4969 NewMode =
4970 DAG.getNode(ISD::SRL, SL, MVT::i32, BitTable, RoundModeTimesNumBits);
4971
4972 // TODO: SimplifyDemandedBits on the setreg source here can likely reduce
4973 // the table extracted bits into inline immediates.
4974 } else {
4975 // table_index = umin(value, value - 4)
4976 // MODE.fp_round = (bit_table >> (table_index << 2)) & 0xf
4977 SDValue BitTable =
4979
4980 SDValue Four = DAG.getConstant(4, SL, MVT::i32);
4981 SDValue OffsetEnum = DAG.getNode(ISD::SUB, SL, MVT::i32, NewMode, Four);
4982 SDValue IndexVal =
4983 DAG.getNode(ISD::UMIN, SL, MVT::i32, NewMode, OffsetEnum);
4984
4985 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4986 SDValue RoundModeTimesNumBits =
4987 DAG.getNode(ISD::SHL, SL, MVT::i32, IndexVal, Two);
4988
4989 SDValue TableValue =
4990 DAG.getNode(ISD::SRL, SL, MVT::i64, BitTable, RoundModeTimesNumBits);
4991 SDValue TruncTable = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, TableValue);
4992
4993 // No need to mask out the high bits since the setreg will ignore them
4994 // anyway.
4995 NewMode = TruncTable;
4996 }
4997
4998 // Insert a readfirstlane in case the value is a VGPR. We could do this
4999 // earlier and keep more operations scalar, but that interferes with
5000 // combining the source.
5001 SDValue ReadFirstLaneID =
5002 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, SL, MVT::i32);
5003 NewMode = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5004 ReadFirstLaneID, NewMode);
5005 }
5006
5007 // N.B. The setreg will be later folded into s_round_mode on supported
5008 // targets.
5009 SDValue IntrinID =
5010 DAG.getTargetConstant(Intrinsic::amdgcn_s_setreg, SL, MVT::i32);
5011 uint32_t BothRoundHwReg =
5013 SDValue RoundBothImm = DAG.getTargetConstant(BothRoundHwReg, SL, MVT::i32);
5014
5015 SDValue SetReg =
5016 DAG.getNode(ISD::INTRINSIC_VOID, SL, Op->getVTList(), Op.getOperand(0),
5017 IntrinID, RoundBothImm, NewMode);
5018
5019 return SetReg;
5020}
5021
5023 unsigned AS = cast<MemSDNode>(Op)->getAddressSpace();
5024 if (AS == AMDGPUAS::BUFFER_RESOURCE)
5025 return Op.getOperand(0);
5027 return SDValue();
5028
5029 // I$ prefetch
5030 if (!Subtarget->hasSafeSmemPrefetch() && !Op.getConstantOperandVal(4))
5031 return SDValue();
5032
5033 // Prefetch the 64-bit address that a 32-bit constant pointer is cast to, as
5034 // a load does.
5035 SDValue Ptr = Op.getOperand(1);
5036 if (Ptr.getValueType() != MVT::i32)
5037 return Op;
5039 Ops[1] = DAG.getAddrSpaceCast(SDLoc(Op), MVT::i64, Ptr,
5042 return SDValue(DAG.UpdateNodeOperands(Op.getNode(), Ops), 0);
5043}
5044
5045// Work around DAG legality rules only based on the result type.
5047 bool IsStrict = Op.getOpcode() == ISD::STRICT_FP_EXTEND;
5048 SDValue Src = Op.getOperand(IsStrict ? 1 : 0);
5049 EVT SrcVT = Src.getValueType();
5050
5051 if (SrcVT.getScalarType() != MVT::bf16)
5052 return Op;
5053
5054 SDLoc SL(Op);
5055 SDValue BitCast =
5056 DAG.getNode(ISD::BITCAST, SL, SrcVT.changeTypeToInteger(), Src);
5057
5058 EVT DstVT = Op.getValueType();
5059 if (IsStrict)
5060 llvm_unreachable("Need STRICT_BF16_TO_FP");
5061
5062 return DAG.getNode(ISD::BF16_TO_FP, SL, DstVT, BitCast);
5063}
5064
5066 SDLoc SL(Op);
5067 if (Op.getValueType() != MVT::i64)
5068 return Op;
5069
5070 uint32_t ModeHwReg =
5072 SDValue ModeHwRegImm = DAG.getTargetConstant(ModeHwReg, SL, MVT::i32);
5073 uint32_t TrapHwReg =
5075 SDValue TrapHwRegImm = DAG.getTargetConstant(TrapHwReg, SL, MVT::i32);
5076
5077 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::Other);
5078 SDValue IntrinID =
5079 DAG.getTargetConstant(Intrinsic::amdgcn_s_getreg, SL, MVT::i32);
5080 SDValue GetModeReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, VTList,
5081 Op.getOperand(0), IntrinID, ModeHwRegImm);
5082 SDValue GetTrapReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, VTList,
5083 Op.getOperand(0), IntrinID, TrapHwRegImm);
5084 SDValue TokenReg =
5085 DAG.getNode(ISD::TokenFactor, SL, MVT::Other, GetModeReg.getValue(1),
5086 GetTrapReg.getValue(1));
5087
5088 SDValue CvtPtr =
5089 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, GetModeReg, GetTrapReg);
5090 SDValue Result = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
5091
5092 return DAG.getMergeValues({Result, TokenReg}, SL);
5093}
5094
5096 SDLoc SL(Op);
5097 if (Op.getOperand(1).getValueType() != MVT::i64)
5098 return Op;
5099
5100 SDValue Input = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op.getOperand(1));
5101 SDValue NewModeReg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Input,
5102 DAG.getConstant(0, SL, MVT::i32));
5103 SDValue NewTrapReg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Input,
5104 DAG.getConstant(1, SL, MVT::i32));
5105
5106 SDValue ReadFirstLaneID =
5107 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, SL, MVT::i32);
5108 NewModeReg = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5109 ReadFirstLaneID, NewModeReg);
5110 NewTrapReg = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5111 ReadFirstLaneID, NewTrapReg);
5112
5113 unsigned ModeHwReg =
5115 SDValue ModeHwRegImm = DAG.getTargetConstant(ModeHwReg, SL, MVT::i32);
5116 unsigned TrapHwReg =
5118 SDValue TrapHwRegImm = DAG.getTargetConstant(TrapHwReg, SL, MVT::i32);
5119
5120 SDValue IntrinID =
5121 DAG.getTargetConstant(Intrinsic::amdgcn_s_setreg, SL, MVT::i32);
5122 SDValue SetModeReg =
5123 DAG.getNode(ISD::INTRINSIC_VOID, SL, MVT::Other, Op.getOperand(0),
5124 IntrinID, ModeHwRegImm, NewModeReg);
5125 SDValue SetTrapReg =
5126 DAG.getNode(ISD::INTRINSIC_VOID, SL, MVT::Other, Op.getOperand(0),
5127 IntrinID, TrapHwRegImm, NewTrapReg);
5128 return DAG.getNode(ISD::TokenFactor, SL, MVT::Other, SetTrapReg, SetModeReg);
5129}
5130
5132 const MachineFunction &MF) const {
5133 Register Reg =
5135 .Case("m0", AMDGPU::M0)
5136 .Case("exec", AMDGPU::EXEC)
5137 .Case("exec_lo", AMDGPU::EXEC_LO)
5138 .Case("exec_hi", AMDGPU::EXEC_HI)
5139 .Case("flat_scratch", AMDGPU::FLAT_SCR)
5140 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
5141 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
5142 .Case("src_flat_scratch_base", AMDGPU::SRC_FLAT_SCRATCH_BASE)
5143 .Case("src_flat_scratch_base_lo", AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)
5144 .Case("src_flat_scratch_base_hi", AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)
5145 .Default(Register());
5146 if (!Reg)
5147 return Reg;
5148
5149 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
5150 if (!Subtarget->hasFlatScrRegister() &&
5151 TRI->regsOverlap(Reg, AMDGPU::FLAT_SCR))
5152 return Register();
5153
5154 if (!Subtarget->hasGloballyAddressableScratch() &&
5155 TRI->regsOverlap(Reg, AMDGPU::SRC_FLAT_SCRATCH_BASE))
5156 return Register();
5157
5158 switch (Reg) {
5159 case AMDGPU::M0:
5160 case AMDGPU::EXEC_LO:
5161 case AMDGPU::EXEC_HI:
5162 case AMDGPU::FLAT_SCR_LO:
5163 case AMDGPU::FLAT_SCR_HI:
5164 case AMDGPU::SRC_FLAT_SCRATCH_BASE_LO:
5165 case AMDGPU::SRC_FLAT_SCRATCH_BASE_HI:
5166 if (VT.getSizeInBits() == 32)
5167 return Reg;
5168 break;
5169 case AMDGPU::EXEC:
5170 case AMDGPU::FLAT_SCR:
5171 case AMDGPU::SRC_FLAT_SCRATCH_BASE:
5172 if (VT.getSizeInBits() == 64)
5173 return Reg;
5174 break;
5175 default:
5176 llvm_unreachable("missing register type checking");
5177 }
5178
5180 Twine("invalid type for register \"" + StringRef(RegName) + "\"."));
5181}
5182
5183// If kill is not the last instruction, split the block so kill is always a
5184// proper terminator.
5187 MachineBasicBlock *BB) const {
5188 MachineBasicBlock *SplitBB = BB->splitAt(MI, /*UpdateLiveIns=*/true);
5190 MI.setDesc(TII->getKillTerminatorFromPseudo(MI.getOpcode()));
5191 return SplitBB;
5192}
5193
5194// Split block \p MBB at \p MI, as to insert a loop. If \p InstInLoop is true,
5195// \p MI will be the only instruction in the loop body block. Otherwise, it will
5196// be the first instruction in the remainder block.
5197//
5198/// \returns { LoopBody, Remainder }
5199static std::pair<MachineBasicBlock *, MachineBasicBlock *>
5201 MachineFunction *MF = MBB.getParent();
5203
5204 // To insert the loop we need to split the block. Move everything after this
5205 // point to a new block, and insert a new empty block between the two.
5207 MachineBasicBlock *RemainderBB = MF->CreateMachineBasicBlock();
5209 ++MBBI;
5210
5211 MF->insert(MBBI, LoopBB);
5212 MF->insert(MBBI, RemainderBB);
5213
5214 LoopBB->addSuccessor(LoopBB);
5215 LoopBB->addSuccessor(RemainderBB);
5216
5217 // Move the rest of the block into a new block.
5218 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
5219
5220 if (InstInLoop) {
5221 auto Next = std::next(I);
5222
5223 // Move instruction to loop body.
5224 LoopBB->splice(LoopBB->begin(), &MBB, I, Next);
5225
5226 // Move the rest of the block.
5227 RemainderBB->splice(RemainderBB->begin(), &MBB, Next, MBB.end());
5228 } else {
5229 RemainderBB->splice(RemainderBB->begin(), &MBB, I, MBB.end());
5230 }
5231
5232 MBB.addSuccessor(LoopBB);
5233
5234 return std::pair(LoopBB, RemainderBB);
5235}
5236
5237/// Insert \p MI into a BUNDLE with an S_WAITCNT 0 immediately following it.
5239 MachineBasicBlock *MBB = MI.getParent();
5241 auto I = MI.getIterator();
5242 auto E = std::next(I);
5243
5244 // clang-format off
5245 BuildMI(*MBB, E, MI.getDebugLoc(), TII->get(AMDGPU::S_WAITCNT))
5246 .addImm(0);
5247 // clang-format on
5248
5249 MIBundleBuilder Bundler(*MBB, I, E);
5250 finalizeBundle(*MBB, Bundler.begin());
5251}
5252
5255 MachineBasicBlock *BB) const {
5256 const DebugLoc &DL = MI.getDebugLoc();
5257
5259
5261
5262 // Apparently kill flags are only valid if the def is in the same block?
5263 if (MachineOperand *Src = TII->getNamedOperand(MI, AMDGPU::OpName::data0))
5264 Src->setIsKill(false);
5265
5266 auto [LoopBB, RemainderBB] = splitBlockForLoop(MI, *BB, true);
5267
5268 MachineBasicBlock::iterator I = LoopBB->end();
5269
5270 const unsigned EncodedReg = AMDGPU::Hwreg::HwregEncoding::encode(
5272
5273 // Clear TRAP_STS.MEM_VIOL
5274 BuildMI(*LoopBB, LoopBB->begin(), DL, TII->get(AMDGPU::S_SETREG_IMM32_B32))
5275 .addImm(0)
5276 .addImm(EncodedReg);
5277
5279
5280 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5281
5282 // Load and check TRAP_STS.MEM_VIOL
5283 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_GETREG_B32), Reg)
5284 .addImm(EncodedReg);
5285
5286 // clang-format off
5287 // FIXME: Do we need to use an isel pseudo that may clobber scc?
5288 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_CMP_LG_U32))
5289 .addReg(Reg)
5290 .addImm(0);
5291 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
5292 .addMBB(LoopBB);
5293 // clang-format on
5294
5295 return RemainderBB;
5296}
5297
5298// Do a v_movrels_b32 or v_movreld_b32 for each unique value of \p IdxReg in the
5299// wavefront. If the value is uniform and just happens to be in a VGPR, this
5300// will only do one iteration. In the worst case, this will loop 64 times.
5301//
5302// TODO: Just use v_readlane_b32 if we know the VGPR has a uniform value.
5305 MachineBasicBlock &OrigBB, MachineBasicBlock &LoopBB,
5306 const DebugLoc &DL, const MachineOperand &Idx,
5307 unsigned InitReg, unsigned ResultReg, unsigned PhiReg,
5308 unsigned InitSaveExecReg, int Offset, bool UseGPRIdxMode,
5309 Register &SGPRIdxReg) {
5310
5311 MachineFunction *MF = OrigBB.getParent();
5312 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5313 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5316
5317 const TargetRegisterClass *BoolRC = TRI->getBoolRC();
5318 Register PhiExec = MRI.createVirtualRegister(BoolRC);
5319 Register NewExec = MRI.createVirtualRegister(BoolRC);
5320 Register CurrentIdxReg =
5321 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5322 Register CondReg = MRI.createVirtualRegister(BoolRC);
5323
5324 BuildMI(LoopBB, I, DL, TII->get(TargetOpcode::PHI), PhiReg)
5325 .addReg(InitReg)
5326 .addMBB(&OrigBB)
5327 .addReg(ResultReg)
5328 .addMBB(&LoopBB);
5329
5330 BuildMI(LoopBB, I, DL, TII->get(TargetOpcode::PHI), PhiExec)
5331 .addReg(InitSaveExecReg)
5332 .addMBB(&OrigBB)
5333 .addReg(NewExec)
5334 .addMBB(&LoopBB);
5335
5336 // Read the next variant <- also loop target.
5337 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), CurrentIdxReg)
5338 .addReg(Idx.getReg(), getUndefRegState(Idx.isUndef()));
5339
5340 // Compare the just read M0 value to all possible Idx values.
5341 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::V_CMP_EQ_U32_e64), CondReg)
5342 .addReg(CurrentIdxReg)
5343 .addReg(Idx.getReg(), {}, Idx.getSubReg());
5344
5345 // Update EXEC, save the original EXEC value to VCC.
5346 BuildMI(LoopBB, I, DL, TII->get(LMC.AndSaveExecOpc), NewExec)
5347 .addReg(CondReg)
5348 .setOperandDead(3); // Dead scc
5349
5350 MRI.setSimpleHint(NewExec, CondReg);
5351
5352 if (UseGPRIdxMode) {
5353 if (Offset == 0) {
5354 SGPRIdxReg = CurrentIdxReg;
5355 } else {
5356 SGPRIdxReg = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
5357 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_ADD_I32), SGPRIdxReg)
5358 .addReg(CurrentIdxReg)
5359 .addImm(Offset)
5360 .setOperandDead(3); // Dead scc
5361 }
5362 } else {
5363 // Move index from VCC into M0
5364 if (Offset == 0) {
5365 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::COPY), AMDGPU::M0)
5366 .addReg(CurrentIdxReg);
5367 } else {
5368 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5369 .addReg(CurrentIdxReg)
5370 .addImm(Offset)
5371 .setOperandDead(3); // Dead scc
5372 }
5373 }
5374
5375 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
5376 MachineInstr *InsertPt =
5377 BuildMI(LoopBB, I, DL, TII->get(LMC.XorTermOpc), LMC.ExecReg)
5378 .addReg(LMC.ExecReg)
5379 .addReg(NewExec)
5380 .setOperandDead(3); // Dead scc
5381
5382 // XXX - s_xor_b64 sets scc to 1 if the result is nonzero, so can we use
5383 // s_cbranch_scc0?
5384
5385 // Loop back to V_READFIRSTLANE_B32 if there are still variants to cover.
5386 // clang-format off
5387 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_CBRANCH_EXECNZ))
5388 .addMBB(&LoopBB);
5389 // clang-format on
5390
5391 return InsertPt->getIterator();
5392}
5393
5394// This has slightly sub-optimal regalloc when the source vector is killed by
5395// the read. The register allocator does not understand that the kill is
5396// per-workitem, so is kept alive for the whole loop so we end up not re-using a
5397// subregister from it, using 1 more VGPR than necessary. This was saved when
5398// this was expanded after register allocation.
5401 unsigned InitResultReg, unsigned PhiReg, int Offset,
5402 bool UseGPRIdxMode, Register &SGPRIdxReg) {
5403 MachineFunction *MF = MBB.getParent();
5404 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5405 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5406 MachineRegisterInfo &MRI = MF->getRegInfo();
5407 const DebugLoc &DL = MI.getDebugLoc();
5409
5410 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
5411 Register DstReg = MI.getOperand(0).getReg();
5412 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
5413 Register TmpExec = MRI.createVirtualRegister(BoolXExecRC);
5415
5416 BuildMI(MBB, I, DL, TII->get(TargetOpcode::IMPLICIT_DEF), TmpExec);
5417
5418 // Save the EXEC mask
5419 // clang-format off
5420 BuildMI(MBB, I, DL, TII->get(LMC.MovOpc), SaveExec)
5421 .addReg(LMC.ExecReg);
5422 // clang-format on
5423
5424 auto [LoopBB, RemainderBB] = splitBlockForLoop(MI, MBB, false);
5425
5426 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5427
5428 auto InsPt = emitLoadM0FromVGPRLoop(TII, MRI, MBB, *LoopBB, DL, *Idx,
5429 InitResultReg, DstReg, PhiReg, TmpExec,
5430 Offset, UseGPRIdxMode, SGPRIdxReg);
5431
5432 MachineBasicBlock *LandingPad = MF->CreateMachineBasicBlock();
5434 ++MBBI;
5435 MF->insert(MBBI, LandingPad);
5436 LoopBB->removeSuccessor(RemainderBB);
5437 LandingPad->addSuccessor(RemainderBB);
5438 LoopBB->addSuccessor(LandingPad);
5439 MachineBasicBlock::iterator First = LandingPad->begin();
5440 // clang-format off
5441 BuildMI(*LandingPad, First, DL, TII->get(LMC.MovOpc), LMC.ExecReg)
5442 .addReg(SaveExec);
5443 // clang-format on
5444
5445 return InsPt;
5446}
5447
5448// Returns subreg index, offset
5449static std::pair<unsigned, int>
5451 const TargetRegisterClass *SuperRC, unsigned VecReg,
5452 int Offset) {
5453 int NumElts = TRI.getRegSizeInBits(*SuperRC) / 32;
5454
5455 // Skip out of bounds offsets, or else we would end up using an undefined
5456 // register.
5457 if (Offset >= NumElts || Offset < 0)
5458 return std::pair(AMDGPU::sub0, Offset);
5459
5460 return std::pair(SIRegisterInfo::getSubRegFromChannel(Offset), 0);
5461}
5462
5465 int Offset) {
5466 MachineBasicBlock *MBB = MI.getParent();
5467 const DebugLoc &DL = MI.getDebugLoc();
5469
5470 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5471
5472 assert(Idx->getReg() != AMDGPU::NoRegister);
5473
5474 if (Offset == 0) {
5475 // clang-format off
5476 BuildMI(*MBB, I, DL, TII->get(AMDGPU::COPY), AMDGPU::M0)
5477 .add(*Idx);
5478 // clang-format on
5479 } else {
5480 BuildMI(*MBB, I, DL, TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5481 .add(*Idx)
5482 .addImm(Offset)
5483 .setOperandDead(3); // Dead scc
5484 }
5485}
5486
5489 int Offset) {
5490 MachineBasicBlock *MBB = MI.getParent();
5491 const DebugLoc &DL = MI.getDebugLoc();
5493
5494 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5495
5496 if (Offset == 0)
5497 return Idx->getReg();
5498
5499 Register Tmp = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5500 BuildMI(*MBB, I, DL, TII->get(AMDGPU::S_ADD_I32), Tmp)
5501 .add(*Idx)
5502 .addImm(Offset)
5503 .setOperandDead(3); // Dead scc
5504 return Tmp;
5505}
5506
5509 const GCNSubtarget &ST) {
5510 const SIInstrInfo *TII = ST.getInstrInfo();
5511 const SIRegisterInfo &TRI = TII->getRegisterInfo();
5512 MachineFunction *MF = MBB.getParent();
5513 MachineRegisterInfo &MRI = MF->getRegInfo();
5514
5515 Register Dst = MI.getOperand(0).getReg();
5516 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5517 Register SrcReg = TII->getNamedOperand(MI, AMDGPU::OpName::src)->getReg();
5518 int Offset = TII->getNamedOperand(MI, AMDGPU::OpName::offset)->getImm();
5519
5520 const TargetRegisterClass *VecRC = MRI.getRegClass(SrcReg);
5521 const TargetRegisterClass *IdxRC = MRI.getRegClass(Idx->getReg());
5522
5523 unsigned SubReg;
5524 std::tie(SubReg, Offset) =
5525 computeIndirectRegAndOffset(TRI, VecRC, SrcReg, Offset);
5526
5527 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5528
5529 // Check for a SGPR index.
5530 if (TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5532 const DebugLoc &DL = MI.getDebugLoc();
5533
5534 if (UseGPRIdxMode) {
5535 // TODO: Look at the uses to avoid the copy. This may require rescheduling
5536 // to avoid interfering with other uses, so probably requires a new
5537 // optimization pass.
5538 Register Idx = getIndirectSGPRIdx(TII, MRI, MI, Offset);
5539
5540 const MCInstrDesc &GPRIDXDesc =
5541 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), true);
5542 BuildMI(MBB, I, DL, GPRIDXDesc, Dst)
5543 .addReg(SrcReg)
5544 .addReg(Idx)
5545 .addImm(SubReg);
5546 } else {
5548
5549 BuildMI(MBB, I, DL, TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5550 .addReg(SrcReg, {}, SubReg)
5551 .addReg(SrcReg, RegState::Implicit);
5552 }
5553
5554 MI.eraseFromParent();
5555
5556 return &MBB;
5557 }
5558
5559 // Control flow needs to be inserted if indexing with a VGPR.
5560 const DebugLoc &DL = MI.getDebugLoc();
5562
5563 Register PhiReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5564 Register InitReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5565
5566 BuildMI(MBB, I, DL, TII->get(TargetOpcode::IMPLICIT_DEF), InitReg);
5567
5568 Register SGPRIdxReg;
5569 auto InsPt = loadM0FromVGPR(TII, MBB, MI, InitReg, PhiReg, Offset,
5570 UseGPRIdxMode, SGPRIdxReg);
5571
5572 MachineBasicBlock *LoopBB = InsPt->getParent();
5573
5574 if (UseGPRIdxMode) {
5575 const MCInstrDesc &GPRIDXDesc =
5576 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), true);
5577
5578 BuildMI(*LoopBB, InsPt, DL, GPRIDXDesc, Dst)
5579 .addReg(SrcReg)
5580 .addReg(SGPRIdxReg)
5581 .addImm(SubReg);
5582 } else {
5583 BuildMI(*LoopBB, InsPt, DL, TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5584 .addReg(SrcReg, {}, SubReg)
5585 .addReg(SrcReg, RegState::Implicit);
5586 }
5587
5588 MI.eraseFromParent();
5589
5590 return LoopBB;
5591}
5592
5595 const GCNSubtarget &ST) {
5596 const SIInstrInfo *TII = ST.getInstrInfo();
5597 const SIRegisterInfo &TRI = TII->getRegisterInfo();
5598 MachineFunction *MF = MBB.getParent();
5599 MachineRegisterInfo &MRI = MF->getRegInfo();
5600
5601 Register Dst = MI.getOperand(0).getReg();
5602 const MachineOperand *SrcVec = TII->getNamedOperand(MI, AMDGPU::OpName::src);
5603 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5604 const MachineOperand *Val = TII->getNamedOperand(MI, AMDGPU::OpName::val);
5605 int Offset = TII->getNamedOperand(MI, AMDGPU::OpName::offset)->getImm();
5606 const TargetRegisterClass *VecRC = MRI.getRegClass(SrcVec->getReg());
5607 const TargetRegisterClass *IdxRC = MRI.getRegClass(Idx->getReg());
5608
5609 // This can be an immediate, but will be folded later.
5610 assert(Val->getReg());
5611
5612 unsigned SubReg;
5613 std::tie(SubReg, Offset) =
5614 computeIndirectRegAndOffset(TRI, VecRC, SrcVec->getReg(), Offset);
5615 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5616
5617 if (Idx->getReg() == AMDGPU::NoRegister) {
5619 const DebugLoc &DL = MI.getDebugLoc();
5620
5621 assert(Offset == 0);
5622
5623 BuildMI(MBB, I, DL, TII->get(TargetOpcode::INSERT_SUBREG), Dst)
5624 .add(*SrcVec)
5625 .add(*Val)
5626 .addImm(SubReg);
5627
5628 MI.eraseFromParent();
5629 return &MBB;
5630 }
5631
5632 // Check for a SGPR index.
5633 if (TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5635 const DebugLoc &DL = MI.getDebugLoc();
5636
5637 if (UseGPRIdxMode) {
5638 Register Idx = getIndirectSGPRIdx(TII, MRI, MI, Offset);
5639
5640 const MCInstrDesc &GPRIDXDesc =
5641 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), false);
5642 BuildMI(MBB, I, DL, GPRIDXDesc, Dst)
5643 .addReg(SrcVec->getReg())
5644 .add(*Val)
5645 .addReg(Idx)
5646 .addImm(SubReg);
5647 } else {
5649
5650 const MCInstrDesc &MovRelDesc = TII->getIndirectRegWriteMovRelPseudo(
5651 TRI.getRegSizeInBits(*VecRC), 32, false);
5652 BuildMI(MBB, I, DL, MovRelDesc, Dst)
5653 .addReg(SrcVec->getReg())
5654 .add(*Val)
5655 .addImm(SubReg);
5656 }
5657 MI.eraseFromParent();
5658 return &MBB;
5659 }
5660
5661 // Control flow needs to be inserted if indexing with a VGPR.
5662 if (Val->isReg())
5663 MRI.clearKillFlags(Val->getReg());
5664
5665 const DebugLoc &DL = MI.getDebugLoc();
5666
5667 Register PhiReg = MRI.createVirtualRegister(VecRC);
5668
5669 Register SGPRIdxReg;
5670 auto InsPt = loadM0FromVGPR(TII, MBB, MI, SrcVec->getReg(), PhiReg, Offset,
5671 UseGPRIdxMode, SGPRIdxReg);
5672 MachineBasicBlock *LoopBB = InsPt->getParent();
5673
5674 if (UseGPRIdxMode) {
5675 const MCInstrDesc &GPRIDXDesc =
5676 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), false);
5677
5678 BuildMI(*LoopBB, InsPt, DL, GPRIDXDesc, Dst)
5679 .addReg(PhiReg)
5680 .add(*Val)
5681 .addReg(SGPRIdxReg)
5682 .addImm(SubReg);
5683 } else {
5684 const MCInstrDesc &MovRelDesc = TII->getIndirectRegWriteMovRelPseudo(
5685 TRI.getRegSizeInBits(*VecRC), 32, false);
5686 BuildMI(*LoopBB, InsPt, DL, MovRelDesc, Dst)
5687 .addReg(PhiReg)
5688 .add(*Val)
5689 .addImm(SubReg);
5690 }
5691
5692 MI.eraseFromParent();
5693 return LoopBB;
5694}
5695
5697 MachineBasicBlock *BB) {
5698 // For targets older than GFX12, we emit a sequence of 32-bit operations.
5699 // For GFX12, we emit s_add_u64 and s_sub_u64.
5700 MachineFunction *MF = BB->getParent();
5701 const SIInstrInfo *TII = MF->getSubtarget<GCNSubtarget>().getInstrInfo();
5702 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5704 const DebugLoc &DL = MI.getDebugLoc();
5705 MachineOperand &Dest = MI.getOperand(0);
5706 MachineOperand &Src0 = MI.getOperand(1);
5707 MachineOperand &Src1 = MI.getOperand(2);
5708 bool IsAdd = (MI.getOpcode() == AMDGPU::S_ADD_U64_PSEUDO);
5709 if (ST.hasScalarAddSub64()) {
5710 // FIXME: If scc is used, this deletes the def
5711 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U64 : AMDGPU::S_SUB_U64;
5712 // clang-format off
5713 BuildMI(*BB, MI, DL, TII->get(Opc), Dest.getReg())
5714 .add(Src0)
5715 .add(Src1);
5716 // clang-format on
5717 } else {
5718 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5719 const TargetRegisterClass *BoolRC = TRI->getBoolRC();
5720
5721 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5722 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5723
5724 MachineOperand Src0Sub0 = TII->buildExtractSubRegOrImm(
5725 MI, MRI, Src0, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5726 MachineOperand Src0Sub1 = TII->buildExtractSubRegOrImm(
5727 MI, MRI, Src0, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5728
5729 MachineOperand Src1Sub0 = TII->buildExtractSubRegOrImm(
5730 MI, MRI, Src1, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5731 MachineOperand Src1Sub1 = TII->buildExtractSubRegOrImm(
5732 MI, MRI, Src1, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5733
5734 const MachineOperand &ImpDefSCC = MI.getOperand(3);
5735 assert(ImpDefSCC.getReg() == AMDGPU::SCC && ImpDefSCC.isDef());
5736
5737 unsigned LoOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
5738 unsigned HiOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
5739 BuildMI(*BB, MI, DL, TII->get(LoOpc), DestSub0).add(Src0Sub0).add(Src1Sub0);
5740 auto Hi = BuildMI(*BB, MI, DL, TII->get(HiOpc), DestSub1)
5741 .add(Src0Sub1)
5742 .add(Src1Sub1);
5743 if (ImpDefSCC.isDead())
5744 Hi.setOperandDead(3);
5745 BuildMI(*BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dest.getReg())
5746 .addReg(DestSub0)
5747 .addImm(AMDGPU::sub0)
5748 .addReg(DestSub1)
5749 .addImm(AMDGPU::sub1);
5750 }
5751 MI.eraseFromParent();
5752 return BB;
5753}
5754
5756 MachineFunction *MF = BB->getParent();
5757 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5758 const SIInstrInfo *TII = ST.getInstrInfo();
5759 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5760 MachineRegisterInfo &MRI = MF->getRegInfo();
5761 const DebugLoc &DL = MI.getDebugLoc();
5762 Register Dst = MI.getOperand(0).getReg();
5763 const MachineOperand &Src0 = MI.getOperand(1);
5764 const MachineOperand &Src1 = MI.getOperand(2);
5765 Register SrcCond = MI.getOperand(3).getReg();
5766
5767 Register DstLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5768 Register DstHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5769 const TargetRegisterClass *CondRC = TRI->getWaveMaskRegClass();
5770 Register SrcCondCopy = MRI.createVirtualRegister(CondRC);
5771
5772 int Src0Idx =
5773 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
5774 int Src1Idx =
5775 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src1);
5776 const TargetRegisterClass *Src0RC =
5777 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), Src0Idx));
5778 const TargetRegisterClass *Src1RC =
5779 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), Src1Idx));
5780
5781 const TargetRegisterClass *Src0SubRC =
5782 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
5783 const TargetRegisterClass *Src1SubRC =
5784 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
5785
5786 MachineOperand Src0Sub0 = TII->buildExtractSubRegOrImm(
5787 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
5788 MachineOperand Src1Sub0 = TII->buildExtractSubRegOrImm(
5789 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
5790
5791 MachineOperand Src0Sub1 = TII->buildExtractSubRegOrImm(
5792 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
5793 MachineOperand Src1Sub1 = TII->buildExtractSubRegOrImm(
5794 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
5795
5796 BuildMI(*BB, MI, DL, TII->get(AMDGPU::COPY), SrcCondCopy).addReg(SrcCond);
5797 BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B32_e64), DstLo)
5798 .addImm(0)
5799 .add(Src0Sub0)
5800 .addImm(0)
5801 .add(Src1Sub0)
5802 .addReg(SrcCondCopy);
5803
5804 BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B32_e64), DstHi)
5805 .addImm(0)
5806 .add(Src0Sub1)
5807 .addImm(0)
5808 .add(Src1Sub1)
5809 .addReg(SrcCondCopy);
5810
5811 BuildMI(*BB, MI, DL, TII->get(AMDGPU::REG_SEQUENCE), Dst)
5812 .addReg(DstLo)
5813 .addImm(AMDGPU::sub0)
5814 .addReg(DstHi)
5815 .addImm(AMDGPU::sub1);
5816 MI.eraseFromParent();
5817}
5818
5820 switch (Opc) {
5821 case AMDGPU::S_MIN_U32:
5822 return std::numeric_limits<uint32_t>::max();
5823 case AMDGPU::S_MIN_I32:
5824 return std::numeric_limits<int32_t>::max();
5825 case AMDGPU::S_MAX_U32:
5826 return std::numeric_limits<uint32_t>::min();
5827 case AMDGPU::S_MAX_I32:
5828 return std::numeric_limits<int32_t>::min();
5829 case AMDGPU::V_ADD_F32_e64: // -0.0
5830 return 0x80000000;
5831 case AMDGPU::V_SUB_F32_e64: // +0.0
5832 return 0x0;
5833 case AMDGPU::S_ADD_I32:
5834 case AMDGPU::S_SUB_I32:
5835 case AMDGPU::S_OR_B32:
5836 case AMDGPU::S_XOR_B32:
5837 return std::numeric_limits<uint32_t>::min();
5838 case AMDGPU::S_AND_B32:
5839 return std::numeric_limits<uint32_t>::max();
5840 case AMDGPU::V_MIN_F32_e64:
5841 case AMDGPU::V_MAX_F32_e64:
5842 return 0x7fc00000; // qNAN
5843 case AMDGPU::V_CMP_LT_U64_e64: // umin.u64
5844 return std::numeric_limits<uint64_t>::max();
5845 case AMDGPU::V_CMP_LT_I64_e64: // min.i64
5846 return std::numeric_limits<int64_t>::max();
5847 case AMDGPU::V_CMP_GT_U64_e64: // umax.u64
5848 return std::numeric_limits<uint64_t>::min();
5849 case AMDGPU::V_CMP_GT_I64_e64: // max.i64
5850 return std::numeric_limits<int64_t>::min();
5851 case AMDGPU::V_MIN_F64_e64:
5852 case AMDGPU::V_MAX_F64_e64:
5853 case AMDGPU::V_MIN_NUM_F64_e64:
5854 case AMDGPU::V_MAX_NUM_F64_e64:
5855 return 0x7FF8000000000000; // qNAN
5856 case AMDGPU::S_ADD_U64_PSEUDO:
5857 case AMDGPU::S_SUB_U64_PSEUDO:
5858 case AMDGPU::S_OR_B64:
5859 case AMDGPU::S_XOR_B64:
5860 return std::numeric_limits<uint64_t>::min();
5861 case AMDGPU::S_AND_B64:
5862 return std::numeric_limits<uint64_t>::max();
5863 case AMDGPU::V_ADD_F64_e64:
5864 case AMDGPU::V_ADD_F64_pseudo_e64:
5865 return 0x8000000000000000; // -0.0
5866 default:
5867 llvm_unreachable("Unexpected opcode in getIdentityValueForWaveReduction");
5868 }
5869}
5870
5871static bool is32bitWaveReduceOperation(unsigned Opc) {
5872 return Opc == AMDGPU::S_MIN_U32 || Opc == AMDGPU::S_MIN_I32 ||
5873 Opc == AMDGPU::S_MAX_U32 || Opc == AMDGPU::S_MAX_I32 ||
5874 Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32 ||
5875 Opc == AMDGPU::S_AND_B32 || Opc == AMDGPU::S_OR_B32 ||
5876 Opc == AMDGPU::S_XOR_B32 || Opc == AMDGPU::V_MIN_F32_e64 ||
5877 Opc == AMDGPU::V_MAX_F32_e64 || Opc == AMDGPU::V_ADD_F32_e64 ||
5878 Opc == AMDGPU::V_SUB_F32_e64;
5879}
5880
5882 return Opc == AMDGPU::V_MIN_F32_e64 || Opc == AMDGPU::V_MAX_F32_e64 ||
5883 Opc == AMDGPU::V_ADD_F32_e64 || Opc == AMDGPU::V_SUB_F32_e64 ||
5884 Opc == AMDGPU::V_MIN_F64_e64 || Opc == AMDGPU::V_MAX_F64_e64 ||
5885 Opc == AMDGPU::V_MIN_NUM_F64_e64 || Opc == AMDGPU::V_MAX_NUM_F64_e64 ||
5886 Opc == AMDGPU::V_ADD_F64_e64 || Opc == AMDGPU::V_ADD_F64_pseudo_e64;
5887}
5888
5889static std::tuple<unsigned, unsigned>
5891 unsigned DPPOpc;
5892 switch (Opc) {
5893 case AMDGPU::S_MIN_U32:
5894 DPPOpc = AMDGPU::V_MIN_U32_dpp;
5895 break;
5896 case AMDGPU::S_MIN_I32:
5897 DPPOpc = AMDGPU::V_MIN_I32_dpp;
5898 break;
5899 case AMDGPU::S_MAX_U32:
5900 DPPOpc = AMDGPU::V_MAX_U32_dpp;
5901 break;
5902 case AMDGPU::S_MAX_I32:
5903 DPPOpc = AMDGPU::V_MAX_I32_dpp;
5904 break;
5905 case AMDGPU::S_ADD_I32:
5906 case AMDGPU::S_SUB_I32:
5907 DPPOpc = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_dpp
5908 : AMDGPU::V_ADD_CO_U32_dpp;
5909 break;
5910 case AMDGPU::S_AND_B32:
5911 DPPOpc = AMDGPU::V_AND_B32_dpp;
5912 break;
5913 case AMDGPU::S_OR_B32:
5914 DPPOpc = AMDGPU::V_OR_B32_dpp;
5915 break;
5916 case AMDGPU::S_XOR_B32:
5917 DPPOpc = AMDGPU::V_XOR_B32_dpp;
5918 break;
5919 case AMDGPU::V_ADD_F32_e64:
5920 case AMDGPU::V_SUB_F32_e64:
5921 DPPOpc = AMDGPU::V_ADD_F32_dpp;
5922 break;
5923 case AMDGPU::V_MIN_F32_e64:
5924 DPPOpc = AMDGPU::V_MIN_F32_dpp;
5925 break;
5926 case AMDGPU::V_MAX_F32_e64:
5927 DPPOpc = AMDGPU::V_MAX_F32_dpp;
5928 break;
5929 case AMDGPU::V_CMP_LT_U64_e64: // umin.u64
5930 case AMDGPU::V_CMP_LT_I64_e64: // min.i64
5931 case AMDGPU::V_CMP_GT_U64_e64: // umax.u64
5932 case AMDGPU::V_CMP_GT_I64_e64: // max.i64
5933 case AMDGPU::S_ADD_U64_PSEUDO:
5934 case AMDGPU::S_SUB_U64_PSEUDO:
5935 case AMDGPU::S_AND_B64:
5936 case AMDGPU::S_OR_B64:
5937 case AMDGPU::S_XOR_B64:
5938 case AMDGPU::V_MIN_NUM_F64_e64:
5939 case AMDGPU::V_MIN_F64_e64:
5940 case AMDGPU::V_MAX_NUM_F64_e64:
5941 case AMDGPU::V_MAX_F64_e64:
5942 case AMDGPU::V_ADD_F64_pseudo_e64:
5943 case AMDGPU::V_ADD_F64_e64:
5944 DPPOpc = AMDGPU::V_MOV_B64_DPP_PSEUDO;
5945 break;
5946 default:
5947 llvm_unreachable("unhandled lane op");
5948 }
5949 unsigned ClampOpc = Opc;
5950 if (!ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
5951 if (Opc == AMDGPU::S_SUB_I32)
5952 ClampOpc = AMDGPU::S_ADD_I32;
5953 if (Opc == AMDGPU::S_ADD_U64_PSEUDO || Opc == AMDGPU::S_SUB_U64_PSEUDO)
5954 ClampOpc = AMDGPU::V_ADD_CO_U32_e64;
5955 else if (Opc == AMDGPU::S_AND_B64)
5956 ClampOpc = AMDGPU::V_AND_B32_e64;
5957 else if (Opc == AMDGPU::S_OR_B64)
5958 ClampOpc = AMDGPU::V_OR_B32_e64;
5959 else if (Opc == AMDGPU::S_XOR_B64)
5960 ClampOpc = AMDGPU::V_XOR_B32_e64;
5961 else
5962 ClampOpc = ST.getInstrInfo()->getVALUOp(ClampOpc);
5963 }
5964 return {DPPOpc, ClampOpc};
5965}
5966
5967static std::pair<Register, Register>
5969 const TargetRegisterClass *SrcRC, const GCNSubtarget &ST,
5970 MachineRegisterInfo &MRI) {
5971 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5972 const SIInstrInfo *TII = ST.getInstrInfo();
5973 const TargetRegisterClass *SrcSubRC =
5974 TRI->getSubRegisterClass(SrcRC, AMDGPU::sub0);
5975 Register Op1L =
5976 TII->buildExtractSubReg(MI, MRI, Op, SrcRC, AMDGPU::sub0, SrcSubRC);
5977 Register Op1H =
5978 TII->buildExtractSubReg(MI, MRI, Op, SrcRC, AMDGPU::sub1, SrcSubRC);
5979 return {Op1L, Op1H};
5980}
5981
5984 const GCNSubtarget &ST,
5985 unsigned Opc) {
5987 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5988 const DebugLoc &DL = MI.getDebugLoc();
5989 const SIInstrInfo *TII = ST.getInstrInfo();
5990
5991 // Reduction operations depend on whether the input operand is SGPR or VGPR.
5992 Register SrcReg = MI.getOperand(1).getReg();
5993 bool isSGPR = TRI->isSGPRClass(MRI.getRegClass(SrcReg));
5994 Register DstReg = MI.getOperand(0).getReg();
5995 unsigned Stratergy = static_cast<unsigned>(MI.getOperand(2).getImm());
5996 enum WAVE_REDUCE_STRATEGY : unsigned { DEFAULT = 0, ITERATIVE = 1, DPP = 2 };
5997 MachineBasicBlock *RetBB = nullptr;
5998 unsigned MIOpc = MI.getOpcode();
5999 auto BuildRegSequence = [&](MachineBasicBlock &BB,
6001 Register Src0, Register Src1) {
6002 auto RegSequence =
6003 BuildMI(BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dst)
6004 .addReg(Src0)
6005 .addImm(AMDGPU::sub0)
6006 .addReg(Src1)
6007 .addImm(AMDGPU::sub1);
6008 return RegSequence;
6009 };
6010 if (isSGPR) {
6011 switch (Opc) {
6012 case AMDGPU::S_MIN_U32:
6013 case AMDGPU::S_MIN_I32:
6014 case AMDGPU::V_MIN_F32_e64:
6015 case AMDGPU::S_MAX_U32:
6016 case AMDGPU::S_MAX_I32:
6017 case AMDGPU::V_MAX_F32_e64:
6018 case AMDGPU::S_AND_B32:
6019 case AMDGPU::S_OR_B32: {
6020 // Idempotent operations.
6021 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstReg).addReg(SrcReg);
6022 RetBB = &BB;
6023 break;
6024 }
6025 case AMDGPU::V_CMP_LT_U64_e64: // umin
6026 case AMDGPU::V_CMP_LT_I64_e64: // min
6027 case AMDGPU::V_CMP_GT_U64_e64: // umax
6028 case AMDGPU::V_CMP_GT_I64_e64: // max
6029 case AMDGPU::V_MIN_F64_e64:
6030 case AMDGPU::V_MIN_NUM_F64_e64:
6031 case AMDGPU::V_MAX_F64_e64:
6032 case AMDGPU::V_MAX_NUM_F64_e64:
6033 case AMDGPU::S_AND_B64:
6034 case AMDGPU::S_OR_B64: {
6035 // Idempotent operations.
6036 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B64), DstReg).addReg(SrcReg);
6037 RetBB = &BB;
6038 break;
6039 }
6040 case AMDGPU::S_XOR_B32:
6041 case AMDGPU::S_XOR_B64:
6042 case AMDGPU::S_ADD_I32:
6043 case AMDGPU::S_ADD_U64_PSEUDO:
6044 case AMDGPU::V_ADD_F32_e64:
6045 case AMDGPU::V_ADD_F64_e64:
6046 case AMDGPU::V_ADD_F64_pseudo_e64:
6047 case AMDGPU::S_SUB_I32:
6048 case AMDGPU::S_SUB_U64_PSEUDO:
6049 case AMDGPU::V_SUB_F32_e64: {
6050 const TargetRegisterClass *WaveMaskRegClass = TRI->getWaveMaskRegClass();
6051 const TargetRegisterClass *DstRegClass = MRI.getRegClass(DstReg);
6052 Register ExecMask = MRI.createVirtualRegister(WaveMaskRegClass);
6053 Register NumActiveLanes =
6054 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6055
6056 bool IsWave32 = ST.isWave32();
6057 unsigned MovOpc = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6058 MCRegister ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6059 unsigned BitCountOpc =
6060 IsWave32 ? AMDGPU::S_BCNT1_I32_B32 : AMDGPU::S_BCNT1_I32_B64;
6061
6062 BuildMI(BB, MI, DL, TII->get(MovOpc), ExecMask).addReg(ExecReg);
6063
6064 auto NewAccumulator =
6065 BuildMI(BB, MI, DL, TII->get(BitCountOpc), NumActiveLanes)
6066 .addReg(ExecMask)
6067 .setOperandDead(2); // Dead scc
6068
6069 switch (Opc) {
6070 case AMDGPU::S_XOR_B32:
6071 case AMDGPU::S_XOR_B64: {
6072 // Performing an XOR operation on a uniform value
6073 // depends on the parity of the number of active lanes.
6074 // For even parity, the result will be 0, for odd
6075 // parity the result will be the same as the input value.
6076 Register ParityRegister =
6077 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6078 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_AND_B32), ParityRegister)
6079 .addReg(NewAccumulator->getOperand(0).getReg())
6080 .addImm(1)
6081 .setOperandDead(3); // Dead scc
6082 // Check if Src is a known identity constant.
6083 MachineInstr *SrcDef = MRI.getVRegDef(SrcReg);
6084 if (SrcDef && SrcDef->isMoveImmediate()) {
6085 int64_t Imm = SrcDef->getOperand(1).getImm();
6086 if (Imm == 1) { // 1 * parity(exec) = parity(exec)
6087 if (Opc == AMDGPU::S_XOR_B32) {
6088 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstReg)
6089 .addReg(ParityRegister);
6090 } else {
6091 Register DstHi =
6092 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6093 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstHi).addImm(0);
6094 BuildRegSequence(BB, MI, DstReg, ParityRegister, DstHi);
6095 }
6096 break;
6097 }
6098 }
6099 if (Opc == AMDGPU::S_XOR_B32) {
6100 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6101 .addReg(SrcReg)
6102 .addReg(ParityRegister);
6103 } else {
6104 Register DestSub0 =
6105 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6106 Register DestSub1 =
6107 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6108 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6109 MRI.getRegClass(SrcReg), ST, MRI);
6110 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub0)
6111 .addReg(Op1L)
6112 .addReg(ParityRegister);
6113 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub1)
6114 .addReg(Op1H)
6115 .addReg(ParityRegister);
6116 BuildRegSequence(BB, MI, DstReg, DestSub0, DestSub1);
6117 }
6118 break;
6119 }
6120 case AMDGPU::S_SUB_I32: {
6121 Register NegatedVal = MRI.createVirtualRegister(DstRegClass);
6122 // Take the negation of the source operand.
6123 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedVal)
6124 .addImm(0)
6125 .addReg(SrcReg)
6126 .setOperandDead(3); // Dead scc
6127 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6128 .addReg(NegatedVal)
6129 .addReg(NewAccumulator->getOperand(0).getReg());
6130 break;
6131 }
6132 case AMDGPU::S_ADD_I32: {
6133 // Check if Src is a known identity constant.
6134 MachineInstr *SrcDef = MRI.getVRegDef(SrcReg);
6135 if (SrcDef && SrcDef->isMoveImmediate()) {
6136 int64_t Imm = SrcDef->getOperand(1).getImm();
6137 if (Imm == 1) { // 1 * bitcount(exec) = bitcount(exec)
6138 BuildMI(BB, MI, DL, TII->get(AMDGPU::COPY), DstReg)
6139 .addReg(NewAccumulator->getOperand(0).getReg());
6140 break;
6141 }
6142 }
6143 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6144 .addReg(SrcReg)
6145 .addReg(NewAccumulator->getOperand(0).getReg());
6146 break;
6147 }
6148 case AMDGPU::S_ADD_U64_PSEUDO:
6149 case AMDGPU::S_SUB_U64_PSEUDO: {
6150 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6151 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6152 Register Op1H_Op0L_Reg =
6153 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6154 Register Op1L_Op0H_Reg =
6155 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6156 Register CarryReg =
6157 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6158 Register AddReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6159 Register NegatedValLo =
6160 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6161 Register NegatedValHi =
6162 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6163 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6164 MRI.getRegClass(SrcReg), ST, MRI);
6165 // Check if Src is a known identity constant.
6166 MachineInstr *SrcDef = MRI.getVRegDef(SrcReg);
6167 if (SrcDef && SrcDef->isMoveImmediate()) {
6168 int64_t Imm = SrcDef->getOperand(1).getImm();
6169 if (Imm == 1 && Opc == AMDGPU::S_ADD_U64_PSEUDO) {
6170 // 1 * bitcount(exec) = bitcount(exec)
6171 Register DstHi =
6172 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6173 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstHi).addImm(0);
6174 BuildRegSequence(BB, MI, DstReg,
6175 NewAccumulator->getOperand(0).getReg(), DstHi);
6176 break;
6177 }
6178 }
6179 if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6180 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedValLo)
6181 .addImm(0)
6182 .addReg(NewAccumulator->getOperand(0).getReg())
6183 .setOperandDead(3); // Dead scc
6184 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ASHR_I32), NegatedValHi)
6185 .addReg(NegatedValLo)
6186 .addImm(31)
6187 .setOperandDead(3); // Dead scc
6188 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), Op1L_Op0H_Reg)
6189 .addReg(Op1L)
6190 .addReg(NegatedValHi);
6191 }
6192 Register LowOpcode = Opc == AMDGPU::S_SUB_U64_PSEUDO
6193 ? NegatedValLo
6194 : NewAccumulator->getOperand(0).getReg();
6195 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub0)
6196 .addReg(Op1L)
6197 .addReg(LowOpcode);
6198 if (ST.hasScalarMulHiInsts()) {
6199 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_HI_U32), CarryReg)
6200 .addReg(Op1L)
6201 .addReg(LowOpcode);
6202 } else {
6203 Register VCarryReg =
6204 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6205 Register LowOpVGPR =
6206 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6207 BuildMI(BB, MI, DL, TII->get(AMDGPU::COPY), LowOpVGPR)
6208 .addReg(LowOpcode);
6209 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_MUL_HI_U32_e64), VCarryReg)
6210 .addReg(Op1L)
6211 .addReg(LowOpVGPR);
6212 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), CarryReg)
6213 .addReg(VCarryReg);
6214 }
6215 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), Op1H_Op0L_Reg)
6216 .addReg(Op1H)
6217 .addReg(LowOpcode);
6218
6219 Register HiVal = Opc == AMDGPU::S_SUB_U64_PSEUDO ? AddReg : DestSub1;
6220 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ADD_U32), HiVal)
6221 .addReg(CarryReg)
6222 .addReg(Op1H_Op0L_Reg)
6223 .setOperandDead(3); // Dead scc
6224
6225 if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6226 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ADD_U32), DestSub1)
6227 .addReg(HiVal)
6228 .addReg(Op1L_Op0H_Reg)
6229 .setOperandDead(3); // Dead scc
6230 }
6231 BuildRegSequence(BB, MI, DstReg, DestSub0, DestSub1);
6232 break;
6233 }
6234 case AMDGPU::V_ADD_F32_e64:
6235 case AMDGPU::V_ADD_F64_e64:
6236 case AMDGPU::V_ADD_F64_pseudo_e64:
6237 case AMDGPU::V_SUB_F32_e64: {
6238 bool is32BitOpc = is32bitWaveReduceOperation(Opc);
6239 const TargetRegisterClass *VregRC = TII->getRegClass(TII->get(Opc), 0);
6240 Register ActiveLanesVreg = MRI.createVirtualRegister(VregRC);
6241 Register DstVreg = MRI.createVirtualRegister(VregRC);
6242 // Get number of active lanes as a float val.
6243 BuildMI(BB, MI, DL,
6244 TII->get(is32BitOpc ? AMDGPU::V_CVT_F32_I32_e64
6245 : AMDGPU::V_CVT_F64_I32_e64),
6246 ActiveLanesVreg)
6247 .addReg(NewAccumulator->getOperand(0).getReg())
6248 .addImm(0) // clamp
6249 .addImm(0); // output-modifier
6250
6251 // Take negation of input for SUB reduction
6252 unsigned srcMod = (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6253 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64)
6256 unsigned MulOpc = is32BitOpc ? AMDGPU::V_MUL_F32_e64
6257 : ST.getGeneration() >= AMDGPUSubtarget::GFX12
6258 ? AMDGPU::V_MUL_F64_pseudo_e64
6259 : AMDGPU::V_MUL_F64_e64;
6260 auto DestVregInst = BuildMI(BB, MI, DL, TII->get(MulOpc),
6261 DstVreg)
6262 .addImm(srcMod) // src0 modifier
6263 .addReg(SrcReg)
6264 .addImm(SISrcMods::NONE) // src1 modifier
6265 .addReg(ActiveLanesVreg)
6266 .addImm(SISrcMods::NONE) // clamp
6267 .addImm(SISrcMods::NONE); // output-mod
6268 if (is32BitOpc) {
6269 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6270 .addReg(DstVreg);
6271 } else {
6272 Register LaneValueLoReg =
6273 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6274 Register LaneValueHiReg =
6275 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6276 auto [Op1L, Op1H] =
6277 ExtractSubRegs(MI, DestVregInst->getOperand(0), VregRC, ST, MRI);
6278 // lane value input should be in an sgpr
6279 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6280 LaneValueLoReg)
6281 .addReg(Op1L);
6282 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6283 LaneValueHiReg)
6284 .addReg(Op1H);
6285 NewAccumulator =
6286 BuildRegSequence(BB, MI, DstReg, LaneValueLoReg, LaneValueHiReg);
6287 }
6288 }
6289 }
6290 RetBB = &BB;
6291 }
6292 }
6293 } else {
6295 Register SrcReg = MI.getOperand(1).getReg();
6296 bool is32BitOpc = is32bitWaveReduceOperation(Opc);
6298 bool NeedsMovDPP = !is32BitOpc;
6299 // Create virtual registers required for lowering.
6300 const TargetRegisterClass *WaveMaskRegClass = TRI->getWaveMaskRegClass();
6301 const TargetRegisterClass *DstRegClass = MRI.getRegClass(DstReg);
6302 const TargetRegisterClass *SrcRegClass = MRI.getRegClass(SrcReg);
6303 bool IsWave32 = ST.isWave32();
6304 unsigned MovOpcForExec = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6305 unsigned ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6306 if (Stratergy == WAVE_REDUCE_STRATEGY::ITERATIVE ||
6307 !ST.hasDPP()) { // If target doesn't support DPP operations, default to
6308 // iterative stratergy
6309
6310 // To reduce the VGPR using iterative approach, we need to iterate
6311 // over all the active lanes. Lowering consists of ComputeLoop,
6312 // which iterate over only active lanes. We use copy of EXEC register
6313 // as induction variable and every active lane modifies it using bitset0
6314 // so that we will get the next active lane for next iteration.
6315
6316 // Create Control flow for loop
6317 // Split MI's Machine Basic block into For loop
6318 auto [ComputeLoop, ComputeEnd] = splitBlockForLoop(MI, BB, true);
6319
6320 Register LoopIterator = MRI.createVirtualRegister(WaveMaskRegClass);
6321 Register IdentityValReg = MRI.createVirtualRegister(DstRegClass);
6322 Register AccumulatorReg = MRI.createVirtualRegister(DstRegClass);
6323 Register ActiveBitsReg = MRI.createVirtualRegister(WaveMaskRegClass);
6324 Register NewActiveBitsReg = MRI.createVirtualRegister(WaveMaskRegClass);
6325 Register FF1Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6326 Register LaneValueReg = MRI.createVirtualRegister(DstRegClass);
6327
6328 // Create initial values of induction variable from Exec, Accumulator and
6329 // insert branch instr to newly created ComputeBlock
6330 BuildMI(BB, I, DL, TII->get(MovOpcForExec), LoopIterator).addReg(ExecReg);
6331 uint64_t IdentityValue =
6332 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6333 ? 0x0 // +0.0 for double sub reduction
6335 BuildMI(BB, I, DL,
6336 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6337 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6338 IdentityValReg)
6339 .addImm(IdentityValue);
6340 // clang-format off
6341 BuildMI(BB, I, DL, TII->get(AMDGPU::S_BRANCH))
6342 .addMBB(ComputeLoop);
6343 // clang-format on
6344
6345 // Start constructing ComputeLoop
6346 I = ComputeLoop->begin();
6347 auto Accumulator =
6348 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::PHI), AccumulatorReg)
6349 .addReg(IdentityValReg)
6350 .addMBB(&BB);
6351 auto ActiveBits =
6352 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::PHI), ActiveBitsReg)
6353 .addReg(LoopIterator)
6354 .addMBB(&BB);
6355
6356 I = ComputeLoop->end();
6357 MachineInstr *NewAccumulator;
6358 // Perform the computations
6359 unsigned SFFOpc =
6360 IsWave32 ? AMDGPU::S_FF1_I32_B32 : AMDGPU::S_FF1_I32_B64;
6361 BuildMI(*ComputeLoop, I, DL, TII->get(SFFOpc), FF1Reg)
6362 .addReg(ActiveBitsReg);
6363 if (is32BitOpc) {
6364 Register OpDstReg = DstReg;
6365 bool hasSrc0Modifier = AMDGPU::getNamedOperandIdx(
6366 Opc, AMDGPU::OpName::src0_modifiers) != -1;
6367 bool hasSrc1Modifier = AMDGPU::getNamedOperandIdx(
6368 Opc, AMDGPU::OpName::src1_modifiers) != -1;
6369 bool hasClamp =
6370 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1;
6371 bool hasOpSel =
6372 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel) != -1;
6373 bool hasOMod =
6374 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1;
6375 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6376 LaneValueReg)
6377 .addReg(SrcReg)
6378 .addReg(FF1Reg);
6379 if (ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
6380 // Get the Lane Value in VGPR to avoid the Constant Bus Restriction
6381 Register LaneValVgpr = MRI.createVirtualRegister(SrcRegClass);
6382 Register VgprResultReg = MRI.createVirtualRegister(SrcRegClass);
6383 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::COPY), LaneValVgpr)
6384 .addReg(LaneValueReg);
6385 OpDstReg = VgprResultReg;
6386 LaneValueReg = LaneValVgpr;
6387 }
6388 auto OpInstr = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), OpDstReg);
6389 if (hasSrc0Modifier)
6390 OpInstr.addImm(SISrcMods::NONE); // src0 modifier
6391 OpInstr.addReg(AccumulatorReg); // src0
6392 if (hasSrc1Modifier)
6393 OpInstr.addImm(SISrcMods::NONE); // src1 modifier
6394 OpInstr.addReg(LaneValueReg); // src1
6395 if (hasClamp)
6396 OpInstr.addImm(0); // clamp
6397 if (hasOpSel)
6398 OpInstr.addImm(0); // opsel
6399 if (hasOMod)
6400 OpInstr.addImm(0); // omod
6401 if (TII->isSALU(Opc))
6402 OpInstr.setOperandDead(3); // Dead scc
6403 if (ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
6404 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6405 DstReg)
6406 .addReg(OpDstReg);
6407 }
6408 } else {
6409 Register LaneValueLoReg =
6410 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6411 Register LaneValueHiReg =
6412 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6413 Register LaneValReg =
6414 MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
6415 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6416 MRI.getRegClass(SrcReg), ST, MRI);
6417 // lane value input should be in an sgpr
6418 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6419 LaneValueLoReg)
6420 .addReg(Op1L)
6421 .addReg(FF1Reg);
6422 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6423 LaneValueHiReg)
6424 .addReg(Op1H)
6425 .addReg(FF1Reg);
6426 auto LaneValue = BuildRegSequence(*ComputeLoop, I, LaneValReg,
6427 LaneValueLoReg, LaneValueHiReg);
6428 switch (Opc) {
6429 case AMDGPU::S_OR_B64:
6430 case AMDGPU::S_AND_B64:
6431 case AMDGPU::S_XOR_B64: {
6432 NewAccumulator = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstReg)
6433 .addReg(Accumulator->getOperand(0).getReg())
6434 .addReg(LaneValue->getOperand(0).getReg())
6435 .setOperandDead(3); // Dead scc
6436 break;
6437 }
6438 case AMDGPU::V_CMP_GT_I64_e64:
6439 case AMDGPU::V_CMP_GT_U64_e64:
6440 case AMDGPU::V_CMP_LT_I64_e64:
6441 case AMDGPU::V_CMP_LT_U64_e64: {
6442 Register LaneMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6443 Register ComparisonResultReg =
6444 MRI.createVirtualRegister(WaveMaskRegClass);
6445 int SrcIdx =
6446 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src);
6447 const TargetRegisterClass *VregClass =
6448 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), SrcIdx));
6449 Register AccumulatorVReg = MRI.createVirtualRegister(VregClass);
6450 auto [SrcReg0Sub0, SrcReg0Sub1] = ExtractSubRegs(
6451 MI, Accumulator->getOperand(0), VregClass, ST, MRI);
6452 BuildRegSequence(*ComputeLoop, I, AccumulatorVReg, SrcReg0Sub0,
6453 SrcReg0Sub1);
6454 BuildMI(*ComputeLoop, I, DL, TII->get(Opc), LaneMaskReg)
6455 .addReg(LaneValue->getOperand(0).getReg())
6456 .addReg(AccumulatorVReg);
6457
6458 unsigned AndOpc = IsWave32 ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64;
6459 BuildMI(*ComputeLoop, I, DL, TII->get(AndOpc), ComparisonResultReg)
6460 .addReg(LaneMaskReg)
6461 .addReg(ActiveBitsReg);
6462
6463 NewAccumulator = BuildMI(*ComputeLoop, I, DL,
6464 TII->get(AMDGPU::S_CSELECT_B64), DstReg)
6465 .addReg(LaneValue->getOperand(0).getReg())
6466 .addReg(Accumulator->getOperand(0).getReg());
6467 break;
6468 }
6469 case AMDGPU::V_MIN_F64_e64:
6470 case AMDGPU::V_MIN_NUM_F64_e64:
6471 case AMDGPU::V_MAX_F64_e64:
6472 case AMDGPU::V_MAX_NUM_F64_e64:
6473 case AMDGPU::V_ADD_F64_e64:
6474 case AMDGPU::V_ADD_F64_pseudo_e64: {
6475 int SrcIdx =
6476 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src);
6477 const TargetRegisterClass *VregRC =
6478 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), SrcIdx));
6479 Register AccumulatorVReg = MRI.createVirtualRegister(VregRC);
6480 Register DstVreg = MRI.createVirtualRegister(VregRC);
6481 Register LaneValLo =
6482 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6483 Register LaneValHi =
6484 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6485 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::COPY), AccumulatorVReg)
6486 .addReg(Accumulator->getOperand(0).getReg());
6487 unsigned Modifier =
6488 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6491 auto DstVregInst =
6492 BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstVreg)
6493 .addImm(Modifier) // src0 modifiers
6494 .addReg(LaneValue->getOperand(0).getReg())
6495 .addImm(SISrcMods::NONE) // src1 modifiers
6496 .addReg(AccumulatorVReg)
6497 .addImm(SISrcMods::NONE) // clamp
6498 .addImm(SISrcMods::NONE); // omod
6499 auto ReadLaneLo =
6500 BuildMI(*ComputeLoop, I, DL,
6501 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValLo);
6502 auto ReadLaneHi =
6503 BuildMI(*ComputeLoop, I, DL,
6504 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValHi);
6505 MachineBasicBlock::iterator Iters = *ReadLaneLo;
6506 auto [Op1L, Op1H] = ExtractSubRegs(*Iters, DstVregInst->getOperand(0),
6507 VregRC, ST, MRI);
6508 ReadLaneLo.addReg(Op1L);
6509 ReadLaneHi.addReg(Op1H);
6510 NewAccumulator =
6511 BuildRegSequence(*ComputeLoop, I, DstReg, LaneValLo, LaneValHi);
6512 break;
6513 }
6514 case AMDGPU::S_ADD_U64_PSEUDO:
6515 case AMDGPU::S_SUB_U64_PSEUDO: {
6516 NewAccumulator = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstReg)
6517 .addReg(Accumulator->getOperand(0).getReg())
6518 .addReg(LaneValue->getOperand(0).getReg())
6519 .setOperandDead(3); // Dead scc
6520 ComputeLoop =
6521 expand64BitScalarArithmetic(*NewAccumulator, ComputeLoop);
6522 break;
6523 }
6524 }
6525 }
6526 // Manipulate the iterator to get the next active lane
6527 unsigned BITSETOpc =
6528 IsWave32 ? AMDGPU::S_BITSET0_B32 : AMDGPU::S_BITSET0_B64;
6529 BuildMI(*ComputeLoop, I, DL, TII->get(BITSETOpc), NewActiveBitsReg)
6530 .addReg(FF1Reg)
6531 .addReg(ActiveBitsReg);
6532
6533 // Add phi nodes
6534 Accumulator.addReg(DstReg).addMBB(ComputeLoop);
6535 ActiveBits.addReg(NewActiveBitsReg).addMBB(ComputeLoop);
6536
6537 // Creating branching
6538 MachineInstrBuilder SetSCCInstr;
6539 if (!ST.hasScalarCompareEq64()) {
6540 // For targets <= gfx7, use an S_OR_B32/B64 instruction to set SCC.
6541 Register LaneMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6542 unsigned CMPOpc = IsWave32 ? AMDGPU::S_OR_B32 : AMDGPU::S_OR_B64;
6543 SetSCCInstr =
6544 BuildMI(*ComputeLoop, I, DL, TII->get(CMPOpc), LaneMaskReg);
6545 } else {
6546 unsigned CMPOpc =
6547 IsWave32 ? AMDGPU::S_CMP_LG_U32 : AMDGPU::S_CMP_LG_U64;
6548 SetSCCInstr = BuildMI(*ComputeLoop, I, DL, TII->get(CMPOpc));
6549 }
6550 SetSCCInstr.addReg(NewActiveBitsReg);
6551 if (ST.hasScalarCompareEq64())
6552 SetSCCInstr.addImm(0);
6553 else
6554 SetSCCInstr.addReg(NewActiveBitsReg);
6555 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
6556 .addMBB(ComputeLoop);
6557
6558 RetBB = ComputeEnd;
6559 } else {
6560 assert(ST.hasDPP() && "Sub Target does not support DPP Operations");
6561 MachineBasicBlock *CurrBB = &BB;
6562 Register SrcWithIdentity = MRI.createVirtualRegister(SrcRegClass);
6563 Register IdentityVGPR = MRI.createVirtualRegister(SrcRegClass);
6564 Register IdentitySGPR = MRI.createVirtualRegister(DstRegClass);
6565 Register DPPRowShr1 = MRI.createVirtualRegister(SrcRegClass);
6566 Register DPPRowShr2 = MRI.createVirtualRegister(SrcRegClass);
6567 Register DPPRowShr4 = MRI.createVirtualRegister(SrcRegClass);
6568 Register DPPRowShr8 = MRI.createVirtualRegister(SrcRegClass);
6569 Register RowBcast15 = MRI.createVirtualRegister(SrcRegClass);
6570 Register ReducedValSGPR = MRI.createVirtualRegister(DstRegClass);
6571 Register NegatedReducedVal = MRI.createVirtualRegister(DstRegClass);
6572 Register RowBcast31 = MRI.createVirtualRegister(SrcRegClass);
6573 Register UndefExec = MRI.createVirtualRegister(WaveMaskRegClass);
6574 Register FinalDPPResult;
6575 MachineInstr *SrcWithIdentityInstr;
6576 MachineInstr *LastBcastInstr;
6577 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::IMPLICIT_DEF), UndefExec);
6578
6580 BuildMI(*CurrBB, MI, DL,
6581 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6582 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6583 IdentitySGPR)
6584 .addImm(IdentityValue);
6585 auto IdentityCopyInstr =
6586 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::COPY), IdentityVGPR)
6587 .addReg(IdentitySGPR);
6588 unsigned DPPOpc, ClampOpc;
6589 std::tie(DPPOpc, ClampOpc) = getDPPOpcForWaveReduction(Opc, ST);
6590 auto BuildSetInactiveInstr = [&](Register Dst, Register Src0,
6591 Register Src1) {
6592 return BuildMI(BB, MI, DL, TII->get(AMDGPU::V_SET_INACTIVE_B32),
6593 Dst)
6594 .addImm(0) // src0 modifiers
6595 .addReg(Src0) // src0
6596 .addImm(0) // src1 modifiers
6597 .addReg(Src1) // identity value for inactive lanes
6598 .addReg(UndefExec); // bool i1
6599 };
6600 auto BuildDPPMachineInstr = [&](Register Dst, Register Src,
6601 unsigned DPPCtrl) {
6602 auto DPPInstr =
6603 BuildMI(*CurrBB, MI, DL, TII->get(DPPOpc), Dst).addReg(Src); // old
6604 if (isFPOp && !NeedsMovDPP)
6605 DPPInstr.addImm(SISrcMods::NONE); // src0 modifier
6606 DPPInstr.addReg(Src); // src0
6607 if (isFPOp && !NeedsMovDPP)
6608 DPPInstr.addImm(SISrcMods::NONE); // src1 modifier
6609 if (!NeedsMovDPP)
6610 DPPInstr.addReg(Src); // src1
6611 if (AMDGPU::getNamedOperandIdx(DPPOpc, AMDGPU::OpName::clamp) >= 0)
6612 DPPInstr.addImm(0); // clamp
6613 DPPInstr
6614 .addImm(DPPCtrl) // dpp-ctrl
6615 .addImm(0xf) // row-mask
6616 .addImm(0xf) // bank-mask
6617 .addImm(0); // bound-control
6618 };
6619 auto BuildClampInstr = [&](Register Dst, Register Src0, Register Src1,
6620 bool isAddSub = false,
6621 bool needsCarryIn = false,
6622 Register CarryIn = Register()) {
6623 unsigned InstrOpc = ClampOpc;
6624 Register CarryOutReg = MRI.createVirtualRegister(WaveMaskRegClass);
6625 if (needsCarryIn)
6626 InstrOpc = AMDGPU::V_ADDC_U32_e64;
6627 auto ClampInstr = BuildMI(*CurrBB, MI, DL, TII->get(InstrOpc), Dst);
6628 if (isFPOp)
6629 ClampInstr.addImm(SISrcMods::NONE); // src0 mod
6630 if (isAddSub) {
6631 if (needsCarryIn)
6632 ClampInstr.addReg(CarryOutReg,
6634 RegState::Dead); // killed carry-out reg
6635 else
6636 ClampInstr.addReg(CarryOutReg, RegState::Define); // carry-out reg
6637 }
6638 ClampInstr.addReg(Src0); // src0
6639 if (isFPOp)
6640 ClampInstr.addImm(SISrcMods::NONE); // src1 mod
6641 ClampInstr.addReg(Src1); // src1
6642 if (needsCarryIn)
6643 ClampInstr.addReg(CarryIn); // carry-in reg
6644 if (AMDGPU::getNamedOperandIdx(InstrOpc, AMDGPU::OpName::clamp) >= 0)
6645 ClampInstr.addImm(0); // clamp
6646 if (isFPOp)
6647 ClampInstr.addImm(0); // omod
6648 LastBcastInstr = ClampInstr;
6649 return CarryOutReg;
6650 };
6651 auto BuildPostDPPInstr = [&](Register Src0, Register Src1) {
6652 bool isAddSubOpc =
6653 Opc == AMDGPU::S_ADD_U64_PSEUDO || Opc == AMDGPU::S_SUB_U64_PSEUDO;
6654 bool isBitWiseOpc = Opc == AMDGPU::S_AND_B64 ||
6655 Opc == AMDGPU::S_OR_B64 || Opc == AMDGPU::S_XOR_B64;
6656 Register ReturnReg = MRI.createVirtualRegister(SrcRegClass);
6657 if (isAddSubOpc || isBitWiseOpc) {
6658 Register ResLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6659 Register ResHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6660 MachineOperand Src0Operand =
6661 MachineOperand::CreateReg(Src0, /*isDef=*/false);
6662 MachineOperand Src1Operand =
6663 MachineOperand::CreateReg(Src1, /*isDef=*/false);
6664 auto [Src0Lo, Src0Hi] =
6665 ExtractSubRegs(MI, Src0Operand, SrcRegClass, ST, MRI);
6666 auto [Src1Lo, Src1Hi] =
6667 ExtractSubRegs(MI, Src1Operand, SrcRegClass, ST, MRI);
6668 Register CarryReg = BuildClampInstr(
6669 ResLo, Src0Lo, Src1Lo, isAddSubOpc, /*needsCarryIn*/ false);
6670 BuildClampInstr(ResHi, Src0Hi, Src1Hi, isAddSubOpc,
6671 /*needsCarryIn*/ isAddSubOpc, CarryReg);
6672 BuildRegSequence(*CurrBB, MI, ReturnReg, ResLo, ResHi);
6673 } else {
6674 if (isFPOp) {
6675 BuildMI(*CurrBB, MI, DL, TII->get(Opc), ReturnReg)
6676 .addImm(SISrcMods::NONE) // src0 modifiers
6677 .addReg(Src0)
6678 .addImm(SISrcMods::NONE) // src1 modifiers
6679 .addReg(Src1)
6680 .addImm(SISrcMods::NONE) // clamp
6681 .addImm(SISrcMods::NONE); // omod
6682 } else {
6683 Register CmpMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6684 BuildMI(*CurrBB, MI, DL, TII->get(Opc), CmpMaskReg)
6685 .addReg(Src0) // src0
6686 .addReg(Src1); // src1
6687 LastBcastInstr =
6688 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B64_PSEUDO),
6689 ReturnReg)
6690 .addReg(Src1) // src0
6691 .addReg(Src0) // src1
6692 .addReg(CmpMaskReg); // src2
6693 expand64BitV_CNDMASK(*LastBcastInstr, CurrBB);
6694 }
6695 }
6696 return ReturnReg;
6697 };
6698
6699 // Set inactive lanes to the identity value.
6700 if (is32BitOpc) {
6701 SrcWithIdentityInstr =
6702 BuildSetInactiveInstr(SrcWithIdentity, SrcReg, IdentityVGPR);
6703 } else {
6704 Register SrcWithIdentitylo =
6705 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6706 Register SrcWithIdentityhi =
6707 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6708 auto [Reg0Sub0, Reg0Sub1] = ExtractSubRegs(
6709 MI, IdentityCopyInstr->getOperand(0), SrcRegClass, ST, MRI);
6710 auto [SrcReg0Sub0, SrcReg0Sub1] =
6711 ExtractSubRegs(MI, MI.getOperand(1), SrcRegClass, ST, MRI);
6712 MachineInstr *SetInactiveLoInstr =
6713 BuildSetInactiveInstr(SrcWithIdentitylo, SrcReg0Sub0, Reg0Sub0);
6714 MachineInstr *SetInactiveHiInstr =
6715 BuildSetInactiveInstr(SrcWithIdentityhi, SrcReg0Sub1, Reg0Sub1);
6716 SrcWithIdentityInstr =
6717 BuildRegSequence(*CurrBB, MI, SrcWithIdentity,
6718 SetInactiveLoInstr->getOperand(0).getReg(),
6719 SetInactiveHiInstr->getOperand(0).getReg());
6720 }
6721 // DPP reduction
6722 Register SrcWithIdentityReg =
6723 SrcWithIdentityInstr->getOperand(0).getReg();
6724 BuildDPPMachineInstr(DPPRowShr1, SrcWithIdentityReg,
6726 if (NeedsMovDPP)
6727 DPPRowShr1 = BuildPostDPPInstr(SrcWithIdentityReg, DPPRowShr1);
6728
6729 BuildDPPMachineInstr(DPPRowShr2, DPPRowShr1,
6731 if (NeedsMovDPP)
6732 DPPRowShr2 = BuildPostDPPInstr(DPPRowShr1, DPPRowShr2);
6733
6734 BuildDPPMachineInstr(DPPRowShr4, DPPRowShr2,
6736 if (NeedsMovDPP)
6737 DPPRowShr4 = BuildPostDPPInstr(DPPRowShr2, DPPRowShr4);
6738
6739 BuildDPPMachineInstr(DPPRowShr8, DPPRowShr4,
6741 if (NeedsMovDPP)
6742 DPPRowShr8 = BuildPostDPPInstr(DPPRowShr4, DPPRowShr8);
6743
6744 if (ST.hasDPPBroadcasts()) {
6745 BuildDPPMachineInstr(RowBcast15, DPPRowShr8, AMDGPU::DPP::BCAST15);
6746 if (NeedsMovDPP)
6747 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, RowBcast15);
6748 } else {
6749 // magic constant: 0x1E0
6750 // To Set BIT_MODE : bit 15 = 0
6751 // XOR mask : bit [14:10] = 0
6752 // OR mask : bit [9:5] = 15
6753 // AND mask : bit [4:0] = 0
6754 if (is32BitOpc) {
6755 Register SwizzledValue =
6756 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6757 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6758 SwizzledValue)
6759 .addReg(DPPRowShr8) // addr
6760 .addImm(0x1E0) // swizzle offset (i16)
6761 .addImm(0x0); // gds (i1)
6762 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue);
6763 } else {
6764 Register SwizzledValuelo =
6765 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6766 Register SwizzledValuehi =
6767 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6768 Register SwizzledValue64 = MRI.createVirtualRegister(SrcRegClass);
6769 MachineOperand DPPRowShr8Op =
6770 MachineOperand::CreateReg(DPPRowShr8, /*isDef=*/false);
6771 auto [Op1L, Op1H] =
6772 ExtractSubRegs(MI, DPPRowShr8Op, SrcRegClass, ST, MRI);
6773 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6774 SwizzledValuelo)
6775 .addReg(Op1L) // addr
6776 .addImm(0x1E0) // swizzle offset (i16)
6777 .addImm(0x0); // gds (i1)
6778 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6779 SwizzledValuehi)
6780 .addReg(Op1H) // addr
6781 .addImm(0x1E0) // swizzle offset (i16)
6782 .addImm(0x0); // gds (i1)
6783 BuildRegSequence(*CurrBB, MI, SwizzledValue64, SwizzledValuelo,
6784 SwizzledValuehi);
6785 if (NeedsMovDPP)
6786 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, SwizzledValue64);
6787 else
6788 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue64);
6789 }
6790 }
6791 FinalDPPResult = RowBcast15;
6792 if (!IsWave32) {
6793 if (ST.hasDPPBroadcasts()) {
6794 BuildDPPMachineInstr(RowBcast31, RowBcast15, AMDGPU::DPP::BCAST31);
6795 if (NeedsMovDPP)
6796 RowBcast31 = BuildPostDPPInstr(RowBcast15, RowBcast31);
6797 } else {
6798 Register ShiftedThreadID =
6799 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6800 Register PermuteByteOffset =
6801 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6802 Register PermutedValue = MRI.createVirtualRegister(SrcRegClass);
6803 Register Lane32Offset =
6804 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6805 Register WordSizeConst =
6806 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6807 Register ThreadIDRegLo =
6808 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6809 Register ThreadIDReg =
6810 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6811 // Get the thread ID.
6812 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MBCNT_LO_U32_B32_e64),
6813 ThreadIDRegLo)
6814 .addImm(-1)
6815 .addImm(0);
6816 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MBCNT_HI_U32_B32_e64),
6817 ThreadIDReg)
6818 .addImm(-1)
6819 .addReg(ThreadIDRegLo);
6820 // shift each lane over by 32 positions, so value in 31st lane is
6821 // present in 63rd lane.
6822 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), Lane32Offset)
6823 .addImm(0x20);
6824 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_ADD_U32_e64),
6825 ShiftedThreadID)
6826 .addReg(ThreadIDReg)
6827 .addReg(Lane32Offset)
6828 .addImm(0); // clamp
6829 // multiply by reg size.
6830 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), WordSizeConst)
6831 .addImm(0x4);
6832 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MUL_LO_U32_e64),
6833 PermuteByteOffset)
6834 .addReg(WordSizeConst)
6835 .addReg(ShiftedThreadID);
6836 // Permute the lanes
6837 if (is32BitOpc) {
6838 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6839 PermutedValue)
6840 .addReg(PermuteByteOffset) // addr
6841 .addReg(RowBcast15) // data
6842 .addImm(0); // offset
6843 } else {
6844 Register PermutedValuelo =
6845 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6846 Register PermutedValuehi =
6847 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6848 MachineOperand RowBcast15Op =
6849 MachineOperand::CreateReg(RowBcast15, /*isDef=*/false);
6850 auto [RowBcast15Lo, RowBcast15Hi] =
6851 ExtractSubRegs(MI, RowBcast15Op, SrcRegClass, ST, MRI);
6852 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6853 PermutedValuelo)
6854 .addReg(PermuteByteOffset) // addr
6855 .addReg(RowBcast15Lo) // swizzle offset (i16)
6856 .addImm(0x0); // gds (i1)
6857 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6858 PermutedValuehi)
6859 .addReg(PermuteByteOffset) // addr
6860 .addReg(RowBcast15Hi) // swizzle offset (i16)
6861 .addImm(0x0); // gds (i1)
6862 BuildRegSequence(*CurrBB, MI, PermutedValue, PermutedValuelo,
6863 PermutedValuehi);
6864 }
6865 if (NeedsMovDPP)
6866 RowBcast31 = BuildPostDPPInstr(RowBcast15, PermutedValue);
6867 else
6868 BuildClampInstr(RowBcast31, RowBcast15, PermutedValue);
6869 }
6870 FinalDPPResult = RowBcast31;
6871 }
6872 if (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6873 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64) {
6874 Register NegatedValVGPR = MRI.createVirtualRegister(SrcRegClass);
6875 // Opc for f32 reduction is V_SUB_F32.
6876 // For f64, there is no equivalent V_SUB_F64 opcode, so use
6877 // V_ADD_F64/V_ADD_F64_pseudo, and negate the second operand.
6878 BuildMI(*CurrBB, MI, DL, TII->get(Opc),
6879 NegatedValVGPR)
6880 .addImm(SISrcMods::NONE) // src0 mods
6881 .addReg(IdentityVGPR) // src0
6882 .addImm(is32BitOpc ? SISrcMods::NONE : SISrcMods::NEG) // src1 mods
6883 .addReg(IsWave32 ? RowBcast15 : RowBcast31) // src1
6884 .addImm(SISrcMods::NONE) // clamp
6885 .addImm(SISrcMods::NONE); // omod
6886 FinalDPPResult = NegatedValVGPR;
6887 }
6888 // The final reduced value is in the last lane.
6889 if (is32BitOpc) {
6890 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6891 ReducedValSGPR)
6892 .addReg(FinalDPPResult)
6893 .addImm(ST.getWavefrontSize() - 1);
6894 } else {
6895 Register LaneValueLoReg =
6896 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6897 Register LaneValueHiReg =
6898 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6899 const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
6900 MachineOperand FinalDPPResultOperand =
6901 MachineOperand::CreateReg(FinalDPPResult, /*isDef=*/false);
6902 auto [Op1L, Op1H] =
6903 ExtractSubRegs(MI, FinalDPPResultOperand, SrcRC, ST, MRI);
6904 // lane value input should be in an sgpr
6905 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6906 LaneValueLoReg)
6907 .addReg(Op1L)
6908 .addImm(ST.getWavefrontSize() - 1);
6909 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6910 LaneValueHiReg)
6911 .addReg(Op1H)
6912 .addImm(ST.getWavefrontSize() - 1);
6913 BuildRegSequence(*CurrBB, MI, ReducedValSGPR, LaneValueLoReg,
6914 LaneValueHiReg);
6915 }
6916 if (Opc == AMDGPU::S_SUB_I32) {
6917 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedReducedVal)
6918 .addImm(0)
6919 .addReg(ReducedValSGPR)
6920 .setOperandDead(3); // Dead scc
6921 } else if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6922 auto NegatedValInstr =
6923 BuildMI(*CurrBB, MI, DL, TII->get(Opc), NegatedReducedVal)
6924 .addImm(0)
6925 .addReg(ReducedValSGPR)
6926 .setOperandDead(3); // Dead scc
6927 CurrBB = expand64BitScalarArithmetic(*NegatedValInstr, CurrBB);
6928 }
6929 // Mark the final result as a whole-wave-mode calculation.
6930 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::STRICT_WWM), DstReg)
6931 .addReg(Opc == AMDGPU::S_SUB_I32 || Opc == AMDGPU::S_SUB_U64_PSEUDO
6932 ? NegatedReducedVal
6933 : ReducedValSGPR);
6934 RetBB = CurrBB;
6935 }
6936 }
6937 MI.eraseFromParent();
6938 return RetBB;
6939}
6940
6943 MachineBasicBlock *BB) const {
6944 MachineFunction *MF = BB->getParent();
6946 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
6948 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
6949 MachineRegisterInfo &MRI = MF->getRegInfo();
6950 const DebugLoc &DL = MI.getDebugLoc();
6951
6952 switch (MI.getOpcode()) {
6953 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U32:
6954 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MIN_U32);
6955 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U64:
6956 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_LT_U64_e64);
6957 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I32:
6958 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MIN_I32);
6959 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I64:
6960 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_LT_I64_e64);
6961 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F32:
6962 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_MIN_F32_e64);
6963 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F64:
6964 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6965 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6966 ? AMDGPU::V_MIN_NUM_F64_e64
6967 : AMDGPU::V_MIN_F64_e64);
6968 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U32:
6969 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MAX_U32);
6970 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U64:
6971 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_GT_U64_e64);
6972 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I32:
6973 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MAX_I32);
6974 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I64:
6975 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_GT_I64_e64);
6976 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F32:
6977 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_MAX_F32_e64);
6978 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F64:
6979 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6980 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6981 ? AMDGPU::V_MAX_NUM_F64_e64
6982 : AMDGPU::V_MAX_F64_e64);
6983 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_I32:
6984 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_ADD_I32);
6985 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_U64:
6986 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_ADD_U64_PSEUDO);
6987 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F32:
6988 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_ADD_F32_e64);
6989 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F64:
6990 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6991 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6992 ? AMDGPU::V_ADD_F64_pseudo_e64
6993 : AMDGPU::V_ADD_F64_e64);
6994 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_I32:
6995 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_SUB_I32);
6996 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_U64:
6997 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_SUB_U64_PSEUDO);
6998 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32:
6999 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_SUB_F32_e64);
7000 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64:
7001 // There is no S/V_SUB_F64 opcode. Double type subtraction is expanded as
7002 // fadd + neg, by setting the NEG bit in the instruction.
7003 return lowerWaveReduce(MI, *BB, *getSubtarget(),
7004 ST.getGeneration() >= AMDGPUSubtarget::GFX12
7005 ? AMDGPU::V_ADD_F64_pseudo_e64
7006 : AMDGPU::V_ADD_F64_e64);
7007 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B32:
7008 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_AND_B32);
7009 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B64:
7010 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_AND_B64);
7011 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B32:
7012 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_OR_B32);
7013 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B64:
7014 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_OR_B64);
7015 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B32:
7016 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_XOR_B32);
7017 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B64:
7018 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_XOR_B64);
7019 case AMDGPU::S_UADDO_PSEUDO:
7020 case AMDGPU::S_USUBO_PSEUDO: {
7021 MachineOperand &Dest0 = MI.getOperand(0);
7022 MachineOperand &Dest1 = MI.getOperand(1);
7023 MachineOperand &Src0 = MI.getOperand(2);
7024 MachineOperand &Src1 = MI.getOperand(3);
7025
7026 unsigned Opc = (MI.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
7027 ? AMDGPU::S_ADD_U32
7028 : AMDGPU::S_SUB_U32;
7029 // clang-format off
7030 BuildMI(*BB, MI, DL, TII->get(Opc), Dest0.getReg())
7031 .add(Src0)
7032 .add(Src1);
7033 // clang-format on
7034
7035 unsigned SelOpc =
7036 Subtarget->isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7037 BuildMI(*BB, MI, DL, TII->get(SelOpc), Dest1.getReg()).addImm(-1).addImm(0);
7038
7039 MI.eraseFromParent();
7040 return BB;
7041 }
7042 case AMDGPU::S_ADD_U64_PSEUDO:
7043 case AMDGPU::S_SUB_U64_PSEUDO: {
7044 return expand64BitScalarArithmetic(MI, BB);
7045 }
7046 case AMDGPU::V_ADD_U64_PSEUDO:
7047 case AMDGPU::V_SUB_U64_PSEUDO: {
7048 bool IsAdd = (MI.getOpcode() == AMDGPU::V_ADD_U64_PSEUDO);
7049
7050 MachineOperand &Dest = MI.getOperand(0);
7051 MachineOperand &Src0 = MI.getOperand(1);
7052 MachineOperand &Src1 = MI.getOperand(2);
7053
7054 if (ST.hasAddSubU64Insts()) {
7055 auto I = BuildMI(*BB, MI, DL,
7056 TII->get(IsAdd ? AMDGPU::V_ADD_U64_e64
7057 : AMDGPU::V_SUB_U64_e64),
7058 Dest.getReg())
7059 .add(Src0)
7060 .add(Src1)
7061 .addImm(0); // clamp
7062 TII->legalizeOperands(*I);
7063 MI.eraseFromParent();
7064 return BB;
7065 }
7066
7067 if (IsAdd && ST.hasLshlAddU64Inst()) {
7068 auto Add = BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_LSHL_ADD_U64_e64),
7069 Dest.getReg())
7070 .add(Src0)
7071 .addImm(0)
7072 .add(Src1);
7073 TII->legalizeOperands(*Add);
7074 MI.eraseFromParent();
7075 return BB;
7076 }
7077
7078 const auto *CarryRC = TRI->getWaveMaskRegClass();
7079
7080 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7081 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7082
7083 Register CarryReg = MRI.createVirtualRegister(CarryRC);
7084 Register DeadCarryReg = MRI.createVirtualRegister(CarryRC);
7085
7086 const TargetRegisterClass *Src0RC = Src0.isReg()
7087 ? MRI.getRegClass(Src0.getReg())
7088 : &AMDGPU::VReg_64RegClass;
7089 const TargetRegisterClass *Src1RC = Src1.isReg()
7090 ? MRI.getRegClass(Src1.getReg())
7091 : &AMDGPU::VReg_64RegClass;
7092
7093 const TargetRegisterClass *Src0SubRC =
7094 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
7095 const TargetRegisterClass *Src1SubRC =
7096 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
7097
7098 MachineOperand SrcReg0Sub0 = TII->buildExtractSubRegOrImm(
7099 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
7100 MachineOperand SrcReg1Sub0 = TII->buildExtractSubRegOrImm(
7101 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
7102
7103 MachineOperand SrcReg0Sub1 = TII->buildExtractSubRegOrImm(
7104 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
7105 MachineOperand SrcReg1Sub1 = TII->buildExtractSubRegOrImm(
7106 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
7107
7108 unsigned LoOpc =
7109 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
7110 MachineInstr *LoHalf = BuildMI(*BB, MI, DL, TII->get(LoOpc), DestSub0)
7111 .addReg(CarryReg, RegState::Define)
7112 .add(SrcReg0Sub0)
7113 .add(SrcReg1Sub0)
7114 .addImm(0); // clamp bit
7115
7116 unsigned HiOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
7117 MachineInstr *HiHalf =
7118 BuildMI(*BB, MI, DL, TII->get(HiOpc), DestSub1)
7119 .addReg(DeadCarryReg, RegState::Define | RegState::Dead)
7120 .add(SrcReg0Sub1)
7121 .add(SrcReg1Sub1)
7122 .addReg(CarryReg)
7123 .addImm(0); // clamp bit
7124
7125 BuildMI(*BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dest.getReg())
7126 .addReg(DestSub0)
7127 .addImm(AMDGPU::sub0)
7128 .addReg(DestSub1)
7129 .addImm(AMDGPU::sub1);
7130 TII->legalizeOperands(*LoHalf);
7131 TII->legalizeOperands(*HiHalf);
7132 MI.eraseFromParent();
7133 return BB;
7134 }
7135 case AMDGPU::S_ADD_CO_PSEUDO:
7136 case AMDGPU::S_SUB_CO_PSEUDO: {
7137 // This pseudo has a chance to be selected
7138 // only from uniform add/subcarry node. All the VGPR operands
7139 // therefore assumed to be splat vectors.
7141 MachineOperand &Dest = MI.getOperand(0);
7142 MachineOperand &CarryDest = MI.getOperand(1);
7143 MachineOperand &Src0 = MI.getOperand(2);
7144 MachineOperand &Src1 = MI.getOperand(3);
7145 MachineOperand &Src2 = MI.getOperand(4);
7146 if (Src0.isReg() && TRI->isVectorRegister(MRI, Src0.getReg())) {
7147 Register RegOp0 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7148 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp0)
7149 .addReg(Src0.getReg());
7150 Src0.setReg(RegOp0);
7151 }
7152 if (Src1.isReg() && TRI->isVectorRegister(MRI, Src1.getReg())) {
7153 Register RegOp1 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7154 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp1)
7155 .addReg(Src1.getReg());
7156 Src1.setReg(RegOp1);
7157 }
7158 Register RegOp2 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7159 if (TRI->isVectorRegister(MRI, Src2.getReg())) {
7160 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp2)
7161 .addReg(Src2.getReg());
7162 Src2.setReg(RegOp2);
7163 }
7164
7165 if (ST.isWave64()) {
7166 if (ST.hasScalarCompareEq64()) {
7167 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U64))
7168 .addReg(Src2.getReg())
7169 .addImm(0);
7170 } else {
7171 const TargetRegisterClass *Src2RC = MRI.getRegClass(Src2.getReg());
7172 const TargetRegisterClass *SubRC =
7173 TRI->getSubRegisterClass(Src2RC, AMDGPU::sub0);
7174 MachineOperand Src2Sub0 = TII->buildExtractSubRegOrImm(
7175 MII, MRI, Src2, Src2RC, AMDGPU::sub0, SubRC);
7176 MachineOperand Src2Sub1 = TII->buildExtractSubRegOrImm(
7177 MII, MRI, Src2, Src2RC, AMDGPU::sub1, SubRC);
7178 Register Src2_32 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7179
7180 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_OR_B32), Src2_32)
7181 .add(Src2Sub0)
7182 .add(Src2Sub1);
7183
7184 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U32))
7185 .addReg(Src2_32)
7186 .addImm(0);
7187 }
7188 } else {
7189 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U32))
7190 .addReg(Src2.getReg())
7191 .addImm(0);
7192 }
7193
7194 unsigned Opc = MI.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO
7195 ? AMDGPU::S_ADDC_U32
7196 : AMDGPU::S_SUBB_U32;
7197
7198 BuildMI(*BB, MII, DL, TII->get(Opc), Dest.getReg()).add(Src0).add(Src1);
7199
7200 unsigned SelOpc =
7201 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7202
7203 BuildMI(*BB, MII, DL, TII->get(SelOpc), CarryDest.getReg())
7204 .addImm(-1)
7205 .addImm(0);
7206
7207 MI.eraseFromParent();
7208 return BB;
7209 }
7210 case AMDGPU::SI_INIT_M0: {
7211 MachineOperand &M0Init = MI.getOperand(0);
7212 BuildMI(*BB, MI.getIterator(), MI.getDebugLoc(),
7213 TII->get(M0Init.isReg() ? AMDGPU::COPY : AMDGPU::S_MOV_B32),
7214 AMDGPU::M0)
7215 .add(M0Init);
7216 MI.eraseFromParent();
7217 return BB;
7218 }
7219 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM: {
7220 // Set SCC to true, in case the barrier instruction gets converted to a NOP.
7221 BuildMI(*BB, MI.getIterator(), MI.getDebugLoc(),
7222 TII->get(AMDGPU::S_CMP_EQ_U32))
7223 .addImm(0)
7224 .addImm(0);
7225 return BB;
7226 }
7227 case AMDGPU::GET_GROUPSTATICSIZE: {
7228 assert(getTargetMachine().getTargetTriple().getOS() == Triple::AMDHSA ||
7229 getTargetMachine().getTargetTriple().getOS() == Triple::AMDPAL);
7230 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_MOV_B32))
7231 .add(MI.getOperand(0))
7232 .addImm(MFI->getLDSSize());
7233 MI.eraseFromParent();
7234 return BB;
7235 }
7236 case AMDGPU::GET_SHADERCYCLESHILO: {
7237 assert(MF->getSubtarget<GCNSubtarget>().hasShaderCyclesHiLoRegisters());
7238 // The algorithm is:
7239 //
7240 // hi1 = getreg(SHADER_CYCLES_HI)
7241 // lo1 = getreg(SHADER_CYCLES_LO)
7242 // hi2 = getreg(SHADER_CYCLES_HI)
7243 //
7244 // If hi1 == hi2 then there was no overflow and the result is hi2:lo1.
7245 // Otherwise there was overflow and the result is hi2:0. In both cases the
7246 // result should represent the actual time at some point during the sequence
7247 // of three getregs.
7248 using namespace AMDGPU::Hwreg;
7249 Register RegHi1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7250 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegHi1)
7251 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7252 Register RegLo1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7253 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegLo1)
7254 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES, 0, 32));
7255 Register RegHi2 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7256 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegHi2)
7257 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7258 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CMP_EQ_U32))
7259 .addReg(RegHi1)
7260 .addReg(RegHi2);
7261 Register RegLo = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7262 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CSELECT_B32), RegLo)
7263 .addReg(RegLo1)
7264 .addImm(0);
7265 BuildMI(*BB, MI, DL, TII->get(AMDGPU::REG_SEQUENCE))
7266 .add(MI.getOperand(0))
7267 .addReg(RegLo)
7268 .addImm(AMDGPU::sub0)
7269 .addReg(RegHi2)
7270 .addImm(AMDGPU::sub1);
7271 MI.eraseFromParent();
7272 return BB;
7273 }
7274 case AMDGPU::SI_INDIRECT_SRC_V1:
7275 case AMDGPU::SI_INDIRECT_SRC_V2:
7276 case AMDGPU::SI_INDIRECT_SRC_V3:
7277 case AMDGPU::SI_INDIRECT_SRC_V4:
7278 case AMDGPU::SI_INDIRECT_SRC_V5:
7279 case AMDGPU::SI_INDIRECT_SRC_V6:
7280 case AMDGPU::SI_INDIRECT_SRC_V7:
7281 case AMDGPU::SI_INDIRECT_SRC_V8:
7282 case AMDGPU::SI_INDIRECT_SRC_V9:
7283 case AMDGPU::SI_INDIRECT_SRC_V10:
7284 case AMDGPU::SI_INDIRECT_SRC_V11:
7285 case AMDGPU::SI_INDIRECT_SRC_V12:
7286 case AMDGPU::SI_INDIRECT_SRC_V16:
7287 case AMDGPU::SI_INDIRECT_SRC_V32:
7288 return emitIndirectSrc(MI, *BB, *getSubtarget());
7289 case AMDGPU::SI_INDIRECT_DST_V1:
7290 case AMDGPU::SI_INDIRECT_DST_V2:
7291 case AMDGPU::SI_INDIRECT_DST_V3:
7292 case AMDGPU::SI_INDIRECT_DST_V4:
7293 case AMDGPU::SI_INDIRECT_DST_V5:
7294 case AMDGPU::SI_INDIRECT_DST_V6:
7295 case AMDGPU::SI_INDIRECT_DST_V7:
7296 case AMDGPU::SI_INDIRECT_DST_V8:
7297 case AMDGPU::SI_INDIRECT_DST_V9:
7298 case AMDGPU::SI_INDIRECT_DST_V10:
7299 case AMDGPU::SI_INDIRECT_DST_V11:
7300 case AMDGPU::SI_INDIRECT_DST_V12:
7301 case AMDGPU::SI_INDIRECT_DST_V16:
7302 case AMDGPU::SI_INDIRECT_DST_V32:
7303 return emitIndirectDst(MI, *BB, *getSubtarget());
7304 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
7305 case AMDGPU::SI_KILL_I1_PSEUDO:
7306 return splitKillBlock(MI, BB);
7307 case AMDGPU::V_CNDMASK_B64_PSEUDO: {
7309 return BB;
7310 }
7311 case AMDGPU::SI_BR_UNDEF: {
7312 MachineInstr *Br = BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
7313 .add(MI.getOperand(0));
7314 Br->getOperand(1).setIsUndef(); // read undef SCC
7315 MI.eraseFromParent();
7316 return BB;
7317 }
7318 case AMDGPU::ADJCALLSTACKUP:
7319 case AMDGPU::ADJCALLSTACKDOWN: {
7321 MachineInstrBuilder MIB(*MF, &MI);
7322 MIB.addReg(Info->getStackPtrOffsetReg(), RegState::ImplicitDefine)
7323 .addReg(Info->getStackPtrOffsetReg(), RegState::Implicit);
7324 return BB;
7325 }
7326 case AMDGPU::SI_CALL_ISEL: {
7327 unsigned ReturnAddrReg = TII->getRegisterInfo().getReturnAddressReg(*MF);
7328
7330 MIB = BuildMI(*BB, MI, DL, TII->get(AMDGPU::SI_CALL))
7331 .addDef(ReturnAddrReg, RegState::Dead);
7332
7333 for (const MachineOperand &MO : MI.operands())
7334 MIB.add(MO);
7335
7336 MIB.cloneMemRefs(MI);
7337 MIB.setMIFlags(MI.getFlags());
7338 MI.eraseFromParent();
7339 return BB;
7340 }
7341 case AMDGPU::V_ADDC_U32_e32:
7342 case AMDGPU::V_SUBB_U32_e32:
7343 case AMDGPU::V_SUBBREV_U32_e32:
7344 // These instructions have an implicit use of vcc which counts towards the
7345 // constant bus limit.
7346 TII->legalizeOperands(MI);
7347 return BB;
7348 case AMDGPU::DS_GWS_INIT:
7349 case AMDGPU::DS_GWS_SEMA_BR:
7350 case AMDGPU::DS_GWS_BARRIER:
7351 case AMDGPU::DS_GWS_SEMA_V:
7352 case AMDGPU::DS_GWS_SEMA_P:
7353 case AMDGPU::DS_GWS_SEMA_RELEASE_ALL:
7354 // A s_waitcnt 0 is required to be the instruction immediately following.
7355 if (getSubtarget()->hasGWSAutoReplay()) {
7357 return BB;
7358 }
7359
7360 return emitGWSMemViolTestLoop(MI, BB);
7361 case AMDGPU::S_SETREG_B32: {
7362 // Try to optimize cases that only set the denormal mode or rounding mode.
7363 //
7364 // If the s_setreg_b32 fully sets all of the bits in the rounding mode or
7365 // denormal mode to a constant, we can use s_round_mode or s_denorm_mode
7366 // instead.
7367 //
7368 // FIXME: This could be predicates on the immediate, but tablegen doesn't
7369 // allow you to have a no side effect instruction in the output of a
7370 // sideeffecting pattern.
7371 auto [ID, Offset, Width] =
7372 AMDGPU::Hwreg::HwregEncoding::decode(MI.getOperand(1).getImm());
7373 if (ID != AMDGPU::Hwreg::ID_MODE)
7374 return BB;
7375
7376 const unsigned WidthMask = maskTrailingOnes<unsigned>(Width);
7377 const unsigned SetMask = WidthMask << Offset;
7378
7379 if (getSubtarget()->hasDenormModeInst()) {
7380 unsigned SetDenormOp = 0;
7381 unsigned SetRoundOp = 0;
7382
7383 // The dedicated instructions can only set the whole denorm or round mode
7384 // at once, not a subset of bits in either.
7385 if (SetMask ==
7387 // If this fully sets both the round and denorm mode, emit the two
7388 // dedicated instructions for these.
7389 SetRoundOp = AMDGPU::S_ROUND_MODE;
7390 SetDenormOp = AMDGPU::S_DENORM_MODE;
7391 } else if (SetMask == AMDGPU::Hwreg::FP_ROUND_MASK) {
7392 SetRoundOp = AMDGPU::S_ROUND_MODE;
7393 } else if (SetMask == AMDGPU::Hwreg::FP_DENORM_MASK) {
7394 SetDenormOp = AMDGPU::S_DENORM_MODE;
7395 }
7396
7397 if (SetRoundOp || SetDenormOp) {
7398 MachineInstr *Def = MRI.getVRegDef(MI.getOperand(0).getReg());
7399 if (Def && Def->isMoveImmediate() && Def->getOperand(1).isImm()) {
7400 unsigned ImmVal = Def->getOperand(1).getImm();
7401 if (SetRoundOp) {
7402 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SetRoundOp))
7403 .addImm(ImmVal & 0xf);
7404
7405 // If we also have the denorm mode, get just the denorm mode bits.
7406 ImmVal >>= 4;
7407 }
7408
7409 if (SetDenormOp) {
7410 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SetDenormOp))
7411 .addImm(ImmVal & 0xf);
7412 }
7413
7414 MI.eraseFromParent();
7415 return BB;
7416 }
7417 }
7418 }
7419
7420 // If only FP bits are touched, used the no side effects pseudo.
7421 if ((SetMask & (AMDGPU::Hwreg::FP_ROUND_MASK |
7422 AMDGPU::Hwreg::FP_DENORM_MASK)) == SetMask)
7423 MI.setDesc(TII->get(AMDGPU::S_SETREG_B32_mode));
7424
7425 return BB;
7426 }
7427 case AMDGPU::S_INVERSE_BALLOT_U32:
7428 case AMDGPU::S_INVERSE_BALLOT_U64:
7429 // These opcodes only exist to let SIFixSGPRCopies insert a readfirstlane if
7430 // necessary. After that they are equivalent to a COPY.
7431 MI.setDesc(TII->get(AMDGPU::COPY));
7432 return BB;
7433 case AMDGPU::ENDPGM_TRAP: {
7434 if (BB->succ_empty() && std::next(MI.getIterator()) == BB->end()) {
7435 MI.setDesc(TII->get(AMDGPU::S_ENDPGM));
7436 MI.addOperand(MachineOperand::CreateImm(0));
7437 return BB;
7438 }
7439
7440 // We need a block split to make the real endpgm a terminator. We also don't
7441 // want to break phis in successor blocks, so we can't just delete to the
7442 // end of the block.
7443
7444 MachineBasicBlock *SplitBB = BB->splitAt(MI, false /*UpdateLiveIns*/);
7446 MF->push_back(TrapBB);
7447 // clang-format off
7448 BuildMI(*TrapBB, TrapBB->end(), DL, TII->get(AMDGPU::S_ENDPGM))
7449 .addImm(0);
7450 BuildMI(*BB, &MI, DL, TII->get(AMDGPU::S_CBRANCH_EXECNZ))
7451 .addMBB(TrapBB);
7452 // clang-format on
7453
7454 BB->addSuccessor(TrapBB);
7455 MI.eraseFromParent();
7456 return SplitBB;
7457 }
7458 case AMDGPU::SIMULATED_TRAP: {
7459 assert(Subtarget->hasPrivEnabledTrap2NopBug());
7460 MachineBasicBlock *SplitBB =
7461 TII->insertSimulatedTrap(MRI, *BB, MI, MI.getDebugLoc());
7462 MI.eraseFromParent();
7463 return SplitBB;
7464 }
7465 case AMDGPU::SI_TCRETURN_GFX_WholeWave:
7466 case AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN: {
7468
7469 // During ISel, it's difficult to propagate the original EXEC mask to use as
7470 // an input to SI_WHOLE_WAVE_FUNC_RETURN. Set it up here instead.
7471 MachineInstr *Setup = TII->getWholeWaveFunctionSetup(*BB->getParent());
7472 assert(Setup && "Couldn't find SI_SETUP_WHOLE_WAVE_FUNC");
7473 Register OriginalExec = Setup->getOperand(0).getReg();
7474 MF->getRegInfo().clearKillFlags(OriginalExec);
7475 MI.getOperand(0).setReg(OriginalExec);
7476 return BB;
7477 }
7478 case AMDGPU::V_DOT2_F32_F16:
7479 case AMDGPU::V_DOT2_F32_BF16: {
7480 // Hint RA to assign dst and src2 the same physical register.
7481 // For targets without VOP2, but with VOPD, variant of the instruction this
7482 // is one of the conditions to attempt converting VOP3P to VOPD.
7483 MRI.setSimpleHint(MI.getOperand(0).getReg(), MI.getOperand(6).getReg());
7484 return BB;
7485 }
7486 case AMDGPU::SCHED_BARRIER:
7487 case AMDGPU::SCHED_GROUP_BARRIER:
7488 MI.getOperand(0).setImm(MI.getOperand(0).getImm() &
7489 static_cast<unsigned>(AMDGPU::SchedGroupMask::ALL));
7490 return BB;
7491 default:
7492 if (TII->isImage(MI) || TII->isMUBUF(MI)) {
7493 if (!MI.mayStore())
7495 return BB;
7496 }
7498 }
7499}
7500
7502 // This currently forces unfolding various combinations of fsub into fma with
7503 // free fneg'd operands. As long as we have fast FMA (controlled by
7504 // isFMAFasterThanFMulAndFAdd), we should perform these.
7505
7506 // When fma is quarter rate, for f64 where add / sub are at best half rate,
7507 // most of these combines appear to be cycle neutral but save on instruction
7508 // count / code size.
7509 return true;
7510}
7511
7513
7515 EVT VT) const {
7516 if (!VT.isVector()) {
7517 return MVT::i1;
7518 }
7519 return EVT::getVectorVT(Ctx, MVT::i1, VT.getVectorNumElements());
7520}
7521
7523 // TODO: Should i16 be used always if legal? For now it would force VALU
7524 // shifts.
7525 return (VT == MVT::i16) ? MVT::i16 : MVT::i32;
7526}
7527
7529 return (Ty.getScalarSizeInBits() <= 16 && Subtarget->has16BitInsts())
7530 ? Ty.changeElementSize(16)
7531 : Ty.changeElementSize(32);
7532}
7533
7534// Answering this is somewhat tricky and depends on the specific device which
7535// have different rates for fma or all f64 operations.
7536//
7537// v_fma_f64 and v_mul_f64 always take the same number of cycles as each other
7538// regardless of which device (although the number of cycles differs between
7539// devices), so it is always profitable for f64.
7540//
7541// v_fma_f32 takes 4 or 16 cycles depending on the device, so it is profitable
7542// only on full rate devices. Normally, we should prefer selecting v_mad_f32
7543// which we can always do even without fused FP ops since it returns the same
7544// result as the separate operations and since it is always full
7545// rate. Therefore, we lie and report that it is not faster for f32. v_mad_f32
7546// however does not support denormals, so we do report fma as faster if we have
7547// a fast fma device and require denormals.
7548//
7550 DenormalFPEnv FPEnv) const {
7551 VT = VT.getScalarType();
7552 if (!VT.isSimple())
7553 return false;
7554
7555 switch (VT.getSimpleVT().SimpleTy) {
7556 case MVT::f32: {
7557 // If mad is not available this depends only on if f32 fma is full rate.
7558 if (!Subtarget->hasMadMacF32Insts())
7559 return Subtarget->hasFastFMAF32();
7560
7561 // Otherwise f32 mad is always full rate and returns the same result as
7562 // the separate operations so should be preferred over fma.
7563 // However does not support denormals.
7565 return Subtarget->hasFastFMAF32() || Subtarget->hasDLInsts();
7566
7567 // If the subtarget has v_fmac_f32, that's just as good as v_mac_f32.
7568 return Subtarget->hasFastFMAF32() && Subtarget->hasDLInsts();
7569 }
7570 case MVT::f64:
7571 return true;
7572 case MVT::f16:
7573 case MVT::bf16:
7574 return Subtarget->has16BitInsts() &&
7576 default:
7577 break;
7578 }
7579
7580 return false;
7581}
7582
7587
7589 Type *Ty) const {
7591 getValueType(F.getDataLayout(), Ty, /*AllowUnknown=*/true),
7592 F.getDenormalFPEnv());
7593}
7594
7596 LLT Ty) const {
7597 switch (Ty.getScalarSizeInBits()) {
7598 case 16:
7599 return isFMAFasterThanFMulAndFAdd(MF, MVT::f16);
7600 case 32:
7601 return isFMAFasterThanFMulAndFAdd(MF, MVT::f32);
7602 case 64:
7603 return isFMAFasterThanFMulAndFAdd(MF, MVT::f64);
7604 default:
7605 break;
7606 }
7607
7608 return false;
7609}
7610
7612 // TODO: Check future ftz flag
7613 // v_mad_f32/v_mac_f32 do not support denormals.
7614 if (VT == MVT::f32)
7615 return Subtarget->hasMadMacF32Insts() &&
7617 if (VT == MVT::f16)
7618 return Subtarget->hasMadF16() &&
7620
7621 return false;
7622}
7623
7625 if (!Ty.isScalar())
7626 return false;
7627
7628 DenormalFPEnv FPEnv = getDenormalFPEnv(*MI.getMF());
7629 if (Ty.getScalarSizeInBits() == 16)
7630 return isFMADLegal(MVT::f16, FPEnv);
7631 if (Ty.getScalarSizeInBits() == 32)
7632 return isFMADLegal(MVT::f32, FPEnv);
7633
7634 return false;
7635}
7636
7638 const SDNode *N) const {
7639 return isFMADLegal(N->getValueType(0),
7641}
7642
7644 return isFMADLegal(getValueType(F.getDataLayout(), Ty->getScalarType(),
7645 /*AllowUnknown=*/true),
7646 F.getDenormalFPEnv());
7647}
7648
7649//===----------------------------------------------------------------------===//
7650// Custom DAG Lowering Operations
7651//===----------------------------------------------------------------------===//
7652
7653// Work around LegalizeDAG doing the wrong thing and fully scalarizing if the
7654// wider vector type is legal.
7656 SelectionDAG &DAG) const {
7657 unsigned Opc = Op.getOpcode();
7658 EVT VT = Op.getValueType();
7660
7661 auto [Lo, Hi] = DAG.SplitVectorOperand(Op.getNode(), 0);
7662 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VT);
7663
7664 SDLoc SL(Op);
7665
7666 // Forward any trailing scalar operands unchanged to both halves.
7667 SmallVector<SDValue, 2> LoOps = {Lo};
7668 SmallVector<SDValue, 2> HiOps = {Hi};
7669 auto TrailingOps = drop_begin(Op->ops());
7670 LoOps.append(TrailingOps.begin(), TrailingOps.end());
7671 HiOps.append(TrailingOps.begin(), TrailingOps.end());
7672
7673 SDValue OpLo = DAG.getNode(Opc, SL, LoVT, LoOps, Op->getFlags());
7674 SDValue OpHi = DAG.getNode(Opc, SL, HiVT, HiOps, Op->getFlags());
7675
7676 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7677}
7678
7679// Enable lowering of ROTR for vxi32 types. This is a workaround for a
7680// regression whereby extra unnecessary instructions were added to codegen
7681// for rotr operations, casued by legalising v2i32 or. This resulted in extra
7682// instructions to extract the result from the vector.
7684 [[maybe_unused]] EVT VT = Op.getValueType();
7685
7686 assert((VT == MVT::v2i32 || VT == MVT::v4i32 || VT == MVT::v8i32 ||
7687 VT == MVT::v16i32) &&
7688 "Unexpected ValueType.");
7689
7690 return DAG.UnrollVectorOp(Op.getNode());
7691}
7692
7693// Work around LegalizeDAG doing the wrong thing and fully scalarizing if the
7694// wider vector type is legal.
7696 SelectionDAG &DAG) const {
7697 unsigned Opc = Op.getOpcode();
7698 EVT VT = Op.getValueType();
7700
7701 auto [Lo0, Hi0] = DAG.SplitVectorOperand(Op.getNode(), 0);
7702 auto [Lo1, Hi1] = DAG.SplitVectorOperand(Op.getNode(), 1);
7703
7704 SDLoc SL(Op);
7705
7706 SDValue OpLo =
7707 DAG.getNode(Opc, SL, Lo0.getValueType(), Lo0, Lo1, Op->getFlags());
7708 SDValue OpHi =
7709 DAG.getNode(Opc, SL, Hi0.getValueType(), Hi0, Hi1, Op->getFlags());
7710
7711 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7712}
7713
7715 SelectionDAG &DAG) const {
7716 unsigned Opc = Op.getOpcode();
7717 EVT VT = Op.getValueType();
7719
7720 SDValue Op0 = Op.getOperand(0);
7721 SDValue Lo0, Hi0;
7722 if (Op0.getValueType().isVector())
7723 std::tie(Lo0, Hi0) = DAG.SplitVectorOperand(Op.getNode(), 0);
7724 else
7725 Lo0 = Hi0 = DAG.getFreeze(Op0);
7726
7727 auto [Lo1, Hi1] = DAG.SplitVectorOperand(Op.getNode(), 1);
7728 auto [Lo2, Hi2] = DAG.SplitVectorOperand(Op.getNode(), 2);
7729
7730 SDLoc SL(Op);
7731 auto ResVT = DAG.GetSplitDestVTs(VT);
7732
7733 SDValue OpLo =
7734 DAG.getNode(Opc, SL, ResVT.first, Lo0, Lo1, Lo2, Op->getFlags());
7735 SDValue OpHi =
7736 DAG.getNode(Opc, SL, ResVT.second, Hi0, Hi1, Hi2, Op->getFlags());
7737
7738 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7739}
7740
7742 switch (Op.getOpcode()) {
7743 default:
7745 case ISD::BRCOND:
7746 return LowerBRCOND(Op, DAG);
7747 case ISD::RETURNADDR:
7748 return LowerRETURNADDR(Op, DAG);
7749 case ISD::SPONENTRY:
7750 return LowerSPONENTRY(Op, DAG);
7751 case ISD::LOAD: {
7752 SDValue Result = LowerLOAD(Op, DAG);
7753 assert((!Result.getNode() || Result.getNode()->getNumValues() == 2) &&
7754 "Load should return a value and a chain");
7755 return Result;
7756 }
7757 case ISD::FSQRT: {
7758 EVT VT = Op.getValueType();
7759 if (VT == MVT::f32)
7760 return lowerFSQRTF32(Op, DAG);
7761 if (VT == MVT::f64)
7762 return lowerFSQRTF64(Op, DAG);
7763 return SDValue();
7764 }
7765 case ISD::FSIN:
7766 case ISD::FCOS:
7767 return LowerTrig(Op, DAG);
7768 case ISD::SELECT:
7769 return LowerSELECT(Op, DAG);
7770 case ISD::FDIV:
7771 return LowerFDIV(Op, DAG);
7772 case ISD::FFREXP:
7773 return LowerFFREXP(Op, DAG);
7775 return LowerATOMIC_CMP_SWAP(Op, DAG);
7776 case ISD::STORE:
7777 return LowerSTORE(Op, DAG);
7778 case ISD::GlobalAddress: {
7781 return LowerGlobalAddress(MFI, Op, DAG);
7782 }
7783 case ISD::BlockAddress:
7784 return LowerBlockAddress(Op, DAG);
7786 return LowerExternalSymbol(Op, DAG);
7788 return LowerINTRINSIC_WO_CHAIN(Op, DAG);
7790 return LowerCONVERT_FROM_ARBITRARY_FP(Op, DAG);
7792 return LowerCONVERT_TO_ARBITRARY_FP(Op, DAG);
7794 return LowerINTRINSIC_W_CHAIN(Op, DAG);
7796 return LowerINTRINSIC_VOID(Op, DAG);
7797 case ISD::ADDRSPACECAST:
7798 return lowerADDRSPACECAST(Op, DAG);
7800 return lowerINSERT_SUBVECTOR(Op, DAG);
7802 return lowerINSERT_VECTOR_ELT(Op, DAG);
7804 return lowerEXTRACT_VECTOR_ELT(Op, DAG);
7806 return lowerVECTOR_SHUFFLE(Op, DAG);
7808 return lowerSCALAR_TO_VECTOR(Op, DAG);
7809 case ISD::BUILD_VECTOR:
7810 return lowerBUILD_VECTOR(Op, DAG);
7811 case ISD::FP_ROUND:
7813 return lowerFP_ROUND(Op, DAG);
7814 case ISD::TRAP:
7815 return lowerTRAP(Op, DAG);
7816 case ISD::DEBUGTRAP:
7817 return lowerDEBUGTRAP(Op, DAG);
7818 case ISD::ABS:
7819 case ISD::FABS:
7820 case ISD::FNEG:
7821 case ISD::FCANONICALIZE:
7822 case ISD::BSWAP:
7823 return splitUnaryVectorOp(Op, DAG);
7826 if (Op.getValueType().isVector() && Op.getValueType() != MVT::v2i16 &&
7827 Op.getOperand(0).getValueType().getScalarType() == MVT::f32)
7828 return splitUnaryVectorOp(Op, DAG);
7829 return LowerFP_TO_INT_SAT(Op, DAG);
7830 case ISD::FSUB:
7831 if (Op.getValueType() == MVT::bf16) {
7832 // Custom expansion:
7833 // fsub bf16 %a, %b -> fadd v2bf16(widen %a), fneg v2bf16(widen %b)
7834 // Then extract back to bf16.
7835 //
7836 // We create fneg on v2bf16 (not bf16) so the instruction selector can
7837 // fold the negation into the packed add's neg_lo/neg_hi modifiers,
7838 // generating a single v_pk_add_bf16 instruction. If we negate bf16 first,
7839 // it becomes a separate v_xor instruction before widening.
7840 SDLoc DL(Op);
7841 SDValue Op0 = Op.getOperand(0);
7842 SDValue Op1 = Op.getOperand(1);
7843
7844 // Widen both operands to v2bf16
7845 SDValue Vec0 = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2bf16, Op0);
7846 SDValue Vec1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2bf16, Op1);
7847
7848 // Create FNEG v2bf16 for the second operand
7849 SDValue NegVec1 = DAG.getNode(ISD::FNEG, DL, MVT::v2bf16, Vec1);
7850
7851 // Perform FADD v2bf16
7852 SDValue Result = DAG.getNode(ISD::FADD, DL, MVT::v2bf16, Vec0, NegVec1);
7853
7854 // Extract element 0 back to bf16
7855 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::bf16, Result,
7856 DAG.getConstant(0, DL, MVT::i32));
7857 }
7858 return SDValue();
7859 case ISD::FMINNUM:
7860 case ISD::FMAXNUM:
7861 return lowerFMINNUM_FMAXNUM(Op, DAG);
7862 case ISD::FMINIMUMNUM:
7863 case ISD::FMAXIMUMNUM:
7864 return lowerFMINIMUMNUM_FMAXIMUMNUM(Op, DAG);
7865 case ISD::FLDEXP:
7866 case ISD::STRICT_FLDEXP:
7867 return lowerFLDEXP(Op, DAG);
7868 case ISD::FMA:
7869 return splitTernaryVectorOp(Op, DAG);
7870 case ISD::FP_TO_SINT:
7871 case ISD::FP_TO_UINT:
7872 if (Subtarget->hasVCvtPkIU16F32() && Op.getValueType() == MVT::i16 &&
7873 Op.getOperand(0).getValueType() == MVT::f32) {
7874 // Make f32->i16 legal so we can select V_CVT_PK_[IU]16_F32.
7875 return Op;
7876 }
7877 return LowerFP_TO_INT(Op, DAG);
7878 case ISD::SHL:
7879 case ISD::SRA:
7880 case ISD::SRL:
7881 case ISD::ADD:
7882 case ISD::SUB:
7883 case ISD::SMIN:
7884 case ISD::SMAX:
7885 case ISD::UMIN:
7886 case ISD::UMAX:
7887 case ISD::FMINNUM_IEEE:
7888 case ISD::FMAXNUM_IEEE:
7889 case ISD::FMINIMUM:
7890 case ISD::FMAXIMUM:
7891 case ISD::UADDSAT:
7892 case ISD::USUBSAT:
7893 case ISD::SADDSAT:
7894 case ISD::SSUBSAT:
7895 case ISD::FADD:
7896 case ISD::FMUL:
7897 return splitBinaryVectorOp(Op, DAG);
7898 case ISD::FCOPYSIGN:
7899 return lowerFCOPYSIGN(Op, DAG);
7900 case ISD::MUL:
7901 return lowerMUL(Op, DAG);
7902 case ISD::SMULO:
7903 case ISD::UMULO:
7904 return lowerXMULO(Op, DAG);
7905 case ISD::SMUL_LOHI:
7906 case ISD::UMUL_LOHI:
7907 return lowerXMUL_LOHI(Op, DAG);
7909 return LowerDYNAMIC_STACKALLOC(Op, DAG);
7910 case ISD::STACKSAVE:
7911 return LowerSTACKSAVE(Op, DAG);
7912 case ISD::GET_ROUNDING:
7913 return lowerGET_ROUNDING(Op, DAG);
7914 case ISD::SET_ROUNDING:
7915 return lowerSET_ROUNDING(Op, DAG);
7916 case ISD::PREFETCH:
7917 return lowerPREFETCH(Op, DAG);
7918 case ISD::FP_EXTEND:
7920 return lowerFP_EXTEND(Op, DAG);
7921 case ISD::GET_FPENV:
7922 return lowerGET_FPENV(Op, DAG);
7923 case ISD::SET_FPENV:
7924 return lowerSET_FPENV(Op, DAG);
7925 case ISD::ROTR:
7926 return lowerROTR(Op, DAG);
7927 case ISD::INLINEASM:
7928 return LowerINLINEASM(Op, DAG);
7929 }
7930 return SDValue();
7931}
7932
7933// TFE results are dword granular: value dwords followed by one status dword.
7934static std::pair<SDValue, SDValue>
7936 LLVMContext &C = *DAG.getContext();
7937 unsigned NumValueDWords = divideCeil(VT.getSizeInBits(), 32);
7939 DAG.getVectorIdxConstant(NumValueDWords, DL));
7940 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, DL);
7941 SDValue ValueDWords =
7942 NumValueDWords == 1
7943 ? DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op, ZeroIdx)
7945 EVT::getVectorVT(C, MVT::i32, NumValueDWords), Op,
7946 ZeroIdx);
7947 if (!VT.isVector() && VT.getSizeInBits() < 32)
7948 ValueDWords =
7949 DAG.getNode(ISD::TRUNCATE, DL, VT.changeTypeToInteger(), ValueDWords);
7950 return {DAG.getNode(ISD::BITCAST, DL, VT, ValueDWords), Status};
7951}
7952
7953// Used for D16: Casts the result of an instruction into the right vector,
7954// packs values if loads return unpacked values.
7956 const SDLoc &DL, SelectionDAG &DAG,
7957 bool Unpacked) {
7958 if (!LoadVT.isVector())
7959 return Result;
7960
7961 // Cast back to the original packed type or to a larger type that is a
7962 // multiple of 32 bit for D16. Widening the return type is a required for
7963 // legalization.
7964 EVT FittingLoadVT = LoadVT;
7965 if ((LoadVT.getVectorNumElements() % 2) == 1) {
7966 FittingLoadVT =
7968 LoadVT.getVectorNumElements() + 1);
7969 }
7970
7971 if (Unpacked) { // From v2i32/v4i32 back to v2f16/v4f16.
7972 // Truncate to v2i16/v4i16.
7973 EVT IntLoadVT = FittingLoadVT.changeTypeToInteger();
7974
7975 // Workaround legalizer not scalarizing truncate after vector op
7976 // legalization but not creating intermediate vector trunc.
7978 DAG.ExtractVectorElements(Result, Elts);
7979 for (SDValue &Elt : Elts)
7980 Elt = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Elt);
7981
7982 // Pad illegal v1i16/v3fi6 to v4i16
7983 if ((LoadVT.getVectorNumElements() % 2) == 1)
7984 Elts.push_back(DAG.getPOISON(MVT::i16));
7985
7986 Result = DAG.getBuildVector(IntLoadVT, DL, Elts);
7987
7988 // Bitcast to original type (v2f16/v4f16).
7989 return DAG.getNode(ISD::BITCAST, DL, FittingLoadVT, Result);
7990 }
7991
7992 // Cast back to the original packed type.
7993 return DAG.getNode(ISD::BITCAST, DL, FittingLoadVT, Result);
7994}
7995
7996SDValue SITargetLowering::adjustLoadValueType(unsigned Opcode, MemSDNode *M,
7997 SelectionDAG &DAG,
7999 bool IsIntrinsic) const {
8000 SDLoc DL(M);
8001
8002 bool IsTFE = M->getNumValues() == 3;
8003 bool Unpacked = Subtarget->hasUnpackedD16VMem();
8004 EVT LoadVT = M->getValueType(0);
8005
8006 EVT EquivLoadVT = LoadVT;
8007 if (LoadVT.isVector()) {
8008 if (Unpacked) {
8009 EquivLoadVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32,
8010 LoadVT.getVectorNumElements());
8011 } else if ((LoadVT.getVectorNumElements() % 2) == 1) {
8012 // Widen v3f16 to legal type
8013 EquivLoadVT =
8015 LoadVT.getVectorNumElements() + 1);
8016 }
8017 }
8018
8019 if (IsTFE) {
8020 unsigned NumValueDWords = divideCeil(EquivLoadVT.getSizeInBits(), 32);
8021 EVT LoadDWordsVT =
8022 EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumValueDWords + 1);
8023 SDVTList VTList = DAG.getVTList(LoadDWordsVT, MVT::Other);
8024 SDValue Load = DAG.getMemIntrinsicNode(
8025 Opcode, DL, VTList, Ops, M->getMemoryVT(), M->getMemOperand());
8026 auto [Value, Status] = splitTFEValueAndStatus(Load, EquivLoadVT, DL, DAG);
8027 SDValue Adjusted =
8028 adjustLoadValueTypeImpl(Value, LoadVT, DL, DAG, Unpacked);
8029 return DAG.getMergeValues({Adjusted, Status, Load.getValue(1)}, DL);
8030 }
8031
8032 // Change from v4f16/v2f16 to EquivLoadVT.
8033 SDVTList VTList = DAG.getVTList(EquivLoadVT, MVT::Other);
8034
8035 SDValue Load = DAG.getMemIntrinsicNode(
8036 IsIntrinsic ? (unsigned)ISD::INTRINSIC_W_CHAIN : Opcode, DL, VTList, Ops,
8037 M->getMemoryVT(), M->getMemOperand());
8038
8039 SDValue Adjusted = adjustLoadValueTypeImpl(Load, LoadVT, DL, DAG, Unpacked);
8040
8041 return DAG.getMergeValues({Adjusted, Load.getValue(1)}, DL);
8042}
8043
8044SDValue SITargetLowering::lowerIntrinsicLoad(MemSDNode *M, bool IsFormat,
8045 SelectionDAG &DAG,
8046 ArrayRef<SDValue> Ops) const {
8047 SDLoc DL(M);
8048 EVT LoadVT = M->getValueType(0);
8049 EVT EltType = LoadVT.getScalarType();
8050 EVT IntVT = LoadVT.changeTypeToInteger();
8051
8052 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
8053
8054 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
8055 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
8057 "unsupported sub-dword format buffer load", DL.getDebugLoc()));
8058 return DAG.getMergeValues({DAG.getPOISON(LoadVT), M->getOperand(0)}, DL);
8059 }
8060
8061 assert(M->getNumValues() == 2 || M->getNumValues() == 3);
8062 bool IsTFE = M->getNumValues() == 3;
8063
8064 if (IsD16 && IsTFE && !Subtarget->hasBufferTFEFormatD16()) {
8065 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
8067 "TFE D16 format buffer load is not supported on this GPU",
8068 DL.getDebugLoc()));
8069 return DAG.getErrorMergeValues({M->value_begin(), M->value_end()},
8070 M->getOperand(0), DL);
8071 }
8072
8073 unsigned Opc = IsD16 ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_D16_TFE
8074 : AMDGPUISD::BUFFER_LOAD_FORMAT_D16)
8075 : IsFormat ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_TFE
8076 : AMDGPUISD::BUFFER_LOAD_FORMAT)
8077 : IsTFE ? AMDGPUISD::BUFFER_LOAD_TFE
8078 : AMDGPUISD::BUFFER_LOAD;
8079
8080 if (IsD16)
8081 return adjustLoadValueType(Opc, M, DAG, Ops);
8082
8083 // Handle BUFFER_LOAD_BYTE/UBYTE/SHORT/USHORT overloaded intrinsics
8084 if (!IsD16 && !LoadVT.isVector() && EltType.getSizeInBits() < 32)
8085 return handleByteShortBufferLoads(DAG, LoadVT, DL, Ops, M->getMemOperand(),
8086 IsTFE);
8087
8088 if (isTypeLegal(LoadVT)) {
8089 return getMemIntrinsicNode(Opc, DL, M->getVTList(), Ops, IntVT,
8090 M->getMemOperand(), DAG);
8091 }
8092
8093 EVT CastVT = getEquivalentMemType(*DAG.getContext(), LoadVT);
8094 SDVTList VTList = IsTFE ? DAG.getVTList(CastVT, MVT::i32, MVT::Other)
8095 : DAG.getVTList(CastVT, MVT::Other);
8096 SDValue MemNode = getMemIntrinsicNode(Opc, DL, VTList, Ops, CastVT,
8097 M->getMemOperand(), DAG);
8098 SDValue Data = DAG.getNode(ISD::BITCAST, DL, LoadVT, MemNode);
8099 if (IsTFE)
8100 return DAG.getMergeValues({Data, MemNode.getValue(1), MemNode.getValue(2)},
8101 DL);
8102 return DAG.getMergeValues({Data, MemNode.getValue(1)}, DL);
8103}
8104
8106 SelectionDAG &DAG) {
8107 EVT VT = N->getValueType(0);
8108 SDValue Src = N->getOperand(1);
8109 SDLoc SL(N);
8110
8111 if (Src.getOpcode() == ISD::SETCC) {
8112 SDValue Op0 = Src.getOperand(0);
8113 SDValue Op1 = Src.getOperand(1);
8114 // Need to expand bfloat to float for comparison (setcc).
8115 if (Op0.getValueType() == MVT::bf16) {
8116 Op0 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op0);
8117 Op1 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op1);
8118 }
8119 // (ballot (ISD::SETCC ...)) -> (AMDGPUISD::SETCC ...)
8120 return DAG.getNode(AMDGPUISD::SETCC, SL, VT, Op0, Op1, Src.getOperand(2));
8121 }
8122 if (const ConstantSDNode *Arg = dyn_cast<ConstantSDNode>(Src)) {
8123 // (ballot 0) -> 0
8124 if (Arg->isZero())
8125 return DAG.getConstant(0, SL, VT);
8126
8127 // (ballot 1) -> EXEC/EXEC_LO
8128 if (Arg->isOne()) {
8129 Register Exec;
8130 if (VT.getScalarSizeInBits() == 32)
8131 Exec = AMDGPU::EXEC_LO;
8132 else if (VT.getScalarSizeInBits() == 64)
8133 Exec = AMDGPU::EXEC;
8134 else
8135 return SDValue();
8136
8137 return DAG.getCopyFromReg(DAG.getEntryNode(), SL, Exec, VT);
8138 }
8139 }
8140
8141 // (ballot (i1 $src)) -> (AMDGPUISD::SETCC (i32 (zext $src)) (i32 0)
8142 // ISD::SETNE)
8143 return DAG.getNode(
8144 AMDGPUISD::SETCC, SL, VT, DAG.getZExtOrTrunc(Src, SL, MVT::i32),
8145 DAG.getConstant(0, SL, MVT::i32), DAG.getCondCode(ISD::SETNE));
8146}
8147
8149 Intrinsic::ID IntrinsicID) {
8150 bool Signed = IntrinsicID == Intrinsic::amdgcn_sbfe;
8151 SDLoc DL(Op);
8152 EVT VT = Op.getValueType();
8153 SDValue Src = Op.getOperand(1);
8154 SDValue Offset = Op.getOperand(2);
8155 SDValue Width = Op.getOperand(3);
8156
8157 if (VT != MVT::i32) {
8160 Twine(Intrinsic::getBaseName(IntrinsicID)) + " only supports i32",
8161 DL.getDebugLoc()));
8162 return DAG.getPOISON(VT);
8163 }
8164
8165 return DAG.getNode(Signed ? AMDGPUISD::BFE_I32 : AMDGPUISD::BFE_U32, DL, VT,
8166 Src, Offset, Width);
8167}
8168
8170 EVT VT);
8171
8173 SelectionDAG &DAG) {
8174 EVT VT = N->getValueType(0);
8175 unsigned ValSize = VT.getSizeInBits();
8176 unsigned IID = N->getConstantOperandVal(0);
8177 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
8178 IID == Intrinsic::amdgcn_permlanex16;
8179 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
8180 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
8181 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
8182 IID == Intrinsic::amdgcn_permlane_up ||
8183 IID == Intrinsic::amdgcn_permlane_down ||
8184 IID == Intrinsic::amdgcn_permlane_xor;
8185 SDLoc SL(N);
8186 MVT IntVT = MVT::getIntegerVT(ValSize);
8187 const GCNSubtarget *ST = TLI.getSubtarget();
8188
8189 unsigned SplitSize = 32;
8190 if (IID == Intrinsic::amdgcn_update_dpp && (ValSize % 64 == 0) &&
8191 ST->hasDPALU_DPP() &&
8192 AMDGPU::isLegalDPALU_DPPControl(*ST, N->getConstantOperandVal(3)))
8193 SplitSize = 64;
8194
8195 auto createLaneOp = [&DAG, &SL, N, IID](SDValue Src0, SDValue Src1,
8196 SDValue Src2, MVT ValT) -> SDValue {
8198 switch (IID) {
8199 case Intrinsic::amdgcn_permlane16:
8200 case Intrinsic::amdgcn_permlanex16:
8201 case Intrinsic::amdgcn_update_dpp:
8202 Operands.push_back(N->getOperand(6));
8203 Operands.push_back(N->getOperand(5));
8204 Operands.push_back(N->getOperand(4));
8205 [[fallthrough]];
8206 case Intrinsic::amdgcn_writelane:
8207 case Intrinsic::amdgcn_permlane_bcast:
8208 case Intrinsic::amdgcn_permlane_up:
8209 case Intrinsic::amdgcn_permlane_down:
8210 case Intrinsic::amdgcn_permlane_xor:
8211 Operands.push_back(Src2);
8212 [[fallthrough]];
8213 case Intrinsic::amdgcn_readlane:
8214 case Intrinsic::amdgcn_set_inactive:
8215 case Intrinsic::amdgcn_set_inactive_chain_arg:
8216 case Intrinsic::amdgcn_mov_dpp8:
8217 Operands.push_back(Src1);
8218 [[fallthrough]];
8219 case Intrinsic::amdgcn_readfirstlane:
8220 case Intrinsic::amdgcn_permlane64:
8221 Operands.push_back(Src0);
8222 break;
8223 default:
8224 llvm_unreachable("unhandled lane op");
8225 }
8226
8227 Operands.push_back(DAG.getTargetConstant(IID, SL, MVT::i32));
8228 std::reverse(Operands.begin(), Operands.end());
8229
8230 if (SDNode *GL = N->getGluedNode()) {
8231 assert(GL->getOpcode() == ISD::CONVERGENCECTRL_GLUE);
8232 GL = GL->getOperand(0).getNode();
8233 Operands.push_back(DAG.getNode(ISD::CONVERGENCECTRL_GLUE, SL, MVT::Glue,
8234 SDValue(GL, 0)));
8235 }
8236
8237 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, ValT, Operands);
8238 };
8239
8240 SDValue Src0 = N->getOperand(1);
8241 SDValue Src1, Src2;
8242 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
8243 IID == Intrinsic::amdgcn_mov_dpp8 ||
8244 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
8245 IsPermlaneShuffle) {
8246 Src1 = N->getOperand(2);
8247 if (IID == Intrinsic::amdgcn_writelane ||
8248 IID == Intrinsic::amdgcn_update_dpp || IsPermLane16 ||
8249 IsPermlaneShuffle)
8250 Src2 = N->getOperand(3);
8251 }
8252
8253 if (ValSize == SplitSize) {
8254 // Already legal
8255 return SDValue();
8256 }
8257
8258 if (ValSize < 32) {
8259 bool IsFloat = VT.isFloatingPoint();
8260 Src0 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src0) : Src0,
8261 SL, MVT::i32);
8262
8263 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16) {
8264 Src1 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src1) : Src1,
8265 SL, MVT::i32);
8266 }
8267
8268 if (IID == Intrinsic::amdgcn_writelane) {
8269 Src2 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src2) : Src2,
8270 SL, MVT::i32);
8271 }
8272
8273 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, MVT::i32);
8274 SDValue Trunc = DAG.getAnyExtOrTrunc(LaneOp, SL, IntVT);
8275 return IsFloat ? DAG.getBitcast(VT, Trunc) : Trunc;
8276 }
8277
8278 if (ValSize % SplitSize != 0)
8279 return SDValue();
8280
8281 auto unrollLaneOp = [&DAG, &SL](SDNode *N) -> SDValue {
8282 EVT VT = N->getValueType(0);
8283 unsigned NE = VT.getVectorNumElements();
8284 EVT EltVT = VT.getVectorElementType();
8286 unsigned NumOperands = N->getNumOperands();
8287 SmallVector<SDValue, 4> Operands(NumOperands);
8288 SDNode *GL = N->getGluedNode();
8289
8290 // only handle convergencectrl_glue
8292
8293 for (unsigned i = 0; i != NE; ++i) {
8294 for (unsigned j = 0, e = GL ? NumOperands - 1 : NumOperands; j != e;
8295 ++j) {
8296 SDValue Operand = N->getOperand(j);
8297 EVT OperandVT = Operand.getValueType();
8298 if (OperandVT.isVector()) {
8299 // A vector operand; extract a single element.
8300 EVT OperandEltVT = OperandVT.getVectorElementType();
8301 Operands[j] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, OperandEltVT,
8302 Operand, DAG.getVectorIdxConstant(i, SL));
8303 } else {
8304 // A scalar operand; just use it as is.
8305 Operands[j] = Operand;
8306 }
8307 }
8308
8309 if (GL)
8310 Operands[NumOperands - 1] =
8311 DAG.getNode(ISD::CONVERGENCECTRL_GLUE, SL, MVT::Glue,
8312 SDValue(GL->getOperand(0).getNode(), 0));
8313
8314 Scalars.push_back(DAG.getNode(N->getOpcode(), SL, EltVT, Operands));
8315 }
8316
8317 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NE);
8318 return DAG.getBuildVector(VecVT, SL, Scalars);
8319 };
8320
8321 if (VT.isVector()) {
8322 switch (MVT::SimpleValueType EltTy =
8324 case MVT::i32:
8325 case MVT::f32:
8326 if (SplitSize == 32) {
8327 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VT.getSimpleVT());
8328 return unrollLaneOp(LaneOp.getNode());
8329 }
8330 [[fallthrough]];
8331 case MVT::i16:
8332 case MVT::f16:
8333 case MVT::bf16: {
8334 unsigned SubVecNumElt =
8335 SplitSize / VT.getVectorElementType().getSizeInBits();
8336 MVT SubVecVT = MVT::getVectorVT(EltTy, SubVecNumElt);
8338 SDValue Src0SubVec, Src1SubVec, Src2SubVec;
8339 for (unsigned i = 0, EltIdx = 0; i < ValSize / SplitSize; i++) {
8340 Src0SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src0,
8341 DAG.getConstant(EltIdx, SL, MVT::i32));
8342
8343 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive ||
8344 IsPermLane16) {
8345 Src1SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src1,
8346 DAG.getConstant(EltIdx, SL, MVT::i32));
8347
8348 Pieces.push_back(
8349 createLaneOp(Src0SubVec, Src1SubVec, Src2, SubVecVT));
8350 } else if (IID == Intrinsic::amdgcn_writelane) {
8351 Src2SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src2,
8352 DAG.getConstant(EltIdx, SL, MVT::i32));
8353 Pieces.push_back(
8354 createLaneOp(Src0SubVec, Src1, Src2SubVec, SubVecVT));
8355 } else {
8356 Pieces.push_back(createLaneOp(Src0SubVec, Src1, Src2, SubVecVT));
8357 }
8358
8359 EltIdx += SubVecNumElt;
8360 }
8361 return DAG.getNode(ISD::CONCAT_VECTORS, SL, VT, Pieces);
8362 }
8363 default:
8364 // Handle all other cases by bitcasting to i32 vectors
8365 break;
8366 }
8367 }
8368
8369 MVT VecVT =
8370 MVT::getVectorVT(MVT::getIntegerVT(SplitSize), ValSize / SplitSize);
8371 Src0 = DAG.getBitcast(VecVT, Src0);
8372
8373 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
8374 Src1 = DAG.getBitcast(VecVT, Src1);
8375
8376 if (IID == Intrinsic::amdgcn_writelane)
8377 Src2 = DAG.getBitcast(VecVT, Src2);
8378
8379 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VecVT);
8380 SDValue UnrolledLaneOp = unrollLaneOp(LaneOp.getNode());
8381 return DAG.getBitcast(VT, UnrolledLaneOp);
8382}
8383
8385 SelectionDAG &DAG) {
8386 EVT VT = N->getValueType(0);
8387
8388 if (VT.getSizeInBits() != 32)
8389 return SDValue();
8390
8391 SDLoc SL(N);
8392
8393 SDValue Value = N->getOperand(1);
8394 SDValue Index = N->getOperand(2);
8395
8396 // ds_bpermute requires index to be multiplied by 4
8397 SDValue ShiftAmount = DAG.getShiftAmountConstant(2, MVT::i32, SL);
8398 SDValue ShiftedIndex =
8399 DAG.getNode(ISD::SHL, SL, Index.getValueType(), Index, ShiftAmount);
8400
8401 // Intrinsics will require i32 to operate on
8402 SDValue ValueI32 = DAG.getBitcast(MVT::i32, Value);
8403
8404 auto MakeIntrinsic = [&DAG, &SL](unsigned IID, MVT RetVT,
8405 SmallVector<SDValue> IntrinArgs) -> SDValue {
8407 Operands[0] = DAG.getTargetConstant(IID, SL, MVT::i32);
8408 Operands.append(IntrinArgs);
8409 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, RetVT, Operands);
8410 };
8411
8412 // If we can bpermute across the whole wave, then just do that
8414 SDValue BPermute = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8415 {ShiftedIndex, ValueI32});
8416 return DAG.getBitcast(VT, BPermute);
8417 }
8418
8419 assert(TLI.getSubtarget()->isWave64());
8420
8421 // Otherwise, we need to make use of whole wave mode
8422 SDValue PoisonVal = DAG.getPOISON(ValueI32->getValueType(0));
8423
8424 // Set inactive lanes to poison
8425 SDValue WWMValue = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8426 {ValueI32, PoisonVal});
8427 SDValue WWMIndex = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8428 {ShiftedIndex, PoisonVal});
8429
8430 SDValue Swapped =
8431 MakeIntrinsic(Intrinsic::amdgcn_permlane64, MVT::i32, {WWMValue});
8432
8433 // Get permutation of each half, then we'll select which one to use
8434 SDValue BPermSameHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8435 {WWMIndex, WWMValue});
8436 SDValue BPermOtherHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute,
8437 MVT::i32, {WWMIndex, Swapped});
8438 SDValue BPermOtherHalfWWM =
8439 MakeIntrinsic(Intrinsic::amdgcn_wwm, MVT::i32, {BPermOtherHalf});
8440
8441 // Select which side to take the permute from
8442 SDValue ThreadIDMask = DAG.getAllOnesConstant(SL, MVT::i32);
8443 // We can get away with only using mbcnt_lo here since we're only
8444 // trying to detect which side of 32 each lane is on, and mbcnt_lo
8445 // returns 32 for lanes 32-63.
8446 SDValue ThreadID =
8447 MakeIntrinsic(Intrinsic::amdgcn_mbcnt_lo, MVT::i32,
8448 {ThreadIDMask, DAG.getTargetConstant(0, SL, MVT::i32)});
8449
8450 SDValue SameOrOtherHalf =
8451 DAG.getNode(ISD::AND, SL, MVT::i32,
8452 DAG.getNode(ISD::XOR, SL, MVT::i32, ThreadID, Index),
8453 DAG.getTargetConstant(32, SL, MVT::i32));
8454 SDValue UseSameHalf =
8455 DAG.getSetCC(SL, MVT::i1, SameOrOtherHalf,
8456 DAG.getConstant(0, SL, MVT::i32), ISD::SETEQ);
8457 SDValue Result = DAG.getSelect(SL, MVT::i32, UseSameHalf, BPermSameHalf,
8458 BPermOtherHalfWWM);
8459 return DAG.getBitcast(VT, Result);
8460}
8461
8464 SelectionDAG &DAG) const {
8465 switch (N->getOpcode()) {
8467 if (SDValue Res = lowerINSERT_VECTOR_ELT(SDValue(N, 0), DAG))
8468 Results.push_back(Res);
8469 return;
8470 }
8472 if (SDValue Res = lowerEXTRACT_VECTOR_ELT(SDValue(N, 0), DAG))
8473 Results.push_back(Res);
8474 return;
8475 }
8477 if (SDValue Res = LowerCONVERT_TO_ARBITRARY_FP(SDValue(N, 0), DAG))
8478 Results.push_back(Res);
8479 return;
8480 }
8482 unsigned IID = N->getConstantOperandVal(0);
8483 switch (IID) {
8484 case Intrinsic::amdgcn_wave_reduce_min:
8485 case Intrinsic::amdgcn_wave_reduce_umin:
8486 case Intrinsic::amdgcn_wave_reduce_max:
8487 case Intrinsic::amdgcn_wave_reduce_umax:
8488 case Intrinsic::amdgcn_wave_reduce_add:
8489 case Intrinsic::amdgcn_wave_reduce_sub:
8490 case Intrinsic::amdgcn_wave_reduce_and:
8491 case Intrinsic::amdgcn_wave_reduce_or:
8492 case Intrinsic::amdgcn_wave_reduce_xor: {
8493 EVT VT = N->getValueType(0);
8494 if (isTypeLegal(VT))
8495 return;
8496 SDLoc SL(N);
8497 bool NeedsSignExt = IID == Intrinsic::amdgcn_wave_reduce_min ||
8498 IID == Intrinsic::amdgcn_wave_reduce_max ||
8499 IID == Intrinsic::amdgcn_wave_reduce_add ||
8500 IID == Intrinsic::amdgcn_wave_reduce_sub;
8501 unsigned ExtOpc = NeedsSignExt ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
8502 SDValue ExtSrc = DAG.getNode(ExtOpc, SL, MVT::i32, N->getOperand(1));
8503 SDValue Result = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
8504 N->getOperand(0), ExtSrc, N->getOperand(2));
8505 Results.push_back(DAG.getNode(ISD::TRUNCATE, SL, VT, Result));
8506 return;
8507 }
8508 case Intrinsic::amdgcn_make_buffer_rsrc:
8509 Results.push_back(lowerPointerAsRsrcIntrin(N, DAG));
8510 return;
8511 case Intrinsic::amdgcn_cvt_pkrtz: {
8512 SDValue Src0 = N->getOperand(1);
8513 SDValue Src1 = N->getOperand(2);
8514 SDLoc SL(N);
8515 SDValue Cvt =
8516 DAG.getNode(AMDGPUISD::CVT_PKRTZ_F16_F32, SL, MVT::i32, Src0, Src1);
8517 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Cvt));
8518 return;
8519 }
8520 case Intrinsic::amdgcn_cvt_pknorm_i16:
8521 case Intrinsic::amdgcn_cvt_pknorm_u16:
8522 case Intrinsic::amdgcn_cvt_pk_i16:
8523 case Intrinsic::amdgcn_cvt_pk_u16: {
8524 SDValue Src0 = N->getOperand(1);
8525 SDValue Src1 = N->getOperand(2);
8526 SDLoc SL(N);
8527 unsigned Opcode;
8528
8529 if (IID == Intrinsic::amdgcn_cvt_pknorm_i16)
8530 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
8531 else if (IID == Intrinsic::amdgcn_cvt_pknorm_u16)
8532 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
8533 else if (IID == Intrinsic::amdgcn_cvt_pk_i16)
8534 Opcode = AMDGPUISD::CVT_PK_I16_I32;
8535 else
8536 Opcode = AMDGPUISD::CVT_PK_U16_U32;
8537
8538 EVT VT = N->getValueType(0);
8539 if (isTypeLegal(VT))
8540 Results.push_back(DAG.getNode(Opcode, SL, VT, Src0, Src1));
8541 else {
8542 SDValue Cvt = DAG.getNode(Opcode, SL, MVT::i32, Src0, Src1);
8543 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, Cvt));
8544 }
8545 return;
8546 }
8547 case Intrinsic::amdgcn_s_buffer_load: {
8548 SDValue Op = SDValue(N, 0);
8549 EVT VT = Op.getValueType();
8550 Results.push_back(lowerSBuffer(VT, VT, SDLoc(Op), DAG.getEntryNode(),
8551 Op.getOperand(1), Op.getOperand(2),
8552 Op.getOperand(3), DAG));
8553 return;
8554 }
8555 case Intrinsic::amdgcn_dead: {
8556 for (unsigned I = 0, E = N->getNumValues(); I < E; ++I)
8557 Results.push_back(DAG.getPOISON(N->getValueType(I)));
8558 return;
8559 }
8560 }
8561 break;
8562 }
8564 if (N->getConstantOperandVal(1) != Intrinsic::amdgcn_ptr_s_buffer_load &&
8565 N->getValueType(0).isSimple() &&
8566 SBufferLoadDiagnosticVTs[N->getSimpleValueType(0).SimpleTy])
8567 break;
8568 if (SDValue Res = LowerINTRINSIC_W_CHAIN(SDValue(N, 0), DAG)) {
8569 if (Res.getOpcode() == ISD::MERGE_VALUES) {
8570 // FIXME: Hacky
8571 for (unsigned I = 0; I < Res.getNumOperands(); I++) {
8572 Results.push_back(Res.getOperand(I));
8573 }
8574 } else {
8575 for (unsigned I = 0; I < N->getNumValues(); ++I)
8576 Results.push_back(Res.getValue(I));
8577 }
8578 return;
8579 }
8580
8581 break;
8582 }
8583 case ISD::SELECT: {
8584 SDLoc SL(N);
8585 EVT VT = N->getValueType(0);
8586 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VT);
8587 SDValue LHS = DAG.getNode(ISD::BITCAST, SL, NewVT, N->getOperand(1));
8588 SDValue RHS = DAG.getNode(ISD::BITCAST, SL, NewVT, N->getOperand(2));
8589
8590 EVT SelectVT = NewVT;
8591 if (NewVT.bitsLT(MVT::i32)) {
8592 LHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, LHS);
8593 RHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, RHS);
8594 SelectVT = MVT::i32;
8595 }
8596
8597 SDValue NewSelect =
8598 DAG.getNode(ISD::SELECT, SL, SelectVT, N->getOperand(0), LHS, RHS);
8599
8600 if (NewVT != SelectVT)
8601 NewSelect = DAG.getNode(ISD::TRUNCATE, SL, NewVT, NewSelect);
8602 Results.push_back(DAG.getNode(ISD::BITCAST, SL, VT, NewSelect));
8603 return;
8604 }
8605 case ISD::FNEG: {
8606 if (N->getValueType(0) != MVT::v2f16)
8607 break;
8608
8609 SDLoc SL(N);
8610 SDValue BC = DAG.getNode(ISD::BITCAST, SL, MVT::i32, N->getOperand(0));
8611
8612 SDValue Op = DAG.getNode(ISD::XOR, SL, MVT::i32, BC,
8613 DAG.getConstant(0x80008000, SL, MVT::i32));
8614 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Op));
8615 return;
8616 }
8617 case ISD::FABS: {
8618 if (N->getValueType(0) != MVT::v2f16)
8619 break;
8620
8621 SDLoc SL(N);
8622 SDValue BC = DAG.getNode(ISD::BITCAST, SL, MVT::i32, N->getOperand(0));
8623
8624 SDValue Op = DAG.getNode(ISD::AND, SL, MVT::i32, BC,
8625 DAG.getConstant(0x7fff7fff, SL, MVT::i32));
8626 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Op));
8627 return;
8628 }
8629 case ISD::FSQRT: {
8630 if (N->getValueType(0) != MVT::f16)
8631 break;
8632 Results.push_back(lowerFSQRTF16(SDValue(N, 0), DAG));
8633 break;
8634 }
8635 default:
8637 break;
8638 }
8639}
8640
8641/// Helper function for LowerBRCOND
8642static SDNode *findUser(SDValue Value, unsigned Opcode) {
8643
8644 for (SDUse &U : Value->uses()) {
8645 if (U.get() != Value)
8646 continue;
8647
8648 if (U.getUser()->getOpcode() == Opcode)
8649 return U.getUser();
8650 }
8651 return nullptr;
8652}
8653
8654unsigned SITargetLowering::isCFIntrinsic(const SDNode *Intr) const {
8655 if (Intr->getOpcode() == ISD::INTRINSIC_W_CHAIN) {
8656 switch (Intr->getConstantOperandVal(1)) {
8657 case Intrinsic::amdgcn_if:
8658 return AMDGPUISD::IF;
8659 case Intrinsic::amdgcn_else:
8660 return AMDGPUISD::ELSE;
8661 case Intrinsic::amdgcn_loop:
8662 return AMDGPUISD::LOOP;
8663 case Intrinsic::amdgcn_end_cf:
8664 llvm_unreachable("should not occur");
8665 default:
8666 return 0;
8667 }
8668 }
8669
8670 // break, if_break, else_break are all only used as inputs to loop, not
8671 // directly as branch conditions.
8672 return 0;
8673}
8674
8681
8683 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS())
8684 return false;
8685
8686 // FIXME: Either avoid relying on address space here or change the default
8687 // address space for functions to avoid the explicit check.
8688 return (GV->getValueType()->isFunctionTy() ||
8691}
8692
8694 return !shouldEmitFixup(GV) && !shouldEmitGOTReloc(GV);
8695}
8696
8698 if (!GV->hasExternalLinkage())
8699 return true;
8700
8701 // With object linking, external LDS declarations need relocations so the
8702 // linker can assign their offsets.
8704 if (const auto *GVar = dyn_cast<GlobalVariable>(GV)) {
8705 if (GVar->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS ||
8706 GVar->getAddressSpace() == AMDGPUAS::BARRIER) {
8707 assert(GVar->isDeclaration() &&
8708 "AS 3 & 13 GVs should be declaration here "
8709 "when object linking is enabled");
8710 return false;
8711 }
8712 }
8713 }
8714
8715 const auto OS = getTargetMachine().getTargetTriple().getOS();
8716 return OS == Triple::AMDHSA || OS == Triple::AMDPAL;
8717}
8718
8719/// This transforms the control flow intrinsics to get the branch destination as
8720/// last parameter, also switches branch target with BR if the need arise
8721SDValue SITargetLowering::LowerBRCOND(SDValue BRCOND, SelectionDAG &DAG) const {
8722 SDLoc DL(BRCOND);
8723
8724 SDNode *Intr = BRCOND.getOperand(1).getNode();
8725 SDValue Target = BRCOND.getOperand(2);
8726 SDNode *BR = nullptr;
8727 SDNode *SetCC = nullptr;
8728
8729 switch (Intr->getOpcode()) {
8730 case ISD::SETCC: {
8731 // As long as we negate the condition everything is fine
8732 SetCC = Intr;
8733 Intr = SetCC->getOperand(0).getNode();
8734 break;
8735 }
8736 case ISD::XOR: {
8737 // Similar to SETCC, if we have (xor c, -1), we will be fine.
8738 SDValue LHS = Intr->getOperand(0);
8739 SDValue RHS = Intr->getOperand(1);
8740 if (auto *C = dyn_cast<ConstantSDNode>(RHS); C && C->getZExtValue()) {
8741 Intr = LHS.getNode();
8742 break;
8743 }
8744 [[fallthrough]];
8745 }
8746 default: {
8747 // Get the target from BR if we don't negate the condition
8748 BR = findUser(BRCOND, ISD::BR);
8749 assert(BR && "brcond missing unconditional branch user");
8750 Target = BR->getOperand(1);
8751 }
8752 }
8753
8754 unsigned CFNode = isCFIntrinsic(Intr);
8755 if (CFNode == 0) {
8756 // This is a uniform branch so we don't need to legalize.
8757 return BRCOND;
8758 }
8759
8760 bool HaveChain = Intr->getOpcode() == ISD::INTRINSIC_VOID ||
8762
8763 assert(!SetCC ||
8764 (SetCC->getConstantOperandVal(1) == 1 &&
8765 cast<CondCodeSDNode>(SetCC->getOperand(2).getNode())->get() ==
8766 ISD::SETNE));
8767
8768 // operands of the new intrinsic call
8770 if (HaveChain)
8771 Ops.push_back(BRCOND.getOperand(0));
8772
8773 Ops.append(Intr->op_begin() + (HaveChain ? 2 : 1), Intr->op_end());
8774 Ops.push_back(Target);
8775
8776 ArrayRef<EVT> Res(Intr->value_begin() + 1, Intr->value_end());
8777
8778 // build the new intrinsic call
8779 SDNode *Result = DAG.getNode(CFNode, DL, DAG.getVTList(Res), Ops).getNode();
8780
8781 if (!HaveChain) {
8782 SDValue Ops[] = {SDValue(Result, 0), BRCOND.getOperand(0)};
8783
8785 }
8786
8787 if (BR) {
8788 // Give the branch instruction our target
8789 SDValue Ops[] = {BR->getOperand(0), BRCOND.getOperand(2)};
8790 SDValue NewBR = DAG.getNode(ISD::BR, DL, BR->getVTList(), Ops);
8791 DAG.ReplaceAllUsesWith(BR, NewBR.getNode());
8792 }
8793
8794 SDValue Chain = SDValue(Result, Result->getNumValues() - 1);
8795
8796 // Copy the intrinsic results to registers
8797 for (unsigned i = 1, e = Intr->getNumValues() - 1; i != e; ++i) {
8798 SDNode *CopyToReg = findUser(SDValue(Intr, i), ISD::CopyToReg);
8799 if (!CopyToReg)
8800 continue;
8801
8802 Chain = DAG.getCopyToReg(Chain, DL, CopyToReg->getOperand(1),
8803 SDValue(Result, i - 1), SDValue());
8804
8805 DAG.ReplaceAllUsesWith(SDValue(CopyToReg, 0), CopyToReg->getOperand(0));
8806 }
8807
8808 // Remove the old intrinsic from the chain
8809 DAG.ReplaceAllUsesOfValueWith(SDValue(Intr, Intr->getNumValues() - 1),
8810 Intr->getOperand(0));
8811
8812 return Chain;
8813}
8814
8815SDValue SITargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const {
8816 MVT VT = Op.getSimpleValueType();
8817 SDLoc DL(Op);
8818 // Checking the depth
8819 if (Op.getConstantOperandVal(0) != 0)
8820 return DAG.getConstant(0, DL, VT);
8821
8823 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8824 // Check for kernel and shader functions
8825 if (Info->isEntryFunction())
8826 return DAG.getConstant(0, DL, VT);
8827
8828 MachineFrameInfo &MFI = MF.getFrameInfo();
8829 // There is a call to @llvm.returnaddress in this function
8830 MFI.setReturnAddressIsTaken(true);
8831
8832 const SIRegisterInfo *TRI = getSubtarget()->getRegisterInfo();
8833 // Get the return address reg and mark it as an implicit live-in
8834 Register Reg = MF.addLiveIn(TRI->getReturnAddressReg(MF),
8835 getRegClassFor(VT, Op.getNode()->isDivergent()));
8836
8837 return DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg, VT);
8838}
8839
8840SDValue SITargetLowering::LowerSPONENTRY(SDValue Op, SelectionDAG &DAG) const {
8842 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
8843
8844 // For functions that set up their own stack, select the GET_STACK_BASE
8845 // pseudo.
8846 if (MFI->isBottomOfStack())
8847 return Op;
8848
8849 // For everything else, create a dummy stack object.
8850 int FI = MF.getFrameInfo().CreateFixedObject(1, 0, /*IsImmutable=*/false);
8851 return DAG.getFrameIndex(FI, Op.getValueType());
8852}
8853
8854SDValue SITargetLowering::getFPExtOrFPRound(SelectionDAG &DAG, SDValue Op,
8855 const SDLoc &DL, EVT VT) const {
8856 return Op.getValueType().bitsLE(VT)
8857 ? DAG.getNode(ISD::FP_EXTEND, DL, VT, Op)
8858 : DAG.getNode(ISD::FP_ROUND, DL, VT, Op,
8859 DAG.getTargetConstant(0, DL, MVT::i32));
8860}
8861
8862SDValue SITargetLowering::splitFP_ROUNDVectorOp(SDValue Op,
8863 SelectionDAG &DAG) const {
8864 EVT DstVT = Op.getValueType();
8865 unsigned NumElts = DstVT.getVectorNumElements();
8866 assert(NumElts > 2 && isPowerOf2_32(NumElts));
8867
8868 auto [Lo, Hi] = DAG.SplitVectorOperand(Op.getNode(), 0);
8869
8870 SDLoc DL(Op);
8871 unsigned Opc = Op.getOpcode();
8872 SDValue Flags = Op.getOperand(1);
8873 EVT HalfDstVT =
8874 EVT::getVectorVT(*DAG.getContext(), DstVT.getScalarType(), NumElts / 2);
8875 SDValue OpLo = DAG.getNode(Opc, DL, HalfDstVT, Lo, Flags);
8876 SDValue OpHi = DAG.getNode(Opc, DL, HalfDstVT, Hi, Flags);
8877
8878 return DAG.getNode(ISD::CONCAT_VECTORS, DL, DstVT, OpLo, OpHi);
8879}
8880
8881SDValue SITargetLowering::lowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const {
8882 bool IsStrict = Op->isStrictFPOpcode();
8883 SDValue Src = Op.getOperand(IsStrict ? 1 : 0);
8884 EVT SrcVT = Src.getValueType();
8885 EVT DstVT = Op.getValueType();
8886
8887 if (DstVT.isVectorOf(MVT::f16)) {
8888 assert(Subtarget->hasCvtPkF16F32Inst() && "support v_cvt_pk_f16_f32");
8889 if (SrcVT.getScalarType() != MVT::f32)
8890 return SDValue();
8891 return SrcVT == MVT::v2f32 ? Op : splitFP_ROUNDVectorOp(Op, DAG);
8892 }
8893
8894 if (SrcVT.getScalarType() != MVT::f64)
8895 return Op;
8896
8897 SDLoc DL(Op);
8898 if (DstVT == MVT::f16) {
8899 // TODO: Handle strictfp
8900 if (Op.getOpcode() != ISD::FP_ROUND)
8901 return Op;
8902
8903 if (!Subtarget->has16BitInsts()) {
8904 SDValue FpToFp16 = DAG.getNode(ISD::FP_TO_FP16, DL, MVT::i32, Src);
8905 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FpToFp16);
8906 return DAG.getNode(ISD::BITCAST, DL, MVT::f16, Trunc);
8907 }
8908 if (Op->getFlags().hasApproximateFuncs()) {
8909 SDValue Flags = Op.getOperand(1);
8910 SDValue Src32 = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, Src, Flags);
8911 return DAG.getNode(ISD::FP_ROUND, DL, MVT::f16, Src32, Flags);
8912 }
8913 SDValue FpToFp16 = LowerF64ToF16Safe(Src, DL, DAG);
8914 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FpToFp16);
8915 return DAG.getNode(ISD::BITCAST, DL, MVT::f16, Trunc);
8916 }
8917
8918 assert(DstVT.getScalarType() == MVT::bf16 &&
8919 "custom lower FP_ROUND for f16 or bf16");
8920 assert(Subtarget->hasBF16ConversionInsts() && "f32 -> bf16 is legal");
8921
8922 // Round-inexact-to-odd f64 to f32, then do the final rounding using the
8923 // hardware f32 -> bf16 instruction.
8924 EVT F32VT = SrcVT.changeElementType(*DAG.getContext(), MVT::f32);
8925 SDValue Rod = expandRoundInexactToOdd(F32VT, Src, DL, DAG);
8926 if (IsStrict) {
8927 return DAG.getNode(
8928 ISD::STRICT_FP_ROUND, DL, {DstVT, MVT::Other},
8929 {Op.getOperand(0), Rod, DAG.getTargetConstant(0, DL, MVT::i32)});
8930 }
8931 return DAG.getNode(ISD::FP_ROUND, DL, DstVT, Rod,
8932 DAG.getTargetConstant(0, DL, MVT::i32));
8933}
8934
8935SDValue SITargetLowering::lowerFMINNUM_FMAXNUM(SDValue Op,
8936 SelectionDAG &DAG) const {
8937 EVT VT = Op.getValueType();
8938 const MachineFunction &MF = DAG.getMachineFunction();
8939 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8940 bool IsIEEEMode = Info->getMode().IEEE;
8941
8942 // FIXME: Assert during selection that this is only selected for
8943 // ieee_mode. Currently a combine can produce the ieee version for non-ieee
8944 // mode functions, but this happens to be OK since it's only done in cases
8945 // where there is known no sNaN.
8946 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8947 return expandFMINNUM_FMAXNUM(Op.getNode(), DAG);
8948
8949 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8950 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8951 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8952 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8953 return splitBinaryVectorOp(Op, DAG);
8954 return Op;
8955}
8956
8957SDValue
8958SITargetLowering::lowerFMINIMUMNUM_FMAXIMUMNUM(SDValue Op,
8959 SelectionDAG &DAG) const {
8960 EVT VT = Op.getValueType();
8961 const MachineFunction &MF = DAG.getMachineFunction();
8962 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8963 bool IsIEEEMode = Info->getMode().IEEE;
8964
8965 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8966 return expandFMINIMUMNUM_FMAXIMUMNUM(Op.getNode(), DAG);
8967
8968 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8969 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8970 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8971 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8972 return splitBinaryVectorOp(Op, DAG);
8973 return Op;
8974}
8975
8976SDValue SITargetLowering::lowerFLDEXP(SDValue Op, SelectionDAG &DAG) const {
8977 bool IsStrict = Op.getOpcode() == ISD::STRICT_FLDEXP;
8978 EVT VT = Op.getValueType();
8979 assert(VT == MVT::f16);
8980
8981 SDValue Exp = Op.getOperand(IsStrict ? 2 : 1);
8982 EVT ExpVT = Exp.getValueType();
8983 if (ExpVT == MVT::i16)
8984 return Op;
8985
8986 SDLoc DL(Op);
8987
8988 // Correct the exponent type for f16 to i16.
8989 // Clamp the range of the exponent to the instruction's range.
8990
8991 // TODO: This should be a generic narrowing legalization, and can easily be
8992 // for GlobalISel.
8993
8994 SDValue MinExp = DAG.getSignedConstant(minIntN(16), DL, ExpVT);
8995 SDValue ClampMin = DAG.getNode(ISD::SMAX, DL, ExpVT, Exp, MinExp);
8996
8997 SDValue MaxExp = DAG.getSignedConstant(maxIntN(16), DL, ExpVT);
8998 SDValue Clamp = DAG.getNode(ISD::SMIN, DL, ExpVT, ClampMin, MaxExp);
8999
9000 SDValue TruncExp = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Clamp);
9001
9002 if (IsStrict) {
9003 return DAG.getNode(ISD::STRICT_FLDEXP, DL, {VT, MVT::Other},
9004 {Op.getOperand(0), Op.getOperand(1), TruncExp});
9005 }
9006
9007 return DAG.getNode(ISD::FLDEXP, DL, VT, Op.getOperand(0), TruncExp);
9008}
9009
9011 switch (Op->getOpcode()) {
9012 case ISD::ABS:
9013 case ISD::SRA:
9014 case ISD::SMIN:
9015 case ISD::SMAX:
9016 return ISD::SIGN_EXTEND;
9017 case ISD::SRL:
9018 case ISD::UMIN:
9019 case ISD::UMAX:
9020 case ISD::USUBSAT:
9021 case ISD::UADDSAT:
9022 return ISD::ZERO_EXTEND;
9023 case ISD::ADD:
9024 case ISD::SUB:
9025 case ISD::AND:
9026 case ISD::OR:
9027 case ISD::XOR:
9028 case ISD::SHL:
9029 case ISD::SELECT:
9030 case ISD::MUL:
9031 // operation result won't be influenced by garbage high bits.
9032 // TODO: are all of those cases correct, and are there more?
9033 return ISD::ANY_EXTEND;
9034 case ISD::SETCC: {
9035 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
9037 }
9038 default:
9039 llvm_unreachable("unexpected opcode!");
9040 }
9041}
9042
9043SDValue
9044SITargetLowering::promoteUniformUnaryOpToI32(SDValue Op,
9045 DAGCombinerInfo &DCI) const {
9046 EVT OpTy = Op.getValueType();
9047 SelectionDAG &DAG = DCI.DAG;
9048 EVT ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
9049
9050 if (isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
9051 return SDValue();
9052
9053 SDLoc DL(Op);
9054 SDValue Input = Op.getOperand(0);
9055 const unsigned ExtOp = getExtOpcodeForPromotedOp(Op);
9056 Input = DAG.getNode(ExtOp, DL, ExtTy, Input);
9057
9058 SDValue NewVal = DAG.getNode(Op.getOpcode(), DL, ExtTy, Input);
9059
9060 return DAG.getNode(ISD::TRUNCATE, DL, OpTy, NewVal);
9061}
9062
9063SDValue SITargetLowering::promoteUniformOpToI32(SDValue Op,
9064 DAGCombinerInfo &DCI) const {
9065 const unsigned Opc = Op.getOpcode();
9066 assert(Opc == ISD::ADD || Opc == ISD::SUB || Opc == ISD::SHL ||
9067 Opc == ISD::SRL || Opc == ISD::SRA || Opc == ISD::AND ||
9068 Opc == ISD::OR || Opc == ISD::XOR || Opc == ISD::MUL ||
9069 Opc == ISD::SETCC || Opc == ISD::SELECT || Opc == ISD::SMIN ||
9070 Opc == ISD::SMAX || Opc == ISD::UMIN || Opc == ISD::UMAX ||
9071 Opc == ISD::USUBSAT || Opc == ISD::UADDSAT);
9072
9073 EVT OpTy = (Opc != ISD::SETCC) ? Op.getValueType()
9074 : Op->getOperand(0).getValueType();
9075 auto &DAG = DCI.DAG;
9076 auto ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
9077
9078 if (DCI.isBeforeLegalizeOps() ||
9079 isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
9080 return SDValue();
9081
9082 SDLoc DL(Op);
9083 SDValue LHS;
9084 SDValue RHS;
9085 if (Opc == ISD::SELECT) {
9086 LHS = Op->getOperand(1);
9087 RHS = Op->getOperand(2);
9088 } else {
9089 LHS = Op->getOperand(0);
9090 RHS = Op->getOperand(1);
9091 }
9092
9093 const unsigned ExtOp = getExtOpcodeForPromotedOp(Op);
9094 LHS = DAG.getNode(ExtOp, DL, ExtTy, {LHS});
9095
9096 // Special case: for shifts, the RHS always needs a zext.
9097 if (Opc == ISD::SHL || Opc == ISD::SRL || Opc == ISD::SRA)
9098 RHS = DAG.getNode(ISD::ZERO_EXTEND, DL, ExtTy, {RHS});
9099 else
9100 RHS = DAG.getNode(ExtOp, DL, ExtTy, {RHS});
9101
9102 // setcc always return i1/i1 vec so no need to truncate after.
9103 if (Opc == ISD::SETCC) {
9104 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
9105 return DAG.getSetCC(DL, Op.getValueType(), LHS, RHS, CC);
9106 }
9107
9108 // For other ops, we extend the operation's return type as well so we need to
9109 // truncate back to the original type.
9110 SDValue NewVal;
9111 if (Opc == ISD::SELECT)
9112 NewVal = DAG.getNode(ISD::SELECT, DL, ExtTy, {Op->getOperand(0), LHS, RHS});
9113 else if (Opc == ISD::UADDSAT) {
9114 SDValue Sum = DAG.getNode(ISD::ADD, DL, ExtTy, LHS, RHS);
9115 SDValue MaxVal = DAG.getConstant(
9116 APInt::getMaxValue(OpTy.getScalarSizeInBits()).zext(32), DL, ExtTy);
9117 NewVal = DAG.getNode(ISD::UMIN, DL, ExtTy, Sum, MaxVal);
9118 } else
9119 NewVal = DAG.getNode(Opc, DL, ExtTy, {LHS, RHS});
9120
9121 return DAG.getZExtOrTrunc(NewVal, DL, OpTy);
9122}
9123
9124SDValue SITargetLowering::lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
9125 SDValue Mag = Op.getOperand(0);
9126 EVT MagVT = Mag.getValueType();
9127
9128 if (MagVT.getVectorNumElements() > 2)
9129 return splitBinaryVectorOp(Op, DAG);
9130
9131 SDValue Sign = Op.getOperand(1);
9132 EVT SignVT = Sign.getValueType();
9133
9134 if (MagVT == SignVT)
9135 return Op;
9136
9137 // fcopysign v2f16:mag, v2f32:sign ->
9138 // fcopysign v2f16:mag,
9139 // bitcast (trunc (srl (bitcast sign to v2i32), 16) to v2i16)
9140
9141 SDLoc SL(Op);
9142 SDValue SignAsInt32 = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Sign);
9143 SDValue ShiftAmt = DAG.getShiftAmountConstant(16, MVT::v2i32, SL);
9144 SDValue SignShifted =
9145 DAG.getNode(ISD::SRL, SL, MVT::v2i32, SignAsInt32, ShiftAmt);
9146 SDValue SignAsInt16 = DAG.getNode(ISD::TRUNCATE, SL, MVT::v2i16, SignShifted);
9147
9148 SDValue SignAsHalf16 = DAG.getNode(ISD::BITCAST, SL, MagVT, SignAsInt16);
9149
9150 return DAG.getNode(ISD::FCOPYSIGN, SL, MagVT, Mag, SignAsHalf16);
9151}
9152
9153// Custom lowering for vector multiplications and s_mul_u64.
9154SDValue SITargetLowering::lowerMUL(SDValue Op, SelectionDAG &DAG) const {
9155 EVT VT = Op.getValueType();
9156
9157 // Split vector operands.
9158 if (VT.isVector())
9159 return splitBinaryVectorOp(Op, DAG);
9160
9161 assert(VT == MVT::i64 && "The following code is a special for s_mul_u64");
9162
9163 // There are four ways to lower s_mul_u64:
9164 //
9165 // 1. If all the operands are uniform, then we lower it as it is.
9166 //
9167 // 2. If the operands are divergent, then we have to split s_mul_u64 in 32-bit
9168 // multiplications because there is not a vector equivalent of s_mul_u64.
9169 //
9170 // 3. If the cost model decides that it is more efficient to use vector
9171 // registers, then we have to split s_mul_u64 in 32-bit multiplications.
9172 // This happens in splitScalarSMULU64() in SIInstrInfo.cpp .
9173 //
9174 // 4. If the cost model decides to use vector registers and both of the
9175 // operands are zero-extended/sign-extended from 32-bits, then we split the
9176 // s_mul_u64 in two 32-bit multiplications. The problem is that it is not
9177 // possible to check if the operands are zero-extended or sign-extended in
9178 // SIInstrInfo.cpp. For this reason, here, we replace s_mul_u64 with
9179 // s_mul_u64_u32_pseudo if both operands are zero-extended and we replace
9180 // s_mul_u64 with s_mul_i64_i32_pseudo if both operands are sign-extended.
9181 // If the cost model decides that we have to use vector registers, then
9182 // splitScalarSMulPseudo() (in SIInstrInfo.cpp) split s_mul_u64_u32/
9183 // s_mul_i64_i32_pseudo in two vector multiplications. If the cost model
9184 // decides that we should use scalar registers, then s_mul_u64_u32_pseudo/
9185 // s_mul_i64_i32_pseudo is lowered as s_mul_u64 in expandPostRAPseudo() in
9186 // SIInstrInfo.cpp .
9187
9188 if (Op->isDivergent())
9189 return SDValue();
9190
9191 SDValue Op0 = Op.getOperand(0);
9192 SDValue Op1 = Op.getOperand(1);
9193 // If all the operands are zero-enteted to 32-bits, then we replace s_mul_u64
9194 // with s_mul_u64_u32_pseudo. If all the operands are sign-extended to
9195 // 32-bits, then we replace s_mul_u64 with s_mul_i64_i32_pseudo.
9196 KnownBits Op0KnownBits = DAG.computeKnownBits(Op0);
9197 unsigned Op0LeadingZeros = Op0KnownBits.countMinLeadingZeros();
9198 KnownBits Op1KnownBits = DAG.computeKnownBits(Op1);
9199 unsigned Op1LeadingZeros = Op1KnownBits.countMinLeadingZeros();
9200 SDLoc SL(Op);
9201 if (Op0LeadingZeros >= 32 && Op1LeadingZeros >= 32)
9202 return SDValue(
9203 DAG.getMachineNode(AMDGPU::S_MUL_U64_U32_PSEUDO, SL, VT, Op0, Op1), 0);
9204 unsigned Op0SignBits = DAG.ComputeNumSignBits(Op0);
9205 unsigned Op1SignBits = DAG.ComputeNumSignBits(Op1);
9206 if (Op0SignBits >= 33 && Op1SignBits >= 33)
9207 return SDValue(
9208 DAG.getMachineNode(AMDGPU::S_MUL_I64_I32_PSEUDO, SL, VT, Op0, Op1), 0);
9209 // If all the operands are uniform, then we lower s_mul_u64 as it is.
9210 return Op;
9211}
9212
9213SDValue SITargetLowering::lowerXMULO(SDValue Op, SelectionDAG &DAG) const {
9214 EVT VT = Op.getValueType();
9215 SDLoc SL(Op);
9216 SDValue LHS = Op.getOperand(0);
9217 SDValue RHS = Op.getOperand(1);
9218 bool isSigned = Op.getOpcode() == ISD::SMULO;
9219
9220 if (ConstantSDNode *RHSC = isConstOrConstSplat(RHS)) {
9221 const APInt &C = RHSC->getAPIntValue();
9222 // mulo(X, 1 << S) -> { X << S, (X << S) >> S != X }
9223 if (C.isPowerOf2()) {
9224 // smulo(x, signed_min) is same as umulo(x, signed_min).
9225 bool UseArithShift = isSigned && !C.isMinSignedValue();
9226 SDValue ShiftAmt = DAG.getConstant(C.logBase2(), SL, MVT::i32);
9227 SDValue Result = DAG.getNode(ISD::SHL, SL, VT, LHS, ShiftAmt);
9228 SDValue Overflow =
9229 DAG.getSetCC(SL, MVT::i1,
9230 DAG.getNode(UseArithShift ? ISD::SRA : ISD::SRL, SL, VT,
9231 Result, ShiftAmt),
9232 LHS, ISD::SETNE);
9233 return DAG.getMergeValues({Result, Overflow}, SL);
9234 }
9235 }
9236
9237 SDValue Result = DAG.getNode(ISD::MUL, SL, VT, LHS, RHS);
9238 SDValue Top =
9239 DAG.getNode(isSigned ? ISD::MULHS : ISD::MULHU, SL, VT, LHS, RHS);
9240
9241 SDValue Sign = isSigned
9242 ? DAG.getNode(ISD::SRA, SL, VT, Result,
9243 DAG.getConstant(VT.getScalarSizeInBits() - 1,
9244 SL, MVT::i32))
9245 : DAG.getConstant(0, SL, VT);
9246 SDValue Overflow = DAG.getSetCC(SL, MVT::i1, Top, Sign, ISD::SETNE);
9247
9248 return DAG.getMergeValues({Result, Overflow}, SL);
9249}
9250
9251SDValue SITargetLowering::lowerXMUL_LOHI(SDValue Op, SelectionDAG &DAG) const {
9252 if (Op->isDivergent()) {
9253 // Select to V_MAD_[IU]64_[IU]32.
9254 return Op;
9255 }
9256 if (Subtarget->hasSMulHi()) {
9257 // Expand to S_MUL_I32 + S_MUL_HI_[IU]32.
9258 return SDValue();
9259 }
9260 // The multiply is uniform but we would have to use V_MUL_HI_[IU]32 to
9261 // calculate the high part, so we might as well do the whole thing with
9262 // V_MAD_[IU]64_[IU]32.
9263 return Op;
9264}
9265
9266SDValue SITargetLowering::lowerTRAP(SDValue Op, SelectionDAG &DAG) const {
9267 if (!Subtarget->hasTrapHandler() ||
9268 Subtarget->getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbi::AMDHSA)
9269 return lowerTrapEndpgm(Op, DAG);
9270
9271 return Subtarget->supportsGetDoorbellID() ? lowerTrapHsa(Op, DAG)
9272 : lowerTrapHsaQueuePtr(Op, DAG);
9273}
9274
9275SDValue SITargetLowering::lowerTrapEndpgm(SDValue Op, SelectionDAG &DAG) const {
9276 SDLoc SL(Op);
9277 SDValue Chain = Op.getOperand(0);
9278 return DAG.getNode(AMDGPUISD::ENDPGM_TRAP, SL, MVT::Other, Chain);
9279}
9280
9281SDValue
9282SITargetLowering::loadImplicitKernelArgument(SelectionDAG &DAG, MVT VT,
9283 const SDLoc &DL, Align Alignment,
9284 ImplicitParameter Param) const {
9287 SDValue Ptr = lowerKernArgParameterPtr(DAG, DL, DAG.getEntryNode(), Offset);
9288 MachinePointerInfo PtrInfo =
9290 return DAG.getLoad(
9291 VT, DL, DAG.getEntryNode(), Ptr, PtrInfo.getWithOffset(Offset), Alignment,
9293}
9294
9295SDValue SITargetLowering::lowerTrapHsaQueuePtr(SDValue Op,
9296 SelectionDAG &DAG) const {
9297 SDLoc SL(Op);
9298 SDValue Chain = Op.getOperand(0);
9299
9300 SDValue QueuePtr;
9301 // For code object version 5, QueuePtr is passed through implicit kernarg.
9302 const Module *M = DAG.getMachineFunction().getFunction().getParent();
9304 QueuePtr =
9305 loadImplicitKernelArgument(DAG, MVT::i64, SL, Align(8), QUEUE_PTR);
9306 } else {
9308 SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
9309 Register UserSGPR = Info->getQueuePtrUserSGPR();
9310
9311 if (UserSGPR == AMDGPU::NoRegister) {
9312 // We probably are in a function incorrectly marked with
9313 // amdgpu-no-queue-ptr. This is undefined. We don't want to delete the
9314 // trap, so just use a null pointer.
9315 QueuePtr = DAG.getConstant(0, SL, MVT::i64);
9316 } else {
9317 QueuePtr = CreateLiveInRegister(DAG, &AMDGPU::SReg_64RegClass, UserSGPR,
9318 MVT::i64);
9319 }
9320 }
9321
9322 SDValue SGPR01 = DAG.getRegister(AMDGPU::SGPR0_SGPR1, MVT::i64);
9323 SDValue ToReg = DAG.getCopyToReg(Chain, SL, SGPR01, QueuePtr, SDValue());
9324
9326 SDValue Ops[] = {ToReg, DAG.getTargetConstant(TrapID, SL, MVT::i16), SGPR01,
9327 ToReg.getValue(1)};
9328 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9329}
9330
9331SDValue SITargetLowering::lowerTrapHsa(SDValue Op, SelectionDAG &DAG) const {
9332 SDLoc SL(Op);
9333 SDValue Chain = Op.getOperand(0);
9334
9335 // We need to simulate the 's_trap 2' instruction on targets that run in
9336 // PRIV=1 (where it is treated as a nop).
9337 if (Subtarget->hasPrivEnabledTrap2NopBug())
9338 return DAG.getNode(AMDGPUISD::SIMULATED_TRAP, SL, MVT::Other, Chain);
9339
9341 SDValue Ops[] = {Chain, DAG.getTargetConstant(TrapID, SL, MVT::i16)};
9342 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9343}
9344
9345SDValue SITargetLowering::lowerDEBUGTRAP(SDValue Op, SelectionDAG &DAG) const {
9346 SDLoc SL(Op);
9347 SDValue Chain = Op.getOperand(0);
9349
9350 if (!Subtarget->hasTrapHandler() ||
9351 Subtarget->getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbi::AMDHSA) {
9352 LLVMContext &Ctx = MF.getFunction().getContext();
9353 Ctx.diagnose(DiagnosticInfoUnsupported(MF.getFunction(),
9354 "debugtrap handler not supported",
9355 Op.getDebugLoc(), DS_Warning));
9356 return Chain;
9357 }
9358
9359 uint64_t TrapID =
9361 SDValue Ops[] = {Chain, DAG.getTargetConstant(TrapID, SL, MVT::i16)};
9362 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9363}
9364
9365/// When a divergent value (in VGPR) is passed to an inline asm with an SGPR
9366/// constraint ('s'), we need to insert v_readfirstlane to move the value from
9367/// VGPR to SGPR. This is done by modifying the CopyToReg nodes in the glue
9368/// chain that feed into the INLINEASM node.
9369SDValue SITargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const {
9370 unsigned NumOps = Op.getNumOperands();
9371
9372 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
9373 SmallSet<Register, 8> SGPRInputRegs;
9374
9375 unsigned NumVals = 0;
9376 for (unsigned I = InlineAsm::Op_FirstOperand; I < NumOps - 1;
9377 I += 1 + NumVals) {
9378 const InlineAsm::Flag Flags(Op.getConstantOperandVal(I));
9379 NumVals = Flags.getNumOperandRegisters();
9380
9381 unsigned RCID;
9382 bool IsSGPRInput = Flags.getKind() == InlineAsm::Kind::RegUse &&
9383 NumVals > 0 && Flags.hasRegClassConstraint(RCID) &&
9384 TRI->isSGPRClass(TRI->getRegClass(RCID));
9385
9386 for (unsigned J = 0; J < NumVals; ++J) {
9387 SDValue Val = Op.getOperand(I + 1 + J);
9388 if (const RegisterSDNode *RegNode =
9390 Register Reg = RegNode->getReg();
9391 if (IsSGPRInput || (Reg.isPhysical() && TRI->isSGPRPhysReg(Reg)))
9392 SGPRInputRegs.insert(Reg);
9393 }
9394 }
9395 }
9396
9397 if (SGPRInputRegs.empty())
9398 return Op;
9399
9400 // Walk the glue chain and insert readfirstlane for divergent SGPR inputs.
9401 SDLoc DL(Op);
9402 SDNode *N = Op.getOperand(NumOps - 1).getNode();
9403
9404 while (N && N->getOpcode() == ISD::CopyToReg) {
9405 Register Reg = cast<RegisterSDNode>(N->getOperand(1))->getReg();
9406 SDValue SrcVal = N->getOperand(2);
9407
9408 // Insert readfirstlane if copying a divergent value to an SGPR input.
9409 if (SrcVal->isDivergent() && SGPRInputRegs.count(Reg)) {
9410 SDValue ReadFirstLaneID =
9411 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
9412 SDValue ReadFirstLane =
9414 ReadFirstLaneID, SrcVal);
9415
9416 SmallVector<SDValue, 4> Ops = {N->getOperand(0), N->getOperand(1),
9417 ReadFirstLane};
9418 if (N->getNumOperands() > 3)
9419 Ops.push_back(N->getOperand(3)); // Glue input
9420
9421 DAG.UpdateNodeOperands(N, Ops);
9422 }
9423
9424 // Follow glue chain to next CopyToReg.
9425 SDNode *Next = nullptr;
9426 for (unsigned I = 0, E = N->getNumOperands(); I != E; ++I) {
9427 if (N->getOperand(I).getValueType() == MVT::Glue) {
9428 Next = N->getOperand(I).getNode();
9429 break;
9430 }
9431 }
9432 N = Next;
9433 }
9434
9435 return Op;
9436}
9437
9438SDValue SITargetLowering::getSegmentAperture(unsigned AS, const SDLoc &DL,
9439 SelectionDAG &DAG) const {
9440 unsigned BaseAS = AS;
9441 unsigned SANum = AMDGPU::getSyntheticApertureNumber(AS);
9443 BaseAS = AMDGPUAS::LOCAL_ADDRESS;
9444
9445 SDValue Aperture = getBaseSegmentAperture(BaseAS, DL, DAG);
9446
9447 if (SANum != AMDGPU::SyntheticAperture::None) {
9448 SDValue Tag = DAG.getConstant(SANum, DL, MVT::i32);
9449 return DAG.getNode(ISD::OR, DL, MVT::i32, Aperture, Tag);
9450 }
9451
9452 return Aperture;
9453}
9454
9455SDValue SITargetLowering::getBaseSegmentAperture(unsigned AS, const SDLoc &DL,
9456 SelectionDAG &DAG) const {
9457 const bool IsLDS = (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::BARRIER);
9458
9459 if (Subtarget->hasApertureRegs()) {
9460 const unsigned ApertureRegNo =
9461 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
9462 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
9463 !Subtarget->hasGloballyAddressableScratch()) &&
9464 "Cannot use src_private_base with globally addressable scratch!");
9465 // Note: this feature (register) is broken. When used as a 32-bit operand,
9466 // it returns a wrong value (all zeroes?). The real value is in the upper 32
9467 // bits.
9468 //
9469 // To work around the issue, emit a 64 bit copy from this register
9470 // then extract the high bits. Note that this shouldn't even result in a
9471 // shift being emitted and simply become a pair of registers (e.g.):
9472 // s_mov_b64 s[6:7], src_shared_base
9473 // v_mov_b32_e32 v1, s7
9474 SDValue Copy =
9475 DAG.getCopyFromReg(DAG.getEntryNode(), DL, ApertureRegNo, MVT::v2i32);
9476 return DAG.getExtractVectorElt(DL, MVT::i32, Copy, 1);
9477 }
9478
9479 // For code object version 5, private_base and shared_base are passed through
9480 // implicit kernargs.
9481 const Module *M = DAG.getMachineFunction().getFunction().getParent();
9484 return loadImplicitKernelArgument(DAG, MVT::i32, DL, Align(4), Param);
9485 }
9486
9488 SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
9489 Register UserSGPR = Info->getQueuePtrUserSGPR();
9490 if (UserSGPR == AMDGPU::NoRegister) {
9491 // We probably are in a function incorrectly marked with
9492 // amdgpu-no-queue-ptr. This is undefined.
9493 return DAG.getPOISON(MVT::i32);
9494 }
9495
9496 SDValue QueuePtr =
9497 CreateLiveInRegister(DAG, &AMDGPU::SReg_64RegClass, UserSGPR, MVT::i64);
9498
9499 // Offset into amd_queue_t for group_segment_aperture_base_hi /
9500 // private_segment_aperture_base_hi.
9501 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
9502
9503 SDValue Ptr =
9504 DAG.getObjectPtrOffset(DL, QueuePtr, TypeSize::getFixed(StructOffset));
9505
9506 // TODO: Use custom target PseudoSourceValue.
9507 // TODO: We should use the value from the IR intrinsic call, but it might not
9508 // be available and how do we get it?
9509 MachinePointerInfo PtrInfo(AMDGPUAS::CONSTANT_ADDRESS);
9510 return DAG.getLoad(MVT::i32, DL, QueuePtr.getValue(1), Ptr, PtrInfo,
9511 commonAlignment(Align(64), StructOffset),
9514}
9515
9516/// Return true if the value is a known valid address, such that a null check is
9517/// not necessary.
9519 const AMDGPUTargetMachine &TM, unsigned AddrSpace) {
9521 return true;
9522
9523 if (auto *ConstVal = dyn_cast<ConstantSDNode>(Val))
9524 return ConstVal->getSExtValue() != AMDGPU::getNullPointerValue(AddrSpace);
9525
9526 // TODO: Search through arithmetic, handle arguments and loads
9527 // marked nonnull.
9528 return false;
9529}
9530
9531SDValue SITargetLowering::lowerADDRSPACECAST(SDValue Op,
9532 SelectionDAG &DAG) const {
9533 SDLoc SL(Op);
9534
9535 const AMDGPUTargetMachine &TM =
9536 static_cast<const AMDGPUTargetMachine &>(getTargetMachine());
9537
9538 const auto *ASC = cast<AddrSpaceCastSDNode>(Op);
9539 unsigned SrcAS = ASC->getSrcAddressSpace();
9540 SDValue Src = ASC->getOperand(0);
9541 unsigned DestAS = ASC->getDestAddressSpace();
9542 bool IsNonNull = ASC->getFlags().hasNonNull();
9543
9544 SDValue FlatNullPtr = DAG.getConstant(0, SL, MVT::i64);
9545
9546 // flat -> local/private/barrier
9547 if (SrcAS == AMDGPUAS::FLAT_ADDRESS) {
9548 if (DestAS == AMDGPUAS::LOCAL_ADDRESS ||
9549 DestAS == AMDGPUAS::PRIVATE_ADDRESS || DestAS == AMDGPUAS::BARRIER) {
9550 SDValue Ptr = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Src);
9551
9552 if (DestAS == AMDGPUAS::PRIVATE_ADDRESS &&
9553 Subtarget->hasGloballyAddressableScratch()) {
9554 // flat -> private with globally addressable scratch: subtract
9555 // src_flat_scratch_base_lo.
9556 SDValue FlatScratchBaseLo(
9557 DAG.getMachineNode(
9558 AMDGPU::S_MOV_B32, SL, MVT::i32,
9559 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO, MVT::i32)),
9560 0);
9561 Ptr = DAG.getNode(ISD::SUB, SL, MVT::i32, Ptr, FlatScratchBaseLo);
9562 }
9563
9564 if (IsNonNull || isKnownNonNull(Op, DAG, TM, SrcAS))
9565 return Ptr;
9566
9567 unsigned NullVal = AMDGPU::getNullPointerValue(DestAS);
9568 SDValue SegmentNullPtr = DAG.getConstant(NullVal, SL, MVT::i32);
9569 SDValue NonNull = DAG.getSetCC(SL, MVT::i1, Src, FlatNullPtr, ISD::SETNE);
9570
9571 return DAG.getNode(ISD::SELECT, SL, MVT::i32, NonNull, Ptr,
9572 SegmentNullPtr);
9573 }
9574 }
9575
9576 // local/private/barrier -> flat
9577 if (DestAS == AMDGPUAS::FLAT_ADDRESS) {
9578 if (SrcAS == AMDGPUAS::LOCAL_ADDRESS ||
9579 SrcAS == AMDGPUAS::PRIVATE_ADDRESS || SrcAS == AMDGPUAS::BARRIER) {
9580 SDValue CvtPtr;
9581 if (SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
9582 Subtarget->hasGloballyAddressableScratch()) {
9583 // For wave32: Addr = (TID[4:0] << 52) + FLAT_SCRATCH_BASE + privateAddr
9584 // For wave64: Addr = (TID[5:0] << 51) + FLAT_SCRATCH_BASE + privateAddr
9585 SDValue AllOnes = DAG.getSignedTargetConstant(-1, SL, MVT::i32);
9586 SDValue ThreadID = DAG.getConstant(0, SL, MVT::i32);
9587 ThreadID = DAG.getNode(
9588 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
9589 DAG.getTargetConstant(Intrinsic::amdgcn_mbcnt_lo, SL, MVT::i32),
9590 AllOnes, ThreadID);
9591 if (Subtarget->isWave64())
9592 ThreadID = DAG.getNode(
9593 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
9594 DAG.getTargetConstant(Intrinsic::amdgcn_mbcnt_hi, SL, MVT::i32),
9595 AllOnes, ThreadID);
9596 SDValue ShAmt = DAG.getShiftAmountConstant(
9597 57 - 32 - Subtarget->getWavefrontSizeLog2(), MVT::i32, SL);
9598 SDValue SrcHi = DAG.getNode(ISD::SHL, SL, MVT::i32, ThreadID, ShAmt);
9599 CvtPtr = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, SrcHi);
9600 CvtPtr = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
9601 // Accessing src_flat_scratch_base_lo as a 64-bit operand gives the full
9602 // 64-bit hi:lo value.
9603 SDValue FlatScratchBase = {
9604 DAG.getMachineNode(
9605 AMDGPU::S_MOV_B64, SL, MVT::i64,
9606 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE, MVT::i64)),
9607 0};
9608 CvtPtr = DAG.getNode(ISD::ADD, SL, MVT::i64, CvtPtr, FlatScratchBase);
9609 } else {
9610 SDValue Aperture = getSegmentAperture(SrcAS, SL, DAG);
9611
9612 CvtPtr = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, Aperture);
9613 CvtPtr = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
9614 }
9615
9616 if (IsNonNull || isKnownNonNull(Op, DAG, TM, SrcAS))
9617 return CvtPtr;
9618
9619 unsigned NullVal = AMDGPU::getNullPointerValue(SrcAS);
9620 SDValue SegmentNullPtr = DAG.getConstant(NullVal, SL, MVT::i32);
9621
9622 SDValue NonNull =
9623 DAG.getSetCC(SL, MVT::i1, Src, SegmentNullPtr, ISD::SETNE);
9624
9625 return DAG.getNode(ISD::SELECT, SL, MVT::i64, NonNull, CvtPtr,
9626 FlatNullPtr);
9627 }
9628 }
9629
9630 if (SrcAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT &&
9631 Op.getValueType() == MVT::i64) {
9632 const SIMachineFunctionInfo *Info =
9633 DAG.getMachineFunction().getInfo<SIMachineFunctionInfo>();
9634 if (Info->get32BitAddressHighBits() == 0)
9635 return DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i64, Src);
9636
9637 SDValue Hi = DAG.getConstant(Info->get32BitAddressHighBits(), SL, MVT::i32);
9638 SDValue Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, Hi);
9639 return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
9640 }
9641
9642 if (DestAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT &&
9643 Src.getValueType() == MVT::i64)
9644 return DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Src);
9645
9646 // global <-> flat are no-ops and never emitted.
9647
9648 // Invalid casts are poison.
9649 return DAG.getPOISON(Op->getValueType(0));
9650}
9651
9652// This lowers an INSERT_SUBVECTOR by extracting the individual elements from
9653// the small vector and inserting them into the big vector. That is better than
9654// the default expansion of doing it via a stack slot. Even though the use of
9655// the stack slot would be optimized away afterwards, the stack slot itself
9656// remains.
9657SDValue SITargetLowering::lowerINSERT_SUBVECTOR(SDValue Op,
9658 SelectionDAG &DAG) const {
9659 SDValue Vec = Op.getOperand(0);
9660 SDValue Ins = Op.getOperand(1);
9661 SDValue Idx = Op.getOperand(2);
9662 EVT VecVT = Vec.getValueType();
9663 EVT InsVT = Ins.getValueType();
9664 EVT EltVT = VecVT.getVectorElementType();
9665 unsigned InsNumElts = InsVT.getVectorNumElements();
9666 unsigned IdxVal = Idx->getAsZExtVal();
9667 SDLoc SL(Op);
9668
9669 if (EltVT.getScalarSizeInBits() == 16 && IdxVal % 2 == 0) {
9670 // Insert 32-bit registers at a time.
9671 assert(InsNumElts % 2 == 0 && "expect legal vector types");
9672
9673 unsigned VecNumElts = VecVT.getVectorNumElements();
9674 EVT NewVecVT =
9675 EVT::getVectorVT(*DAG.getContext(), MVT::i32, VecNumElts / 2);
9676 EVT NewInsVT = InsNumElts == 2 ? MVT::i32
9678 MVT::i32, InsNumElts / 2);
9679
9680 Vec = DAG.getNode(ISD::BITCAST, SL, NewVecVT, Vec);
9681 Ins = DAG.getNode(ISD::BITCAST, SL, NewInsVT, Ins);
9682
9683 for (unsigned I = 0; I != InsNumElts / 2; ++I) {
9684 SDValue Elt;
9685 if (InsNumElts == 2) {
9686 Elt = Ins;
9687 } else {
9688 Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Ins,
9689 DAG.getConstant(I, SL, MVT::i32));
9690 }
9691 Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, SL, NewVecVT, Vec, Elt,
9692 DAG.getConstant(IdxVal / 2 + I, SL, MVT::i32));
9693 }
9694
9695 return DAG.getNode(ISD::BITCAST, SL, VecVT, Vec);
9696 }
9697
9698 for (unsigned I = 0; I != InsNumElts; ++I) {
9699 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Ins,
9700 DAG.getConstant(I, SL, MVT::i32));
9701 Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, SL, VecVT, Vec, Elt,
9702 DAG.getConstant(IdxVal + I, SL, MVT::i32));
9703 }
9704 return Vec;
9705}
9706
9707SDValue SITargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op,
9708 SelectionDAG &DAG) const {
9709 SDValue Vec = Op.getOperand(0);
9710 SDValue InsVal = Op.getOperand(1);
9711 SDValue Idx = Op.getOperand(2);
9712 EVT VecVT = Vec.getValueType();
9713 EVT EltVT = VecVT.getVectorElementType();
9714 unsigned VecSize = VecVT.getSizeInBits();
9715 unsigned EltSize = EltVT.getSizeInBits();
9716 SDLoc SL(Op);
9717
9718 // Specially handle the case of v4i16 with static indexing.
9719 unsigned NumElts = VecVT.getVectorNumElements();
9720 auto *KIdx = dyn_cast<ConstantSDNode>(Idx);
9721 if (NumElts == 4 && EltSize == 16 && KIdx) {
9722 SDValue BCVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Vec);
9723
9724 SDValue LoHalf = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, BCVec,
9725 DAG.getConstant(0, SL, MVT::i32));
9726 SDValue HiHalf = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, BCVec,
9727 DAG.getConstant(1, SL, MVT::i32));
9728
9729 SDValue LoVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, LoHalf);
9730 SDValue HiVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, HiHalf);
9731
9732 unsigned Idx = KIdx->getZExtValue();
9733 bool InsertLo = Idx < 2;
9734 SDValue InsHalf = DAG.getNode(
9735 ISD::INSERT_VECTOR_ELT, SL, MVT::v2i16, InsertLo ? LoVec : HiVec,
9736 DAG.getNode(ISD::BITCAST, SL, MVT::i16, InsVal),
9737 DAG.getConstant(InsertLo ? Idx : (Idx - 2), SL, MVT::i32));
9738
9739 InsHalf = DAG.getNode(ISD::BITCAST, SL, MVT::i32, InsHalf);
9740
9741 SDValue Concat =
9742 InsertLo ? DAG.getBuildVector(MVT::v2i32, SL, {InsHalf, HiHalf})
9743 : DAG.getBuildVector(MVT::v2i32, SL, {LoHalf, InsHalf});
9744
9745 return DAG.getNode(ISD::BITCAST, SL, VecVT, Concat);
9746 }
9747
9748 // Static indexing does not lower to stack access, and hence there is no need
9749 // for special custom lowering to avoid stack access.
9750 if (isa<ConstantSDNode>(Idx))
9751 return SDValue();
9752
9753 // Avoid stack access for dynamic indexing by custom lowering to
9754 // v_bfi_b32 (v_bfm_b32 16, (shl idx, 16)), val, vec
9755
9756 assert(VecSize <= 64 && "Expected target vector size to be <= 64 bits");
9757
9758 MVT IntVT = MVT::getIntegerVT(VecSize);
9759
9760 // Convert vector index to bit-index and get the required bit mask.
9761 assert(isPowerOf2_32(EltSize));
9762 const auto EltMask = maskTrailingOnes<uint64_t>(EltSize);
9763 SDValue ScaleFactor = DAG.getConstant(Log2_32(EltSize), SL, MVT::i32);
9764 SDValue ScaledIdx = DAG.getNode(ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9765 SDValue BFM = DAG.getNode(ISD::SHL, SL, IntVT,
9766 DAG.getConstant(EltMask, SL, IntVT), ScaledIdx);
9767
9768 // 1. Create a congruent vector with the target value in each element.
9769 SDValue ExtVal = DAG.getNode(ISD::BITCAST, SL, IntVT,
9770 DAG.getSplatBuildVector(VecVT, SL, InsVal));
9771
9772 // 2. Mask off all other indices except the required index within (1).
9773 SDValue LHS = DAG.getNode(ISD::AND, SL, IntVT, BFM, ExtVal);
9774
9775 // 3. Mask off the required index within the target vector.
9776 SDValue BCVec = DAG.getNode(ISD::BITCAST, SL, IntVT, Vec);
9777 SDValue RHS =
9778 DAG.getNode(ISD::AND, SL, IntVT, DAG.getNOT(SL, BFM, IntVT), BCVec);
9779
9780 // 4. Get (2) and (3) ORed into the target vector.
9781 SDValue BFI =
9782 DAG.getNode(ISD::OR, SL, IntVT, LHS, RHS, SDNodeFlags::Disjoint);
9783
9784 return DAG.getNode(ISD::BITCAST, SL, VecVT, BFI);
9785}
9786
9787SDValue SITargetLowering::lowerEXTRACT_VECTOR_ELT(SDValue Op,
9788 SelectionDAG &DAG) const {
9789 SDLoc SL(Op);
9790
9791 EVT ResultVT = Op.getValueType();
9792 SDValue Vec = Op.getOperand(0);
9793 SDValue Idx = Op.getOperand(1);
9794 EVT VecVT = Vec.getValueType();
9795 unsigned VecSize = VecVT.getSizeInBits();
9796 EVT EltVT = VecVT.getVectorElementType();
9797
9798 DAGCombinerInfo DCI(DAG, AfterLegalizeVectorOps, true, nullptr);
9799
9800 // Make sure we do any optimizations that will make it easier to fold
9801 // source modifiers before obscuring it with bit operations.
9802
9803 // XXX - Why doesn't this get called when vector_shuffle is expanded?
9804 if (SDValue Combined = performExtractVectorEltCombine(Op.getNode(), DCI))
9805 return Combined;
9806
9807 if (VecSize == 128 || VecSize == 256 || VecSize == 512) {
9808 SDValue Lo, Hi;
9809 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VecVT);
9810
9811 if (VecSize == 128) {
9812 SDValue V2 = DAG.getBitcast(MVT::v2i64, Vec);
9813 Lo = DAG.getBitcast(LoVT,
9814 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9815 DAG.getConstant(0, SL, MVT::i32)));
9816 Hi = DAG.getBitcast(HiVT,
9817 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9818 DAG.getConstant(1, SL, MVT::i32)));
9819 } else if (VecSize == 256) {
9820 SDValue V2 = DAG.getBitcast(MVT::v4i64, Vec);
9821 SDValue Parts[4];
9822 for (unsigned P = 0; P < 4; ++P) {
9823 Parts[P] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9824 DAG.getConstant(P, SL, MVT::i32));
9825 }
9826
9827 Lo = DAG.getBitcast(LoVT, DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i64,
9828 Parts[0], Parts[1]));
9829 Hi = DAG.getBitcast(HiVT, DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i64,
9830 Parts[2], Parts[3]));
9831 } else {
9832 assert(VecSize == 512);
9833
9834 SDValue V2 = DAG.getBitcast(MVT::v8i64, Vec);
9835 SDValue Parts[8];
9836 for (unsigned P = 0; P < 8; ++P) {
9837 Parts[P] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9838 DAG.getConstant(P, SL, MVT::i32));
9839 }
9840
9841 Lo = DAG.getBitcast(LoVT,
9842 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v4i64,
9843 Parts[0], Parts[1], Parts[2], Parts[3]));
9844 Hi = DAG.getBitcast(HiVT,
9845 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v4i64,
9846 Parts[4], Parts[5], Parts[6], Parts[7]));
9847 }
9848
9849 EVT IdxVT = Idx.getValueType();
9850 unsigned NElem = VecVT.getVectorNumElements();
9851 assert(isPowerOf2_32(NElem));
9852 SDValue IdxMask = DAG.getConstant(NElem / 2 - 1, SL, IdxVT);
9853 SDValue NewIdx = DAG.getNode(ISD::AND, SL, IdxVT, Idx, IdxMask);
9854 SDValue Half = DAG.getSelectCC(SL, Idx, IdxMask, Hi, Lo, ISD::SETUGT);
9855 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Half, NewIdx);
9856 }
9857
9858 assert(VecSize <= 64);
9859
9860 MVT IntVT = MVT::getIntegerVT(VecSize);
9861
9862 // If Vec is just a SCALAR_TO_VECTOR, then use the scalar integer directly.
9863 SDValue VecBC = peekThroughBitcasts(Vec);
9864 if (VecBC.getOpcode() == ISD::SCALAR_TO_VECTOR) {
9865 SDValue Src = VecBC.getOperand(0);
9866 Src = DAG.getBitcast(Src.getValueType().changeTypeToInteger(), Src);
9867 Vec = DAG.getAnyExtOrTrunc(Src, SL, IntVT);
9868 }
9869
9870 unsigned EltSize = EltVT.getSizeInBits();
9871 assert(isPowerOf2_32(EltSize));
9872
9873 SDValue ScaleFactor = DAG.getConstant(Log2_32(EltSize), SL, MVT::i32);
9874
9875 // Convert vector index to bit-index (* EltSize)
9876 SDValue ScaledIdx = DAG.getNode(ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9877
9878 SDValue BC = DAG.getNode(ISD::BITCAST, SL, IntVT, Vec);
9879 SDValue Elt = DAG.getNode(ISD::SRL, SL, IntVT, BC, ScaledIdx);
9880
9881 if (ResultVT == MVT::f16 || ResultVT == MVT::bf16) {
9882 SDValue Result = DAG.getNode(ISD::TRUNCATE, SL, MVT::i16, Elt);
9883 return DAG.getNode(ISD::BITCAST, SL, ResultVT, Result);
9884 }
9885
9886 return DAG.getAnyExtOrTrunc(Elt, SL, ResultVT);
9887}
9888
9889static bool elementPairIsContiguous(ArrayRef<int> Mask, int Elt) {
9890 assert(Elt % 2 == 0);
9891 return Mask[Elt + 1] == Mask[Elt] + 1 && (Mask[Elt] % 2 == 0);
9892}
9893
9894static bool elementPairIsOddToEven(ArrayRef<int> Mask, int Elt) {
9895 assert(Elt % 2 == 0);
9896 return Mask[Elt] >= 0 && Mask[Elt + 1] >= 0 && (Mask[Elt] & 1) &&
9897 !(Mask[Elt + 1] & 1);
9898}
9899
9900SDValue SITargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
9901 SelectionDAG &DAG) const {
9902 SDLoc SL(Op);
9903 EVT ResultVT = Op.getValueType();
9904 ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(Op);
9905 MVT EltVT = ResultVT.getVectorElementType().getSimpleVT();
9906 const int NewSrcNumElts = 2;
9907 MVT PackVT = MVT::getVectorVT(EltVT, NewSrcNumElts);
9908 int SrcNumElts = Op.getOperand(0).getValueType().getVectorNumElements();
9909
9910 // Break up the shuffle into registers sized pieces.
9911 //
9912 // We're trying to form sub-shuffles that the register allocation pipeline
9913 // won't be able to figure out, like how to use v_pk_mov_b32 to do a register
9914 // blend or 16-bit op_sel. It should be able to figure out how to reassemble a
9915 // pair of copies into a consecutive register copy, so use the ordinary
9916 // extract_vector_elt lowering unless we can use the shuffle.
9917 //
9918 // TODO: This is a bit of hack, and we should probably always use
9919 // extract_subvector for the largest possible subvector we can (or at least
9920 // use it for PackVT aligned pieces). However we have worse support for
9921 // combines on them don't directly treat extract_subvector / insert_subvector
9922 // as legal. The DAG scheduler also ends up doing a worse job with the
9923 // extract_subvectors.
9924 const bool ShouldUseConsecutiveExtract = EltVT.getSizeInBits() == 16;
9925
9926 // vector_shuffle <0,1,6,7> lhs, rhs
9927 // -> concat_vectors (extract_subvector lhs, 0), (extract_subvector rhs, 2)
9928 //
9929 // vector_shuffle <6,7,2,3> lhs, rhs
9930 // -> concat_vectors (extract_subvector rhs, 2), (extract_subvector lhs, 2)
9931 //
9932 // vector_shuffle <6,7,0,1> lhs, rhs
9933 // -> concat_vectors (extract_subvector rhs, 2), (extract_subvector lhs, 0)
9934
9935 // Avoid scalarizing when both halves are reading from consecutive elements.
9936
9937 // If we're treating 2 element shuffles as legal, also create odd-to-even
9938 // shuffles of neighboring pairs.
9939 //
9940 // vector_shuffle <3,2,7,6> lhs, rhs
9941 // -> concat_vectors vector_shuffle <1, 0> (extract_subvector lhs, 0)
9942 // vector_shuffle <1, 0> (extract_subvector rhs, 2)
9943
9945 for (int I = 0, N = ResultVT.getVectorNumElements(); I != N; I += 2) {
9946 if (ShouldUseConsecutiveExtract &&
9948 const int Idx = SVN->getMaskElt(I);
9949 int VecIdx = Idx < SrcNumElts ? 0 : 1;
9950 int EltIdx = Idx < SrcNumElts ? Idx : Idx - SrcNumElts;
9951 SDValue SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT,
9952 SVN->getOperand(VecIdx),
9953 DAG.getConstant(EltIdx, SL, MVT::i32));
9954 Pieces.push_back(SubVec);
9955 } else if (elementPairIsOddToEven(SVN->getMask(), I) &&
9957 int Idx0 = SVN->getMaskElt(I);
9958 int Idx1 = SVN->getMaskElt(I + 1);
9959
9960 SDValue SrcOp0 = SVN->getOperand(0);
9961 SDValue SrcOp1 = SrcOp0;
9962 if (Idx0 >= SrcNumElts) {
9963 SrcOp0 = SVN->getOperand(1);
9964 Idx0 -= SrcNumElts;
9965 }
9966
9967 if (Idx1 >= SrcNumElts) {
9968 SrcOp1 = SVN->getOperand(1);
9969 Idx1 -= SrcNumElts;
9970 }
9971
9972 int AlignedIdx0 = Idx0 & ~(NewSrcNumElts - 1);
9973 int AlignedIdx1 = Idx1 & ~(NewSrcNumElts - 1);
9974
9975 // Extract nearest even aligned piece.
9976 SDValue SubVec0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT, SrcOp0,
9977 DAG.getConstant(AlignedIdx0, SL, MVT::i32));
9978 SDValue SubVec1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT, SrcOp1,
9979 DAG.getConstant(AlignedIdx1, SL, MVT::i32));
9980
9981 int NewMaskIdx0 = Idx0 - AlignedIdx0;
9982 int NewMaskIdx1 = Idx1 - AlignedIdx1;
9983
9984 SDValue Result0 = SubVec0;
9985 SDValue Result1 = SubVec0;
9986
9987 if (SubVec0 != SubVec1) {
9988 NewMaskIdx1 += NewSrcNumElts;
9989 Result1 = SubVec1;
9990 } else {
9991 Result1 = DAG.getPOISON(PackVT);
9992 }
9993
9994 SDValue Shuf = DAG.getVectorShuffle(PackVT, SL, Result0, Result1,
9995 {NewMaskIdx0, NewMaskIdx1});
9996 Pieces.push_back(Shuf);
9997 } else {
9998 const int Idx0 = SVN->getMaskElt(I);
9999 const int Idx1 = SVN->getMaskElt(I + 1);
10000 int VecIdx0 = Idx0 < SrcNumElts ? 0 : 1;
10001 int VecIdx1 = Idx1 < SrcNumElts ? 0 : 1;
10002 int EltIdx0 = Idx0 < SrcNumElts ? Idx0 : Idx0 - SrcNumElts;
10003 int EltIdx1 = Idx1 < SrcNumElts ? Idx1 : Idx1 - SrcNumElts;
10004
10005 SDValue Vec0 = SVN->getOperand(VecIdx0);
10006 SDValue Elt0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec0,
10007 DAG.getSignedConstant(EltIdx0, SL, MVT::i32));
10008
10009 SDValue Vec1 = SVN->getOperand(VecIdx1);
10010 SDValue Elt1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec1,
10011 DAG.getSignedConstant(EltIdx1, SL, MVT::i32));
10012 Pieces.push_back(DAG.getBuildVector(PackVT, SL, {Elt0, Elt1}));
10013 }
10014 }
10015
10016 return DAG.getNode(ISD::CONCAT_VECTORS, SL, ResultVT, Pieces);
10017}
10018
10019SDValue SITargetLowering::lowerSCALAR_TO_VECTOR(SDValue Op,
10020 SelectionDAG &DAG) const {
10021 SDValue SVal = Op.getOperand(0);
10022 EVT ResultVT = Op.getValueType();
10023 EVT SValVT = SVal.getValueType();
10024 SDValue UndefVal = DAG.getPOISON(SValVT);
10025 SDLoc SL(Op);
10026
10028 VElts.push_back(SVal);
10029 for (int I = 1, E = ResultVT.getVectorNumElements(); I < E; ++I)
10030 VElts.push_back(UndefVal);
10031
10032 return DAG.getBuildVector(ResultVT, SL, VElts);
10033}
10034
10035SDValue SITargetLowering::lowerBUILD_VECTOR(SDValue Op,
10036 SelectionDAG &DAG) const {
10037 SDLoc SL(Op);
10038 EVT VT = Op.getValueType();
10039
10040 if (VT == MVT::v2f16 || VT == MVT::v2i16 || VT == MVT::v2bf16) {
10041 assert(!Subtarget->hasVOP3PInsts() && "this should be legal");
10042
10043 SDValue Lo = Op.getOperand(0);
10044 SDValue Hi = Op.getOperand(1);
10045
10046 // Avoid adding defined bits with the zero_extend.
10047 if (Hi.isUndef()) {
10048 Lo = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Lo);
10049 SDValue ExtLo = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Lo);
10050 return DAG.getNode(ISD::BITCAST, SL, VT, ExtLo);
10051 }
10052
10053 Hi = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Hi);
10054 Hi = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Hi);
10055
10056 SDValue ShlHi = DAG.getNode(ISD::SHL, SL, MVT::i32, Hi,
10057 DAG.getConstant(16, SL, MVT::i32));
10058 if (Lo.isUndef())
10059 return DAG.getNode(ISD::BITCAST, SL, VT, ShlHi);
10060
10061 Lo = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Lo);
10062 Lo = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Lo);
10063
10064 SDValue Or =
10065 DAG.getNode(ISD::OR, SL, MVT::i32, Lo, ShlHi, SDNodeFlags::Disjoint);
10066 return DAG.getNode(ISD::BITCAST, SL, VT, Or);
10067 }
10068
10069 // Split into 2-element chunks.
10070 const unsigned NumParts = VT.getVectorNumElements() / 2;
10071 EVT PartVT = MVT::getVectorVT(VT.getVectorElementType().getSimpleVT(), 2);
10072 MVT PartIntVT = MVT::getIntegerVT(PartVT.getSizeInBits());
10073
10075 for (unsigned P = 0; P < NumParts; ++P) {
10076 SDValue Vec = DAG.getBuildVector(
10077 PartVT, SL, {Op.getOperand(P * 2), Op.getOperand(P * 2 + 1)});
10078 Casts.push_back(DAG.getNode(ISD::BITCAST, SL, PartIntVT, Vec));
10079 }
10080
10081 SDValue Blend =
10082 DAG.getBuildVector(MVT::getVectorVT(PartIntVT, NumParts), SL, Casts);
10083 return DAG.getNode(ISD::BITCAST, SL, VT, Blend);
10084}
10085
10087 const GlobalAddressSDNode *GA) const {
10088 // Named barriers have fixed, non-relocated LDS addresses, so a constant
10089 // offset into an array of them can be folded into the address.
10091 const auto *GV = dyn_cast<GlobalVariable>(GA->getGlobal());
10092 return GV && AMDGPU::isNamedBarrier(*GV);
10093 }
10094
10095 // OSes that use ELF REL relocations (instead of RELA) can only store a
10096 // 32-bit addend in the instruction, so it is not safe to allow offset folding
10097 // which can create arbitrary 64-bit addends. (This is only a problem for
10098 // R_AMDGPU_*32_HI relocations since other relocation types are unaffected by
10099 // the high 32 bits of the addend.)
10100 //
10101 // This should be kept in sync with how HasRelocationAddend is initialized in
10102 // the constructor of ELFAMDGPUAsmBackend.
10103 if (!Subtarget->isAmdHsaOS())
10104 return false;
10105
10106 // We can fold offsets for anything that doesn't require a GOT relocation.
10107 return (GA->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS ||
10111}
10112
10113static SDValue
10115 const SDLoc &DL, int64_t Offset, EVT PtrVT,
10116 unsigned GAFlags = SIInstrInfo::MO_NONE) {
10117 assert(isInt<32>(Offset + 4) && "32-bit offset is expected!");
10118 // In order to support pc-relative addressing, the PC_ADD_REL_OFFSET SDNode is
10119 // lowered to the following code sequence:
10120 //
10121 // For constant address space:
10122 // s_getpc_b64 s[0:1]
10123 // s_add_u32 s0, s0, $symbol
10124 // s_addc_u32 s1, s1, 0
10125 //
10126 // s_getpc_b64 returns the address of the s_add_u32 instruction and then
10127 // a fixup or relocation is emitted to replace $symbol with a literal
10128 // constant, which is a pc-relative offset from the encoding of the $symbol
10129 // operand to the global variable.
10130 //
10131 // For global address space:
10132 // s_getpc_b64 s[0:1]
10133 // s_add_u32 s0, s0, $symbol@{gotpc}rel32@lo
10134 // s_addc_u32 s1, s1, $symbol@{gotpc}rel32@hi
10135 //
10136 // s_getpc_b64 returns the address of the s_add_u32 instruction and then
10137 // fixups or relocations are emitted to replace $symbol@*@lo and
10138 // $symbol@*@hi with lower 32 bits and higher 32 bits of a literal constant,
10139 // which is a 64-bit pc-relative offset from the encoding of the $symbol
10140 // operand to the global variable.
10141 if (((const GCNSubtarget &)DAG.getSubtarget()).has64BitLiterals()) {
10142 assert(GAFlags != SIInstrInfo::MO_NONE);
10143
10144 SDValue Ptr =
10145 DAG.getTargetGlobalAddress(GV, DL, MVT::i64, Offset, GAFlags + 2);
10146 return DAG.getNode(AMDGPUISD::PC_ADD_REL_OFFSET64, DL, PtrVT, Ptr);
10147 }
10148
10149 SDValue PtrLo = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, Offset, GAFlags);
10150 SDValue PtrHi;
10151 if (GAFlags == SIInstrInfo::MO_NONE)
10152 PtrHi = DAG.getTargetConstant(0, DL, MVT::i32);
10153 else
10154 PtrHi = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, Offset, GAFlags + 1);
10155 return DAG.getNode(AMDGPUISD::PC_ADD_REL_OFFSET, DL, PtrVT, PtrLo, PtrHi);
10156}
10157
10158SDValue SITargetLowering::LowerGlobalAddress(AMDGPUMachineFunctionInfo *MFI,
10159 SDValue Op,
10160 SelectionDAG &DAG) const {
10161 GlobalAddressSDNode *GSD = cast<GlobalAddressSDNode>(Op);
10162 SDLoc DL(GSD);
10163 EVT PtrVT = Op.getValueType();
10164
10165 const GlobalValue *GV = GSD->getGlobal();
10166 const unsigned AS = GSD->getAddressSpace();
10167 if (((AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::BARRIER) &&
10170 if (AS == AMDGPUAS::LOCAL_ADDRESS && GV->hasExternalLinkage()) {
10171 const GlobalVariable &GVar = *cast<GlobalVariable>(GV);
10172 // HIP uses an unsized array `extern __shared__ T s[]` or similar
10173 // zero-sized type in other languages to declare the dynamic shared
10174 // memory which size is not known at the compile time. They will be
10175 // allocated by the runtime and placed directly after the static
10176 // allocated ones. They all share the same offset.
10177 if (GVar.getGlobalSize(GVar.getDataLayout()) == 0) {
10178 assert(PtrVT == MVT::i32 && "32-bit pointer is expected.");
10179 // Adjust alignment for that dynamic shared memory array.
10181 MFI->setDynLDSAlign(F, GVar);
10182 MFI->setUsesDynamicLDS(true);
10183 return SDValue(
10184 DAG.getMachineNode(AMDGPU::GET_GROUPSTATICSIZE, DL, PtrVT), 0);
10185 }
10186 }
10188 }
10189
10190 if (AS == AMDGPUAS::BARRIER) {
10191 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, GSD->getOffset(),
10193 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0);
10194 }
10195
10196 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
10197 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, GSD->getOffset(),
10199 return DAG.getNode(AMDGPUISD::LDS, DL, MVT::i32, GA);
10200 }
10201
10202 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS()) {
10203 if (Subtarget->has64BitLiterals()) {
10204 SDValue Addr = DAG.getTargetGlobalAddress(
10205 GV, DL, MVT::i64, GSD->getOffset(), SIInstrInfo::MO_ABS64);
10206 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B64, DL, MVT::i64, Addr),
10207 0);
10208 }
10209
10210 SDValue AddrLo = DAG.getTargetGlobalAddress(
10211 GV, DL, MVT::i32, GSD->getOffset(), SIInstrInfo::MO_ABS32_LO);
10212 AddrLo = {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, AddrLo), 0};
10213
10214 SDValue AddrHi = DAG.getTargetGlobalAddress(
10215 GV, DL, MVT::i32, GSD->getOffset(), SIInstrInfo::MO_ABS32_HI);
10216 AddrHi = {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, AddrHi), 0};
10217
10218 return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, AddrLo, AddrHi);
10219 }
10220
10221 if (shouldEmitFixup(GV))
10222 return buildPCRelGlobalAddress(DAG, GV, DL, GSD->getOffset(), PtrVT);
10223
10224 if (shouldEmitPCReloc(GV))
10225 return buildPCRelGlobalAddress(DAG, GV, DL, GSD->getOffset(), PtrVT,
10227
10228 SDValue GOTAddr = buildPCRelGlobalAddress(DAG, GV, DL, 0, PtrVT,
10230 PointerType *PtrTy =
10232 const DataLayout &DataLayout = DAG.getDataLayout();
10233 Align Alignment = DataLayout.getABITypeAlign(PtrTy);
10234 MachinePointerInfo PtrInfo =
10236
10237 return DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), GOTAddr, PtrInfo, Alignment,
10240}
10241
10242SDValue SITargetLowering::LowerExternalSymbol(SDValue Op,
10243 SelectionDAG &DAG) const {
10244 // TODO: Handle this. It should be mostly the same as LowerGlobalAddress.
10245 const Function &Fn = DAG.getMachineFunction().getFunction();
10246 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10247 Fn, "unsupported external symbol", Op.getDebugLoc()));
10248 return DAG.getPOISON(Op.getValueType());
10249}
10250
10252 const SDLoc &DL, SDValue V) const {
10253 // We can't use S_MOV_B32 directly, because there is no way to specify m0 as
10254 // the destination register.
10255 //
10256 // We can't use CopyToReg, because MachineCSE won't combine COPY instructions,
10257 // so we will end up with redundant moves to m0.
10258 //
10259 // We use a pseudo to ensure we emit s_mov_b32 with m0 as the direct result.
10260
10261 // A Null SDValue creates a glue result.
10262 SDNode *M0 = DAG.getMachineNode(AMDGPU::SI_INIT_M0, DL, MVT::Other, MVT::Glue,
10263 V, Chain);
10264 return SDValue(M0, 0);
10265}
10266
10267SDValue SITargetLowering::lowerImplicitZextParam(SelectionDAG &DAG, SDValue Op,
10268 MVT VT,
10269 unsigned Offset) const {
10270 SDLoc SL(Op);
10271 SDValue Param = lowerKernargMemParameter(
10272 DAG, MVT::i32, MVT::i32, SL, DAG.getEntryNode(), Offset, Align(4), false);
10273 // The local size values will have the hi 16-bits as zero.
10274 return DAG.getNode(ISD::AssertZext, SL, MVT::i32, Param,
10275 DAG.getValueType(VT));
10276}
10277
10279 EVT VT) {
10282 "non-hsa intrinsic with hsa target", DL.getDebugLoc()));
10283 return DAG.getPOISON(VT);
10284}
10285
10287 EVT VT) {
10290 "intrinsic not supported on subtarget", DL.getDebugLoc()));
10291 return DAG.getPOISON(VT);
10292}
10293
10295 ArrayRef<SDValue> Elts) {
10296 assert(!Elts.empty());
10297 MVT Type;
10298 unsigned NumElts = Elts.size();
10299
10300 if (NumElts <= 12) {
10301 Type = MVT::getVectorVT(MVT::f32, NumElts);
10302 } else {
10303 assert(Elts.size() <= 16);
10304 Type = MVT::v16f32;
10305 NumElts = 16;
10306 }
10307
10308 SmallVector<SDValue, 16> VecElts(NumElts);
10309 for (unsigned i = 0; i < Elts.size(); ++i) {
10310 SDValue Elt = Elts[i];
10311 if (Elt.getValueType() != MVT::f32)
10312 Elt = DAG.getBitcast(MVT::f32, Elt);
10313 VecElts[i] = Elt;
10314 }
10315 for (unsigned i = Elts.size(); i < NumElts; ++i)
10316 VecElts[i] = DAG.getPOISON(MVT::f32);
10317
10318 if (NumElts == 1)
10319 return VecElts[0];
10320 return DAG.getBuildVector(Type, DL, VecElts);
10321}
10322
10323static SDValue padEltsToUndef(SelectionDAG &DAG, const SDLoc &DL, EVT CastVT,
10324 SDValue Src, int ExtraElts) {
10325 EVT SrcVT = Src.getValueType();
10326
10328
10329 if (SrcVT.isVector())
10330 DAG.ExtractVectorElements(Src, Elts);
10331 else
10332 Elts.push_back(Src);
10333
10334 SDValue Undef = DAG.getPOISON(SrcVT.getScalarType());
10335 while (ExtraElts--)
10336 Elts.push_back(Undef);
10337
10338 return DAG.getBuildVector(CastVT, DL, Elts);
10339}
10340
10341// Re-construct the required return value for a image load intrinsic.
10342// This is more complicated due to the optional use TexFailCtrl which means the
10343// required return type is an aggregate
10345 ArrayRef<EVT> ResultTypes, bool IsTexFail,
10346 bool Unpacked, bool IsD16, int DMaskPop,
10347 int NumVDataDwords, bool IsAtomicPacked16Bit,
10348 const SDLoc &DL) {
10349 // Determine the required return type. This is the same regardless of
10350 // IsTexFail flag
10351 EVT ReqRetVT = ResultTypes[0];
10352 int ReqRetNumElts = ReqRetVT.isVector() ? ReqRetVT.getVectorNumElements() : 1;
10353 int NumDataDwords = ((IsD16 && !Unpacked) || IsAtomicPacked16Bit)
10354 ? (ReqRetNumElts + 1) / 2
10355 : ReqRetNumElts;
10356
10357 int MaskPopDwords = (!IsD16 || Unpacked) ? DMaskPop : (DMaskPop + 1) / 2;
10358
10359 MVT DataDwordVT =
10360 NumDataDwords == 1 ? MVT::i32 : MVT::getVectorVT(MVT::i32, NumDataDwords);
10361
10362 MVT MaskPopVT =
10363 MaskPopDwords == 1 ? MVT::i32 : MVT::getVectorVT(MVT::i32, MaskPopDwords);
10364
10365 SDValue Data(Result, 0);
10366 SDValue TexFail;
10367
10368 if (DMaskPop > 0 && Data.getValueType() != MaskPopVT) {
10369 SDValue ZeroIdx = DAG.getConstant(0, DL, MVT::i32);
10370 if (MaskPopVT.isVector()) {
10371 Data = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, MaskPopVT,
10372 SDValue(Result, 0), ZeroIdx);
10373 } else {
10374 Data = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MaskPopVT,
10375 SDValue(Result, 0), ZeroIdx);
10376 }
10377 }
10378
10379 if (DataDwordVT.isVector() && !IsAtomicPacked16Bit)
10380 Data = padEltsToUndef(DAG, DL, DataDwordVT, Data,
10381 NumDataDwords - MaskPopDwords);
10382
10383 if (IsD16)
10384 Data = adjustLoadValueTypeImpl(Data, ReqRetVT, DL, DAG, Unpacked);
10385
10386 EVT LegalReqRetVT = ReqRetVT;
10387 if (!ReqRetVT.isVector()) {
10388 if (!Data.getValueType().isInteger())
10389 Data = DAG.getNode(ISD::BITCAST, DL,
10390 Data.getValueType().changeTypeToInteger(), Data);
10391 Data = DAG.getNode(ISD::TRUNCATE, DL, ReqRetVT.changeTypeToInteger(), Data);
10392 } else {
10393 // We need to widen the return vector to a legal type
10394 if ((ReqRetVT.getVectorNumElements() % 2) == 1 &&
10395 ReqRetVT.getVectorElementType().getSizeInBits() == 16) {
10396 LegalReqRetVT =
10398 ReqRetVT.getVectorNumElements() + 1);
10399 }
10400 }
10401 Data = DAG.getNode(ISD::BITCAST, DL, LegalReqRetVT, Data);
10402
10403 if (IsTexFail) {
10404 TexFail =
10405 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, SDValue(Result, 0),
10406 DAG.getConstant(MaskPopDwords, DL, MVT::i32));
10407
10408 return DAG.getMergeValues({Data, TexFail, SDValue(Result, 1)}, DL);
10409 }
10410
10411 if (Result->getNumValues() == 1)
10412 return Data;
10413
10414 return DAG.getMergeValues({Data, SDValue(Result, 1)}, DL);
10415}
10416
10417static bool parseTexFail(SDValue TexFailCtrl, SelectionDAG &DAG, SDValue *TFE,
10418 SDValue *LWE, bool &IsTexFail) {
10419 auto *TexFailCtrlConst = cast<ConstantSDNode>(TexFailCtrl.getNode());
10420
10421 uint64_t Value = TexFailCtrlConst->getZExtValue();
10422 if (Value) {
10423 IsTexFail = true;
10424 }
10425
10426 SDLoc DL(TexFailCtrlConst);
10427 *TFE = DAG.getTargetConstant((Value & 0x1) ? 1 : 0, DL, MVT::i32);
10428 Value &= ~(uint64_t)0x1;
10429 *LWE = DAG.getTargetConstant((Value & 0x2) ? 1 : 0, DL, MVT::i32);
10430 Value &= ~(uint64_t)0x2;
10431
10432 return Value == 0;
10433}
10434
10436 MVT PackVectorVT,
10437 SmallVectorImpl<SDValue> &PackedAddrs,
10438 unsigned DimIdx, unsigned EndIdx,
10439 unsigned NumGradients) {
10440 SDLoc DL(Op);
10441 for (unsigned I = DimIdx; I < EndIdx; I++) {
10442 SDValue Addr = Op.getOperand(I);
10443
10444 // Gradients are packed with undef for each coordinate.
10445 // In <hi 16 bit>,<lo 16 bit> notation, the registers look like this:
10446 // 1D: undef,dx/dh; undef,dx/dv
10447 // 2D: dy/dh,dx/dh; dy/dv,dx/dv
10448 // 3D: dy/dh,dx/dh; undef,dz/dh; dy/dv,dx/dv; undef,dz/dv
10449 if (((I + 1) >= EndIdx) ||
10450 ((NumGradients / 2) % 2 == 1 && (I == DimIdx + (NumGradients / 2) - 1 ||
10451 I == DimIdx + NumGradients - 1))) {
10452 if (Addr.getValueType() != MVT::i16)
10453 Addr = DAG.getBitcast(MVT::i16, Addr);
10454 Addr = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Addr);
10455 } else {
10456 Addr = DAG.getBuildVector(PackVectorVT, DL, {Addr, Op.getOperand(I + 1)});
10457 I++;
10458 }
10459 Addr = DAG.getBitcast(MVT::f32, Addr);
10460 PackedAddrs.push_back(Addr);
10461 }
10462}
10463
10464/// Emit a DiagnosticInfoUnsupported for an unsupported image intrinsic and
10465/// return poison values of \p ResultTypes, preserving the chain if present.
10467 ArrayRef<EVT> ResultTypes,
10468 const SDLoc &DL, const Twine &Msg) {
10470 DAG.getMachineFunction().getFunction(), Msg, DL.getDebugLoc()));
10471 return DAG.getErrorMergeValues(ResultTypes, Op.getOperand(0), DL);
10472}
10473
10474SDValue SITargetLowering::lowerImage(SDValue Op,
10476 SelectionDAG &DAG, bool WithChain) const {
10477 SDLoc DL(Op);
10479 const GCNSubtarget *ST = &MF.getSubtarget<GCNSubtarget>();
10480 unsigned IntrOpcode = Intr->BaseOpcode;
10481 // For image atomic: use no-return opcode if result is unused.
10482 if (Intr->AtomicNoRetBaseOpcode != Intr->BaseOpcode &&
10483 !Op.getNode()->hasAnyUseOfValue(0))
10484 IntrOpcode = Intr->AtomicNoRetBaseOpcode;
10485 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
10487 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfo(Intr->Dim);
10488 bool IsGFX10Plus = AMDGPU::isGFX10Plus(*Subtarget);
10489 bool IsGFX11Plus = AMDGPU::isGFX11Plus(*Subtarget);
10490 bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
10491 bool IsGFX13 = AMDGPU::isGFX13(*Subtarget);
10492
10493 SmallVector<EVT, 3> ResultTypes(Op->values());
10494 SmallVector<EVT, 3> OrigResultTypes(Op->values());
10495 if (BaseOpcode->NoReturn && BaseOpcode->Atomic)
10496 ResultTypes.erase(&ResultTypes[0]);
10497
10498 bool IsD16 = false;
10499 bool IsG16 = false;
10500 bool IsA16 = false;
10501 SDValue VData;
10502 int NumVDataDwords = 0;
10503 bool AdjustRetType = false;
10504 bool IsAtomicPacked16Bit = false;
10505
10506 // Offset of intrinsic arguments
10507 const unsigned ArgOffset = WithChain ? 2 : 1;
10508
10509 unsigned DMask;
10510 unsigned DMaskLanes = 0;
10511
10512 if (BaseOpcode->Atomic) {
10513 VData = Op.getOperand(2);
10514
10515 IsAtomicPacked16Bit =
10516 (IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
10517 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16_NORTN ||
10518 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16 ||
10519 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16_NORTN);
10520
10521 if (!IsAtomicPacked16Bit && VData.getValueSizeInBits() != 32 &&
10522 VData.getValueSizeInBits() != 64) {
10523 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10524 "unsupported image atomic data type");
10525 }
10526
10527 bool Is64Bit = VData.getValueSizeInBits() == 64;
10528 if (BaseOpcode->AtomicX2) {
10529 SDValue VData2 = Op.getOperand(3);
10530 VData = DAG.getBuildVector(Is64Bit ? MVT::v2i64 : MVT::v2i32, DL,
10531 {VData, VData2});
10532 if (Is64Bit)
10533 VData = DAG.getBitcast(MVT::v4i32, VData);
10534
10535 if (!BaseOpcode->NoReturn)
10536 ResultTypes[0] = Is64Bit ? MVT::v2i64 : MVT::v2i32;
10537
10538 DMask = Is64Bit ? 0xf : 0x3;
10539 NumVDataDwords = Is64Bit ? 4 : 2;
10540 } else {
10541 DMask = Is64Bit ? 0x3 : 0x1;
10542 NumVDataDwords = Is64Bit ? 2 : 1;
10543 }
10544 } else {
10545 DMask = Op->getConstantOperandVal(ArgOffset + Intr->DMaskIndex);
10546 DMaskLanes = BaseOpcode->Gather4 ? 4 : llvm::popcount(DMask);
10547
10548 if (BaseOpcode->Store) {
10549 VData = Op.getOperand(2);
10550
10551 MVT StoreVT = VData.getSimpleValueType();
10552 MVT StoreScalarVT = StoreVT.getScalarType();
10553 if (StoreScalarVT != MVT::f16 && StoreScalarVT.getSizeInBits() != 32 &&
10554 StoreScalarVT.getSizeInBits() != 64) {
10555 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10556 "unsupported image store data type");
10557 }
10558 if (StoreScalarVT == MVT::f16) {
10559 if (!Subtarget->hasD16Images() || !BaseOpcode->HasD16)
10560 return Op; // D16 is unsupported for this instruction
10561
10562 IsD16 = true;
10563 VData = handleD16VData(VData, DAG, true);
10564 }
10565
10566 NumVDataDwords = (VData.getValueType().getSizeInBits() + 31) / 32;
10567 } else if (!BaseOpcode->NoReturn) {
10568 // Work out the num dwords based on the dmask popcount and underlying type
10569 // and whether packing is supported.
10570 MVT LoadVT = ResultTypes[0].getSimpleVT();
10571 MVT LoadScalarVT = LoadVT.getScalarType();
10572 if (LoadScalarVT != MVT::f16 && LoadScalarVT.getSizeInBits() != 32 &&
10573 LoadScalarVT.getSizeInBits() != 64) {
10574 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10575 "unsupported image load data type");
10576 }
10577 if (LoadScalarVT == MVT::f16) {
10578 if (!Subtarget->hasD16Images() || !BaseOpcode->HasD16)
10579 return Op; // D16 is unsupported for this instruction
10580
10581 IsD16 = true;
10582 }
10583
10584 // Confirm that the return type is large enough for the dmask specified
10585 if ((LoadVT.isVector() && LoadVT.getVectorNumElements() < DMaskLanes) ||
10586 (!LoadVT.isVector() && DMaskLanes > 1))
10587 return Op;
10588
10589 // The sq block of gfx8 and gfx9 do not estimate register use correctly
10590 // for d16 image_gather4, image_gather4_l, and image_gather4_lz
10591 // instructions.
10592 if (IsD16 && !Subtarget->hasUnpackedD16VMem() &&
10593 !(BaseOpcode->Gather4 && Subtarget->hasImageGather4D16Bug()))
10594 NumVDataDwords = (DMaskLanes + 1) / 2;
10595 else
10596 NumVDataDwords = DMaskLanes;
10597
10598 AdjustRetType = true;
10599 }
10600 }
10601
10602 unsigned VAddrEnd = ArgOffset + Intr->VAddrEnd;
10604
10605 // Check for 16 bit addresses or derivatives and pack if true.
10606 MVT VAddrVT =
10607 Op.getOperand(ArgOffset + Intr->GradientStart).getSimpleValueType();
10608 MVT VAddrScalarVT = VAddrVT.getScalarType();
10609 MVT GradPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10610 IsG16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10611
10612 VAddrVT = Op.getOperand(ArgOffset + Intr->CoordStart).getSimpleValueType();
10613 VAddrScalarVT = VAddrVT.getScalarType();
10614 MVT AddrPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10615 IsA16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10616
10617 // Push back extra arguments.
10618 for (unsigned I = Intr->VAddrStart; I < Intr->GradientStart; I++) {
10619 if (IsA16 && (Op.getOperand(ArgOffset + I).getValueType() == MVT::f16)) {
10620 assert(I == Intr->BiasIndex && "Got unexpected 16-bit extra argument");
10621 // Special handling of bias when A16 is on. Bias is of type half but
10622 // occupies full 32-bit.
10623 SDValue Bias = DAG.getBuildVector(
10624 MVT::v2f16, DL,
10625 {Op.getOperand(ArgOffset + I), DAG.getPOISON(MVT::f16)});
10626 VAddrs.push_back(Bias);
10627 } else {
10628 assert((!IsA16 || Intr->NumBiasArgs == 0 || I != Intr->BiasIndex) &&
10629 "Bias needs to be converted to 16 bit in A16 mode");
10630 VAddrs.push_back(Op.getOperand(ArgOffset + I));
10631 }
10632 }
10633
10634 if (BaseOpcode->Gradients && !ST->hasG16() && (IsA16 != IsG16)) {
10635 // 16 bit gradients are supported, but are tied to the A16 control
10636 // so both gradients and addresses must be 16 bit
10637 LLVM_DEBUG(
10638 dbgs() << "Failed to lower image intrinsic: 16 bit addresses "
10639 "require 16 bit args for both gradients and addresses");
10640 return Op;
10641 }
10642
10643 if (IsA16) {
10644 if (!ST->hasA16()) {
10645 LLVM_DEBUG(dbgs() << "Failed to lower image intrinsic: Target does not "
10646 "support 16 bit addresses\n");
10647 return Op;
10648 }
10649 }
10650
10651 // We've dealt with incorrect input so we know that if IsA16, IsG16
10652 // are set then we have to compress/pack operands (either address,
10653 // gradient or both)
10654 // In the case where a16 and gradients are tied (no G16 support) then we
10655 // have already verified that both IsA16 and IsG16 are true
10656 if (BaseOpcode->Gradients && IsG16 && ST->hasG16()) {
10657 // Activate g16
10658 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
10660 IntrOpcode = G16MappingInfo->G16; // set new opcode to variant with _g16
10661 }
10662
10663 // Add gradients (packed or unpacked)
10664 if (IsG16) {
10665 // Pack the gradients
10666 // const int PackEndIdx = IsA16 ? VAddrEnd : (ArgOffset + Intr->CoordStart);
10667 packImage16bitOpsToDwords(DAG, Op, GradPackVectorVT, VAddrs,
10668 ArgOffset + Intr->GradientStart,
10669 ArgOffset + Intr->CoordStart, Intr->NumGradients);
10670 } else {
10671 for (unsigned I = ArgOffset + Intr->GradientStart;
10672 I < ArgOffset + Intr->CoordStart; I++)
10673 VAddrs.push_back(Op.getOperand(I));
10674 }
10675
10676 // Add addresses (packed or unpacked)
10677 if (IsA16) {
10678 packImage16bitOpsToDwords(DAG, Op, AddrPackVectorVT, VAddrs,
10679 ArgOffset + Intr->CoordStart, VAddrEnd,
10680 0 /* No gradients */);
10681 } else {
10682 // Add uncompressed address
10683 for (unsigned I = ArgOffset + Intr->CoordStart; I < VAddrEnd; I++)
10684 VAddrs.push_back(Op.getOperand(I));
10685 }
10686
10687 // If the register allocator cannot place the address registers contiguously
10688 // without introducing moves, then using the non-sequential address encoding
10689 // is always preferable, since it saves VALU instructions and is usually a
10690 // wash in terms of code size or even better.
10691 //
10692 // However, we currently have no way of hinting to the register allocator that
10693 // MIMG addresses should be placed contiguously when it is possible to do so,
10694 // so force non-NSA for the common 2-address case as a heuristic.
10695 //
10696 // SIShrinkInstructions will convert NSA encodings to non-NSA after register
10697 // allocation when possible.
10698 //
10699 // Partial NSA is allowed on GFX11+ where the final register is a contiguous
10700 // set of the remaining addresses.
10701 const unsigned NSAMaxSize = ST->getNSAMaxSize(BaseOpcode->Sampler);
10702 const bool HasPartialNSAEncoding = ST->hasPartialNSAEncoding();
10703 const bool UseNSA = ST->hasNSAEncoding() &&
10704 VAddrs.size() >= ST->getNSAThreshold(MF) &&
10705 (VAddrs.size() <= NSAMaxSize || HasPartialNSAEncoding);
10706 const bool UsePartialNSA =
10707 UseNSA && HasPartialNSAEncoding && VAddrs.size() > NSAMaxSize;
10708
10709 SDValue VAddr;
10710 if (UsePartialNSA) {
10711 VAddr = getBuildDwordsVector(DAG, DL,
10712 ArrayRef(VAddrs).drop_front(NSAMaxSize - 1));
10713 } else if (!UseNSA) {
10714 VAddr = getBuildDwordsVector(DAG, DL, VAddrs);
10715 }
10716
10717 SDValue True = DAG.getTargetConstant(1, DL, MVT::i1);
10718 SDValue False = DAG.getTargetConstant(0, DL, MVT::i1);
10719 SDValue Unorm;
10720 if (!BaseOpcode->Sampler) {
10721 Unorm = True;
10722 } else {
10723 uint64_t UnormConst =
10724 Op.getConstantOperandVal(ArgOffset + Intr->UnormIndex);
10725
10726 Unorm = UnormConst ? True : False;
10727 }
10728
10729 SDValue TFE;
10730 SDValue LWE;
10731 SDValue TexFail = Op.getOperand(ArgOffset + Intr->TexFailCtrlIndex);
10732 bool IsTexFail = false;
10733 if (!parseTexFail(TexFail, DAG, &TFE, &LWE, IsTexFail))
10734 return Op;
10735
10736 if (IsTexFail) {
10737 if (!DMaskLanes) {
10738 // Expecting to get an error flag since TFC is on - and dmask is 0
10739 // Force dmask to be at least 1 otherwise the instruction will fail
10740 DMask = 0x1;
10741 DMaskLanes = 1;
10742 NumVDataDwords = 1;
10743 }
10744 NumVDataDwords += 1;
10745 AdjustRetType = true;
10746 }
10747
10748 // Has something earlier tagged that the return type needs adjusting
10749 // This happens if the instruction is a load or has set TexFailCtrl flags
10750 if (AdjustRetType) {
10751 // NumVDataDwords reflects the true number of dwords required in the return
10752 // type
10753 if (DMaskLanes == 0 && !BaseOpcode->Store) {
10754 // This is a no-op load. This can be eliminated
10755 SDValue Undef = DAG.getPOISON(Op.getValueType());
10756 if (isa<MemSDNode>(Op))
10757 return DAG.getMergeValues({Undef, Op.getOperand(0)}, DL);
10758 return Undef;
10759 }
10760
10761 EVT NewVT = NumVDataDwords > 1 ? EVT::getVectorVT(*DAG.getContext(),
10762 MVT::i32, NumVDataDwords)
10763 : MVT::i32;
10764
10765 ResultTypes[0] = NewVT;
10766 if (ResultTypes.size() == 3) {
10767 // Original result was aggregate type used for TexFailCtrl results
10768 // The actual instruction returns as a vector type which has now been
10769 // created. Remove the aggregate result.
10770 ResultTypes.erase(&ResultTypes[1]);
10771 }
10772 }
10773
10774 unsigned CPol = Op.getConstantOperandVal(ArgOffset + Intr->CachePolicyIndex);
10775 // Keep GLC only when the atomic's result is actually used.
10776 if (BaseOpcode->Atomic && !BaseOpcode->NoReturn)
10778 if (CPol & ~((IsGFX12Plus ? AMDGPU::CPol::ALL : AMDGPU::CPol::ALL_pregfx12) |
10780 return Op;
10781
10783 if (BaseOpcode->Store || BaseOpcode->Atomic)
10784 Ops.push_back(VData); // vdata
10785 if (UsePartialNSA) {
10786 append_range(Ops, ArrayRef(VAddrs).take_front(NSAMaxSize - 1));
10787 Ops.push_back(VAddr);
10788 } else if (UseNSA)
10789 append_range(Ops, VAddrs);
10790 else
10791 Ops.push_back(VAddr);
10792 SDValue Rsrc = Op.getOperand(ArgOffset + Intr->RsrcIndex);
10793 EVT RsrcVT = Rsrc.getValueType();
10794 bool IndexedRsrc = IsGFX13 && RsrcVT == MVT::i32;
10795 if (RsrcVT != MVT::v4i32 && RsrcVT != MVT::v8i32 && !IndexedRsrc)
10796 return Op;
10797 Ops.push_back(Rsrc);
10798 bool IsSampIndexed = false;
10799 if (BaseOpcode->Sampler) {
10800 SDValue Samp = Op.getOperand(ArgOffset + Intr->SampIndex);
10801 EVT SampVT = Samp.getValueType();
10802 IsSampIndexed = IsGFX13 && SampVT == MVT::i32;
10803 if (SampVT != MVT::v4i32 && !IsSampIndexed)
10804 return Op;
10805 Ops.push_back(Samp);
10806 }
10807 Ops.push_back(DAG.getTargetConstant(DMask, DL, MVT::i32));
10808 if (IsGFX10Plus)
10809 Ops.push_back(DAG.getTargetConstant(DimInfo->Encoding, DL, MVT::i32));
10810 if (!IsGFX12Plus || BaseOpcode->Sampler || BaseOpcode->MSAA)
10811 Ops.push_back(Unorm);
10812 Ops.push_back(DAG.getTargetConstant(CPol, DL, MVT::i32));
10813 Ops.push_back(IsA16 && // r128, a16 for gfx9
10814 ST->hasFeature(AMDGPU::FeatureR128A16)
10815 ? True
10816 : False);
10817 if (IsGFX10Plus)
10818 Ops.push_back(IsA16 ? True : False);
10819
10820 if (!Subtarget->hasGFX90AInsts())
10821 Ops.push_back(TFE); // tfe
10822 else if (TFE->getAsZExtVal()) {
10823 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10825 "TFE is not supported on this GPU", DL.getDebugLoc()));
10826 }
10827
10828 if (!IsGFX12Plus || BaseOpcode->Sampler || BaseOpcode->MSAA)
10829 Ops.push_back(LWE); // lwe
10830 if (!IsGFX10Plus)
10831 Ops.push_back(DimInfo->DA ? True : False);
10832 if (BaseOpcode->HasD16)
10833 Ops.push_back(IsD16 ? True : False);
10834 if (isa<MemSDNode>(Op))
10835 Ops.push_back(Op.getOperand(0)); // chain
10836
10837 int NumVAddrDwords =
10838 UseNSA ? VAddrs.size() : VAddr.getValueType().getSizeInBits() / 32;
10839 int Opcode = -1;
10840
10841 if (IsGFX13) {
10842 Opcode =
10843 AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx13, NumVDataDwords,
10844 NumVAddrDwords, IndexedRsrc, IsSampIndexed);
10845 } else if (IsGFX12Plus) {
10846 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx12,
10847 NumVDataDwords, NumVAddrDwords);
10848 } else if (IsGFX11Plus) {
10849 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
10850 UseNSA ? AMDGPU::MIMGEncGfx11NSA
10851 : AMDGPU::MIMGEncGfx11Default,
10852 NumVDataDwords, NumVAddrDwords);
10853 } else if (IsGFX10Plus) {
10854 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
10855 UseNSA ? AMDGPU::MIMGEncGfx10NSA
10856 : AMDGPU::MIMGEncGfx10Default,
10857 NumVDataDwords, NumVAddrDwords);
10858 } else {
10859 if (Subtarget->hasGFX90AInsts()) {
10860 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx90a,
10861 NumVDataDwords, NumVAddrDwords);
10862 if (Opcode == -1) {
10864 DAG, Op, OrigResultTypes, DL,
10865 "requested image instruction is not supported on this GPU");
10866 }
10867 }
10868 if (Opcode == -1 &&
10869 Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10870 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx8,
10871 NumVDataDwords, NumVAddrDwords);
10872 if (Opcode == -1)
10873 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx6,
10874 NumVDataDwords, NumVAddrDwords);
10875 }
10876 if (Opcode == -1)
10877 return Op;
10878
10879 MachineSDNode *NewNode = DAG.getMachineNode(Opcode, DL, ResultTypes, Ops);
10880 if (auto *MemOp = dyn_cast<MemSDNode>(Op)) {
10881 MachineMemOperand *MemRef = MemOp->getMemOperand();
10882 DAG.setNodeMemRefs(NewNode, {MemRef});
10883 }
10884
10885 if (BaseOpcode->NoReturn) {
10886 if (BaseOpcode->Atomic)
10887 return DAG.getMergeValues(
10888 {DAG.getPOISON(OrigResultTypes[0]), SDValue(NewNode, 0)}, DL);
10889
10890 return SDValue(NewNode, 0);
10891 }
10892
10893 if (BaseOpcode->AtomicX2) {
10895 DAG.ExtractVectorElements(SDValue(NewNode, 0), Elt, 0, 1);
10896 return DAG.getMergeValues({Elt[0], SDValue(NewNode, 1)}, DL);
10897 }
10898
10899 return constructRetValue(DAG, NewNode, OrigResultTypes, IsTexFail,
10900 Subtarget->hasUnpackedD16VMem(), IsD16, DMaskLanes,
10901 NumVDataDwords, IsAtomicPacked16Bit, DL);
10902}
10903
10904SDValue SITargetLowering::lowerSBuffer(EVT VT, EVT MemVT, SDLoc DL,
10905 SDValue Chain, SDValue Rsrc,
10906 SDValue Offset, SDValue CachePolicy,
10907 SelectionDAG &DAG,
10908 MachineMemOperand *MMO) const {
10910 bool HasChainResult = MMO != nullptr;
10911
10912 // SBUFFER_LOAD only produces values that fill whole SGPRs, apart from the
10913 // subword loads below.
10914 bool IsSubwordLoad = (MemVT == MVT::i8 || MemVT == MVT::i16) &&
10915 Subtarget->hasScalarSubwordLoads();
10916 if ((!isTypeLegal(VT) || VT.getSizeInBits() % 32 != 0) && !IsSubwordLoad) {
10917 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10918 MF.getFunction(), "unsupported s_buffer_load result type",
10919 DL.getDebugLoc()));
10920 EVT ResultTypes[] = {VT, MVT::Other};
10921 return DAG.getErrorMergeValues(
10922 ArrayRef(ResultTypes, HasChainResult ? 2 : 1), Chain, DL);
10923 }
10924
10925 if (!HasChainResult) {
10926 const DataLayout &DataLayout = DAG.getDataLayout();
10928 DataLayout.getABITypeAlign(MemVT.getTypeForEVT(*DAG.getContext()));
10929
10930 MMO = MF.getMachineMemOperand(MachinePointerInfo(),
10934 MemVT.getStoreSize(), Alignment);
10935 }
10936
10937 if (!Offset->isDivergent()) {
10938 SDValue Ops[] = {Chain, Rsrc, Offset, CachePolicy};
10939
10940 // Lower llvm.amdgcn.*s.buffer.load.{i,u}N intrinsics. First, generate
10941 // s_buffer_load_u* for signed and unsigned load instructions. Next, DAG
10942 // combiner tries to merge the s_buffer_load_uN with a sext instruction
10943 // (performSignExtendInRegCombine()) and it replaces s_buffer_load_uN with
10944 // s_buffer_load_iN.
10945 auto HandleScalarSubwordLoads = [&](unsigned Opcode) -> SDValue {
10946 SDValue BufferLoad = DAG.getMemIntrinsicNode(
10947 Opcode, DL, DAG.getVTList(MVT::i32, MVT::Other), Ops, MemVT, MMO);
10948 SDValue LoadVal = DAG.getAnyExtOrTrunc(
10949 DAG.getNode(ISD::TRUNCATE, DL, MemVT, BufferLoad), DL, VT);
10950 if (HasChainResult)
10951 return DAG.getMergeValues({LoadVal, BufferLoad.getValue(1)}, DL);
10952 return LoadVal;
10953 };
10954 if (MemVT == MVT::i8 && Subtarget->hasScalarSubwordLoads())
10955 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_UBYTE);
10956
10957 if (MemVT == MVT::i16 && Subtarget->hasScalarSubwordLoads())
10958 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_USHORT);
10959
10960 // Widen vec3 load to vec4. Only 32-bit elements have a vec4 pattern.
10961 if (VT.isVector() && VT.getVectorNumElements() == 3 &&
10962 VT.getVectorElementType().getSizeInBits() == 32 &&
10963 !Subtarget->hasScalarDwordx3Loads()) {
10964 EVT WidenedVT =
10966 auto WidenedOp = DAG.getMemIntrinsicNode(
10967 AMDGPUISD::SBUFFER_LOAD, DL, DAG.getVTList(WidenedVT, MVT::Other),
10968 Ops, WidenedVT,
10969 MF.getMachineMemOperand(MMO, 0, WidenedVT.getStoreSize()));
10970 auto Subvector = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, WidenedOp,
10971 DAG.getVectorIdxConstant(0, DL));
10972 if (HasChainResult)
10973 return DAG.getMergeValues({Subvector, WidenedOp.getValue(1)}, DL);
10974 return Subvector;
10975 }
10976
10977 return DAG.getMemIntrinsicNode(AMDGPUISD::SBUFFER_LOAD, DL,
10978 DAG.getVTList(VT, MVT::Other), Ops, MemVT,
10979 MMO);
10980 }
10981
10982 // We have a divergent offset. Emit a MUBUF buffer load instead. We can
10983 // assume that the buffer is unswizzled.
10984 SDValue Ops[] = {
10985 Chain, // Chain
10986 Rsrc, // rsrc
10987 DAG.getConstant(0, DL, MVT::i32), // vindex
10988 {}, // voffset
10989 {}, // soffset
10990 {}, // offset
10991 CachePolicy, // cachepolicy
10992 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
10993 };
10994 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
10995 Subtarget->hasScalarSubwordLoads()) {
10996 setBufferOffsets(Offset, DAG, &Ops[3], Align(4));
10997 SDValue Load = handleByteShortBufferLoads(DAG, MemVT, DL, Ops, MMO);
10998 SDValue LoadVal = DAG.getAnyExtOrTrunc(Load.getOperand(0), DL, VT);
10999 if (HasChainResult)
11000 return DAG.getMergeValues({LoadVal, Load.getOperand(1)}, DL);
11001 return LoadVal;
11002 }
11003
11005 unsigned NumLoads = 1;
11006 MVT LoadVT = VT.getSimpleVT();
11007 unsigned NumElts = LoadVT.isVector() ? LoadVT.getVectorNumElements() : 1;
11008 assert((LoadVT.getScalarType() == MVT::i32 ||
11009 LoadVT.getScalarType() == MVT::f32));
11010
11011 if (NumElts == 8 || NumElts == 16) {
11012 NumLoads = NumElts / 4;
11013 LoadVT = MVT::getVectorVT(LoadVT.getScalarType(), 4);
11014 }
11015
11016 SDVTList VTList = DAG.getVTList({LoadVT, MVT::Other});
11017
11018 // Use the alignment to ensure that the required offsets will fit into the
11019 // immediate offsets.
11020 setBufferOffsets(Offset, DAG, &Ops[3],
11021 NumLoads > 1 ? Align(16 * NumLoads) : Align(4));
11022
11023 uint64_t InstOffset = Ops[5]->getAsZExtVal();
11024 unsigned LoadSize = LoadVT.getStoreSize();
11025 for (unsigned i = 0; i < NumLoads; ++i) {
11026 Ops[5] = DAG.getTargetConstant(InstOffset + 16 * i, DL, MVT::i32);
11027 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(MMO, 16 * i, LoadSize);
11028 Loads.push_back(getMemIntrinsicNode(AMDGPUISD::BUFFER_LOAD, DL, VTList, Ops,
11029 LoadVT, LoadMMO, DAG));
11030 }
11031
11032 if (NumElts == 8 || NumElts == 16) {
11033 SDValue LoadVal = DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Loads);
11034 if (HasChainResult) {
11035 SmallVector<SDValue, 4> LoadChains;
11036 for (SDValue Load : Loads)
11037 LoadChains.push_back(Load.getValue(1));
11038 SDValue Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, LoadChains);
11039 return DAG.getMergeValues({LoadVal, Chain}, DL);
11040 }
11041 return LoadVal;
11042 }
11043
11044 return Loads[0];
11045}
11046
11047SDValue SITargetLowering::lowerWaveID(SelectionDAG &DAG, SDValue Op) const {
11048 // With architected SGPRs, waveIDinGroup is in TTMP8[29:25].
11049 if (!Subtarget->hasArchitectedSGPRs())
11050 return {};
11051 SDLoc SL(Op);
11052 MVT VT = MVT::i32;
11053 SDValue TTMP8 = DAG.getCopyFromReg(DAG.getEntryNode(), SL, AMDGPU::TTMP8, VT);
11054 return DAG.getNode(AMDGPUISD::BFE_U32, SL, VT, TTMP8,
11055 DAG.getConstant(25, SL, VT), DAG.getConstant(5, SL, VT));
11056}
11057
11058SDValue SITargetLowering::lowerConstHwRegRead(SelectionDAG &DAG, SDValue Op,
11059 AMDGPU::Hwreg::Id HwReg,
11060 unsigned LowBit,
11061 unsigned Width) const {
11062 SDLoc SL(Op);
11063 using namespace AMDGPU::Hwreg;
11064 return {DAG.getMachineNode(
11065 AMDGPU::S_GETREG_B32_const, SL, MVT::i32,
11066 DAG.getTargetConstant(HwregEncoding::encode(HwReg, LowBit, Width),
11067 SL, MVT::i32)),
11068 0};
11069}
11070
11071SDValue SITargetLowering::lowerWorkitemID(SelectionDAG &DAG, SDValue Op,
11072 unsigned Dim,
11073 const ArgDescriptor &Arg) const {
11074 SDLoc SL(Op);
11076 unsigned MaxID = Subtarget->getMaxWorkitemID(MF.getFunction(), Dim);
11077 if (MaxID == 0)
11078 return DAG.getConstant(0, SL, MVT::i32);
11079
11080 // It's undefined behavior if a function marked with the amdgpu-no-*
11081 // attributes uses the corresponding intrinsic.
11082 if (!Arg)
11083 return DAG.getPOISON(Op->getValueType(0));
11084
11085 SDValue Val = loadInputValue(DAG, &AMDGPU::VGPR_32RegClass, MVT::i32,
11086 SDLoc(DAG.getEntryNode()), Arg);
11087
11088 // Don't bother inserting AssertZext for packed IDs since we're emitting the
11089 // masking operations anyway.
11090 //
11091 // TODO: We could assert the top bit is 0 for the source copy.
11092 if (Arg.isMasked())
11093 return Val;
11094
11095 // Preserve the known bits after expansion to a copy.
11096 EVT SmallVT = EVT::getIntegerVT(*DAG.getContext(), llvm::bit_width(MaxID));
11097 return DAG.getNode(ISD::AssertZext, SL, MVT::i32, Val,
11098 DAG.getValueType(SmallVT));
11099}
11100
11101SDValue SITargetLowering::lowerFromFP8(SDValue Op, bool IsBF8,
11102 SelectionDAG &DAG) const {
11103 SDLoc SL(Op);
11104 SDValue Src = Op.getOperand(0);
11105 EVT DstVT = Op.getValueType();
11106 bool IsF16 = DstVT.getVectorElementType() == MVT::f16;
11107 assert((!IsF16 || Subtarget->hasFP8F16ConversionInsts()) &&
11108 "fp8/bf8 -> f16 conversion requires FP8F16ConversionInsts");
11109
11110 unsigned Opc;
11111 if (IsF16)
11112 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F16_BF8 : AMDGPUISD::CVT_PK_F16_FP8;
11113 else
11114 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F32_BF8 : AMDGPUISD::CVT_PK_F32_FP8;
11115
11116 // Pack the two i8 lanes into the integer type the packed HW node reads. The
11117 // f16 form takes i16 and the f32 form takes i32. v2i8 bitcasts to i16
11118 // directly and the f32 node reads the low half of an any-extended i32.
11119 EVT PackedVT =
11121 SDValue AsI16 = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
11122 SDValue Packed = DAG.getAnyExtOrTrunc(AsI16, SL, PackedVT);
11123 return DAG.getNode(Opc, SL, DstVT, Packed);
11124}
11125
11126SDValue
11127SITargetLowering::LowerCONVERT_FROM_ARBITRARY_FP(SDValue Op,
11128 SelectionDAG &DAG) const {
11129 // Handle the OCP FP8 formats (E4M3FN, E5M2) and unsigned E5M3 on subtargets
11130 // with matching HW conversions. Other formats use the generic expansion.
11131 APFloatBase::Semantics FPSemantic =
11132 static_cast<APFloatBase::Semantics>(Op.getConstantOperandVal(1));
11133 const bool IsFP8 = FPSemantic == APFloatBase::S_Float8E4M3FN;
11134 const bool IsBF8 = FPSemantic == APFloatBase::S_Float8E5M2;
11135 const bool IsE5M3 = FPSemantic == APFloatBase::S_Float8E5M3FNU;
11136 const bool HasE5M3ConversionInsts =
11137 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11138 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11139 if (!IsSupported)
11140 return SDValue();
11141
11142 EVT DstVT = Op.getValueType();
11143 // The custom action for a v2i8 source also reaches half conversions on
11144 // targets which only have FP8-to-f32 instructions.
11145 if (DstVT.getScalarType() == MVT::f16 &&
11146 !Subtarget->hasFP8F16ConversionInsts())
11147 return SDValue();
11148
11149 if (IsE5M3) {
11150 if (DstVT.getScalarType() != MVT::f32)
11151 return SDValue();
11152
11153 SDLoc SL(Op);
11154 SDValue Src = Op.getOperand(0);
11155 assert((!DstVT.isVector() || DstVT == MVT::v2f32) &&
11156 "only the v2f32 vector result is custom lowered");
11157
11158 if (DstVT.isVector())
11159 Src = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
11160 Src = DAG.getAnyExtOrTrunc(Src, SL, MVT::i32);
11161
11162 auto ConvertByte = [&](unsigned ByteSel) {
11163 return DAG.getNode(AMDGPUISD::CVT_F32_FP8_E5M3, SL, MVT::f32, Src,
11164 DAG.getTargetConstant(ByteSel, SL, MVT::i32));
11165 };
11166
11167 if (!DstVT.isVector())
11168 return ConvertByte(0);
11169 return DAG.getBuildVector(DstVT, SL, {ConvertByte(0), ConvertByte(1)});
11170 }
11171
11172 if (!DstVT.isVector()) {
11173 SDValue Src = Op.getOperand(0);
11174 if (Src.getValueType() != MVT::i32) {
11175 SDLoc SL(Op);
11176 SDValue SrcI32 = DAG.getAnyExtOrTrunc(Src, SL, MVT::i32);
11177 return DAG.getNode(ISD::CONVERT_FROM_ARBITRARY_FP, SL, DstVT, SrcI32,
11178 Op.getOperand(1));
11179 }
11180 return Op;
11181 }
11182
11183 EVT EltVT = DstVT.getVectorElementType();
11184 if (EltVT == MVT::f16 || EltVT == MVT::f32)
11185 return lowerFromFP8(Op, IsBF8, DAG);
11186 return SDValue();
11187}
11188
11189SDValue SITargetLowering::lowerToFP8(SDValue Op, bool IsBF8, bool IsE5M3,
11190 SelectionDAG &DAG) const {
11191 SDLoc SL(Op);
11192 SDValue Src = Op.getOperand(0);
11193 EVT ResVT = Op.getValueType();
11194 bool IsF16 = Src.getValueType().getScalarType() == MVT::f16;
11195 assert((!IsF16 || Subtarget->hasF16FP8ConversionInsts()) &&
11196 "f16 -> fp8/bf8 conversion requires F16FP8ConversionInsts");
11197 assert((!ResVT.isVector() || ResVT == MVT::v2i8) &&
11198 "only the v2i8 vector result is custom lowered");
11199
11200 if (IsF16) {
11201 unsigned Opc =
11202 IsBF8 ? AMDGPUISD::CVT_PK_BF8_F16 : AMDGPUISD::CVT_PK_FP8_F16;
11203 SDValue Bytes = DAG.getNode(Opc, SL, MVT::i16, Src);
11204 return DAG.getNode(ISD::BITCAST, SL, ResVT, Bytes);
11205 }
11206
11207 unsigned Opc = IsBF8 ? AMDGPUISD::CVT_PK_BF8_F32
11208 : IsE5M3 ? AMDGPUISD::CVT_PK_FP8_F32_E5M3
11209 : AMDGPUISD::CVT_PK_FP8_F32;
11210 SDValue PoisonI32 = DAG.getPOISON(MVT::i32);
11211 SDValue WordSel = DAG.getTargetConstant(0, SL, MVT::i1);
11212
11213 if (!ResVT.isVector()) {
11214 // Convert one lane, the second is unused. Feed it the same source so the
11215 // instruction does not read an undefined register.
11216 SDValue Packed =
11217 DAG.getNode(Opc, SL, MVT::i32, Src, Src, PoisonI32, WordSel);
11218 return DAG.getAnyExtOrTrunc(Packed, SL, ResVT);
11219 }
11220
11221 SDValue A = DAG.getExtractVectorElt(SL, MVT::f32, Src, 0);
11222 SDValue B = DAG.getExtractVectorElt(SL, MVT::f32, Src, 1);
11223 SDValue Packed = DAG.getNode(Opc, SL, MVT::i32, A, B, PoisonI32, WordSel);
11224 SDValue Bytes = DAG.getNode(ISD::TRUNCATE, SL, MVT::i16, Packed);
11225 return DAG.getNode(ISD::BITCAST, SL, ResVT, Bytes);
11226}
11227
11228SDValue
11229SITargetLowering::LowerCONVERT_TO_ARBITRARY_FP(SDValue Op,
11230 SelectionDAG &DAG) const {
11231 // The OCP FP8 formats (E4M3FN, E5M2) and unsigned E5M3 map to HW conversions
11232 // on subtargets that support them. Everything else uses generic expansion.
11234 static_cast<APFloatBase::Semantics>(Op.getConstantOperandVal(1));
11235 const bool IsFP8 = Sem == APFloatBase::S_Float8E4M3FN;
11236 const bool IsBF8 = Sem == APFloatBase::S_Float8E5M2;
11237 const bool IsE5M3 = Sem == APFloatBase::S_Float8E5M3FNU;
11238 const bool HasE5M3ConversionInsts =
11239 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11240 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11241 if (!IsSupported)
11242 return SDValue();
11243
11244 // The HW conversions only support nearest-even. The OCP conversions do not
11245 // saturate. The unsigned E5M3 conversion always clamps out-of-range inputs,
11246 // which also refines the non-saturating form where those inputs are poison.
11247 if (static_cast<RoundingMode>(Op.getConstantOperandVal(2)) !=
11249 return SDValue();
11250 if (!IsE5M3 && Op.getConstantOperandVal(3) != 0)
11251 return SDValue();
11252
11253 EVT SrcEltVT = Op.getOperand(0).getValueType().getScalarType();
11254 // The f32 form is built here rather than by a tablegen pattern because the
11255 // HW result is i32 while the node result is i16 after the i8 promotion.
11256 if (SrcEltVT == MVT::f32)
11257 return lowerToFP8(Op, IsBF8, IsE5M3, DAG);
11258 if (!IsE5M3 && SrcEltVT == MVT::f16 &&
11259 Subtarget->hasF16FP8ConversionInsts()) {
11260 // A scalar conversion is selected from the generic node by tablegen, only
11261 // the illegal v2i8 result type needs lowering here.
11262 if (!Op.getValueType().isVector())
11263 return Op;
11264 return lowerToFP8(Op, IsBF8, false, DAG);
11265 }
11266 return SDValue();
11267}
11268
11269SDValue SITargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
11270 SelectionDAG &DAG) const {
11272 auto *MFI = MF.getInfo<SIMachineFunctionInfo>();
11273
11274 EVT VT = Op.getValueType();
11275 SDLoc DL(Op);
11276 unsigned IntrinsicID = Op.getConstantOperandVal(0);
11277
11278 // TODO: Should this propagate fast-math-flags?
11279
11280 switch (IntrinsicID) {
11281 case Intrinsic::amdgcn_wave_reduce_min:
11282 case Intrinsic::amdgcn_wave_reduce_umin:
11283 case Intrinsic::amdgcn_wave_reduce_fmin:
11284 case Intrinsic::amdgcn_wave_reduce_max:
11285 case Intrinsic::amdgcn_wave_reduce_umax:
11286 case Intrinsic::amdgcn_wave_reduce_fmax:
11287 case Intrinsic::amdgcn_wave_reduce_add:
11288 case Intrinsic::amdgcn_wave_reduce_fadd:
11289 case Intrinsic::amdgcn_wave_reduce_sub:
11290 case Intrinsic::amdgcn_wave_reduce_fsub:
11291 case Intrinsic::amdgcn_wave_reduce_and:
11292 case Intrinsic::amdgcn_wave_reduce_or:
11293 case Intrinsic::amdgcn_wave_reduce_xor: {
11294 EVT SrcVT = Op.getOperand(1).getValueType();
11295 if (SrcVT.getFixedSizeInBits() == 16) {
11296 bool IsFPOp = SrcVT.isFloatingPoint();
11297 bool NeedsSignExt = IntrinsicID == Intrinsic::amdgcn_wave_reduce_min ||
11298 IntrinsicID == Intrinsic::amdgcn_wave_reduce_max ||
11299 IntrinsicID == Intrinsic::amdgcn_wave_reduce_add ||
11300 IntrinsicID == Intrinsic::amdgcn_wave_reduce_sub;
11301 unsigned ExtOpc = IsFPOp ? ISD::FP_EXTEND
11302 : NeedsSignExt ? ISD::SIGN_EXTEND
11304 auto SrcType = IsFPOp ? MVT::f16 : MVT::i16;
11305 auto ExtType = IsFPOp ? MVT::f32 : MVT::i32;
11306 SDValue ExtendedSrc = DAG.getNode(ExtOpc, DL, ExtType, Op.getOperand(1));
11307 SDValue Strategy = Op.getOperand(2);
11308 SDValue Result = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, ExtType,
11309 Op.getOperand(0), ExtendedSrc, Strategy);
11310 if (IsFPOp)
11311 return DAG.getNode(ISD::FP_ROUND, DL, SrcType, Result,
11312 DAG.getTargetConstant(1, DL, MVT::i32));
11313 else
11314 return DAG.getNode(ISD::TRUNCATE, DL, SrcType, Result);
11315 }
11316 return SDValue();
11317 }
11318 case Intrinsic::amdgcn_implicit_buffer_ptr: {
11319 if (getSubtarget()->isAmdHsaOrMesa(MF.getFunction()))
11320 return emitNonHSAIntrinsicError(DAG, DL, VT);
11321 return getPreloadedValue(DAG, *MFI, VT,
11323 }
11324 case Intrinsic::amdgcn_dispatch_ptr:
11325 case Intrinsic::amdgcn_queue_ptr: {
11326 if (!Subtarget->isAmdHsaOrMesa(MF.getFunction())) {
11327 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11328 MF.getFunction(), "unsupported hsa intrinsic without hsa target",
11329 DL.getDebugLoc()));
11330 return DAG.getPOISON(VT);
11331 }
11332
11333 auto RegID = IntrinsicID == Intrinsic::amdgcn_dispatch_ptr
11336 return getPreloadedValue(DAG, *MFI, VT, RegID);
11337 }
11338 case Intrinsic::amdgcn_implicitarg_ptr: {
11339 if (MFI->isEntryFunction())
11340 return getImplicitArgPtr(DAG, DL);
11341 return getPreloadedValue(DAG, *MFI, VT,
11343 }
11344 case Intrinsic::amdgcn_kernarg_segment_ptr: {
11345 if (!AMDGPU::isKernel(MF.getFunction())) {
11346 // This only makes sense to call in a kernel, so just lower to null.
11347 return DAG.getConstant(0, DL, VT);
11348 }
11349
11350 return getPreloadedValue(DAG, *MFI, VT,
11352 }
11353 case Intrinsic::amdgcn_dispatch_id: {
11354 return getPreloadedValue(DAG, *MFI, VT, AMDGPUFunctionArgInfo::DISPATCH_ID);
11355 }
11356 case Intrinsic::amdgcn_rcp:
11357 return DAG.getNode(AMDGPUISD::RCP, DL, VT, Op.getOperand(1));
11358 case Intrinsic::amdgcn_rsq:
11359 return DAG.getNode(AMDGPUISD::RSQ, DL, VT, Op.getOperand(1));
11360 case Intrinsic::amdgcn_rsq_legacy:
11361 if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
11362 return emitRemovedIntrinsicError(DAG, DL, VT);
11363 return SDValue();
11364 case Intrinsic::amdgcn_rcp_legacy:
11365 if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
11366 return emitRemovedIntrinsicError(DAG, DL, VT);
11367 return DAG.getNode(AMDGPUISD::RCP_LEGACY, DL, VT, Op.getOperand(1));
11368 case Intrinsic::amdgcn_fma_legacy:
11369 case Intrinsic::amdgcn_sudot4:
11370 case Intrinsic::amdgcn_sudot8:
11371 case Intrinsic::amdgcn_tanh:
11372 return SDValue();
11373 case Intrinsic::amdgcn_rsq_clamp: {
11374 if (Subtarget->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS)
11375 return DAG.getNode(AMDGPUISD::RSQ_CLAMP, DL, VT, Op.getOperand(1));
11376
11377 Type *Type = VT.getTypeForEVT(*DAG.getContext());
11378 APFloat Max = APFloat::getLargest(Type->getFltSemantics());
11379 APFloat Min = APFloat::getLargest(Type->getFltSemantics(), true);
11380
11381 SDValue Rsq = DAG.getNode(AMDGPUISD::RSQ, DL, VT, Op.getOperand(1));
11382 SDValue Tmp =
11383 DAG.getNode(ISD::FMINNUM, DL, VT, Rsq, DAG.getConstantFP(Max, DL, VT));
11384 return DAG.getNode(ISD::FMAXNUM, DL, VT, Tmp,
11385 DAG.getConstantFP(Min, DL, VT));
11386 }
11387 case Intrinsic::r600_read_ngroups_x:
11388 if (Subtarget->isAmdHsaOS())
11389 return emitNonHSAIntrinsicError(DAG, DL, VT);
11390
11391 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11393 false);
11394 case Intrinsic::r600_read_ngroups_y:
11395 if (Subtarget->isAmdHsaOS())
11396 return emitNonHSAIntrinsicError(DAG, DL, VT);
11397
11398 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11400 false);
11401 case Intrinsic::r600_read_ngroups_z:
11402 if (Subtarget->isAmdHsaOS())
11403 return emitNonHSAIntrinsicError(DAG, DL, VT);
11404
11405 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11407 false);
11408 case Intrinsic::r600_read_local_size_x:
11409 if (Subtarget->isAmdHsaOS())
11410 return emitNonHSAIntrinsicError(DAG, DL, VT);
11411
11412 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11414 case Intrinsic::r600_read_local_size_y:
11415 if (Subtarget->isAmdHsaOS())
11416 return emitNonHSAIntrinsicError(DAG, DL, VT);
11417
11418 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11420 case Intrinsic::r600_read_local_size_z:
11421 if (Subtarget->isAmdHsaOS())
11422 return emitNonHSAIntrinsicError(DAG, DL, VT);
11423
11424 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11426 case Intrinsic::amdgcn_workgroup_id_x:
11427 return lowerWorkGroupId(DAG, *MFI, VT,
11431 case Intrinsic::amdgcn_workgroup_id_y:
11432 return lowerWorkGroupId(DAG, *MFI, VT,
11436 case Intrinsic::amdgcn_workgroup_id_z:
11437 return lowerWorkGroupId(DAG, *MFI, VT,
11441 case Intrinsic::amdgcn_cluster_id_x:
11442 return Subtarget->hasClusters()
11443 ? getPreloadedValue(DAG, *MFI, VT,
11445 : DAG.getPOISON(VT);
11446 case Intrinsic::amdgcn_cluster_id_y:
11447 return Subtarget->hasClusters()
11448 ? getPreloadedValue(DAG, *MFI, VT,
11450 : DAG.getPOISON(VT);
11451 case Intrinsic::amdgcn_cluster_id_z:
11452 return Subtarget->hasClusters()
11453 ? getPreloadedValue(DAG, *MFI, VT,
11455 : DAG.getPOISON(VT);
11456 case Intrinsic::amdgcn_cluster_workgroup_id_x:
11457 return Subtarget->hasClusters()
11458 ? getPreloadedValue(
11459 DAG, *MFI, VT,
11461 : DAG.getPOISON(VT);
11462 case Intrinsic::amdgcn_cluster_workgroup_id_y:
11463 return Subtarget->hasClusters()
11464 ? getPreloadedValue(
11465 DAG, *MFI, VT,
11467 : DAG.getPOISON(VT);
11468 case Intrinsic::amdgcn_cluster_workgroup_id_z:
11469 return Subtarget->hasClusters()
11470 ? getPreloadedValue(
11471 DAG, *MFI, VT,
11473 : DAG.getPOISON(VT);
11474 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
11475 return Subtarget->hasClusters()
11476 ? lowerConstHwRegRead(DAG, Op, AMDGPU::Hwreg::ID_IB_STS2, 21, 4)
11477 : SDValue();
11478 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
11479 return Subtarget->hasClusters()
11480 ? getPreloadedValue(
11481 DAG, *MFI, VT,
11483 : DAG.getPOISON(VT);
11484 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
11485 return Subtarget->hasClusters()
11486 ? getPreloadedValue(
11487 DAG, *MFI, VT,
11489 : DAG.getPOISON(VT);
11490 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
11491 return Subtarget->hasClusters()
11492 ? getPreloadedValue(
11493 DAG, *MFI, VT,
11495 : DAG.getPOISON(VT);
11496 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
11497 return Subtarget->hasClusters()
11498 ? getPreloadedValue(
11499 DAG, *MFI, VT,
11501 : DAG.getPOISON(VT);
11502 case Intrinsic::amdgcn_wave_id:
11503 return lowerWaveID(DAG, Op);
11504 case Intrinsic::amdgcn_lds_kernel_id: {
11505 if (MFI->isEntryFunction())
11506 return getLDSKernelId(DAG, DL);
11507 return getPreloadedValue(DAG, *MFI, VT,
11509 }
11510 case Intrinsic::amdgcn_workitem_id_x:
11511 return lowerWorkitemID(DAG, Op, 0, MFI->getArgInfo().WorkItemIDX);
11512 case Intrinsic::amdgcn_workitem_id_y:
11513 return lowerWorkitemID(DAG, Op, 1, MFI->getArgInfo().WorkItemIDY);
11514 case Intrinsic::amdgcn_workitem_id_z:
11515 return lowerWorkitemID(DAG, Op, 2, MFI->getArgInfo().WorkItemIDZ);
11516 case Intrinsic::amdgcn_wavefrontsize:
11517 return DAG.getConstant(MF.getSubtarget<GCNSubtarget>().getWavefrontSize(),
11518 SDLoc(Op), MVT::i32);
11519 case Intrinsic::amdgcn_s_buffer_load: {
11520 unsigned CPol = Op.getConstantOperandVal(3);
11521 // s_buffer_load, because of how it's optimized, can't be volatile
11522 // so reject ones with the volatile bit set.
11523 if (CPol & ~((Subtarget->getGeneration() >= AMDGPUSubtarget::GFX12)
11526 return Op;
11527 return lowerSBuffer(VT, VT, DL, DAG.getEntryNode(), Op.getOperand(1),
11528 Op.getOperand(2), Op.getOperand(3), DAG);
11529 }
11530 case Intrinsic::amdgcn_fdiv_fast:
11531 return lowerFDIV_FAST(Op, DAG);
11532 case Intrinsic::amdgcn_sin:
11533 return DAG.getNode(AMDGPUISD::SIN_HW, DL, VT, Op.getOperand(1));
11534
11535 case Intrinsic::amdgcn_cos:
11536 return DAG.getNode(AMDGPUISD::COS_HW, DL, VT, Op.getOperand(1));
11537
11538 case Intrinsic::amdgcn_mul_u24:
11539 return DAG.getNode(AMDGPUISD::MUL_U24, DL, VT, Op.getOperand(1),
11540 Op.getOperand(2));
11541 case Intrinsic::amdgcn_mul_i24:
11542 return DAG.getNode(AMDGPUISD::MUL_I24, DL, VT, Op.getOperand(1),
11543 Op.getOperand(2));
11544
11545 case Intrinsic::amdgcn_log_clamp: {
11546 if (Subtarget->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS)
11547 return SDValue();
11548
11549 return emitRemovedIntrinsicError(DAG, DL, VT);
11550 }
11551 case Intrinsic::amdgcn_fract:
11552 return DAG.getNode(AMDGPUISD::FRACT, DL, VT, Op.getOperand(1));
11553
11554 case Intrinsic::amdgcn_class: {
11555 SDValue Src = Op.getOperand(1);
11556 EVT SrcVT = Src.getValueType();
11557 bool IsLegal = SrcVT == MVT::f32 || SrcVT == MVT::f64 ||
11558 (SrcVT == MVT::f16 && Subtarget->has16BitInsts());
11559 if (!IsLegal) {
11560 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11562 "llvm.amdgcn.class only supports f16, f32, and f64",
11563 DL.getDebugLoc()));
11564 return DAG.getPOISON(VT);
11565 }
11566 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, VT, Src, Op.getOperand(2));
11567 }
11568 case Intrinsic::amdgcn_div_fmas:
11569 return DAG.getNode(AMDGPUISD::DIV_FMAS, DL, VT, Op.getOperand(1),
11570 Op.getOperand(2), Op.getOperand(3), Op.getOperand(4));
11571
11572 case Intrinsic::amdgcn_div_fixup:
11573 return DAG.getNode(AMDGPUISD::DIV_FIXUP, DL, VT, Op.getOperand(1),
11574 Op.getOperand(2), Op.getOperand(3));
11575
11576 case Intrinsic::amdgcn_div_scale: {
11577 const ConstantSDNode *Param = cast<ConstantSDNode>(Op.getOperand(3));
11578
11579 // Translate to the operands expected by the machine instruction. The
11580 // first parameter must be the same as the first instruction.
11581 SDValue Numerator = Op.getOperand(1);
11582 SDValue Denominator = Op.getOperand(2);
11583
11584 // Note this order is opposite of the machine instruction's operations,
11585 // which is s0.f = Quotient, s1.f = Denominator, s2.f = Numerator. The
11586 // intrinsic has the numerator as the first operand to match a normal
11587 // division operation.
11588
11589 SDValue Src0 = Param->isAllOnes() ? Numerator : Denominator;
11590
11591 return DAG.getNode(AMDGPUISD::DIV_SCALE, DL, Op->getVTList(), Src0,
11592 Denominator, Numerator);
11593 }
11594 case Intrinsic::amdgcn_ballot:
11595 return lowerBALLOTIntrinsic(*this, Op.getNode(), DAG);
11596 case Intrinsic::amdgcn_fmed3:
11597 return DAG.getNode(AMDGPUISD::FMED3, DL, VT, Op.getOperand(1),
11598 Op.getOperand(2), Op.getOperand(3), Op->getFlags());
11599 case Intrinsic::amdgcn_fdot2:
11600 return DAG.getNode(AMDGPUISD::FDOT2, DL, VT, Op.getOperand(1),
11601 Op.getOperand(2), Op.getOperand(3), Op.getOperand(4));
11602 case Intrinsic::amdgcn_fmul_legacy:
11603 return DAG.getNode(AMDGPUISD::FMUL_LEGACY, DL, VT, Op.getOperand(1),
11604 Op.getOperand(2));
11605 case Intrinsic::amdgcn_sbfe:
11606 case Intrinsic::amdgcn_ubfe:
11607 return lowerBFEIntrinsic(Op, DAG, IntrinsicID);
11608 case Intrinsic::amdgcn_cvt_pkrtz:
11609 case Intrinsic::amdgcn_cvt_pknorm_i16:
11610 case Intrinsic::amdgcn_cvt_pknorm_u16:
11611 case Intrinsic::amdgcn_cvt_pk_i16:
11612 case Intrinsic::amdgcn_cvt_pk_u16: {
11613 // FIXME: Stop adding cast if v2f16/v2i16 are legal.
11614 EVT VT = Op.getValueType();
11615 unsigned Opcode;
11616
11617 if (IntrinsicID == Intrinsic::amdgcn_cvt_pkrtz)
11618 Opcode = AMDGPUISD::CVT_PKRTZ_F16_F32;
11619 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_i16)
11620 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
11621 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_u16)
11622 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
11623 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pk_i16)
11624 Opcode = AMDGPUISD::CVT_PK_I16_I32;
11625 else
11626 Opcode = AMDGPUISD::CVT_PK_U16_U32;
11627
11628 if (isTypeLegal(VT))
11629 return DAG.getNode(Opcode, DL, VT, Op.getOperand(1), Op.getOperand(2));
11630
11631 SDValue Node =
11632 DAG.getNode(Opcode, DL, MVT::i32, Op.getOperand(1), Op.getOperand(2));
11633 return DAG.getNode(ISD::BITCAST, DL, VT, Node);
11634 }
11635 case Intrinsic::amdgcn_fmad_ftz:
11636 return DAG.getNode(AMDGPUISD::FMAD_FTZ, DL, VT, Op.getOperand(1),
11637 Op.getOperand(2), Op.getOperand(3));
11638
11639 case Intrinsic::amdgcn_if_break:
11640 return SDValue(DAG.getMachineNode(AMDGPU::SI_IF_BREAK, DL, VT,
11641 Op->getOperand(1), Op->getOperand(2)),
11642 0);
11643
11644 case Intrinsic::amdgcn_groupstaticsize: {
11646 if (OS == Triple::AMDHSA || OS == Triple::AMDPAL)
11647 return Op;
11648
11649 const Module *M = MF.getFunction().getParent();
11650 const GlobalValue *GV =
11651 Intrinsic::getDeclarationIfExists(M, Intrinsic::amdgcn_groupstaticsize);
11652 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, 0,
11654 return {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0};
11655 }
11656 case Intrinsic::amdgcn_is_shared:
11657 case Intrinsic::amdgcn_is_private: {
11658 SDLoc SL(Op);
11659 SDValue SrcVec =
11660 DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(1));
11661 SDValue SrcHi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, SrcVec,
11662 DAG.getConstant(1, SL, MVT::i32));
11663
11664 unsigned AS = (IntrinsicID == Intrinsic::amdgcn_is_shared)
11666 : AMDGPUAS::PRIVATE_ADDRESS;
11667 if (AS == AMDGPUAS::PRIVATE_ADDRESS &&
11668 Subtarget->hasGloballyAddressableScratch()) {
11669 SDValue FlatScratchBaseHi(
11670 DAG.getMachineNode(
11671 AMDGPU::S_MOV_B32, DL, MVT::i32,
11672 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, MVT::i32)),
11673 0);
11674 // Test bits 63..58 against the aperture address.
11675 return DAG.getSetCC(
11676 SL, MVT::i1,
11677 DAG.getNode(ISD::XOR, SL, MVT::i32, SrcHi, FlatScratchBaseHi),
11678 DAG.getConstant(1u << 26, SL, MVT::i32), ISD::SETULT);
11679 }
11680
11681 SDValue Aperture = getSegmentAperture(AS, SL, DAG);
11682 return DAG.getSetCC(SL, MVT::i1, SrcHi, Aperture, ISD::SETEQ);
11683 }
11684 case Intrinsic::amdgcn_perm:
11685 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, Op.getOperand(1),
11686 Op.getOperand(2), Op.getOperand(3));
11687 case Intrinsic::amdgcn_reloc_constant: {
11688 Module *M = MF.getFunction().getParent();
11689 const MDNode *Metadata = cast<MDNodeSDNode>(Op.getOperand(1))->getMD();
11690 auto SymbolName = cast<MDString>(Metadata->getOperand(0))->getString();
11691 auto *RelocSymbol = cast<GlobalVariable>(
11692 M->getOrInsertGlobal(SymbolName, Type::getInt32Ty(M->getContext())));
11693 SDValue GA = DAG.getTargetGlobalAddress(RelocSymbol, DL, MVT::i32, 0,
11695 return {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0};
11696 }
11697 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
11698 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
11699 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
11700 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
11701 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
11702 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
11703 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
11704 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
11705 if (Op.getOperand(4).getValueType() == MVT::i32)
11706 return SDValue();
11707
11708 SDLoc SL(Op);
11709 auto IndexKeyi32 = DAG.getAnyExtOrTrunc(Op.getOperand(4), SL, MVT::i32);
11710 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11711 Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11712 Op.getOperand(3), IndexKeyi32);
11713 }
11714 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
11715 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
11716 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
11717 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
11718 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
11719 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
11720 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
11721 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
11722 if (Op.getOperand(4).getValueType() == MVT::i64)
11723 return SDValue();
11724
11725 SDLoc SL(Op);
11726 auto IndexKeyi64 =
11727 Op.getOperand(4).getValueType() == MVT::v2i32
11728 ? DAG.getBitcast(MVT::i64, Op.getOperand(4))
11729 : DAG.getAnyExtOrTrunc(Op.getOperand(4), SL, MVT::i64);
11730 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11731 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11732 Op.getOperand(3), IndexKeyi64, Op.getOperand(5),
11733 Op.getOperand(6)});
11734 }
11735 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
11736 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
11737 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
11738 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
11739 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
11740 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8: {
11741 EVT IndexKeyTy = IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
11742 ? MVT::i64
11743 : MVT::i32;
11744 if (Op.getOperand(6).getValueType() == IndexKeyTy)
11745 return SDValue();
11746
11747 SDLoc SL(Op);
11748 auto IndexKey =
11749 Op.getOperand(6).getValueType().isVector()
11750 ? DAG.getBitcast(IndexKeyTy, Op.getOperand(6))
11751 : DAG.getAnyExtOrTrunc(Op.getOperand(6), SL, IndexKeyTy);
11753 Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11754 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11755 IndexKey, Op.getOperand(7), Op.getOperand(8)};
11756 if (IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8)
11757 Args.push_back(Op.getOperand(9));
11758 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(), Args);
11759 }
11760 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
11761 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
11762 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
11763 if (Op.getOperand(6).getValueType() == MVT::i32)
11764 return SDValue();
11765
11766 SDLoc SL(Op);
11767 auto IndexKeyi32 = DAG.getAnyExtOrTrunc(Op.getOperand(6), SL, MVT::i32);
11768 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11769 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11770 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11771 IndexKeyi32, Op.getOperand(7)});
11772 }
11773 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
11774 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
11775 unsigned AFmt = (unsigned)Op.getConstantOperandVal(1);
11776 unsigned BFmt = (unsigned)Op.getConstantOperandVal(3);
11777 unsigned AScaleFmt = (unsigned)Op.getConstantOperandVal(8);
11778 unsigned BScaleFmt = (unsigned)Op.getConstantOperandVal(11);
11779 if (!AMDGPU::isValidWMMAScaleFmtCombination(AFmt, AScaleFmt, BFmt,
11780 BScaleFmt)) {
11782 "invalid matrix and scale format combination in wmma call");
11783 Op->print(errs());
11784 errs() << '\n';
11785 }
11786 return SDValue();
11787 }
11788 case Intrinsic::amdgcn_readlane:
11789 case Intrinsic::amdgcn_readfirstlane:
11790 case Intrinsic::amdgcn_writelane:
11791 case Intrinsic::amdgcn_permlane16:
11792 case Intrinsic::amdgcn_permlanex16:
11793 case Intrinsic::amdgcn_permlane64:
11794 case Intrinsic::amdgcn_set_inactive:
11795 case Intrinsic::amdgcn_set_inactive_chain_arg:
11796 case Intrinsic::amdgcn_mov_dpp8:
11797 case Intrinsic::amdgcn_update_dpp:
11798 case Intrinsic::amdgcn_permlane_bcast:
11799 case Intrinsic::amdgcn_permlane_up:
11800 case Intrinsic::amdgcn_permlane_down:
11801 case Intrinsic::amdgcn_permlane_xor:
11802 return lowerLaneOp(*this, Op.getNode(), DAG);
11803 case Intrinsic::amdgcn_dead: {
11805 for (const EVT ValTy : Op.getNode()->values())
11806 Poisons.push_back(DAG.getPOISON(ValTy));
11807 return DAG.getMergeValues(Poisons, SDLoc(Op));
11808 }
11809 case Intrinsic::amdgcn_wave_shuffle:
11810 return lowerWaveShuffle(*this, Op.getNode(), DAG);
11811 default:
11812 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
11814 return lowerImage(Op, ImageDimIntr, DAG, false);
11815
11816 return Op;
11817 }
11818}
11819
11820// On targets not supporting constant in soffset field, turn zero to
11821// SGPR_NULL to avoid generating an extra s_mov with zero.
11823 const GCNSubtarget *Subtarget) {
11824 if (Subtarget->hasRestrictedSOffset() && isNullConstant(SOffset))
11825 return DAG.getRegister(AMDGPU::SGPR_NULL, MVT::i32);
11826 return SOffset;
11827}
11828
11829SDValue SITargetLowering::lowerRawBufferAtomicIntrin(SDValue Op,
11830 SelectionDAG &DAG,
11831 unsigned NewOpcode) const {
11832 SDLoc DL(Op);
11833
11834 SDValue VData = Op.getOperand(2);
11835 if (VData.getValueSizeInBits() != 32 && VData.getValueSizeInBits() != 64) {
11836 SmallVector<EVT, 2> ResultTypes(Op->values());
11837 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
11838 "unsupported buffer atomic data type");
11839 }
11840 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
11841 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
11842 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
11843 SDValue Ops[] = {
11844 Op.getOperand(0), // Chain
11845 VData, // vdata
11846 Rsrc, // rsrc
11847 DAG.getConstant(0, DL, MVT::i32), // vindex
11848 VOffset, // voffset
11849 SOffset, // soffset
11850 Offset, // offset
11851 Op.getOperand(6), // cachepolicy
11852 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
11853 };
11854
11855 auto *M = cast<MemSDNode>(Op);
11856
11857 EVT MemVT = VData.getValueType();
11858 return DAG.getMemIntrinsicNode(NewOpcode, DL, Op->getVTList(), Ops, MemVT,
11859 M->getMemOperand());
11860}
11861
11862SDValue
11863SITargetLowering::lowerStructBufferAtomicIntrin(SDValue Op, SelectionDAG &DAG,
11864 unsigned NewOpcode) const {
11865 SDLoc DL(Op);
11866
11867 SDValue VData = Op.getOperand(2);
11868 if (VData.getValueSizeInBits() != 32 && VData.getValueSizeInBits() != 64) {
11869 SmallVector<EVT, 2> ResultTypes(Op->values());
11870 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
11871 "unsupported buffer atomic data type");
11872 }
11873 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
11874 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
11875 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
11876 SDValue Ops[] = {
11877 Op.getOperand(0), // Chain
11878 VData, // vdata
11879 Rsrc, // rsrc
11880 Op.getOperand(4), // vindex
11881 VOffset, // voffset
11882 SOffset, // soffset
11883 Offset, // offset
11884 Op.getOperand(7), // cachepolicy
11885 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
11886 };
11887
11888 auto *M = cast<MemSDNode>(Op);
11889
11890 EVT MemVT = VData.getValueType();
11891 return DAG.getMemIntrinsicNode(NewOpcode, DL, Op->getVTList(), Ops, MemVT,
11892 M->getMemOperand());
11893}
11894
11896 SDLoc DL) {
11897 SDNode *N = Op.getNode();
11898 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
11899 unsigned NumOperands = N->getNumOperands();
11900 if (N->getOperand(NumOperands - 1) == Zero)
11901 return;
11903 Ops[NumOperands - 1] = Zero; // M0 = 0
11904 DAG.UpdateNodeOperands(N, Ops);
11905}
11906
11907SDValue SITargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op,
11908 SelectionDAG &DAG) const {
11909 unsigned IntrID = Op.getConstantOperandVal(1);
11910 SDLoc DL(Op);
11911
11912 switch (IntrID) {
11913 case Intrinsic::amdgcn_cluster_load_b32:
11914 case Intrinsic::amdgcn_cluster_load_b64:
11915 case Intrinsic::amdgcn_cluster_load_b128: {
11916 if (Subtarget->hasGFX1250_STRICT())
11918 return SDValue();
11919 }
11920 case Intrinsic::amdgcn_ds_ordered_add:
11921 case Intrinsic::amdgcn_ds_ordered_swap: {
11922 MemSDNode *M = cast<MemSDNode>(Op);
11923 SDValue Chain = M->getOperand(0);
11924 SDValue M0 = M->getOperand(2);
11925 SDValue Value = M->getOperand(3);
11926 unsigned IndexOperand = M->getConstantOperandVal(7);
11927 unsigned WaveRelease = M->getConstantOperandVal(8);
11928 unsigned WaveDone = M->getConstantOperandVal(9);
11929
11930 unsigned OrderedCountIndex = IndexOperand & 0x3f;
11931 IndexOperand &= ~0x3f;
11932 unsigned CountDw = 0;
11933
11934 if (Subtarget->getGeneration() >= AMDGPUSubtarget::GFX10) {
11935 CountDw = (IndexOperand >> 24) & 0xf;
11936 IndexOperand &= ~(0xf << 24);
11937
11938 if (CountDw < 1 || CountDw > 4) {
11939 const Function &Fn = DAG.getMachineFunction().getFunction();
11940 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11941 Fn, "ds_ordered_count: dword count must be between 1 and 4",
11942 DL.getDebugLoc()));
11943 CountDw = 1;
11944 }
11945 }
11946
11947 if (IndexOperand) {
11948 const Function &Fn = DAG.getMachineFunction().getFunction();
11949 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11950 Fn, "ds_ordered_count: bad index operand", DL.getDebugLoc()));
11951 }
11952
11953 if (WaveDone && !WaveRelease) {
11954 // TODO: Move this to IR verifier
11955 const Function &Fn = DAG.getMachineFunction().getFunction();
11956 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11957 Fn, "ds_ordered_count: wave_done requires wave_release",
11958 DL.getDebugLoc()));
11959 }
11960
11961 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
11962 unsigned ShaderType =
11964 unsigned Offset0 = OrderedCountIndex << 2;
11965 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
11966
11967 if (Subtarget->getGeneration() >= AMDGPUSubtarget::GFX10)
11968 Offset1 |= (CountDw - 1) << 6;
11969
11970 if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX11)
11971 Offset1 |= ShaderType << 2;
11972
11973 unsigned Offset = Offset0 | (Offset1 << 8);
11974
11975 SDValue Ops[] = {
11976 Chain, Value, DAG.getTargetConstant(Offset, DL, MVT::i16),
11977 copyToM0(DAG, Chain, DL, M0).getValue(1), // Glue
11978 };
11979 return DAG.getMemIntrinsicNode(AMDGPUISD::DS_ORDERED_COUNT, DL,
11980 M->getVTList(), Ops, M->getMemoryVT(),
11981 M->getMemOperand());
11982 }
11983 case Intrinsic::amdgcn_ptr_s_buffer_load: {
11984 unsigned CPol = Op.getConstantOperandVal(4);
11985 if (CPol & ~((Subtarget->getGeneration() >= AMDGPUSubtarget::GFX12)
11988 return Op;
11989
11990 MemSDNode *M = cast<MemSDNode>(Op);
11991 return lowerSBuffer(
11992 Op.getValueType(), M->getMemoryVT(), DL, Op.getOperand(0),
11993 bufferRsrcPtrToVector(Op.getOperand(2), DAG), Op.getOperand(3),
11994 Op.getOperand(4), DAG, M->getMemOperand());
11995 }
11996 case Intrinsic::amdgcn_raw_buffer_load:
11997 case Intrinsic::amdgcn_raw_ptr_buffer_load:
11998 case Intrinsic::amdgcn_raw_atomic_buffer_load:
11999 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
12000 case Intrinsic::amdgcn_raw_buffer_load_format:
12001 case Intrinsic::amdgcn_raw_ptr_buffer_load_format: {
12002 const bool IsFormat =
12003 IntrID == Intrinsic::amdgcn_raw_buffer_load_format ||
12004 IntrID == Intrinsic::amdgcn_raw_ptr_buffer_load_format;
12005
12006 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12007 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(3), DAG);
12008 auto SOffset = selectSOffset(Op.getOperand(4), DAG, Subtarget);
12009 SDValue Ops[] = {
12010 Op.getOperand(0), // Chain
12011 Rsrc, // rsrc
12012 DAG.getConstant(0, DL, MVT::i32), // vindex
12013 VOffset, // voffset
12014 SOffset, // soffset
12015 Offset, // offset
12016 Op.getOperand(5), // cachepolicy, swizzled buffer
12017 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12018 };
12019
12020 auto *M = cast<MemSDNode>(Op);
12021 return lowerIntrinsicLoad(M, IsFormat, DAG, Ops);
12022 }
12023 case Intrinsic::amdgcn_struct_buffer_load:
12024 case Intrinsic::amdgcn_struct_ptr_buffer_load:
12025 case Intrinsic::amdgcn_struct_buffer_load_format:
12026 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
12027 case Intrinsic::amdgcn_struct_atomic_buffer_load:
12028 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
12029 const bool IsFormat =
12030 IntrID == Intrinsic::amdgcn_struct_buffer_load_format ||
12031 IntrID == Intrinsic::amdgcn_struct_ptr_buffer_load_format;
12032
12033 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12034 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12035 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12036 SDValue Ops[] = {
12037 Op.getOperand(0), // Chain
12038 Rsrc, // rsrc
12039 Op.getOperand(3), // vindex
12040 VOffset, // voffset
12041 SOffset, // soffset
12042 Offset, // offset
12043 Op.getOperand(6), // cachepolicy, swizzled buffer
12044 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12045 };
12046
12047 return lowerIntrinsicLoad(cast<MemSDNode>(Op), IsFormat, DAG, Ops);
12048 }
12049 case Intrinsic::amdgcn_raw_tbuffer_load:
12050 case Intrinsic::amdgcn_raw_ptr_tbuffer_load: {
12051 MemSDNode *M = cast<MemSDNode>(Op);
12052 EVT LoadVT = Op.getValueType();
12053 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12054 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(3), DAG);
12055 auto SOffset = selectSOffset(Op.getOperand(4), DAG, Subtarget);
12056
12057 SDValue Ops[] = {
12058 Op.getOperand(0), // Chain
12059 Rsrc, // rsrc
12060 DAG.getConstant(0, DL, MVT::i32), // vindex
12061 VOffset, // voffset
12062 SOffset, // soffset
12063 Offset, // offset
12064 Op.getOperand(5), // format
12065 Op.getOperand(6), // cachepolicy, swizzled buffer
12066 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12067 };
12068
12069 if (LoadVT.getScalarSizeInBits() == 16)
12070 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12071 Ops);
12072 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT, DL,
12073 Op->getVTList(), Ops, LoadVT, M->getMemOperand(),
12074 DAG);
12075 }
12076 case Intrinsic::amdgcn_struct_tbuffer_load:
12077 case Intrinsic::amdgcn_struct_ptr_tbuffer_load: {
12078 MemSDNode *M = cast<MemSDNode>(Op);
12079 EVT LoadVT = Op.getValueType();
12080 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12081 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12082 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12083
12084 SDValue Ops[] = {
12085 Op.getOperand(0), // Chain
12086 Rsrc, // rsrc
12087 Op.getOperand(3), // vindex
12088 VOffset, // voffset
12089 SOffset, // soffset
12090 Offset, // offset
12091 Op.getOperand(6), // format
12092 Op.getOperand(7), // cachepolicy, swizzled buffer
12093 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12094 };
12095
12096 if (LoadVT.getScalarSizeInBits() == 16)
12097 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12098 Ops);
12099 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT, DL,
12100 Op->getVTList(), Ops, LoadVT, M->getMemOperand(),
12101 DAG);
12102 }
12103 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
12104 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
12105 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FADD);
12106 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
12107 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
12108 return lowerStructBufferAtomicIntrin(Op, DAG,
12109 AMDGPUISD::BUFFER_ATOMIC_FADD);
12110 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
12111 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
12112 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMIN);
12113 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
12114 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
12115 return lowerStructBufferAtomicIntrin(Op, DAG,
12116 AMDGPUISD::BUFFER_ATOMIC_FMIN);
12117 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
12118 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
12119 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMAX);
12120 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
12121 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
12122 return lowerStructBufferAtomicIntrin(Op, DAG,
12123 AMDGPUISD::BUFFER_ATOMIC_FMAX);
12124 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
12125 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
12126 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SWAP);
12127 case Intrinsic::amdgcn_raw_buffer_atomic_add:
12128 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
12129 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12130 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
12131 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
12132 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12133 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
12134 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
12135 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMIN);
12136 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
12137 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
12138 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMIN);
12139 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
12140 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
12141 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMAX);
12142 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
12143 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
12144 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMAX);
12145 case Intrinsic::amdgcn_raw_buffer_atomic_and:
12146 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
12147 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12148 case Intrinsic::amdgcn_raw_buffer_atomic_or:
12149 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
12150 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12151 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
12152 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
12153 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12154 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
12155 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
12156 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12157 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
12158 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
12159 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12160 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
12161 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
12162 return lowerStructBufferAtomicIntrin(Op, DAG,
12163 AMDGPUISD::BUFFER_ATOMIC_SWAP);
12164 case Intrinsic::amdgcn_struct_buffer_atomic_add:
12165 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
12166 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12167 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
12168 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
12169 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12170 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
12171 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
12172 return lowerStructBufferAtomicIntrin(Op, DAG,
12173 AMDGPUISD::BUFFER_ATOMIC_SMIN);
12174 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
12175 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
12176 return lowerStructBufferAtomicIntrin(Op, DAG,
12177 AMDGPUISD::BUFFER_ATOMIC_UMIN);
12178 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
12179 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
12180 return lowerStructBufferAtomicIntrin(Op, DAG,
12181 AMDGPUISD::BUFFER_ATOMIC_SMAX);
12182 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
12183 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
12184 return lowerStructBufferAtomicIntrin(Op, DAG,
12185 AMDGPUISD::BUFFER_ATOMIC_UMAX);
12186 case Intrinsic::amdgcn_struct_buffer_atomic_and:
12187 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
12188 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12189 case Intrinsic::amdgcn_struct_buffer_atomic_or:
12190 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
12191 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12192 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
12193 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
12194 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12195 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
12196 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
12197 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12198 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
12199 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
12200 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12201 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
12202 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
12203 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_CSUB);
12204 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
12205 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
12206 return lowerStructBufferAtomicIntrin(Op, DAG,
12207 AMDGPUISD::BUFFER_ATOMIC_CSUB);
12208 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
12209 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
12210 return lowerRawBufferAtomicIntrin(Op, DAG,
12211 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12212 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
12213 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
12214 return lowerStructBufferAtomicIntrin(Op, DAG,
12215 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12216 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
12217 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap: {
12218 SDValue Src = Op.getOperand(2);
12219 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12220 SmallVector<EVT, 2> ResultTypes(Op->values());
12221 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
12222 "unsupported buffer atomic data type");
12223 }
12224 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(4), DAG);
12225 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12226 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12227 SDValue Ops[] = {
12228 Op.getOperand(0), // Chain
12229 Op.getOperand(2), // src
12230 Op.getOperand(3), // cmp
12231 Rsrc, // rsrc
12232 DAG.getConstant(0, DL, MVT::i32), // vindex
12233 VOffset, // voffset
12234 SOffset, // soffset
12235 Offset, // offset
12236 Op.getOperand(7), // cachepolicy
12237 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12238 };
12239 EVT VT = Op.getValueType();
12240 auto *M = cast<MemSDNode>(Op);
12241
12242 return DAG.getMemIntrinsicNode(AMDGPUISD::BUFFER_ATOMIC_CMPSWAP, DL,
12243 Op->getVTList(), Ops, VT,
12244 M->getMemOperand());
12245 }
12246 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
12247 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap: {
12248 SDValue Src = Op.getOperand(2);
12249 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12250 SmallVector<EVT, 2> ResultTypes(Op->values());
12251 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
12252 "unsupported buffer atomic data type");
12253 }
12254 SDValue Rsrc = bufferRsrcPtrToVector(Op->getOperand(4), DAG);
12255 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(6), DAG);
12256 auto SOffset = selectSOffset(Op.getOperand(7), DAG, Subtarget);
12257 SDValue Ops[] = {
12258 Op.getOperand(0), // Chain
12259 Op.getOperand(2), // src
12260 Op.getOperand(3), // cmp
12261 Rsrc, // rsrc
12262 Op.getOperand(5), // vindex
12263 VOffset, // voffset
12264 SOffset, // soffset
12265 Offset, // offset
12266 Op.getOperand(8), // cachepolicy
12267 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12268 };
12269 EVT VT = Op.getValueType();
12270 auto *M = cast<MemSDNode>(Op);
12271
12272 return DAG.getMemIntrinsicNode(AMDGPUISD::BUFFER_ATOMIC_CMPSWAP, DL,
12273 Op->getVTList(), Ops, VT,
12274 M->getMemOperand());
12275 }
12276 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
12277 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
12278 MemSDNode *M = cast<MemSDNode>(Op);
12279 SDValue NodePtr = M->getOperand(2);
12280 SDValue RayExtent = M->getOperand(3);
12281 SDValue InstanceMask = M->getOperand(4);
12282 SDValue RayOrigin = M->getOperand(5);
12283 SDValue RayDir = M->getOperand(6);
12284 SDValue Offsets = M->getOperand(7);
12285 SDValue TDescr = M->getOperand(8);
12286
12287 assert(NodePtr.getValueType() == MVT::i64);
12288 assert(RayDir.getValueType() == MVT::v3f32);
12289
12290 bool IsBVH8 = IntrID == Intrinsic::amdgcn_image_bvh8_intersect_ray;
12291 const unsigned NumVDataDwords = 10;
12292 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
12293 int Opcode = AMDGPU::getMIMGOpcode(
12294 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
12295 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
12296 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
12297 assert(Opcode != -1);
12298
12300 Ops.push_back(NodePtr);
12301 Ops.push_back(DAG.getBuildVector(
12302 MVT::v2i32, DL,
12303 {DAG.getBitcast(MVT::i32, RayExtent),
12304 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, InstanceMask)}));
12305 Ops.push_back(RayOrigin);
12306 Ops.push_back(RayDir);
12307 Ops.push_back(Offsets);
12308 Ops.push_back(TDescr);
12309 Ops.push_back(M->getChain());
12310
12311 auto *NewNode = DAG.getMachineNode(Opcode, DL, M->getVTList(), Ops);
12312 MachineMemOperand *MemRef = M->getMemOperand();
12313 DAG.setNodeMemRefs(NewNode, {MemRef});
12314 return SDValue(NewNode, 0);
12315 }
12316 case Intrinsic::amdgcn_image_bvh_intersect_ray: {
12317 MemSDNode *M = cast<MemSDNode>(Op);
12318 SDValue NodePtr = M->getOperand(2);
12319 SDValue RayExtent = M->getOperand(3);
12320 SDValue RayOrigin = M->getOperand(4);
12321 SDValue RayDir = M->getOperand(5);
12322 SDValue RayInvDir = M->getOperand(6);
12323 SDValue TDescr = M->getOperand(7);
12324
12325 assert(NodePtr.getValueType() == MVT::i32 ||
12326 NodePtr.getValueType() == MVT::i64);
12327 assert(RayDir.getValueType() == MVT::v3f16 ||
12328 RayDir.getValueType() == MVT::v3f32);
12329
12330 const bool IsGFX11 = AMDGPU::isGFX11(*Subtarget);
12331 const bool IsGFX11Plus = AMDGPU::isGFX11Plus(*Subtarget);
12332 const bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
12333 const bool IsA16 = RayDir.getValueType().getVectorElementType() == MVT::f16;
12334 const bool Is64 = NodePtr.getValueType() == MVT::i64;
12335 const unsigned NumVDataDwords = 4;
12336 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
12337 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
12338 const bool UseNSA = (Subtarget->hasNSAEncoding() &&
12339 NumVAddrs <= Subtarget->getNSAMaxSize()) ||
12340 IsGFX12Plus;
12341 const unsigned BaseOpcodes[2][2] = {
12342 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
12343 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
12344 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
12345 int Opcode;
12346 if (UseNSA) {
12347 Opcode = AMDGPU::getMIMGOpcode(BaseOpcodes[Is64][IsA16],
12348 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
12349 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
12350 : AMDGPU::MIMGEncGfx10NSA,
12351 NumVDataDwords, NumVAddrDwords);
12352 } else {
12353 assert(!IsGFX12Plus);
12354 Opcode = AMDGPU::getMIMGOpcode(BaseOpcodes[Is64][IsA16],
12355 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
12356 : AMDGPU::MIMGEncGfx10Default,
12357 NumVDataDwords, NumVAddrDwords);
12358 }
12359 assert(Opcode != -1);
12360
12362
12363 auto packLanes = [&DAG, &Ops, &DL](SDValue Op, bool IsAligned) {
12365 DAG.ExtractVectorElements(Op, Lanes, 0, 3);
12366 if (Lanes[0].getValueSizeInBits() == 32) {
12367 for (unsigned I = 0; I < 3; ++I)
12368 Ops.push_back(DAG.getBitcast(MVT::i32, Lanes[I]));
12369 } else {
12370 if (IsAligned) {
12371 Ops.push_back(DAG.getBitcast(
12372 MVT::i32,
12373 DAG.getBuildVector(MVT::v2f16, DL, {Lanes[0], Lanes[1]})));
12374 Ops.push_back(Lanes[2]);
12375 } else {
12376 SDValue Elt0 = Ops.pop_back_val();
12377 Ops.push_back(DAG.getBitcast(
12378 MVT::i32, DAG.getBuildVector(MVT::v2f16, DL, {Elt0, Lanes[0]})));
12379 Ops.push_back(DAG.getBitcast(
12380 MVT::i32,
12381 DAG.getBuildVector(MVT::v2f16, DL, {Lanes[1], Lanes[2]})));
12382 }
12383 }
12384 };
12385
12386 if (UseNSA && IsGFX11Plus) {
12387 Ops.push_back(NodePtr);
12388 Ops.push_back(DAG.getBitcast(MVT::i32, RayExtent));
12389 Ops.push_back(RayOrigin);
12390 if (IsA16) {
12391 SmallVector<SDValue, 3> DirLanes, InvDirLanes, MergedLanes;
12392 DAG.ExtractVectorElements(RayDir, DirLanes, 0, 3);
12393 DAG.ExtractVectorElements(RayInvDir, InvDirLanes, 0, 3);
12394 for (unsigned I = 0; I < 3; ++I) {
12395 MergedLanes.push_back(DAG.getBitcast(
12396 MVT::i32, DAG.getBuildVector(MVT::v2f16, DL,
12397 {DirLanes[I], InvDirLanes[I]})));
12398 }
12399 Ops.push_back(DAG.getBuildVector(MVT::v3i32, DL, MergedLanes));
12400 } else {
12401 Ops.push_back(RayDir);
12402 Ops.push_back(RayInvDir);
12403 }
12404 } else {
12405 if (Is64)
12406 DAG.ExtractVectorElements(DAG.getBitcast(MVT::v2i32, NodePtr), Ops, 0,
12407 2);
12408 else
12409 Ops.push_back(NodePtr);
12410
12411 Ops.push_back(DAG.getBitcast(MVT::i32, RayExtent));
12412 packLanes(RayOrigin, true);
12413 packLanes(RayDir, true);
12414 packLanes(RayInvDir, false);
12415 }
12416
12417 if (!UseNSA) {
12418 // Build a single vector containing all the operands so far prepared.
12419 if (NumVAddrDwords > 12) {
12420 SDValue Undef = DAG.getPOISON(MVT::i32);
12421 Ops.append(16 - Ops.size(), Undef);
12422 }
12423 assert(Ops.size() >= 8 && Ops.size() <= 12);
12424 SDValue MergedOps =
12425 DAG.getBuildVector(MVT::getVectorVT(MVT::i32, Ops.size()), DL, Ops);
12426 Ops.clear();
12427 Ops.push_back(MergedOps);
12428 }
12429
12430 Ops.push_back(TDescr);
12431 Ops.push_back(DAG.getTargetConstant(IsA16, DL, MVT::i1));
12432 Ops.push_back(M->getChain());
12433
12434 auto *NewNode = DAG.getMachineNode(Opcode, DL, M->getVTList(), Ops);
12435 MachineMemOperand *MemRef = M->getMemOperand();
12436 DAG.setNodeMemRefs(NewNode, {MemRef});
12437 return SDValue(NewNode, 0);
12438 }
12439 case Intrinsic::amdgcn_global_atomic_fmin_num:
12440 case Intrinsic::amdgcn_global_atomic_fmax_num:
12441 case Intrinsic::amdgcn_flat_atomic_fmin_num:
12442 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12443 MemSDNode *M = cast<MemSDNode>(Op);
12444 SDValue Ops[] = {
12445 M->getOperand(0), // Chain
12446 M->getOperand(2), // Ptr
12447 M->getOperand(3) // Value
12448 };
12449 unsigned Opcode = 0;
12450 switch (IntrID) {
12451 case Intrinsic::amdgcn_global_atomic_fmin_num:
12452 case Intrinsic::amdgcn_flat_atomic_fmin_num: {
12453 Opcode = ISD::ATOMIC_LOAD_FMIN;
12454 break;
12455 }
12456 case Intrinsic::amdgcn_global_atomic_fmax_num:
12457 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12458 Opcode = ISD::ATOMIC_LOAD_FMAX;
12459 break;
12460 }
12461 default:
12462 llvm_unreachable("unhandled atomic opcode");
12463 }
12464 return DAG.getAtomic(Opcode, SDLoc(Op), M->getMemoryVT(), M->getVTList(),
12465 Ops, M->getMemOperand());
12466 }
12467 case Intrinsic::amdgcn_s_alloc_vgpr: {
12468 SDValue NumVGPRs = Op.getOperand(2);
12469 if (!NumVGPRs->isDivergent())
12470 return Op;
12471
12472 SDValue ReadFirstLaneID =
12473 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
12474 NumVGPRs = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32,
12475 ReadFirstLaneID, NumVGPRs);
12476
12477 return DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, Op->getVTList(),
12478 Op.getOperand(0), Op.getOperand(1), NumVGPRs);
12479 }
12480 case Intrinsic::amdgcn_s_get_barrier_state:
12481 case Intrinsic::amdgcn_s_get_named_barrier_state: {
12482 SDValue Chain = Op->getOperand(0);
12484 unsigned Opc;
12485
12486 if (isa<ConstantSDNode>(Op->getOperand(2))) {
12487 uint64_t BarID = cast<ConstantSDNode>(Op->getOperand(2))->getZExtValue();
12488 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state)
12489 BarID = BarID & 0x3F;
12490 Opc = AMDGPU::S_GET_BARRIER_STATE_IMM;
12491 SDValue K = DAG.getTargetConstant(BarID, DL, MVT::i32);
12492 Ops.push_back(K);
12493 Ops.push_back(Chain);
12494 } else {
12495 Opc = AMDGPU::S_GET_BARRIER_STATE_M0;
12496 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
12497 SDValue M0Val = DAG.getNode(ISD::AND, DL, MVT::i32, Op->getOperand(2),
12498 DAG.getConstant(0x3F, DL, MVT::i32));
12499 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
12500 } else
12501 Ops.push_back(copyToM0(DAG, Chain, DL, Op->getOperand(2)).getValue(0));
12502 }
12503
12504 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
12505 return SDValue(NewMI, 0);
12506 }
12507 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
12508 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
12509 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
12510 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12511 SDValue Chain = Op->getOperand(0);
12512 SDValue Ptr = Op->getOperand(2);
12513 EVT VT = Op->getValueType(0);
12514 return DAG.getAtomicLoad(ISD::NON_EXTLOAD, DL, MII->getMemoryVT(), VT,
12515 Chain, Ptr, MII->getMemOperand());
12516 }
12517 case Intrinsic::amdgcn_av_load_b128: {
12518 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12519 SDValue Chain = Op->getOperand(0);
12520 SDValue Ptr = Op->getOperand(2);
12521 EVT VT = Op->getValueType(0);
12522 // Lower to a regular ISD::LOAD. The MachineMemOperand carries Monotonic
12523 // ordering and syncscope so that SIMemoryLegalizer sets cache policy bits.
12524 // Address space filtering in the load_global/load_flat PatFrags selects
12525 // the correct GLOBAL vs FLAT instruction.
12526 return DAG.getLoad(VT, DL, Chain, Ptr, MII->getMemOperand());
12527 }
12528 case Intrinsic::amdgcn_flat_load_monitor_b32:
12529 case Intrinsic::amdgcn_flat_load_monitor_b64:
12530 case Intrinsic::amdgcn_flat_load_monitor_b128: {
12531 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12532 SDValue Chain = Op->getOperand(0);
12533 SDValue Ptr = Op->getOperand(2);
12534 return DAG.getMemIntrinsicNode(AMDGPUISD::FLAT_LOAD_MONITOR, DL,
12535 Op->getVTList(), {Chain, Ptr},
12536 MII->getMemoryVT(), MII->getMemOperand());
12537 }
12538 case Intrinsic::amdgcn_global_load_monitor_b32:
12539 case Intrinsic::amdgcn_global_load_monitor_b64:
12540 case Intrinsic::amdgcn_global_load_monitor_b128: {
12541 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12542 SDValue Chain = Op->getOperand(0);
12543 SDValue Ptr = Op->getOperand(2);
12544 return DAG.getMemIntrinsicNode(AMDGPUISD::GLOBAL_LOAD_MONITOR, DL,
12545 Op->getVTList(), {Chain, Ptr},
12546 MII->getMemoryVT(), MII->getMemOperand());
12547 }
12548 default:
12549
12550 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
12552 return lowerImage(Op, ImageDimIntr, DAG, true);
12553
12554 return SDValue();
12555 }
12556}
12557
12558// Call DAG.getMemIntrinsicNode for a load, but first widen a dwordx3 type to
12559// dwordx4 if on SI and handle TFE loads.
12560SDValue SITargetLowering::getMemIntrinsicNode(unsigned Opcode, const SDLoc &DL,
12561 SDVTList VTList,
12562 ArrayRef<SDValue> Ops, EVT MemVT,
12563 MachineMemOperand *MMO,
12564 SelectionDAG &DAG) const {
12565 LLVMContext &C = *DAG.getContext();
12567 EVT VT = VTList.VTs[0];
12568
12569 assert(VTList.NumVTs == 2 || VTList.NumVTs == 3);
12570 bool IsTFE = VTList.NumVTs == 3;
12571 if (IsTFE) {
12572 unsigned NumValueDWords = divideCeil(VT.getSizeInBits(), 32);
12573 unsigned NumOpDWords = NumValueDWords + 1;
12574 EVT OpDWordsVT = EVT::getVectorVT(C, MVT::i32, NumOpDWords);
12575 SDVTList OpDWordsVTList = DAG.getVTList(OpDWordsVT, VTList.VTs[2]);
12576 MachineMemOperand *OpDWordsMMO =
12577 MF.getMachineMemOperand(MMO, 0, NumOpDWords * 4);
12578 SDValue Op = getMemIntrinsicNode(Opcode, DL, OpDWordsVTList, Ops,
12579 OpDWordsVT, OpDWordsMMO, DAG);
12580 auto [Value, Status] = splitTFEValueAndStatus(Op, VT, DL, DAG);
12581 return DAG.getMergeValues({Value, Status, SDValue(Op.getNode(), 1)}, DL);
12582 }
12583
12584 if (!Subtarget->hasDwordx3LoadStores() &&
12585 (VT == MVT::v3i32 || VT == MVT::v3f32)) {
12586 EVT WidenedVT = EVT::getVectorVT(C, VT.getVectorElementType(), 4);
12587 EVT WidenedMemVT = EVT::getVectorVT(C, MemVT.getVectorElementType(), 4);
12588 MachineMemOperand *WidenedMMO = MF.getMachineMemOperand(MMO, 0, 16);
12589 SDVTList WidenedVTList = DAG.getVTList(WidenedVT, VTList.VTs[1]);
12590 SDValue Op = DAG.getMemIntrinsicNode(Opcode, DL, WidenedVTList, Ops,
12591 WidenedMemVT, WidenedMMO);
12592 SDValue Value = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, Op,
12593 DAG.getVectorIdxConstant(0, DL));
12594 return DAG.getMergeValues({Value, SDValue(Op.getNode(), 1)}, DL);
12595 }
12596
12597 return DAG.getMemIntrinsicNode(Opcode, DL, VTList, Ops, MemVT, MMO);
12598}
12599
12600SDValue SITargetLowering::handleD16VData(SDValue VData, SelectionDAG &DAG,
12601 bool ImageStore) const {
12602 EVT StoreVT = VData.getValueType();
12603
12604 // No change for f16 and legal vector D16 types.
12605 if (!StoreVT.isVector())
12606 return VData;
12607
12608 SDLoc DL(VData);
12609 unsigned NumElements = StoreVT.getVectorNumElements();
12610
12611 if (Subtarget->hasUnpackedD16VMem()) {
12612 // We need to unpack the packed data to store.
12613 EVT IntStoreVT = StoreVT.changeTypeToInteger();
12614 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12615
12616 EVT EquivStoreVT =
12617 EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumElements);
12618 SDValue ZExt = DAG.getNode(ISD::ZERO_EXTEND, DL, EquivStoreVT, IntVData);
12619 return DAG.UnrollVectorOp(ZExt.getNode());
12620 }
12621
12622 // The sq block of gfx8.1 does not estimate register use correctly for d16
12623 // image store instructions. The data operand is computed as if it were not a
12624 // d16 image instruction.
12625 if (ImageStore && Subtarget->hasImageStoreD16Bug()) {
12626 // Bitcast to i16
12627 EVT IntStoreVT = StoreVT.changeTypeToInteger();
12628 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12629
12630 // Decompose into scalars
12632 DAG.ExtractVectorElements(IntVData, Elts);
12633
12634 // Group pairs of i16 into v2i16 and bitcast to i32
12635 SmallVector<SDValue, 4> PackedElts;
12636 for (unsigned I = 0; I < Elts.size() / 2; I += 1) {
12637 SDValue Pair =
12638 DAG.getBuildVector(MVT::v2i16, DL, {Elts[I * 2], Elts[I * 2 + 1]});
12639 SDValue IntPair = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Pair);
12640 PackedElts.push_back(IntPair);
12641 }
12642 if ((NumElements % 2) == 1) {
12643 // Handle v3i16
12644 unsigned I = Elts.size() / 2;
12645 SDValue Pair = DAG.getBuildVector(MVT::v2i16, DL,
12646 {Elts[I * 2], DAG.getPOISON(MVT::i16)});
12647 SDValue IntPair = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Pair);
12648 PackedElts.push_back(IntPair);
12649 }
12650
12651 // Pad using UNDEF
12652 PackedElts.resize(Elts.size(), DAG.getPOISON(MVT::i32));
12653
12654 // Build final vector
12655 EVT VecVT =
12656 EVT::getVectorVT(*DAG.getContext(), MVT::i32, PackedElts.size());
12657 return DAG.getBuildVector(VecVT, DL, PackedElts);
12658 }
12659
12660 if (NumElements == 3) {
12661 EVT IntStoreVT =
12663 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12664
12665 EVT WidenedStoreVT = EVT::getVectorVT(
12666 *DAG.getContext(), StoreVT.getVectorElementType(), NumElements + 1);
12667 EVT WidenedIntVT = EVT::getIntegerVT(*DAG.getContext(),
12668 WidenedStoreVT.getStoreSizeInBits());
12669 SDValue ZExt = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenedIntVT, IntVData);
12670 return DAG.getNode(ISD::BITCAST, DL, WidenedStoreVT, ZExt);
12671 }
12672
12673 assert(isTypeLegal(StoreVT));
12674 return VData;
12675}
12676
12677static bool isAsyncLDSDMA(Intrinsic::ID Intr) {
12678 switch (Intr) {
12679 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12680 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12681 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12682 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
12683 case Intrinsic::amdgcn_load_async_to_lds:
12684 case Intrinsic::amdgcn_global_load_async_lds:
12685 return true;
12686 }
12687 return false;
12688}
12689
12690SDValue SITargetLowering::LowerINTRINSIC_VOID(SDValue Op,
12691 SelectionDAG &DAG) const {
12692 SDLoc DL(Op);
12693 SDValue Chain = Op.getOperand(0);
12694 unsigned IntrinsicID = Op.getConstantOperandVal(1);
12695
12696 switch (IntrinsicID) {
12697 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
12698 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
12699 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
12700 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
12701 if (Subtarget->hasGFX1250_STRICT())
12703 return SDValue();
12704 }
12705 case Intrinsic::amdgcn_exp_compr: {
12706 SDValue Src0 = Op.getOperand(4);
12707 SDValue Src1 = Op.getOperand(5);
12708 // Hack around illegal type on SI by directly selecting it.
12709 if (isTypeLegal(Src0.getValueType()))
12710 return SDValue();
12711
12712 const ConstantSDNode *Done = cast<ConstantSDNode>(Op.getOperand(6));
12713 SDValue Undef = DAG.getPOISON(MVT::f32);
12714 const SDValue Ops[] = {
12715 Op.getOperand(2), // tgt
12716 DAG.getNode(ISD::BITCAST, DL, MVT::f32, Src0), // src0
12717 DAG.getNode(ISD::BITCAST, DL, MVT::f32, Src1), // src1
12718 Undef, // src2
12719 Undef, // src3
12720 Op.getOperand(7), // vm
12721 DAG.getTargetConstant(1, DL, MVT::i1), // compr
12722 Op.getOperand(3), // en
12723 Op.getOperand(0) // Chain
12724 };
12725
12726 unsigned Opc = Done->isZero() ? AMDGPU::EXP : AMDGPU::EXP_DONE;
12727 return SDValue(DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops), 0);
12728 }
12729
12730 case Intrinsic::amdgcn_struct_tbuffer_store:
12731 case Intrinsic::amdgcn_struct_ptr_tbuffer_store: {
12732 SDValue VData = Op.getOperand(2);
12733 bool IsD16 = (VData.getValueType().getScalarSizeInBits() == 16);
12734 if (IsD16)
12735 VData = handleD16VData(VData, DAG);
12736 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12737 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12738 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12739 SDValue Ops[] = {
12740 Chain,
12741 VData, // vdata
12742 Rsrc, // rsrc
12743 Op.getOperand(4), // vindex
12744 VOffset, // voffset
12745 SOffset, // soffset
12746 Offset, // offset
12747 Op.getOperand(7), // format
12748 Op.getOperand(8), // cachepolicy, swizzled buffer
12749 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12750 };
12751 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12752 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12753 MemSDNode *M = cast<MemSDNode>(Op);
12754 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12755 M->getMemoryVT(), M->getMemOperand());
12756 }
12757
12758 case Intrinsic::amdgcn_raw_tbuffer_store:
12759 case Intrinsic::amdgcn_raw_ptr_tbuffer_store: {
12760 SDValue VData = Op.getOperand(2);
12761 bool IsD16 = (VData.getValueType().getScalarSizeInBits() == 16);
12762 if (IsD16)
12763 VData = handleD16VData(VData, DAG);
12764 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12765 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12766 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12767 SDValue Ops[] = {
12768 Chain,
12769 VData, // vdata
12770 Rsrc, // rsrc
12771 DAG.getConstant(0, DL, MVT::i32), // vindex
12772 VOffset, // voffset
12773 SOffset, // soffset
12774 Offset, // offset
12775 Op.getOperand(6), // format
12776 Op.getOperand(7), // cachepolicy, swizzled buffer
12777 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12778 };
12779 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12780 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12781 MemSDNode *M = cast<MemSDNode>(Op);
12782 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12783 M->getMemoryVT(), M->getMemOperand());
12784 }
12785
12786 case Intrinsic::amdgcn_raw_buffer_store:
12787 case Intrinsic::amdgcn_raw_ptr_buffer_store:
12788 case Intrinsic::amdgcn_raw_buffer_store_format:
12789 case Intrinsic::amdgcn_raw_ptr_buffer_store_format: {
12790 const bool IsFormat =
12791 IntrinsicID == Intrinsic::amdgcn_raw_buffer_store_format ||
12792 IntrinsicID == Intrinsic::amdgcn_raw_ptr_buffer_store_format;
12793
12794 SDValue VData = Op.getOperand(2);
12795 EVT VDataVT = VData.getValueType();
12796 EVT EltType = VDataVT.getScalarType();
12797 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
12798
12799 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
12800 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
12802 "unsupported sub-dword format buffer store", DL.getDebugLoc()));
12803 return Chain;
12804 }
12805
12806 if (IsD16) {
12807 VData = handleD16VData(VData, DAG);
12808 VDataVT = VData.getValueType();
12809 }
12810
12811 if (!isTypeLegal(VDataVT)) {
12812 VData =
12813 DAG.getNode(ISD::BITCAST, DL,
12814 getEquivalentMemType(*DAG.getContext(), VDataVT), VData);
12815 }
12816
12817 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12818 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12819 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12820 SDValue Ops[] = {
12821 Chain,
12822 VData,
12823 Rsrc,
12824 DAG.getConstant(0, DL, MVT::i32), // vindex
12825 VOffset, // voffset
12826 SOffset, // soffset
12827 Offset, // offset
12828 Op.getOperand(6), // cachepolicy, swizzled buffer
12829 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12830 };
12831 unsigned Opc =
12832 IsFormat ? AMDGPUISD::BUFFER_STORE_FORMAT : AMDGPUISD::BUFFER_STORE;
12833 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 : Opc;
12834 MemSDNode *M = cast<MemSDNode>(Op);
12835
12836 // Handle BUFFER_STORE_BYTE/SHORT overloaded intrinsics
12837 if (!IsD16 && !VDataVT.isVector() && EltType.getSizeInBits() < 32)
12838 return handleByteShortBufferStores(DAG, VDataVT, DL, Ops, M);
12839
12840 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12841 M->getMemoryVT(), M->getMemOperand());
12842 }
12843
12844 case Intrinsic::amdgcn_struct_buffer_store:
12845 case Intrinsic::amdgcn_struct_ptr_buffer_store:
12846 case Intrinsic::amdgcn_struct_buffer_store_format:
12847 case Intrinsic::amdgcn_struct_ptr_buffer_store_format: {
12848 const bool IsFormat =
12849 IntrinsicID == Intrinsic::amdgcn_struct_buffer_store_format ||
12850 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_store_format;
12851
12852 SDValue VData = Op.getOperand(2);
12853 EVT VDataVT = VData.getValueType();
12854 EVT EltType = VDataVT.getScalarType();
12855 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
12856
12857 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
12858 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
12860 "unsupported sub-dword format buffer store", DL.getDebugLoc()));
12861 return Chain;
12862 }
12863
12864 if (IsD16) {
12865 VData = handleD16VData(VData, DAG);
12866 VDataVT = VData.getValueType();
12867 }
12868
12869 if (!isTypeLegal(VDataVT)) {
12870 VData =
12871 DAG.getNode(ISD::BITCAST, DL,
12872 getEquivalentMemType(*DAG.getContext(), VDataVT), VData);
12873 }
12874
12875 auto Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12876 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12877 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12878 SDValue Ops[] = {
12879 Chain,
12880 VData,
12881 Rsrc,
12882 Op.getOperand(4), // vindex
12883 VOffset, // voffset
12884 SOffset, // soffset
12885 Offset, // offset
12886 Op.getOperand(7), // cachepolicy, swizzled buffer
12887 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12888 };
12889 unsigned Opc =
12890 !IsFormat ? AMDGPUISD::BUFFER_STORE : AMDGPUISD::BUFFER_STORE_FORMAT;
12891 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 : Opc;
12892 MemSDNode *M = cast<MemSDNode>(Op);
12893
12894 // Handle BUFFER_STORE_BYTE/SHORT overloaded intrinsics
12895 EVT VDataType = VData.getValueType().getScalarType();
12896 if (!IsD16 && !VDataVT.isVector() && EltType.getSizeInBits() < 32)
12897 return handleByteShortBufferStores(DAG, VDataType, DL, Ops, M);
12898
12899 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12900 M->getMemoryVT(), M->getMemOperand());
12901 }
12902 case Intrinsic::amdgcn_raw_buffer_load_lds:
12903 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12904 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
12905 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12906 case Intrinsic::amdgcn_struct_buffer_load_lds:
12907 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12908 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
12909 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
12910 unsigned Opc;
12911 bool HasVIndex =
12912 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_lds ||
12913 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_async_lds ||
12914 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_lds ||
12915 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds;
12916 unsigned OpOffset = HasVIndex ? 1 : 0;
12917 SDValue VOffset = Op.getOperand(5 + OpOffset);
12918 bool HasVOffset = !isNullConstant(VOffset);
12919 unsigned Size = Op->getConstantOperandVal(4);
12920
12921 switch (Size) {
12922 default:
12923 return SDValue();
12924 case 1:
12925 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
12926 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
12927 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
12928 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
12929 break;
12930 case 2:
12931 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
12932 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
12933 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
12934 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
12935 break;
12936 case 4:
12937 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
12938 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
12939 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
12940 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
12941 break;
12942 case 12:
12943 if (!Subtarget->hasLDSLoadB96_B128())
12944 return SDValue();
12945 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
12946 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
12947 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
12948 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
12949 break;
12950 case 16:
12951 if (!Subtarget->hasLDSLoadB96_B128())
12952 return SDValue();
12953 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
12954 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
12955 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
12956 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
12957 break;
12958 }
12959
12960 SDValue M0Val = copyToM0(DAG, Chain, DL, Op.getOperand(3));
12961
12963
12964 if (HasVIndex && HasVOffset)
12965 Ops.push_back(DAG.getBuildVector(MVT::v2i32, DL,
12966 {Op.getOperand(5), // VIndex
12967 VOffset}));
12968 else if (HasVIndex)
12969 Ops.push_back(Op.getOperand(5));
12970 else if (HasVOffset)
12971 Ops.push_back(VOffset);
12972
12973 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12974 Ops.push_back(Rsrc);
12975 Ops.push_back(Op.getOperand(6 + OpOffset)); // soffset
12976 Ops.push_back(Op.getOperand(7 + OpOffset)); // imm offset
12977 bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
12978 unsigned Aux = Op.getConstantOperandVal(8 + OpOffset);
12979 Ops.push_back(DAG.getTargetConstant(
12980 Aux & (IsGFX12Plus ? AMDGPU::CPol::ALL : AMDGPU::CPol::ALL_pregfx12),
12981 DL, MVT::i16)); // cpol
12982 Ops.push_back(DAG.getTargetConstant(
12983 Aux & (IsGFX12Plus ? AMDGPU::CPol::SWZ : AMDGPU::CPol::SWZ_pregfx12)
12984 ? 1
12985 : 0,
12986 DL, MVT::i8)); // swz
12987 Ops.push_back(
12988 DAG.getTargetConstant(isAsyncLDSDMA(IntrinsicID), DL, MVT::i8));
12989 Ops.push_back(M0Val.getValue(0)); // Chain
12990 Ops.push_back(M0Val.getValue(1)); // Glue
12991
12992 auto *M = cast<MemSDNode>(Op);
12993 auto *Load = DAG.getMachineNode(Opc, DL, M->getVTList(), Ops);
12994 DAG.setNodeMemRefs(Load, M->memoperands());
12995
12996 return SDValue(Load, 0);
12997 }
12998 // Buffers are handled by LowerBufferFatPointers, and we're going to go
12999 // for "trust me" that the remaining cases are global pointers until
13000 // such time as we can put two mem operands on an intrinsic.
13001 case Intrinsic::amdgcn_load_to_lds:
13002 case Intrinsic::amdgcn_load_async_to_lds:
13003 case Intrinsic::amdgcn_global_load_lds:
13004 case Intrinsic::amdgcn_global_load_async_lds: {
13005 if (!Subtarget->hasVMemToLDSLoad())
13006 return SDValue();
13007
13008 unsigned Opc;
13009 unsigned Size = Op->getConstantOperandVal(4);
13010 switch (Size) {
13011 default:
13012 return SDValue();
13013 case 1:
13014 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
13015 break;
13016 case 2:
13017 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
13018 break;
13019 case 4:
13020 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
13021 break;
13022 case 12:
13023 if (!Subtarget->hasLDSLoadB96_B128())
13024 return SDValue();
13025 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
13026 break;
13027 case 16:
13028 if (!Subtarget->hasLDSLoadB96_B128())
13029 return SDValue();
13030 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
13031 break;
13032 }
13033
13034 SDValue M0Val = copyToM0(DAG, Chain, DL, Op.getOperand(3));
13035
13037
13038 SDValue Addr = Op.getOperand(2); // Global ptr
13039 SDValue VOffset;
13040 // Try to split SAddr and VOffset. Global and LDS pointers share the same
13041 // immediate offset, so we cannot use a regular SelectGlobalSAddr().
13042 if (Addr->isDivergent() && Addr->isAnyAdd()) {
13043 SDValue LHS = Addr.getOperand(0);
13044 SDValue RHS = Addr.getOperand(1);
13045
13046 if (LHS->isDivergent())
13047 std::swap(LHS, RHS);
13048
13049 if (!LHS->isDivergent() && RHS.getOpcode() == ISD::ZERO_EXTEND &&
13050 RHS.getOperand(0).getValueType() == MVT::i32) {
13051 // add (i64 sgpr), (zero_extend (i32 vgpr))
13052 Addr = LHS;
13053 VOffset = RHS.getOperand(0);
13054 }
13055 }
13056
13057 Ops.push_back(Addr);
13058 if (!Addr->isDivergent()) {
13060 if (!VOffset)
13061 VOffset =
13062 SDValue(DAG.getMachineNode(AMDGPU::V_MOV_B32_e32, DL, MVT::i32,
13063 DAG.getTargetConstant(0, DL, MVT::i32)),
13064 0);
13065 Ops.push_back(VOffset);
13066 }
13067
13068 Ops.push_back(Op.getOperand(5)); // Offset
13069
13070 unsigned Aux = Op.getConstantOperandVal(6);
13071 Ops.push_back(DAG.getTargetConstant(Aux & ~AMDGPU::CPol::VIRTUAL_BITS, DL,
13072 MVT::i32)); // CPol
13073 Ops.push_back(
13074 DAG.getTargetConstant(isAsyncLDSDMA(IntrinsicID), DL, MVT::i8));
13075
13076 Ops.push_back(M0Val.getValue(0)); // Chain
13077 Ops.push_back(M0Val.getValue(1)); // Glue
13078
13079 auto *M = cast<MemSDNode>(Op);
13080 auto *Load = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13081 DAG.setNodeMemRefs(Load, M->memoperands());
13082
13083 return SDValue(Load, 0);
13084 }
13085 case Intrinsic::amdgcn_end_cf:
13086 return SDValue(DAG.getMachineNode(AMDGPU::SI_END_CF, DL, MVT::Other,
13087 Op->getOperand(2), Chain),
13088 0);
13089 case Intrinsic::amdgcn_s_barrier_signal_var: {
13090 // Member count of 0 means to re-use a previous member count,
13091 // which, if the named barrier is statically chosen, means we can use
13092 // the immarg form. Otherwisee, fall through to constructiong M0 as for
13093 // s_barrier_init.
13094 SDValue CntOp = Op->getOperand(3);
13095 auto *CntC = dyn_cast<ConstantSDNode>(CntOp);
13096 if (CntC && CntC->isZero()) {
13097 SDValue Chain = Op->getOperand(0);
13098 SDValue BarOp = Op->getOperand(2);
13100
13101 std::optional<uint64_t> BarVal;
13102 if (auto *C = dyn_cast<ConstantSDNode>(BarOp))
13103 BarVal = C->getZExtValue();
13104 else if (auto *GA = dyn_cast<GlobalAddressSDNode>(BarOp))
13106 *GA->getGlobal(), AMDGPUAS::BARRIER))
13107 BarVal = *Addr + GA->getOffset();
13108
13109 if (BarVal) {
13110 unsigned BarID = *BarVal & 0x3F;
13111 Ops.push_back(DAG.getTargetConstant(BarID, DL, MVT::i32));
13112 Ops.push_back(Chain);
13113 auto *NewMI = DAG.getMachineNode(AMDGPU::S_BARRIER_SIGNAL_IMM, DL,
13114 Op->getVTList(), Ops);
13115 return SDValue(NewMI, 0);
13116 }
13117 }
13118 [[fallthrough]];
13119 }
13120 case Intrinsic::amdgcn_s_barrier_init: {
13121 // these two intrinsics have two operands: barrier pointer and member count
13122 SDValue Chain = Op->getOperand(0);
13124 SDValue BarOp = Op->getOperand(2);
13125 SDValue CntOp = Op->getOperand(3);
13126 SDValue M0Val;
13127 unsigned Opc = IntrinsicID == Intrinsic::amdgcn_s_barrier_init
13128 ? AMDGPU::S_BARRIER_INIT_M0
13129 : AMDGPU::S_BARRIER_SIGNAL_M0;
13130 // extract the BarrierID from bits 0-5 of BarOp
13131 SDValue BarID = DAG.getNode(ISD::AND, DL, MVT::i32, BarOp,
13132 DAG.getConstant(0x3F, DL, MVT::i32));
13133 // Member count should be put into M0[ShAmt:+CntMask width]
13134 // Barrier ID should be put into M0[5:0]
13135 unsigned CntMask = AMDGPU::getBarrierMemberCountBitMask(
13136 AMDGPU::getIsaVersion(Subtarget->getCPU()));
13137 SDValue MemberCnt = DAG.getNode(ISD::AND, DL, MVT::i32, CntOp,
13138 DAG.getConstant(CntMask, DL, MVT::i32));
13139 constexpr unsigned ShAmt = 16;
13140 M0Val = DAG.getNode(ISD::SHL, DL, MVT::i32, MemberCnt,
13141 DAG.getShiftAmountConstant(ShAmt, MVT::i32, DL));
13142
13143 M0Val = DAG.getNode(ISD::OR, DL, MVT::i32, M0Val, BarID);
13144
13145 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
13146
13147 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13148 return SDValue(NewMI, 0);
13149 }
13150 case Intrinsic::amdgcn_s_wakeup_barrier: {
13151 if (!Subtarget->hasSWakeupBarrier())
13152 return SDValue();
13153 [[fallthrough]];
13154 }
13155 case Intrinsic::amdgcn_s_barrier_join: {
13156 // these three intrinsics have one operand: barrier pointer
13157 SDValue Chain = Op->getOperand(0);
13159 SDValue BarOp = Op->getOperand(2);
13160 unsigned Opc;
13161
13162 if (isa<ConstantSDNode>(BarOp)) {
13163 uint64_t BarVal = cast<ConstantSDNode>(BarOp)->getZExtValue();
13164 switch (IntrinsicID) {
13165 default:
13166 return SDValue();
13167 case Intrinsic::amdgcn_s_barrier_join:
13168 Opc = AMDGPU::S_BARRIER_JOIN_IMM;
13169 break;
13170 case Intrinsic::amdgcn_s_wakeup_barrier:
13171 Opc = AMDGPU::S_WAKEUP_BARRIER_IMM;
13172 break;
13173 }
13174 // extract the BarrierID from bits 0-5 of the immediate
13175 unsigned BarID = BarVal & 0x3F;
13176 SDValue K = DAG.getTargetConstant(BarID, DL, MVT::i32);
13177 Ops.push_back(K);
13178 Ops.push_back(Chain);
13179 } else {
13180 switch (IntrinsicID) {
13181 default:
13182 return SDValue();
13183 case Intrinsic::amdgcn_s_barrier_join:
13184 Opc = AMDGPU::S_BARRIER_JOIN_M0;
13185 break;
13186 case Intrinsic::amdgcn_s_wakeup_barrier:
13187 Opc = AMDGPU::S_WAKEUP_BARRIER_M0;
13188 break;
13189 }
13190 // extract the BarrierID from bits 0-5 of BarOp, copy to M0[5:0]
13191 SDValue M0Val = DAG.getNode(ISD::AND, DL, MVT::i32, BarOp,
13192 DAG.getConstant(0x3F, DL, MVT::i32));
13193 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
13194 }
13195
13196 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13197 return SDValue(NewMI, 0);
13198 }
13199 case Intrinsic::amdgcn_s_prefetch_data:
13200 case Intrinsic::amdgcn_s_prefetch_inst: {
13201 // For non-global address space preserve the chain and remove the call.
13203 return Op.getOperand(0);
13204 return Op;
13205 }
13206 case Intrinsic::amdgcn_s_buffer_prefetch_data: {
13207 SDValue Ops[] = {
13208 Chain, bufferRsrcPtrToVector(Op.getOperand(2), DAG),
13209 Op.getOperand(3), // offset
13210 Op.getOperand(4), // length
13211 };
13212
13213 MemSDNode *M = cast<MemSDNode>(Op);
13214 return DAG.getMemIntrinsicNode(AMDGPUISD::SBUFFER_PREFETCH_DATA, DL,
13215 Op->getVTList(), Ops, M->getMemoryVT(),
13216 M->getMemOperand());
13217 }
13218 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
13219 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
13220 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
13221 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
13222 SDValue Chain = Op->getOperand(0);
13223 SDValue Ptr = Op->getOperand(2);
13224 SDValue Val = Op->getOperand(3);
13225 return DAG.getAtomic(ISD::ATOMIC_STORE, DL, MII->getMemoryVT(), Chain, Val,
13226 Ptr, MII->getMemOperand());
13227 }
13228 case Intrinsic::amdgcn_av_store_b128: {
13229 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
13230 SDValue Chain = Op->getOperand(0);
13231 SDValue Ptr = Op->getOperand(2);
13232 SDValue Val = Op->getOperand(3);
13233 return DAG.getStore(Chain, DL, Val, Ptr, MII->getMemOperand());
13234 }
13235 default: {
13236 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
13238 return lowerImage(Op, ImageDimIntr, DAG, true);
13239
13240 return Op;
13241 }
13242 }
13243}
13244
13245// Return whether the operation has NoUnsignedWrap property.
13246static bool isNoUnsignedWrap(SDValue Addr) {
13247 return (Addr.getOpcode() == ISD::ADD &&
13248 Addr->getFlags().hasNoUnsignedWrap()) ||
13249 Addr->getOpcode() == ISD::OR;
13250}
13251
13253 EVT PtrVT) const {
13254 return PtrVT == MVT::i64;
13255}
13256
13258 EVT PtrVT) const {
13259 return true;
13260}
13261
13262// The raw.(t)buffer and struct.(t)buffer intrinsics have two offset args:
13263// offset (the offset that is included in bounds checking and swizzling, to be
13264// split between the instruction's voffset and immoffset fields) and soffset
13265// (the offset that is excluded from bounds checking and swizzling, to go in
13266// the instruction's soffset field). This function takes the first kind of
13267// offset and figures out how to split it between voffset and immoffset.
13268std::pair<SDValue, SDValue>
13269SITargetLowering::splitBufferOffsets(SDValue Offset, SelectionDAG &DAG) const {
13270 SDLoc DL(Offset);
13271 const unsigned MaxImm = SIInstrInfo::getMaxMUBUFImmOffset(*Subtarget);
13272 SDValue N0 = Offset;
13273 ConstantSDNode *C1 = nullptr;
13274
13275 if ((C1 = dyn_cast<ConstantSDNode>(N0)))
13276 N0 = SDValue();
13277 else if (DAG.isBaseWithConstantOffset(N0)) {
13278 // On GFX1250+, voffset and immoffset are zero-extended from 32 bits before
13279 // being added, so we can only safely match a 32-bit addition with no
13280 // unsigned overflow.
13281 bool CheckNUW = Subtarget->hasGFX1250Insts();
13282 if (!CheckNUW || isNoUnsignedWrap(N0)) {
13283 C1 = cast<ConstantSDNode>(N0.getOperand(1));
13284 N0 = N0.getOperand(0);
13285 }
13286 }
13287
13288 if (C1) {
13289 unsigned ImmOffset = C1->getZExtValue();
13290 // If the immediate value is too big for the immoffset field, put only bits
13291 // that would normally fit in the immoffset field. The remaining value that
13292 // is copied/added for the voffset field is a large power of 2, and it
13293 // stands more chance of being CSEd with the copy/add for another similar
13294 // load/store.
13295 // However, do not do that rounding down if that is a negative
13296 // number, as it appears to be illegal to have a negative offset in the
13297 // vgpr, even if adding the immediate offset makes it positive.
13298 unsigned Overflow = ImmOffset & ~MaxImm;
13299 ImmOffset -= Overflow;
13300 if ((int32_t)Overflow < 0) {
13301 Overflow += ImmOffset;
13302 ImmOffset = 0;
13303 }
13304 C1 = cast<ConstantSDNode>(DAG.getTargetConstant(ImmOffset, DL, MVT::i32));
13305 if (Overflow) {
13306 auto OverflowVal = DAG.getConstant(Overflow, DL, MVT::i32);
13307 if (!N0)
13308 N0 = OverflowVal;
13309 else {
13310 SDValue Ops[] = {N0, OverflowVal};
13311 N0 = DAG.getNode(ISD::ADD, DL, MVT::i32, Ops);
13312 }
13313 }
13314 }
13315 if (!N0)
13316 N0 = DAG.getConstant(0, DL, MVT::i32);
13317 if (!C1)
13318 C1 = cast<ConstantSDNode>(DAG.getTargetConstant(0, DL, MVT::i32));
13319 return {N0, SDValue(C1, 0)};
13320}
13321
13322// Analyze a combined offset from an amdgcn_s_buffer_load intrinsic and store
13323// the three offsets (voffset, soffset and instoffset) into the SDValue[3] array
13324// pointed to by Offsets.
13325void SITargetLowering::setBufferOffsets(SDValue CombinedOffset,
13326 SelectionDAG &DAG, SDValue *Offsets,
13327 Align Alignment) const {
13328 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
13329 SDLoc DL(CombinedOffset);
13330 if (auto *C = dyn_cast<ConstantSDNode>(CombinedOffset)) {
13331 uint32_t Imm = C->getZExtValue();
13332 uint32_t SOffset, ImmOffset;
13333 if (TII->splitMUBUFOffset(Imm, SOffset, ImmOffset, Alignment)) {
13334 Offsets[0] = DAG.getConstant(0, DL, MVT::i32);
13335 Offsets[1] = DAG.getConstant(SOffset, DL, MVT::i32);
13336 Offsets[2] = DAG.getTargetConstant(ImmOffset, DL, MVT::i32);
13337 return;
13338 }
13339 }
13340 if (DAG.isBaseWithConstantOffset(CombinedOffset)) {
13341 // On GFX1250+, voffset and immoffset are zero-extended from 32 bits before
13342 // being added, so we can only safely match a 32-bit addition with no
13343 // unsigned overflow.
13344 bool CheckNUW = Subtarget->hasGFX1250Insts();
13345 SDValue N0 = CombinedOffset.getOperand(0);
13346 SDValue N1 = CombinedOffset.getOperand(1);
13347 uint32_t SOffset, ImmOffset;
13348 int Offset = cast<ConstantSDNode>(N1)->getSExtValue();
13349 if (Offset >= 0 && (!CheckNUW || isNoUnsignedWrap(CombinedOffset)) &&
13350 TII->splitMUBUFOffset(Offset, SOffset, ImmOffset, Alignment)) {
13351 Offsets[0] = N0;
13352 Offsets[1] = DAG.getConstant(SOffset, DL, MVT::i32);
13353 Offsets[2] = DAG.getTargetConstant(ImmOffset, DL, MVT::i32);
13354 return;
13355 }
13356 }
13357
13358 SDValue SOffsetZero = Subtarget->hasRestrictedSOffset()
13359 ? DAG.getRegister(AMDGPU::SGPR_NULL, MVT::i32)
13360 : DAG.getConstant(0, DL, MVT::i32);
13361
13362 Offsets[0] = CombinedOffset;
13363 Offsets[1] = SOffsetZero;
13364 Offsets[2] = DAG.getTargetConstant(0, DL, MVT::i32);
13365}
13366
13367SDValue SITargetLowering::bufferRsrcPtrToVector(SDValue MaybePointer,
13368 SelectionDAG &DAG) const {
13369 if (!MaybePointer.getValueType().isScalarInteger())
13370 return MaybePointer;
13371
13372 SDValue Rsrc = DAG.getBitcast(MVT::v4i32, MaybePointer);
13373 return Rsrc;
13374}
13375
13376// Wrap a global or flat pointer into a buffer intrinsic using the flags
13377// specified in the intrinsic.
13378SDValue SITargetLowering::lowerPointerAsRsrcIntrin(SDNode *Op,
13379 SelectionDAG &DAG) const {
13380 SDLoc Loc(Op);
13381
13382 SDValue Pointer = Op->getOperand(1);
13383 SDValue Stride = Op->getOperand(2);
13384 SDValue NumRecords = Op->getOperand(3);
13385 SDValue Flags = Op->getOperand(4);
13386
13387 SDValue ExtStride = DAG.getAnyExtOrTrunc(Stride, Loc, MVT::i32);
13388 SDValue Rsrc;
13389
13390 if (Subtarget->getBufferResourceNumRecordsWidth() == 45) {
13391 NumRecords = DAG.getZExtOrTrunc(NumRecords, Loc, MVT::i64);
13392 NumRecords = DAG.getNode(ISD::AND, Loc, MVT::i64, NumRecords,
13393 DAG.getConstant((1ULL << 45) - 1, Loc, MVT::i64));
13394 SDValue Zero = DAG.getConstant(0, Loc, MVT::i32);
13395 // Build the lower 64-bit value, which has a 57-bit base and the lower 7-bit
13396 // num_records.
13397 SDValue ExtPointer = DAG.getAnyExtOrTrunc(Pointer, Loc, MVT::i64);
13398 SDValue NumRecordsLHS =
13399 DAG.getNode(ISD::SHL, Loc, MVT::i64, NumRecords,
13400 DAG.getShiftAmountConstant(57, MVT::i32, Loc));
13401 SDValue LowHalf =
13402 DAG.getNode(ISD::OR, Loc, MVT::i64, ExtPointer, NumRecordsLHS);
13403
13404 // Build the higher 64-bit value, which has the higher 38-bit num_records,
13405 // 6-bit zero (omit), 16-bit stride and scale and 4-bit flag.
13406 SDValue NumRecordsRHS =
13407 DAG.getNode(ISD::SRL, Loc, MVT::i64, NumRecords,
13408 DAG.getShiftAmountConstant(7, MVT::i32, Loc));
13409 SDValue ShiftedStride =
13410 DAG.getNode(ISD::SHL, Loc, MVT::i32, ExtStride,
13411 DAG.getShiftAmountConstant(12, MVT::i32, Loc));
13412 SDValue ExtShiftedStrideVec =
13413 DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i32, Zero, ShiftedStride);
13414 SDValue ExtShiftedStride =
13415 DAG.getNode(ISD::BITCAST, Loc, MVT::i64, ExtShiftedStrideVec);
13416 SDValue ShiftedFlags =
13417 DAG.getNode(ISD::SHL, Loc, MVT::i32, Flags,
13418 DAG.getShiftAmountConstant(28, MVT::i32, Loc));
13419 SDValue ExtShiftedFlagsVec =
13420 DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i32, Zero, ShiftedFlags);
13421 SDValue ExtShiftedFlags =
13422 DAG.getNode(ISD::BITCAST, Loc, MVT::i64, ExtShiftedFlagsVec);
13423 SDValue CombinedFields =
13424 DAG.getNode(ISD::OR, Loc, MVT::i64, NumRecordsRHS, ExtShiftedStride);
13425 SDValue HighHalf =
13426 DAG.getNode(ISD::OR, Loc, MVT::i64, CombinedFields, ExtShiftedFlags);
13427
13428 Rsrc = DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i64, LowHalf, HighHalf);
13429 } else {
13430 NumRecords = DAG.getZExtOrTrunc(NumRecords, Loc, MVT::i32);
13431 auto [LowHalf, HighHalf] =
13432 DAG.SplitScalar(Pointer, Loc, MVT::i32, MVT::i32);
13433 SDValue Mask = DAG.getConstant(0x0000ffff, Loc, MVT::i32);
13434 SDValue Masked = DAG.getNode(ISD::AND, Loc, MVT::i32, HighHalf, Mask);
13435 SDValue ShiftedStride =
13436 DAG.getNode(ISD::SHL, Loc, MVT::i32, ExtStride,
13437 DAG.getShiftAmountConstant(16, MVT::i32, Loc));
13438 SDValue NewHighHalf =
13439 DAG.getNode(ISD::OR, Loc, MVT::i32, Masked, ShiftedStride);
13440
13441 Rsrc = DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v4i32, LowHalf, NewHighHalf,
13442 NumRecords, Flags);
13443 }
13444
13445 SDValue RsrcPtr = DAG.getNode(ISD::BITCAST, Loc, MVT::i128, Rsrc);
13446 return RsrcPtr;
13447}
13448
13449// Handle 8 bit and 16 bit buffer loads
13450SDValue SITargetLowering::handleByteShortBufferLoads(SelectionDAG &DAG,
13451 EVT LoadVT, SDLoc DL,
13453 MachineMemOperand *MMO,
13454 bool IsTFE) const {
13455 EVT IntVT = LoadVT.changeTypeToInteger();
13456
13457 if (IsTFE) {
13458 unsigned Opc = (LoadVT.getScalarType() == MVT::i8)
13459 ? AMDGPUISD::BUFFER_LOAD_UBYTE_TFE
13460 : AMDGPUISD::BUFFER_LOAD_USHORT_TFE;
13462 MachineMemOperand *OpMMO = MF.getMachineMemOperand(MMO, 0, 8);
13463 SDVTList VTs = DAG.getVTList(MVT::v2i32, MVT::Other);
13464 SDValue Op = getMemIntrinsicNode(Opc, DL, VTs, Ops, MVT::v2i32, OpMMO, DAG);
13465 SDValue Status = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op,
13466 DAG.getConstant(1, DL, MVT::i32));
13467 SDValue Data = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op,
13468 DAG.getConstant(0, DL, MVT::i32));
13469 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, IntVT, Data);
13470 SDValue Value = DAG.getNode(ISD::BITCAST, DL, LoadVT, Trunc);
13471 return DAG.getMergeValues({Value, Status, SDValue(Op.getNode(), 1)}, DL);
13472 }
13473
13474 unsigned Opc = LoadVT.getScalarType() == MVT::i8
13475 ? AMDGPUISD::BUFFER_LOAD_UBYTE
13476 : AMDGPUISD::BUFFER_LOAD_USHORT;
13477
13478 SDVTList ResList = DAG.getVTList(MVT::i32, MVT::Other);
13479 SDValue BufferLoad =
13480 DAG.getMemIntrinsicNode(Opc, DL, ResList, Ops, IntVT, MMO);
13481 SDValue LoadVal = DAG.getNode(ISD::TRUNCATE, DL, IntVT, BufferLoad);
13482 LoadVal = DAG.getNode(ISD::BITCAST, DL, LoadVT, LoadVal);
13483
13484 return DAG.getMergeValues({LoadVal, BufferLoad.getValue(1)}, DL);
13485}
13486
13487// Handle 8 bit and 16 bit buffer stores
13488SDValue SITargetLowering::handleByteShortBufferStores(SelectionDAG &DAG,
13489 EVT VDataType, SDLoc DL,
13490 SDValue Ops[],
13491 MemSDNode *M) const {
13492 if (VDataType == MVT::f16 || VDataType == MVT::bf16)
13493 Ops[1] = DAG.getNode(ISD::BITCAST, DL, MVT::i16, Ops[1]);
13494
13495 SDValue BufferStoreExt = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Ops[1]);
13496 Ops[1] = BufferStoreExt;
13497 unsigned Opc = (VDataType == MVT::i8) ? AMDGPUISD::BUFFER_STORE_BYTE
13498 : AMDGPUISD::BUFFER_STORE_SHORT;
13499 ArrayRef<SDValue> OpsRef = ArrayRef(&Ops[0], 9);
13500 return DAG.getMemIntrinsicNode(Opc, DL, M->getVTList(), OpsRef, VDataType,
13501 M->getMemOperand());
13502}
13503
13505 SDValue Op, const SDLoc &SL, EVT VT) {
13506 if (VT.bitsLT(Op.getValueType()))
13507 return DAG.getNode(ISD::TRUNCATE, SL, VT, Op);
13508
13509 switch (ExtType) {
13510 case ISD::SEXTLOAD:
13511 return DAG.getNode(ISD::SIGN_EXTEND, SL, VT, Op);
13512 case ISD::ZEXTLOAD:
13513 return DAG.getNode(ISD::ZERO_EXTEND, SL, VT, Op);
13514 case ISD::EXTLOAD:
13515 return DAG.getNode(ISD::ANY_EXTEND, SL, VT, Op);
13516 case ISD::NON_EXTLOAD:
13517 return Op;
13518 }
13519
13520 llvm_unreachable("invalid ext type");
13521}
13522
13523// Try to turn 8 and 16-bit scalar loads into SMEM eligible 32-bit loads.
13524// TODO: Skip this on GFX12 which does have scalar sub-dword loads.
13525SDValue SITargetLowering::widenLoad(LoadSDNode *Ld,
13526 DAGCombinerInfo &DCI) const {
13527 SelectionDAG &DAG = DCI.DAG;
13528 if (Ld->getAlign() < Align(4) || Ld->isDivergent())
13529 return SDValue();
13530
13531 // FIXME: Constant loads should all be marked invariant.
13532 unsigned AS = Ld->getAddressSpace();
13533 if (AS != AMDGPUAS::CONSTANT_ADDRESS &&
13535 (AS != AMDGPUAS::GLOBAL_ADDRESS || !Ld->isInvariant()))
13536 return SDValue();
13537
13538 // Don't do this early, since it may interfere with adjacent load merging for
13539 // illegal types. We can avoid losing alignment information for exotic types
13540 // pre-legalize.
13541 EVT MemVT = Ld->getMemoryVT();
13542 if ((MemVT.isSimple() && !DCI.isAfterLegalizeDAG()) ||
13543 MemVT.getSizeInBits() >= 32)
13544 return SDValue();
13545
13546 SDLoc SL(Ld);
13547
13548 assert((!MemVT.isVector() || Ld->getExtensionType() == ISD::NON_EXTLOAD) &&
13549 "unexpected vector extload");
13550
13551 // TODO: Drop only high part of range.
13552 SDValue Ptr = Ld->getBasePtr();
13553 SDValue NewLoad = DAG.getLoad(
13554 ISD::UNINDEXED, ISD::NON_EXTLOAD, MVT::i32, SL, Ld->getChain(), Ptr,
13555 Ld->getOffset(), Ld->getPointerInfo(), MVT::i32, Ld->getAlign(),
13556 Ld->getMemOperand()->getFlags(), Ld->getAAInfo()); // Drop ranges
13557
13558 EVT TruncVT = EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits());
13559 if (MemVT.isFloatingPoint()) {
13560 assert(Ld->getExtensionType() == ISD::NON_EXTLOAD &&
13561 "unexpected fp extload");
13562 TruncVT = MemVT.changeTypeToInteger();
13563 }
13564
13565 SDValue Cvt = NewLoad;
13566 if (Ld->getExtensionType() == ISD::SEXTLOAD) {
13567 Cvt = DAG.getNode(ISD::SIGN_EXTEND_INREG, SL, MVT::i32, NewLoad,
13568 DAG.getValueType(TruncVT));
13569 } else if (Ld->getExtensionType() == ISD::ZEXTLOAD ||
13570 Ld->getExtensionType() == ISD::NON_EXTLOAD) {
13571 Cvt = DAG.getZeroExtendInReg(NewLoad, SL, TruncVT);
13572 } else {
13573 assert(Ld->getExtensionType() == ISD::EXTLOAD);
13574 }
13575
13576 EVT VT = Ld->getValueType(0);
13577 EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
13578
13579 DCI.AddToWorklist(Cvt.getNode());
13580
13581 // We may need to handle exotic cases, such as i16->i64 extloads, so insert
13582 // the appropriate extension from the 32-bit load.
13583 Cvt = getLoadExtOrTrunc(DAG, Ld->getExtensionType(), Cvt, SL, IntVT);
13584 DCI.AddToWorklist(Cvt.getNode());
13585
13586 // Handle conversion back to floating point if necessary.
13587 Cvt = DAG.getNode(ISD::BITCAST, SL, VT, Cvt);
13588
13589 return DAG.getMergeValues({Cvt, NewLoad.getValue(1)}, SL);
13590}
13591
13593 const SIMachineFunctionInfo &Info) {
13594 // TODO: Should check if the address can definitely not access stack.
13595 if (Info.isEntryFunction())
13596 return Info.getUserSGPRInfo().hasFlatScratchInit();
13597 return true;
13598}
13599
13600SDValue SITargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
13601 SDLoc DL(Op);
13602 LoadSDNode *Load = cast<LoadSDNode>(Op);
13603 ISD::LoadExtType ExtType = Load->getExtensionType();
13604 EVT MemVT = Load->getMemoryVT();
13605 MachineMemOperand *MMO = Load->getMemOperand();
13606
13607 if (ExtType == ISD::NON_EXTLOAD && MemVT.getSizeInBits() < 32) {
13608 // Legalize uniform 16-bit loads to i16 = trunc (zextload i16->i32)
13609 // to match subword load patterns.
13610 // Only do this for loads that can use scalar subword load instructions.
13611 if (!MemVT.isVector() && MemVT.getSizeInBits() == 16 &&
13612 isTypeLegal(MemVT) && Subtarget->hasScalarSubwordLoads() &&
13614 SDValue Chain = Load->getChain();
13615 SDValue BasePtr = Load->getBasePtr();
13616
13617 // Load as i16 and zero-extend to i32 (matches S_LOAD_U16 behavior)
13618 SDValue NewLD = DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain,
13619 BasePtr, MVT::i16, MMO);
13620
13621 // Truncate back to i16
13622 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, NewLD);
13623
13624 // For f16/bf16, bitcast from i16 to the original fp type
13625 SDValue Result = (MemVT == MVT::i16)
13626 ? Trunc
13627 : DAG.getNode(ISD::BITCAST, DL, MemVT, Trunc);
13628
13629 SDValue Ops[] = {Result, NewLD.getValue(1)};
13630 return DAG.getMergeValues(Ops, DL);
13631 }
13632
13633 if (MemVT == MVT::i16 && isTypeLegal(MVT::i16))
13634 return SDValue();
13635
13636 // FIXME: Copied from PPC
13637 // First, load into 32 bits, then truncate to 1 bit.
13638
13639 SDValue Chain = Load->getChain();
13640 SDValue BasePtr = Load->getBasePtr();
13641
13642 EVT RealMemVT = (MemVT == MVT::i1) ? MVT::i8 : MVT::i16;
13643
13644 SDValue NewLD = DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, BasePtr,
13645 RealMemVT, MMO);
13646
13647 if (!MemVT.isVector()) {
13648 SDValue Ops[] = {DAG.getNode(ISD::TRUNCATE, DL, MemVT, NewLD),
13649 NewLD.getValue(1)};
13650
13651 return DAG.getMergeValues(Ops, DL);
13652 }
13653
13655 for (unsigned I = 0, N = MemVT.getVectorNumElements(); I != N; ++I) {
13656 SDValue Elt = DAG.getNode(ISD::SRL, DL, MVT::i32, NewLD,
13657 DAG.getConstant(I, DL, MVT::i32));
13658
13659 Elts.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Elt));
13660 }
13661
13662 SDValue Ops[] = {DAG.getBuildVector(MemVT, DL, Elts), NewLD.getValue(1)};
13663
13664 return DAG.getMergeValues(Ops, DL);
13665 }
13666
13667 if (!MemVT.isVector())
13668 return SDValue();
13669
13670 assert(Op.getValueType().getVectorElementType() == MVT::i32 &&
13671 "Custom lowering for non-i32 vectors hasn't been implemented.");
13672
13673 Align Alignment = Load->getAlign();
13674 unsigned AS = Load->getAddressSpace();
13675 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
13676 AS == AMDGPUAS::FLAT_ADDRESS &&
13677 Alignment.value() < MemVT.getStoreSize() && MemVT.getSizeInBits() > 32) {
13678 return SplitVectorLoad(Op, DAG);
13679 }
13680
13682 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
13683 // If there is a possibility that flat instruction access scratch memory
13684 // then we need to use the same legalization rules we use for private.
13685 if (AS == AMDGPUAS::FLAT_ADDRESS &&
13686 !Subtarget->hasMultiDwordFlatScratchAddressing())
13687 AS = addressMayBeAccessedAsPrivate(Load->getMemOperand(), *MFI)
13690
13691 unsigned NumElements = MemVT.getVectorNumElements();
13692
13693 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
13695 (AS == AMDGPUAS::GLOBAL_ADDRESS && Load->isSimple() &&
13696 (Load->isInvariant() || isMemOpHasNoClobberedMemOperand(Load)))) {
13697 if ((!Op->isDivergent() || AMDGPU::isUniformMMO(MMO)) &&
13698 Alignment >= Align(4) && NumElements < 32) {
13699 if (MemVT.isPow2VectorType() ||
13700 (Subtarget->hasScalarDwordx3Loads() && NumElements == 3))
13701 return SDValue();
13702 return WidenOrSplitVectorLoad(Op, DAG);
13703 }
13704 // Non-uniform loads will be selected to MUBUF instructions, so they
13705 // have the same legalization requirements as global and private
13706 // loads.
13707 //
13708 }
13709 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
13712 if (NumElements > 4)
13713 return SplitVectorLoad(Op, DAG);
13714 // v3 loads not supported on SI.
13715 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13716 return WidenOrSplitVectorLoad(Op, DAG);
13717
13718 // v3 and v4 loads are supported for private and global memory.
13719 return SDValue();
13720 }
13721 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
13722 // Depending on the setting of the private_element_size field in the
13723 // resource descriptor, we can only make private accesses up to a certain
13724 // size.
13725 switch (Subtarget->getMaxPrivateElementSize()) {
13726 case 4: {
13727 auto [Op0, Op1] = scalarizeVectorLoad(Load, DAG);
13728 return DAG.getMergeValues({Op0, Op1}, DL);
13729 }
13730 case 8:
13731 if (NumElements > 2)
13732 return SplitVectorLoad(Op, DAG);
13733 return SDValue();
13734 case 16:
13735 // Same as global/flat
13736 if (NumElements > 4)
13737 return SplitVectorLoad(Op, DAG);
13738 // v3 loads not supported on SI.
13739 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13740 return WidenOrSplitVectorLoad(Op, DAG);
13741
13742 return SDValue();
13743 default:
13744 llvm_unreachable("unsupported private_element_size");
13745 }
13746 } else if (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::REGION_ADDRESS) {
13747 unsigned Fast = 0;
13748 auto Flags = Load->getMemOperand()->getFlags();
13750 Load->getAlign(), Flags, &Fast) &&
13751 Fast > 1)
13752 return SDValue();
13753
13754 if (MemVT.isVector())
13755 return SplitVectorLoad(Op, DAG);
13756 }
13757
13759 MemVT, *Load->getMemOperand())) {
13760 auto [Op0, Op1] = expandUnalignedLoad(Load, DAG);
13761 return DAG.getMergeValues({Op0, Op1}, DL);
13762 }
13763
13764 return SDValue();
13765}
13766
13767SDValue SITargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
13768 EVT VT = Op.getValueType();
13769 if (VT.getSizeInBits() == 128 || VT.getSizeInBits() == 256 ||
13770 VT.getSizeInBits() == 512)
13771 return splitTernaryVectorOp(Op, DAG);
13772
13773 assert(VT.getSizeInBits() == 64);
13774
13775 SDLoc DL(Op);
13776 SDValue Cond = DAG.getFreeze(Op.getOperand(0));
13777
13778 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
13779 SDValue One = DAG.getConstant(1, DL, MVT::i32);
13780
13781 SDValue LHS = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(1));
13782 SDValue RHS = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(2));
13783
13784 SDValue Lo0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, LHS, Zero);
13785 SDValue Lo1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, RHS, Zero);
13786
13787 SDValue Lo = DAG.getSelect(DL, MVT::i32, Cond, Lo0, Lo1);
13788
13789 SDValue Hi0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, LHS, One);
13790 SDValue Hi1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, RHS, One);
13791
13792 SDValue Hi = DAG.getSelect(DL, MVT::i32, Cond, Hi0, Hi1);
13793
13794 SDValue Res = DAG.getBuildVector(MVT::v2i32, DL, {Lo, Hi});
13795 return DAG.getNode(ISD::BITCAST, DL, VT, Res);
13796}
13797
13798// Catch division cases where we can use shortcuts with rcp and rsq
13799// instructions.
13800SDValue SITargetLowering::lowerFastUnsafeFDIV(SDValue Op,
13801 SelectionDAG &DAG) const {
13802 SDLoc SL(Op);
13803 SDValue LHS = Op.getOperand(0);
13804 SDValue RHS = Op.getOperand(1);
13805 EVT VT = Op.getValueType();
13806 const SDNodeFlags Flags = Op->getFlags();
13807
13808 bool AllowInaccurateRcp = Flags.hasApproximateFuncs();
13809
13810 if (const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(LHS)) {
13811 // Without !fpmath accuracy information, we can't do more because we don't
13812 // know exactly whether rcp is accurate enough to meet !fpmath requirement.
13813 // f16 is always accurate enough
13814 if (!AllowInaccurateRcp && VT != MVT::f16 && VT != MVT::bf16)
13815 return SDValue();
13816
13817 if (CLHS->isOne()) {
13818 // v_rcp_f32 and v_rsq_f32 do not support denormals, and according to
13819 // the CI documentation has a worst case error of 1 ulp.
13820 // OpenCL requires <= 2.5 ulp for 1.0 / x, so it should always be OK to
13821 // use it as long as we aren't trying to use denormals.
13822 //
13823 // v_rcp_f16 and v_rsq_f16 DO support denormals and 0.51ulp.
13824
13825 // 1.0 / sqrt(x) -> rsq(x)
13826
13827 // XXX - Is afn sufficient to do this for f64? The maximum ULP
13828 // error seems really high at 2^29 ULP.
13829 // 1.0 / x -> rcp(x)
13830 return DAG.getNode(AMDGPUISD::RCP, SL, VT, RHS);
13831 }
13832
13833 // Same as for 1.0, but expand the sign out of the constant.
13834 if (CLHS->isMinusOne()) {
13835 // -1.0 / x -> rcp (fneg x)
13836 SDValue FNegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
13837 return DAG.getNode(AMDGPUISD::RCP, SL, VT, FNegRHS);
13838 }
13839 }
13840
13841 // For f16 and bf16 require afn or arcp.
13842 // For f32 require afn.
13843 if (!AllowInaccurateRcp &&
13844 ((VT != MVT::f16 && VT != MVT::bf16) || !Flags.hasAllowReciprocal()))
13845 return SDValue();
13846
13847 // Turn into multiply by the reciprocal.
13848 // x / y -> x * (1.0 / y)
13849 SDValue Recip = DAG.getNode(AMDGPUISD::RCP, SL, VT, RHS);
13850 return DAG.getNode(ISD::FMUL, SL, VT, LHS, Recip, Flags);
13851}
13852
13853SDValue SITargetLowering::lowerFastUnsafeFDIV64(SDValue Op,
13854 SelectionDAG &DAG) const {
13855 SDLoc SL(Op);
13856 SDValue X = Op.getOperand(0);
13857 SDValue Y = Op.getOperand(1);
13858 EVT VT = Op.getValueType();
13859 const SDNodeFlags Flags = Op->getFlags();
13860
13861 bool AllowInaccurateDiv = Flags.hasApproximateFuncs();
13862 if (!AllowInaccurateDiv)
13863 return SDValue();
13864
13865 const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(X);
13866 bool IsNegRcp = CLHS && CLHS->isMinusOne();
13867
13868 // Pull out the negation so it folds for free into the source modifiers.
13869 if (IsNegRcp)
13870 X = DAG.getConstantFP(1.0, SL, VT);
13871
13872 SDValue NegY = IsNegRcp ? Y : DAG.getNode(ISD::FNEG, SL, VT, Y);
13873 SDValue One = DAG.getConstantFP(1.0, SL, VT);
13874
13875 SDValue R = DAG.getNode(AMDGPUISD::RCP, SL, VT, Y);
13876 if (IsNegRcp)
13877 R = DAG.getNode(ISD::FNEG, SL, VT, R);
13878
13879 SDValue Tmp0 = DAG.getNode(ISD::FMA, SL, VT, NegY, R, One);
13880
13881 R = DAG.getNode(ISD::FMA, SL, VT, Tmp0, R, R);
13882 SDValue Tmp1 = DAG.getNode(ISD::FMA, SL, VT, NegY, R, One);
13883 R = DAG.getNode(ISD::FMA, SL, VT, Tmp1, R, R);
13884
13885 // Skip the last 2 correction terms for reciprocal.
13886 if (IsNegRcp || (CLHS && CLHS->isOne()))
13887 return R;
13888
13889 SDValue Ret = DAG.getNode(ISD::FMUL, SL, VT, X, R);
13890 SDValue Tmp2 = DAG.getNode(ISD::FMA, SL, VT, NegY, Ret, X);
13891 return DAG.getNode(ISD::FMA, SL, VT, Tmp2, R, Ret);
13892}
13893
13894static SDValue getFPBinOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL,
13895 EVT VT, SDValue A, SDValue B, SDValue GlueChain,
13896 SDNodeFlags Flags) {
13897 if (GlueChain->getNumValues() <= 1) {
13898 return DAG.getNode(Opcode, SL, VT, A, B, Flags);
13899 }
13900
13901 assert(GlueChain->getNumValues() == 3);
13902
13903 SDVTList VTList = DAG.getVTList(VT, MVT::Other, MVT::Glue);
13904 switch (Opcode) {
13905 default:
13906 llvm_unreachable("no chain equivalent for opcode");
13907 case ISD::FMUL:
13908 Opcode = AMDGPUISD::FMUL_W_CHAIN;
13909 break;
13910 }
13911
13912 return DAG.getNode(Opcode, SL, VTList,
13913 {GlueChain.getValue(1), A, B, GlueChain.getValue(2)},
13914 Flags);
13915}
13916
13917static SDValue getFPTernOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL,
13918 EVT VT, SDValue A, SDValue B, SDValue C,
13919 SDValue GlueChain, SDNodeFlags Flags) {
13920 if (GlueChain->getNumValues() <= 1) {
13921 return DAG.getNode(Opcode, SL, VT, {A, B, C}, Flags);
13922 }
13923
13924 assert(GlueChain->getNumValues() == 3);
13925
13926 SDVTList VTList = DAG.getVTList(VT, MVT::Other, MVT::Glue);
13927 switch (Opcode) {
13928 default:
13929 llvm_unreachable("no chain equivalent for opcode");
13930 case ISD::FMA:
13931 Opcode = AMDGPUISD::FMA_W_CHAIN;
13932 break;
13933 }
13934
13935 return DAG.getNode(Opcode, SL, VTList,
13936 {GlueChain.getValue(1), A, B, C, GlueChain.getValue(2)},
13937 Flags);
13938}
13939
13940SDValue SITargetLowering::LowerFDIV16(SDValue Op, SelectionDAG &DAG) const {
13941 if (SDValue FastLowered = lowerFastUnsafeFDIV(Op, DAG))
13942 return FastLowered;
13943
13944 SDLoc SL(Op);
13945 EVT VT = Op.getValueType();
13946 SDValue LHS = Op.getOperand(0);
13947 SDValue RHS = Op.getOperand(1);
13948
13949 SDValue LHSExt = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, LHS);
13950 SDValue RHSExt = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, RHS);
13951
13952 if (VT == MVT::bf16) {
13953 SDValue ExtDiv =
13954 DAG.getNode(ISD::FDIV, SL, MVT::f32, LHSExt, RHSExt, Op->getFlags());
13955 return DAG.getNode(ISD::FP_ROUND, SL, MVT::bf16, ExtDiv,
13956 DAG.getTargetConstant(0, SL, MVT::i32));
13957 }
13958
13959 assert(VT == MVT::f16);
13960
13961 // a32.u = opx(V_CVT_F32_F16, a.u); // CVT to F32
13962 // b32.u = opx(V_CVT_F32_F16, b.u); // CVT to F32
13963 // r32.u = opx(V_RCP_F32, b32.u); // rcp = 1 / d
13964 // q32.u = opx(V_MUL_F32, a32.u, r32.u); // q = n * rcp
13965 // e32.u = opx(V_MAD_F32, (b32.u^_neg32), q32.u, a32.u); // err = -d * q + n
13966 // q32.u = opx(V_MAD_F32, e32.u, r32.u, q32.u); // q = n * rcp
13967 // e32.u = opx(V_MAD_F32, (b32.u^_neg32), q32.u, a32.u); // err = -d * q + n
13968 // tmp.u = opx(V_MUL_F32, e32.u, r32.u);
13969 // tmp.u = opx(V_AND_B32, tmp.u, 0xff800000)
13970 // q32.u = opx(V_ADD_F32, tmp.u, q32.u);
13971 // q16.u = opx(V_CVT_F16_F32, q32.u);
13972 // q16.u = opx(V_DIV_FIXUP_F16, q16.u, b.u, a.u); // q = touchup(q, d, n)
13973
13974 // We will use ISD::FMA on targets that don't support ISD::FMAD.
13975 unsigned FMADOpCode =
13977 SDValue NegRHSExt = DAG.getNode(ISD::FNEG, SL, MVT::f32, RHSExt);
13978 SDValue Rcp =
13979 DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, RHSExt, Op->getFlags());
13980 SDValue Quot =
13981 DAG.getNode(ISD::FMUL, SL, MVT::f32, LHSExt, Rcp, Op->getFlags());
13982 SDValue Err = DAG.getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13983 Op->getFlags());
13984 Quot = DAG.getNode(FMADOpCode, SL, MVT::f32, Err, Rcp, Quot, Op->getFlags());
13985 Err = DAG.getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13986 Op->getFlags());
13987 SDValue Tmp = DAG.getNode(ISD::FMUL, SL, MVT::f32, Err, Rcp, Op->getFlags());
13988 SDValue TmpCast = DAG.getNode(ISD::BITCAST, SL, MVT::i32, Tmp);
13989 TmpCast = DAG.getNode(ISD::AND, SL, MVT::i32, TmpCast,
13990 DAG.getConstant(0xff800000, SL, MVT::i32));
13991 Tmp = DAG.getNode(ISD::BITCAST, SL, MVT::f32, TmpCast);
13992 Quot = DAG.getNode(ISD::FADD, SL, MVT::f32, Tmp, Quot, Op->getFlags());
13993 SDValue RDst = DAG.getNode(ISD::FP_ROUND, SL, MVT::f16, Quot,
13994 DAG.getTargetConstant(0, SL, MVT::i32));
13995 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f16, RDst, RHS, LHS,
13996 Op->getFlags());
13997}
13998
13999// Faster 2.5 ULP division that does not support denormals.
14000SDValue SITargetLowering::lowerFDIV_FAST(SDValue Op, SelectionDAG &DAG) const {
14001 SDNodeFlags Flags = Op->getFlags();
14002 SDLoc SL(Op);
14003 SDValue LHS = Op.getOperand(1);
14004 SDValue RHS = Op.getOperand(2);
14005
14006 // TODO: The combiner should probably handle elimination of redundant fabs.
14007 SDValue r1 = DAG.SignBitIsZeroFP(RHS)
14008 ? RHS
14009 : DAG.getNode(ISD::FABS, SL, MVT::f32, RHS, Flags);
14010
14011 const APFloat K0Val(0x1p+96f);
14012 const SDValue K0 = DAG.getConstantFP(K0Val, SL, MVT::f32);
14013
14014 const APFloat K1Val(0x1p-32f);
14015 const SDValue K1 = DAG.getConstantFP(K1Val, SL, MVT::f32);
14016
14017 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f32);
14018
14019 EVT SetCCVT =
14020 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f32);
14021
14022 SDValue r2 = DAG.getSetCC(SL, SetCCVT, r1, K0, ISD::SETOGT);
14023
14024 SDValue r3 = DAG.getNode(ISD::SELECT, SL, MVT::f32, r2, K1, One, Flags);
14025
14026 r1 = DAG.getNode(ISD::FMUL, SL, MVT::f32, RHS, r3, Flags);
14027
14028 // rcp does not support denormals.
14029 SDValue r0 = DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, r1, Flags);
14030
14031 SDValue Mul = DAG.getNode(ISD::FMUL, SL, MVT::f32, LHS, r0, Flags);
14032
14033 return DAG.getNode(ISD::FMUL, SL, MVT::f32, r3, Mul, Flags);
14034}
14035
14036// Returns immediate value for setting the F32 denorm mode when using the
14037// S_DENORM_MODE instruction.
14039 const SIMachineFunctionInfo *Info,
14040 const GCNSubtarget *ST) {
14041 assert(ST->hasDenormModeInst() && "Requires S_DENORM_MODE");
14042 uint32_t DPDenormModeDefault = Info->getMode().fpDenormModeDPValue();
14043 uint32_t Mode = SPDenormMode | (DPDenormModeDefault << 2);
14044 return DAG.getTargetConstant(Mode, SDLoc(), MVT::i32);
14045}
14046
14047SDValue SITargetLowering::LowerFDIV32(SDValue Op, SelectionDAG &DAG) const {
14048 if (SDValue FastLowered = lowerFastUnsafeFDIV(Op, DAG))
14049 return FastLowered;
14050
14051 // The selection matcher assumes anything with a chain selecting to a
14052 // mayRaiseFPException machine instruction. Since we're introducing a chain
14053 // here, we need to explicitly report nofpexcept for the regular fdiv
14054 // lowering.
14055 SDNodeFlags Flags = Op->getFlags();
14056 Flags.setNoFPExcept(true);
14057
14058 SDLoc SL(Op);
14059 SDValue LHS = Op.getOperand(0);
14060 SDValue RHS = Op.getOperand(1);
14061
14062 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f32);
14063
14064 SDVTList ScaleVT = DAG.getVTList(MVT::f32, MVT::i1);
14065
14066 SDValue DenominatorScaled =
14067 DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, {RHS, RHS, LHS}, Flags);
14068 SDValue NumeratorScaled =
14069 DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, {LHS, RHS, LHS}, Flags);
14070
14071 // Denominator is scaled to not be denormal, so using rcp is ok.
14072 SDValue ApproxRcp =
14073 DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, DenominatorScaled, Flags);
14074 SDValue NegDivScale0 =
14075 DAG.getNode(ISD::FNEG, SL, MVT::f32, DenominatorScaled, Flags);
14076
14077 using namespace AMDGPU::Hwreg;
14078 const unsigned Denorm32Reg = HwregEncoding::encode(ID_MODE, 4, 2);
14079 const SDValue BitField = DAG.getTargetConstant(Denorm32Reg, SL, MVT::i32);
14080
14081 const MachineFunction &MF = DAG.getMachineFunction();
14082 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
14083 const DenormalMode DenormMode = Info->getMode().FP32Denormals;
14084
14085 const bool PreservesDenormals = DenormMode == DenormalMode::getIEEE();
14086 const bool HasDynamicDenormals =
14087 (DenormMode.Input == DenormalMode::Dynamic) ||
14088 (DenormMode.Output == DenormalMode::Dynamic);
14089
14090 SDValue SavedDenormMode;
14091
14092 if (!PreservesDenormals) {
14093 // Note we can't use the STRICT_FMA/STRICT_FMUL for the non-strict FDIV
14094 // lowering. The chain dependence is insufficient, and we need glue. We do
14095 // not need the glue variants in a strictfp function.
14096
14097 SDVTList BindParamVTs = DAG.getVTList(MVT::Other, MVT::Glue);
14098
14099 SDValue Glue = DAG.getEntryNode();
14100 if (HasDynamicDenormals) {
14101 SDNode *GetReg = DAG.getMachineNode(AMDGPU::S_GETREG_B32, SL,
14102 DAG.getVTList(MVT::i32, MVT::Glue),
14103 {BitField, Glue});
14104 SavedDenormMode = SDValue(GetReg, 0);
14105
14106 Glue = DAG.getMergeValues(
14107 {DAG.getEntryNode(), SDValue(GetReg, 0), SDValue(GetReg, 1)}, SL);
14108 }
14109
14110 SDNode *EnableDenorm;
14111 if (Subtarget->hasDenormModeInst()) {
14112 const SDValue EnableDenormValue =
14113 getSPDenormModeValue(FP_DENORM_FLUSH_NONE, DAG, Info, Subtarget);
14114
14115 EnableDenorm = DAG.getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs, Glue,
14116 EnableDenormValue)
14117 .getNode();
14118 } else {
14119 const SDValue EnableDenormValue =
14120 DAG.getConstant(FP_DENORM_FLUSH_NONE, SL, MVT::i32);
14121 EnableDenorm = DAG.getMachineNode(AMDGPU::S_SETREG_B32, SL, BindParamVTs,
14122 {EnableDenormValue, BitField, Glue});
14123 }
14124
14125 SDValue Ops[3] = {NegDivScale0, SDValue(EnableDenorm, 0),
14126 SDValue(EnableDenorm, 1)};
14127
14128 NegDivScale0 = DAG.getMergeValues(Ops, SL);
14129 }
14130
14131 SDValue Fma0 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0,
14132 ApproxRcp, One, NegDivScale0, Flags);
14133
14134 SDValue Fma1 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, Fma0, ApproxRcp,
14135 ApproxRcp, Fma0, Flags);
14136
14137 SDValue Mul = getFPBinOp(DAG, ISD::FMUL, SL, MVT::f32, NumeratorScaled, Fma1,
14138 Fma1, Flags);
14139
14140 SDValue Fma2 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0, Mul,
14141 NumeratorScaled, Mul, Flags);
14142
14143 SDValue Fma3 =
14144 getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, Fma2, Fma1, Mul, Fma2, Flags);
14145
14146 SDValue Fma4 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0, Fma3,
14147 NumeratorScaled, Fma3, Flags);
14148
14149 if (!PreservesDenormals) {
14150 SDNode *DisableDenorm;
14151 if (!HasDynamicDenormals && Subtarget->hasDenormModeInst()) {
14152 const SDValue DisableDenormValue = getSPDenormModeValue(
14153 FP_DENORM_FLUSH_IN_FLUSH_OUT, DAG, Info, Subtarget);
14154
14155 SDVTList BindParamVTs = DAG.getVTList(MVT::Other, MVT::Glue);
14156 DisableDenorm =
14157 DAG.getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs,
14158 Fma4.getValue(1), DisableDenormValue, Fma4.getValue(2))
14159 .getNode();
14160 } else {
14161 assert(HasDynamicDenormals == (bool)SavedDenormMode);
14162 const SDValue DisableDenormValue =
14163 HasDynamicDenormals
14164 ? SavedDenormMode
14165 : DAG.getConstant(FP_DENORM_FLUSH_IN_FLUSH_OUT, SL, MVT::i32);
14166
14167 DisableDenorm = DAG.getMachineNode(
14168 AMDGPU::S_SETREG_B32, SL, MVT::Other,
14169 {DisableDenormValue, BitField, Fma4.getValue(1), Fma4.getValue(2)});
14170 }
14171
14172 SDValue OutputChain = DAG.getNode(ISD::TokenFactor, SL, MVT::Other,
14173 SDValue(DisableDenorm, 0), DAG.getRoot());
14174 DAG.setRoot(OutputChain);
14175 }
14176
14177 SDValue Scale = NumeratorScaled.getValue(1);
14178 SDValue Fmas = DAG.getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f32,
14179 {Fma4, Fma1, Fma3, Scale}, Flags);
14180
14181 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f32, Fmas, RHS, LHS, Flags);
14182}
14183
14184SDValue SITargetLowering::LowerFDIV64(SDValue Op, SelectionDAG &DAG) const {
14185 if (SDValue FastLowered = lowerFastUnsafeFDIV64(Op, DAG))
14186 return FastLowered;
14187
14188 SDLoc SL(Op);
14189 SDValue X = Op.getOperand(0);
14190 SDValue Y = Op.getOperand(1);
14191
14192 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f64);
14193
14194 SDVTList ScaleVT = DAG.getVTList(MVT::f64, MVT::i1);
14195
14196 SDValue DivScale0 = DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, Y, Y, X);
14197
14198 SDValue NegDivScale0 = DAG.getNode(ISD::FNEG, SL, MVT::f64, DivScale0);
14199
14200 SDValue Rcp = DAG.getNode(AMDGPUISD::RCP, SL, MVT::f64, DivScale0);
14201
14202 SDValue Fma0 = DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Rcp, One);
14203
14204 SDValue Fma1 = DAG.getNode(ISD::FMA, SL, MVT::f64, Rcp, Fma0, Rcp);
14205
14206 SDValue Fma2 = DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Fma1, One);
14207
14208 SDValue DivScale1 = DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, X, Y, X);
14209
14210 SDValue Fma3 = DAG.getNode(ISD::FMA, SL, MVT::f64, Fma1, Fma2, Fma1);
14211 SDValue Mul = DAG.getNode(ISD::FMUL, SL, MVT::f64, DivScale1, Fma3);
14212
14213 SDValue Fma4 =
14214 DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Mul, DivScale1);
14215
14216 SDValue Scale;
14217
14218 if (!Subtarget->hasUsableDivScaleConditionOutput()) {
14219 // Workaround a hardware bug on SI where the condition output from div_scale
14220 // is not usable.
14221
14222 const SDValue Hi = DAG.getConstant(1, SL, MVT::i32);
14223
14224 // Figure out if the scale to use for div_fmas.
14225 SDValue NumBC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, X);
14226 SDValue DenBC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Y);
14227 SDValue Scale0BC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, DivScale0);
14228 SDValue Scale1BC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, DivScale1);
14229
14230 SDValue NumHi =
14231 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, NumBC, Hi);
14232 SDValue DenHi =
14233 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, DenBC, Hi);
14234
14235 SDValue Scale0Hi =
14236 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Scale0BC, Hi);
14237 SDValue Scale1Hi =
14238 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Scale1BC, Hi);
14239
14240 SDValue CmpDen = DAG.getSetCC(SL, MVT::i1, DenHi, Scale0Hi, ISD::SETEQ);
14241 SDValue CmpNum = DAG.getSetCC(SL, MVT::i1, NumHi, Scale1Hi, ISD::SETEQ);
14242 Scale = DAG.getNode(ISD::XOR, SL, MVT::i1, CmpNum, CmpDen);
14243 } else {
14244 Scale = DivScale1.getValue(1);
14245 }
14246
14247 SDValue Fmas =
14248 DAG.getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f64, Fma4, Fma3, Mul, Scale);
14249
14250 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f64, Fmas, Y, X);
14251}
14252
14253SDValue SITargetLowering::LowerFDIV(SDValue Op, SelectionDAG &DAG) const {
14254 EVT VT = Op.getValueType();
14255
14256 if (VT == MVT::f32)
14257 return LowerFDIV32(Op, DAG);
14258
14259 if (VT == MVT::f64)
14260 return LowerFDIV64(Op, DAG);
14261
14262 if (VT == MVT::f16 || VT == MVT::bf16)
14263 return LowerFDIV16(Op, DAG);
14264
14265 llvm_unreachable("Unexpected type for fdiv");
14266}
14267
14268SDValue SITargetLowering::LowerFFREXP(SDValue Op, SelectionDAG &DAG) const {
14269 SDLoc dl(Op);
14270 SDValue Val = Op.getOperand(0);
14271 EVT VT = Val.getValueType();
14272 EVT ResultExpVT = Op->getValueType(1);
14273 EVT InstrExpVT = VT == MVT::f16 ? MVT::i16 : MVT::i32;
14274
14275 SDValue Mant = DAG.getNode(
14277 DAG.getTargetConstant(Intrinsic::amdgcn_frexp_mant, dl, MVT::i32), Val);
14278
14279 SDValue Exp = DAG.getNode(
14280 ISD::INTRINSIC_WO_CHAIN, dl, InstrExpVT,
14281 DAG.getTargetConstant(Intrinsic::amdgcn_frexp_exp, dl, MVT::i32), Val);
14282
14283 if (Subtarget->hasFractBug()) {
14284 SDValue Fabs = DAG.getNode(ISD::FABS, dl, VT, Val);
14285 SDValue Inf =
14287
14288 SDValue IsFinite = DAG.getSetCC(dl, MVT::i1, Fabs, Inf, ISD::SETOLT);
14289 SDValue Zero = DAG.getConstant(0, dl, InstrExpVT);
14290 Exp = DAG.getNode(ISD::SELECT, dl, InstrExpVT, IsFinite, Exp, Zero);
14291 Mant = DAG.getNode(ISD::SELECT, dl, VT, IsFinite, Mant, Val);
14292 }
14293
14294 SDValue CastExp = DAG.getSExtOrTrunc(Exp, dl, ResultExpVT);
14295 return DAG.getMergeValues({Mant, CastExp}, dl);
14296}
14297
14298SDValue SITargetLowering::LowerSTORE(SDValue Op, SelectionDAG &DAG) const {
14299 SDLoc DL(Op);
14300 StoreSDNode *Store = cast<StoreSDNode>(Op);
14301 EVT VT = Store->getMemoryVT();
14302
14303 if (VT == MVT::i1) {
14304 return DAG.getTruncStore(
14305 Store->getChain(), DL,
14306 DAG.getSExtOrTrunc(Store->getValue(), DL, MVT::i32),
14307 Store->getBasePtr(), MVT::i1, Store->getMemOperand());
14308 }
14309
14310 assert(VT.isVector() &&
14311 Store->getValue().getValueType().getScalarType() == MVT::i32);
14312
14313 unsigned AS = Store->getAddressSpace();
14314 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
14315 AS == AMDGPUAS::FLAT_ADDRESS &&
14316 Store->getAlign().value() < VT.getStoreSize() &&
14317 VT.getSizeInBits() > 32) {
14318 return SplitVectorStore(Op, DAG);
14319 }
14320
14322 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
14323 // If there is a possibility that flat instruction access scratch memory
14324 // then we need to use the same legalization rules we use for private.
14325 if (AS == AMDGPUAS::FLAT_ADDRESS &&
14326 !Subtarget->hasMultiDwordFlatScratchAddressing())
14327 AS = addressMayBeAccessedAsPrivate(Store->getMemOperand(), *MFI)
14330
14331 unsigned NumElements = VT.getVectorNumElements();
14333 if (NumElements > 4)
14334 return SplitVectorStore(Op, DAG);
14335 // v3 stores not supported on SI.
14336 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
14337 return SplitVectorStore(Op, DAG);
14338
14340 VT, *Store->getMemOperand()))
14341 return expandUnalignedStore(Store, DAG);
14342
14343 return SDValue();
14344 }
14345 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
14346 switch (Subtarget->getMaxPrivateElementSize()) {
14347 case 4:
14348 return scalarizeVectorStore(Store, DAG);
14349 case 8:
14350 if (NumElements > 2)
14351 return SplitVectorStore(Op, DAG);
14352 return SDValue();
14353 case 16:
14354 if (NumElements > 4 ||
14355 (NumElements == 3 && !Subtarget->hasFlatScratchEnabled()))
14356 return SplitVectorStore(Op, DAG);
14357 return SDValue();
14358 default:
14359 llvm_unreachable("unsupported private_element_size");
14360 }
14361 } else if (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::REGION_ADDRESS) {
14362 unsigned Fast = 0;
14363 auto Flags = Store->getMemOperand()->getFlags();
14365 Store->getAlign(), Flags, &Fast) &&
14366 Fast > 1)
14367 return SDValue();
14368
14369 if (VT.isVector())
14370 return SplitVectorStore(Op, DAG);
14371
14372 return expandUnalignedStore(Store, DAG);
14373 }
14374
14375 // Probably an invalid store. If so we'll end up emitting a selection error.
14376 return SDValue();
14377}
14378
14379// Avoid the full correct expansion for f32 sqrt when promoting from f16.
14380SDValue SITargetLowering::lowerFSQRTF16(SDValue Op, SelectionDAG &DAG) const {
14381 SDLoc SL(Op);
14382 assert(!Subtarget->has16BitInsts());
14383 SDNodeFlags Flags = Op->getFlags();
14384 SDValue Ext =
14385 DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op.getOperand(0), Flags);
14386
14387 SDValue SqrtID = DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, SL, MVT::i32);
14388 SDValue Sqrt =
14389 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::f32, SqrtID, Ext, Flags);
14390
14391 return DAG.getNode(ISD::FP_ROUND, SL, MVT::f16, Sqrt,
14392 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
14393}
14394
14395SDValue SITargetLowering::lowerFSQRTF32(SDValue Op, SelectionDAG &DAG) const {
14396 SDLoc DL(Op);
14397 SDNodeFlags Flags = Op->getFlags();
14398 MVT VT = Op.getValueType().getSimpleVT();
14399 const SDValue X = Op.getOperand(0);
14400
14401 if (allowApproxFunc(DAG, Flags)) {
14402 // Instruction is 1ulp but ignores denormals.
14403 return DAG.getNode(
14405 DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, DL, MVT::i32), X, Flags);
14406 }
14407
14408 SDValue ScaleThreshold = DAG.getConstantFP(0x1.0p-96f, DL, VT);
14409 SDValue NeedScale = DAG.getSetCC(DL, MVT::i1, X, ScaleThreshold, ISD::SETOLT);
14410
14411 SDValue ScaleUpFactor = DAG.getConstantFP(0x1.0p+32f, DL, VT);
14412
14413 SDValue ScaledX = DAG.getNode(ISD::FMUL, DL, VT, X, ScaleUpFactor, Flags);
14414
14415 SDValue SqrtX =
14416 DAG.getNode(ISD::SELECT, DL, VT, NeedScale, ScaledX, X, Flags);
14417
14418 SDValue SqrtS;
14419 if (needsDenormHandlingF32(DAG, X, Flags)) {
14420 SDValue SqrtID =
14421 DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, DL, MVT::i32);
14422 SqrtS = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, SqrtID, SqrtX, Flags);
14423
14424 SDValue SqrtSAsInt = DAG.getNode(ISD::BITCAST, DL, MVT::i32, SqrtS);
14425 SDValue SqrtSNextDownInt =
14426 DAG.getNode(ISD::ADD, DL, MVT::i32, SqrtSAsInt,
14427 DAG.getAllOnesConstant(DL, MVT::i32));
14428 SDValue SqrtSNextDown = DAG.getNode(ISD::BITCAST, DL, VT, SqrtSNextDownInt);
14429
14430 SDValue NegSqrtSNextDown =
14431 DAG.getNode(ISD::FNEG, DL, VT, SqrtSNextDown, Flags);
14432
14433 SDValue SqrtVP =
14434 DAG.getNode(ISD::FMA, DL, VT, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
14435
14436 SDValue SqrtSNextUpInt = DAG.getNode(ISD::ADD, DL, MVT::i32, SqrtSAsInt,
14437 DAG.getConstant(1, DL, MVT::i32));
14438 SDValue SqrtSNextUp = DAG.getNode(ISD::BITCAST, DL, VT, SqrtSNextUpInt);
14439
14440 SDValue NegSqrtSNextUp = DAG.getNode(ISD::FNEG, DL, VT, SqrtSNextUp, Flags);
14441 SDValue SqrtVS =
14442 DAG.getNode(ISD::FMA, DL, VT, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
14443
14444 SDValue Zero = DAG.getConstantFP(0.0f, DL, VT);
14445 SDValue SqrtVPLE0 = DAG.getSetCC(DL, MVT::i1, SqrtVP, Zero, ISD::SETOLE);
14446
14447 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, SqrtVPLE0, SqrtSNextDown, SqrtS,
14448 Flags);
14449
14450 SDValue SqrtVPVSGT0 = DAG.getSetCC(DL, MVT::i1, SqrtVS, Zero, ISD::SETOGT);
14451 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, SqrtVPVSGT0, SqrtSNextUp, SqrtS,
14452 Flags);
14453 } else {
14454 SDValue SqrtR = DAG.getNode(AMDGPUISD::RSQ, DL, VT, SqrtX, Flags);
14455
14456 SqrtS = DAG.getNode(ISD::FMUL, DL, VT, SqrtX, SqrtR, Flags);
14457
14458 SDValue Half = DAG.getConstantFP(0.5f, DL, VT);
14459 SDValue SqrtH = DAG.getNode(ISD::FMUL, DL, VT, SqrtR, Half, Flags);
14460 SDValue NegSqrtH = DAG.getNode(ISD::FNEG, DL, VT, SqrtH, Flags);
14461
14462 SDValue SqrtE = DAG.getNode(ISD::FMA, DL, VT, NegSqrtH, SqrtS, Half, Flags);
14463 SqrtH = DAG.getNode(ISD::FMA, DL, VT, SqrtH, SqrtE, SqrtH, Flags);
14464 SqrtS = DAG.getNode(ISD::FMA, DL, VT, SqrtS, SqrtE, SqrtS, Flags);
14465
14466 SDValue NegSqrtS = DAG.getNode(ISD::FNEG, DL, VT, SqrtS, Flags);
14467 SDValue SqrtD =
14468 DAG.getNode(ISD::FMA, DL, VT, NegSqrtS, SqrtS, SqrtX, Flags);
14469 SqrtS = DAG.getNode(ISD::FMA, DL, VT, SqrtD, SqrtH, SqrtS, Flags);
14470 }
14471
14472 SDValue ScaleDownFactor = DAG.getConstantFP(0x1.0p-16f, DL, VT);
14473
14474 SDValue ScaledDown =
14475 DAG.getNode(ISD::FMUL, DL, VT, SqrtS, ScaleDownFactor, Flags);
14476
14477 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, NeedScale, ScaledDown, SqrtS, Flags);
14478 SDValue IsZeroOrInf =
14479 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, SqrtX,
14480 DAG.getTargetConstant(fcZero | fcPosInf, DL, MVT::i32));
14481
14482 return DAG.getNode(ISD::SELECT, DL, VT, IsZeroOrInf, SqrtX, SqrtS, Flags);
14483}
14484
14485SDValue SITargetLowering::lowerFSQRTF64(SDValue Op, SelectionDAG &DAG) const {
14486 // For double type, the SQRT and RSQ instructions don't have required
14487 // precision, we apply Goldschmidt's algorithm to improve the result:
14488 //
14489 // y0 = rsq(x)
14490 // g0 = x * y0
14491 // h0 = 0.5 * y0
14492 //
14493 // r0 = 0.5 - h0 * g0
14494 // g1 = g0 * r0 + g0
14495 // h1 = h0 * r0 + h0
14496 //
14497 // r1 = 0.5 - h1 * g1 => d0 = x - g1 * g1
14498 // g2 = g1 * r1 + g1 g2 = d0 * h1 + g1
14499 // h2 = h1 * r1 + h1
14500 //
14501 // r2 = 0.5 - h2 * g2 => d1 = x - g2 * g2
14502 // g3 = g2 * r2 + g2 g3 = d1 * h1 + g2
14503 //
14504 // sqrt(x) = g3
14505
14506 SDNodeFlags Flags = Op->getFlags();
14507
14508 SDLoc DL(Op);
14509
14510 SDValue X = Op.getOperand(0);
14511 SDValue ZeroInt = DAG.getConstant(0, DL, MVT::i32);
14512
14513 SDValue SqrtX = X;
14514 SDValue Scaling;
14515 if (!Flags.hasApproximateFuncs()) {
14516 SDValue ScaleConstant = DAG.getConstantFP(0x1.0p-767, DL, MVT::f64);
14517 Scaling = DAG.getSetCC(DL, MVT::i1, X, ScaleConstant, ISD::SETOLT);
14518
14519 // Scale up input if it is too small.
14520 SDValue ScaleUpFactor = DAG.getConstant(256, DL, MVT::i32);
14521 SDValue ScaleUp =
14522 DAG.getNode(ISD::SELECT, DL, MVT::i32, Scaling, ScaleUpFactor, ZeroInt);
14523 SqrtX = DAG.getNode(ISD::FLDEXP, DL, MVT::f64, X, ScaleUp, Flags);
14524 }
14525
14526 SDValue SqrtY = DAG.getNode(AMDGPUISD::RSQ, DL, MVT::f64, SqrtX);
14527
14528 SDValue SqrtS0 = DAG.getNode(ISD::FMUL, DL, MVT::f64, SqrtX, SqrtY);
14529
14530 SDValue Half = DAG.getConstantFP(0.5, DL, MVT::f64);
14531 SDValue SqrtH0 = DAG.getNode(ISD::FMUL, DL, MVT::f64, SqrtY, Half);
14532
14533 SDValue NegSqrtH0 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtH0);
14534 SDValue SqrtR0 = DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtH0, SqrtS0, Half);
14535
14536 SDValue SqrtH1 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtH0, SqrtR0, SqrtH0);
14537
14538 SDValue SqrtS1 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtS0, SqrtR0, SqrtS0);
14539
14540 SDValue NegSqrtS1 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtS1);
14541 SDValue SqrtD0 =
14542 DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtS1, SqrtS1, SqrtX);
14543
14544 SDValue SqrtS2 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtD0, SqrtH1, SqrtS1);
14545
14546 SDValue SqrtRet = SqrtS2;
14547 if (!Flags.hasApproximateFuncs()) {
14548 SDValue NegSqrtS2 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtS2);
14549 SDValue SqrtD1 =
14550 DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtS2, SqrtS2, SqrtX);
14551
14552 SqrtRet = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtD1, SqrtH1, SqrtS2);
14553
14554 SDValue ScaleDownFactor = DAG.getSignedConstant(-128, DL, MVT::i32);
14555 SDValue ScaleDown = DAG.getNode(ISD::SELECT, DL, MVT::i32, Scaling,
14556 ScaleDownFactor, ZeroInt);
14557 SqrtRet = DAG.getNode(ISD::FLDEXP, DL, MVT::f64, SqrtRet, ScaleDown, Flags);
14558 }
14559
14560 // TODO: Check for DAZ and expand to subnormals
14561
14562 SDValue IsZeroOrInf;
14563 if (Flags.hasNoInfs()) {
14564 SDValue Zero = DAG.getConstantFP(0.0, DL, MVT::f64);
14565 IsZeroOrInf = DAG.getSetCC(DL, MVT::i1, SqrtX, Zero, ISD::SETOEQ);
14566 } else {
14567 IsZeroOrInf =
14568 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, SqrtX,
14569 DAG.getTargetConstant(fcZero | fcPosInf, DL, MVT::i32));
14570 }
14571
14572 // If x is +INF, +0, or -0, use its original value
14573 return DAG.getNode(ISD::SELECT, DL, MVT::f64, IsZeroOrInf, SqrtX, SqrtRet,
14574 Flags);
14575}
14576
14577SDValue SITargetLowering::LowerTrig(SDValue Op, SelectionDAG &DAG) const {
14578 SDLoc DL(Op);
14579 EVT VT = Op.getValueType();
14580 SDValue Arg = Op.getOperand(0);
14581 SDValue TrigVal;
14582
14583 // Propagate fast-math flags so that the multiply we introduce can be folded
14584 // if Arg is already the result of a multiply by constant.
14585 auto Flags = Op->getFlags();
14586
14587 // AMDGPUISD nodes of vector type must be unrolled here since
14588 // they will not be expanded elsewhere.
14589 auto UnrollIfVec = [&DAG](SDValue V) -> SDValue {
14590 if (!V.getValueType().isVector())
14591 return V;
14592
14593 return DAG.UnrollVectorOp(cast<SDNode>(V));
14594 };
14595
14596 SDValue OneOver2Pi = DAG.getConstantFP(0.5 * numbers::inv_pi, DL, VT);
14597
14598 if (Subtarget->hasTrigReducedRange()) {
14599 SDValue MulVal = DAG.getNode(ISD::FMUL, DL, VT, Arg, OneOver2Pi, Flags);
14600 TrigVal = UnrollIfVec(DAG.getNode(AMDGPUISD::FRACT, DL, VT, MulVal, Flags));
14601 } else {
14602 TrigVal = DAG.getNode(ISD::FMUL, DL, VT, Arg, OneOver2Pi, Flags);
14603 }
14604
14605 switch (Op.getOpcode()) {
14606 case ISD::FCOS:
14607 TrigVal = DAG.getNode(AMDGPUISD::COS_HW, SDLoc(Op), VT, TrigVal, Flags);
14608 break;
14609 case ISD::FSIN:
14610 TrigVal = DAG.getNode(AMDGPUISD::SIN_HW, SDLoc(Op), VT, TrigVal, Flags);
14611 break;
14612 default:
14613 llvm_unreachable("Wrong trig opcode");
14614 }
14615
14616 return UnrollIfVec(TrigVal);
14617}
14618
14619SDValue SITargetLowering::LowerATOMIC_CMP_SWAP(SDValue Op,
14620 SelectionDAG &DAG) const {
14621 AtomicSDNode *AtomicNode = cast<AtomicSDNode>(Op);
14622 assert(AtomicNode->isCompareAndSwap());
14623 unsigned AS = AtomicNode->getAddressSpace();
14624
14625 // No custom lowering required for local address space
14627 return Op;
14628
14629 // Non-local address space requires custom lowering for atomic compare
14630 // and swap; cmp and swap should be in a v2i32 or v2i64 in case of _X2
14631 SDLoc DL(Op);
14632 SDValue ChainIn = Op.getOperand(0);
14633 SDValue Addr = Op.getOperand(1);
14634 SDValue Old = Op.getOperand(2);
14635 SDValue New = Op.getOperand(3);
14636 EVT VT = Op.getValueType();
14637 MVT SimpleVT = VT.getSimpleVT();
14638 MVT VecType = MVT::getVectorVT(SimpleVT, 2);
14639
14640 SDValue NewOld = DAG.getBuildVector(VecType, DL, {New, Old});
14641 SDValue Ops[] = {ChainIn, Addr, NewOld};
14642
14643 return DAG.getMemIntrinsicNode(AMDGPUISD::ATOMIC_CMP_SWAP, DL,
14644 Op->getVTList(), Ops, VT,
14645 AtomicNode->getMemOperand());
14646}
14647
14648//===----------------------------------------------------------------------===//
14649// Custom DAG optimizations
14650//===----------------------------------------------------------------------===//
14651
14652SDValue
14653SITargetLowering::performUCharToFloatCombine(SDNode *N,
14654 DAGCombinerInfo &DCI) const {
14655 EVT VT = N->getValueType(0);
14656 EVT ScalarVT = VT.getScalarType();
14657 if (ScalarVT != MVT::f32 && ScalarVT != MVT::f16)
14658 return SDValue();
14659
14660 SelectionDAG &DAG = DCI.DAG;
14661 SDLoc DL(N);
14662
14663 SDValue Src = N->getOperand(0);
14664 EVT SrcVT = Src.getValueType();
14665
14666 // TODO: We could try to match extracting the higher bytes, which would be
14667 // easier if i8 vectors weren't promoted to i32 vectors, particularly after
14668 // types are legalized. v4i8 -> v4f32 is probably the only case to worry
14669 // about in practice.
14670 if (DCI.isAfterLegalizeDAG() && SrcVT == MVT::i32) {
14671 if (DAG.MaskedValueIsZero(Src, APInt::getHighBitsSet(32, 24))) {
14672 SDValue Cvt = DAG.getNode(AMDGPUISD::CVT_F32_UBYTE0, DL, MVT::f32, Src);
14673 DCI.AddToWorklist(Cvt.getNode());
14674
14675 // For the f16 case, fold to a cast to f32 and then cast back to f16.
14676 if (ScalarVT != MVT::f32) {
14677 Cvt = DAG.getNode(ISD::FP_ROUND, DL, VT, Cvt,
14678 DAG.getTargetConstant(0, DL, MVT::i32));
14679 }
14680 return Cvt;
14681 }
14682 }
14683
14684 return SDValue();
14685}
14686
14687SDValue SITargetLowering::performFCopySignCombine(SDNode *N,
14688 DAGCombinerInfo &DCI) const {
14689 SDValue MagnitudeOp = N->getOperand(0);
14690 SDValue SignOp = N->getOperand(1);
14691
14692 // The generic combine for fcopysign + fp cast is too conservative with
14693 // vectors, and also gets confused by the splitting we will perform here, so
14694 // peek through FP casts.
14695 if (SignOp.getOpcode() == ISD::FP_EXTEND ||
14696 SignOp.getOpcode() == ISD::FP_ROUND)
14697 SignOp = SignOp.getOperand(0);
14698
14699 SelectionDAG &DAG = DCI.DAG;
14700 SDLoc DL(N);
14701 EVT SignVT = SignOp.getValueType();
14702
14703 // f64 fcopysign is really an f32 copysign on the high bits, so replace the
14704 // lower half with a copy.
14705 // fcopysign f64:x, _:y -> x.lo32, (fcopysign (f32 x.hi32), _:y)
14706 EVT MagVT = MagnitudeOp.getValueType();
14707
14708 unsigned NumElts = MagVT.isVector() ? MagVT.getVectorNumElements() : 1;
14709
14710 if (MagVT.getScalarType() == MVT::f64) {
14711 EVT F32VT = MagVT.isVector()
14712 ? EVT::getVectorVT(*DAG.getContext(), MVT::f32, 2 * NumElts)
14713 : MVT::v2f32;
14714
14715 SDValue MagAsVector = DAG.getNode(ISD::BITCAST, DL, F32VT, MagnitudeOp);
14716
14718 for (unsigned I = 0; I != NumElts; ++I) {
14719 SDValue MagLo =
14720 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, MagAsVector,
14721 DAG.getConstant(2 * I, DL, MVT::i32));
14722 SDValue MagHi =
14723 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, MagAsVector,
14724 DAG.getConstant(2 * I + 1, DL, MVT::i32));
14725
14726 SDValue SignOpElt =
14727 MagVT.isVector()
14729 SignOp, DAG.getConstant(I, DL, MVT::i32))
14730 : SignOp;
14731
14732 SDValue HiOp =
14733 DAG.getNode(ISD::FCOPYSIGN, DL, MVT::f32, MagHi, SignOpElt);
14734
14735 SDValue Vector =
14736 DAG.getNode(ISD::BUILD_VECTOR, DL, MVT::v2f32, MagLo, HiOp);
14737
14738 SDValue NewElt = DAG.getNode(ISD::BITCAST, DL, MVT::f64, Vector);
14739 NewElts.push_back(NewElt);
14740 }
14741
14742 if (NewElts.size() == 1)
14743 return NewElts[0];
14744
14745 return DAG.getNode(ISD::BUILD_VECTOR, DL, MagVT, NewElts);
14746 }
14747
14748 if (SignVT.getScalarType() != MVT::f64)
14749 return SDValue();
14750
14751 // Reduce width of sign operand, we only need the highest bit.
14752 //
14753 // fcopysign f64:x, f64:y ->
14754 // fcopysign f64:x, (extract_vector_elt (bitcast f64:y to v2f32), 1)
14755 // TODO: In some cases it might make sense to go all the way to f16.
14756
14757 EVT F32VT = MagVT.isVector()
14758 ? EVT::getVectorVT(*DAG.getContext(), MVT::f32, 2 * NumElts)
14759 : MVT::v2f32;
14760
14761 SDValue SignAsVector = DAG.getNode(ISD::BITCAST, DL, F32VT, SignOp);
14762
14763 SmallVector<SDValue, 8> F32Signs;
14764 for (unsigned I = 0; I != NumElts; ++I) {
14765 // Take sign from odd elements of cast vector
14766 SDValue SignAsF32 =
14767 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, SignAsVector,
14768 DAG.getConstant(2 * I + 1, DL, MVT::i32));
14769 F32Signs.push_back(SignAsF32);
14770 }
14771
14772 SDValue NewSign =
14773 NumElts == 1
14774 ? F32Signs.back()
14776 EVT::getVectorVT(*DAG.getContext(), MVT::f32, NumElts),
14777 F32Signs);
14778
14779 return DAG.getNode(ISD::FCOPYSIGN, DL, N->getValueType(0), N->getOperand(0),
14780 NewSign);
14781}
14782
14783// (shl (add x, c1), c2) -> add (shl x, c2), (shl c1, c2)
14784// (shl (or x, c1), c2) -> add (shl x, c2), (shl c1, c2) iff x and c1 share no
14785// bits
14786
14787// This is a variant of
14788// (mul (add x, c1), c2) -> add (mul x, c2), (mul c1, c2),
14789//
14790// The normal DAG combiner will do this, but only if the add has one use since
14791// that would increase the number of instructions.
14792//
14793// This prevents us from seeing a constant offset that can be folded into a
14794// memory instruction's addressing mode. If we know the resulting add offset of
14795// a pointer can be folded into an addressing offset, we can replace the pointer
14796// operand with the add of new constant offset. This eliminates one of the uses,
14797// and may allow the remaining use to also be simplified.
14798//
14799SDValue SITargetLowering::performSHLPtrCombine(SDNode *N, unsigned AddrSpace,
14800 EVT MemVT,
14801 DAGCombinerInfo &DCI) const {
14802 SDValue N0 = N->getOperand(0);
14803 SDValue N1 = N->getOperand(1);
14804
14805 // We only do this to handle cases where it's profitable when there are
14806 // multiple uses of the add, so defer to the standard combine.
14807 if ((!N0->isAnyAdd() && N0.getOpcode() != ISD::OR) || N0->hasOneUse())
14808 return SDValue();
14809
14810 const ConstantSDNode *CN1 = dyn_cast<ConstantSDNode>(N1);
14811 if (!CN1)
14812 return SDValue();
14813
14814 const ConstantSDNode *CAdd = dyn_cast<ConstantSDNode>(N0.getOperand(1));
14815 if (!CAdd)
14816 return SDValue();
14817
14818 SelectionDAG &DAG = DCI.DAG;
14819
14820 if (N0->getOpcode() == ISD::OR &&
14821 !DAG.haveNoCommonBitsSet(N0.getOperand(0), N0.getOperand(1)))
14822 return SDValue();
14823
14824 // If the resulting offset is too large, we can't fold it into the
14825 // addressing mode offset.
14826 APInt Offset = CAdd->getAPIntValue() << CN1->getAPIntValue();
14827 Type *Ty = MemVT.getTypeForEVT(*DCI.DAG.getContext());
14828
14829 AddrMode AM;
14830 AM.HasBaseReg = true;
14831 AM.BaseOffs = Offset.getSExtValue();
14832 if (!isLegalAddressingMode(DCI.DAG.getDataLayout(), AM, Ty, AddrSpace))
14833 return SDValue();
14834
14835 SDLoc SL(N);
14836 EVT VT = N->getValueType(0);
14837
14838 SDValue ShlX = DAG.getNode(ISD::SHL, SL, VT, N0.getOperand(0), N1);
14839 SDValue COffset = DAG.getConstant(Offset, SL, VT);
14840
14841 SDNodeFlags Flags;
14842 Flags.setNoUnsignedWrap(
14843 N->getFlags().hasNoUnsignedWrap() &&
14844 (N0.getOpcode() == ISD::OR || N0->getFlags().hasNoUnsignedWrap()));
14845
14846 // Use ISD::ADD even if the original operation was ISD::PTRADD, since we can't
14847 // be sure that the new left operand is a proper base pointer.
14848 return DAG.getNode(ISD::ADD, SL, VT, ShlX, COffset, Flags);
14849}
14850
14851/// MemSDNode::getBasePtr() does not work for intrinsics, which needs to offset
14852/// by the chain and intrinsic ID. Theoretically we would also need to check the
14853/// specific intrinsic, but they all place the pointer operand first.
14854static unsigned getBasePtrIndex(const MemSDNode *N) {
14855 switch (N->getOpcode()) {
14856 case ISD::STORE:
14859 return 2;
14860 default:
14861 return 1;
14862 }
14863}
14864
14865SDValue SITargetLowering::performMemSDNodeCombine(MemSDNode *N,
14866 DAGCombinerInfo &DCI) const {
14867 SelectionDAG &DAG = DCI.DAG;
14868
14869 unsigned PtrIdx = getBasePtrIndex(N);
14870 SDValue Ptr = N->getOperand(PtrIdx);
14871
14872 // TODO: We could also do this for multiplies.
14873 if (Ptr.getOpcode() == ISD::SHL) {
14874 SDValue NewPtr = performSHLPtrCombine(Ptr.getNode(), N->getAddressSpace(),
14875 N->getMemoryVT(), DCI);
14876 if (NewPtr) {
14877 SmallVector<SDValue, 8> NewOps(N->ops());
14878
14879 NewOps[PtrIdx] = NewPtr;
14880 return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0);
14881 }
14882 }
14883
14884 return SDValue();
14885}
14886
14887static bool bitOpWithConstantIsReducible(unsigned Opc, uint32_t Val) {
14888 return (Opc == ISD::AND && (Val == 0 || Val == 0xffffffff)) ||
14889 (Opc == ISD::OR && (Val == 0xffffffff || Val == 0)) ||
14890 (Opc == ISD::XOR && Val == 0);
14891}
14892
14893// Break up 64-bit bit operation of a constant into two 32-bit and/or/xor. This
14894// will typically happen anyway for a VALU 64-bit and. This exposes other 32-bit
14895// integer combine opportunities since most 64-bit operations are decomposed
14896// this way. TODO: We won't want this for SALU especially if it is an inline
14897// immediate.
14898SDValue SITargetLowering::splitBinaryBitConstantOp(
14899 DAGCombinerInfo &DCI, const SDLoc &SL, unsigned Opc, SDValue LHS,
14900 const ConstantSDNode *CRHS) const {
14901 uint64_t Val = CRHS->getZExtValue();
14902 uint32_t ValLo = Lo_32(Val);
14903 uint32_t ValHi = Hi_32(Val);
14904 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
14905
14906 if ((bitOpWithConstantIsReducible(Opc, ValLo) ||
14908 (CRHS->hasOneUse() && !TII->isInlineConstant(CRHS->getAPIntValue()))) {
14909 // We have 64-bit scalar and/or/xor, but do not have vector forms.
14910 if (Subtarget->has64BitLiterals() && CRHS->hasOneUse() &&
14911 !CRHS->user_begin()->isDivergent())
14912 return SDValue();
14913
14914 // If we need to materialize a 64-bit immediate, it will be split up later
14915 // anyway. Avoid creating the harder to understand 64-bit immediate
14916 // materialization.
14917 return splitBinaryBitConstantOpImpl(DCI, SL, Opc, LHS, ValLo, ValHi);
14918 }
14919
14920 return SDValue();
14921}
14922
14924 if (V.getValueType() != MVT::i1)
14925 return false;
14926 switch (V.getOpcode()) {
14927 default:
14928 break;
14929 case ISD::SETCC:
14930 case ISD::IS_FPCLASS:
14931 case AMDGPUISD::FP_CLASS:
14932 return true;
14933 case ISD::AND:
14934 case ISD::OR:
14935 case ISD::XOR:
14936 return isBoolSGPR(V.getOperand(0)) && isBoolSGPR(V.getOperand(1));
14937 case ISD::SADDO:
14938 case ISD::UADDO:
14939 case ISD::SSUBO:
14940 case ISD::USUBO:
14941 case ISD::SMULO:
14942 case ISD::UMULO:
14943 return V.getResNo() == 1;
14945 unsigned IntrinsicID = V.getConstantOperandVal(0);
14946 switch (IntrinsicID) {
14947 case Intrinsic::amdgcn_is_shared:
14948 case Intrinsic::amdgcn_is_private:
14949 return true;
14950 default:
14951 return false;
14952 }
14953
14954 return false;
14955 }
14956 }
14957 return false;
14958}
14959
14960// If a constant has all zeroes or all ones within each byte return it.
14961// Otherwise return 0.
14963 // 0xff for any zero byte in the mask
14964 uint32_t ZeroByteMask = 0;
14965 if (!(C & 0x000000ff))
14966 ZeroByteMask |= 0x000000ff;
14967 if (!(C & 0x0000ff00))
14968 ZeroByteMask |= 0x0000ff00;
14969 if (!(C & 0x00ff0000))
14970 ZeroByteMask |= 0x00ff0000;
14971 if (!(C & 0xff000000))
14972 ZeroByteMask |= 0xff000000;
14973 uint32_t NonZeroByteMask = ~ZeroByteMask; // 0xff for any non-zero byte
14974 if ((NonZeroByteMask & C) != NonZeroByteMask)
14975 return 0; // Partial bytes selected.
14976 return C;
14977}
14978
14979// Check if a node selects whole bytes from its operand 0 starting at a byte
14980// boundary while masking the rest. Returns select mask as in the v_perm_b32
14981// or -1 if not succeeded.
14982// Note byte select encoding:
14983// value 0-3 selects corresponding source byte;
14984// value 0xc selects zero;
14985// value 0xff selects 0xff.
14987 assert(V.getValueSizeInBits() == 32);
14988
14989 if (V.getNumOperands() != 2)
14990 return ~0;
14991
14992 ConstantSDNode *N1 = dyn_cast<ConstantSDNode>(V.getOperand(1));
14993 if (!N1)
14994 return ~0;
14995
14996 uint32_t C = N1->getZExtValue();
14997
14998 switch (V.getOpcode()) {
14999 default:
15000 break;
15001 case ISD::AND:
15002 if (uint32_t ConstMask = getConstantPermuteMask(C))
15003 return (0x03020100 & ConstMask) | (0x0c0c0c0c & ~ConstMask);
15004 break;
15005
15006 case ISD::OR:
15007 if (uint32_t ConstMask = getConstantPermuteMask(C))
15008 return (0x03020100 & ~ConstMask) | ConstMask;
15009 break;
15010
15011 case ISD::SHL:
15012 if (C % 8)
15013 return ~0;
15014
15015 return uint32_t((0x030201000c0c0c0cull << C) >> 32);
15016
15017 case ISD::SRL:
15018 if (C % 8)
15019 return ~0;
15020
15021 return uint32_t(0x0c0c0c0c03020100ull >> C);
15022 }
15023
15024 return ~0;
15025}
15026
15027SDValue SITargetLowering::performAndCombine(SDNode *N,
15028 DAGCombinerInfo &DCI) const {
15029 if (DCI.isBeforeLegalize())
15030 return SDValue();
15031
15032 SelectionDAG &DAG = DCI.DAG;
15033 EVT VT = N->getValueType(0);
15034 SDValue LHS = N->getOperand(0);
15035 SDValue RHS = N->getOperand(1);
15036
15037 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(RHS);
15038 if (VT == MVT::i64 && CRHS) {
15039 if (SDValue Split =
15040 splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::AND, LHS, CRHS))
15041 return Split;
15042 }
15043
15044 if (CRHS && VT == MVT::i32) {
15045 // and (srl x, c), mask => shl (bfe x, nb + c, mask >> nb), nb
15046 // nb = number of trailing zeroes in mask
15047 // It can be optimized out using SDWA for GFX8+ in the SDWA peephole pass,
15048 // given that we are selecting 8 or 16 bit fields starting at byte boundary.
15049 uint64_t Mask = CRHS->getZExtValue();
15050 unsigned Bits = llvm::popcount(Mask);
15051 if (getSubtarget()->hasSDWA() && LHS->getOpcode() == ISD::SRL &&
15052 (Bits == 8 || Bits == 16) && isShiftedMask_64(Mask) && !(Mask & 1)) {
15053 if (auto *CShift = dyn_cast<ConstantSDNode>(LHS->getOperand(1))) {
15054 unsigned Shift = CShift->getZExtValue();
15055 unsigned NB = CRHS->getAPIntValue().countr_zero();
15056 unsigned Offset = NB + Shift;
15057 if ((Offset & (Bits - 1)) == 0) { // Starts at a byte or word boundary.
15058 SDLoc SL(N);
15059 SDValue BFE =
15060 DAG.getNode(AMDGPUISD::BFE_U32, SL, MVT::i32, LHS->getOperand(0),
15061 DAG.getConstant(Offset, SL, MVT::i32),
15062 DAG.getConstant(Bits, SL, MVT::i32));
15063 EVT NarrowVT = EVT::getIntegerVT(*DAG.getContext(), Bits);
15064 SDValue Ext = DAG.getNode(ISD::AssertZext, SL, VT, BFE,
15065 DAG.getValueType(NarrowVT));
15066 SDValue Shl = DAG.getNode(ISD::SHL, SDLoc(LHS), VT, Ext,
15067 DAG.getConstant(NB, SDLoc(CRHS), MVT::i32));
15068 return Shl;
15069 }
15070 }
15071 }
15072
15073 // and (perm x, y, c1), c2 -> perm x, y, permute_mask(c1, c2)
15074 if (LHS.hasOneUse() && LHS.getOpcode() == AMDGPUISD::PERM &&
15075 isa<ConstantSDNode>(LHS.getOperand(2))) {
15076 uint32_t Sel = getConstantPermuteMask(Mask);
15077 if (!Sel)
15078 return SDValue();
15079
15080 // Select 0xc for all zero bytes
15081 Sel = (LHS.getConstantOperandVal(2) & Sel) | (~Sel & 0x0c0c0c0c);
15082 SDLoc DL(N);
15083 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15084 LHS.getOperand(1), DAG.getConstant(Sel, DL, MVT::i32));
15085 }
15086 }
15087
15088 // and (trunc (srl x, c)), mask => srl (trunc x), c
15089 // if mask keeps exactly the bits that srl leaves in the low half
15090 if (CRHS && VT == MVT::i16 && LHS.getOpcode() == ISD::TRUNCATE &&
15091 LHS.hasOneUse() && LHS.getOperand(0).getOpcode() == ISD::SRL) {
15092 auto *Shift = dyn_cast<ConstantSDNode>(LHS.getOperand(0).getOperand(1));
15093 if (Shift && Shift->getZExtValue() < 16 &&
15094 CRHS->getAPIntValue().isMask(16 - Shift->getZExtValue())) {
15095 SDLoc SL(N);
15096 SDValue Trunc =
15097 DAG.getNode(ISD::TRUNCATE, SL, VT, LHS.getOperand(0).getOperand(0));
15098 return DAG.getNode(
15099 ISD::SRL, SL, VT, Trunc,
15100 DAG.getShiftAmountConstant(Shift->getZExtValue(), VT, SL));
15101 }
15102 }
15103
15104 // (and (fcmp ord x, x), (fcmp une (fabs x), inf)) ->
15105 // fp_class x, ~(s_nan | q_nan | n_infinity | p_infinity)
15106 if (LHS.getOpcode() == ISD::SETCC && RHS.getOpcode() == ISD::SETCC) {
15107 ISD::CondCode LCC = cast<CondCodeSDNode>(LHS.getOperand(2))->get();
15108 ISD::CondCode RCC = cast<CondCodeSDNode>(RHS.getOperand(2))->get();
15109
15110 SDValue X = LHS.getOperand(0);
15111 SDValue Y = RHS.getOperand(0);
15112 if (Y.getOpcode() != ISD::FABS || Y.getOperand(0) != X ||
15113 !isTypeLegal(X.getValueType()))
15114 return SDValue();
15115
15116 if (LCC == ISD::SETO) {
15117 if (X != LHS.getOperand(1))
15118 return SDValue();
15119
15120 if (RCC == ISD::SETUNE) {
15121 const ConstantFPSDNode *C1 =
15122 dyn_cast<ConstantFPSDNode>(RHS.getOperand(1));
15123 if (!C1 || !C1->isInfinity() || C1->isNegative())
15124 return SDValue();
15125
15126 const uint32_t Mask = SIInstrFlags::N_NORMAL |
15130
15131 static_assert(
15134 0x3ff) == Mask,
15135 "mask not equal");
15136
15137 SDLoc DL(N);
15138 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, X,
15139 DAG.getConstant(Mask, DL, MVT::i32));
15140 }
15141 }
15142 }
15143
15144 if (RHS.getOpcode() == ISD::SETCC && LHS.getOpcode() == AMDGPUISD::FP_CLASS)
15145 std::swap(LHS, RHS);
15146
15147 if (LHS.getOpcode() == ISD::SETCC && RHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15148 RHS.hasOneUse()) {
15149 ISD::CondCode LCC = cast<CondCodeSDNode>(LHS.getOperand(2))->get();
15150 // and (fcmp seto), (fp_class x, mask) -> fp_class x, mask & ~(p_nan |
15151 // n_nan) and (fcmp setuo), (fp_class x, mask) -> fp_class x, mask & (p_nan
15152 // | n_nan)
15153 const ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(RHS.getOperand(1));
15154 if ((LCC == ISD::SETO || LCC == ISD::SETUO) && Mask &&
15155 (RHS.getOperand(0) == LHS.getOperand(0) &&
15156 LHS.getOperand(0) == LHS.getOperand(1))) {
15157 const unsigned OrdMask = SIInstrFlags::S_NAN | SIInstrFlags::Q_NAN;
15158 unsigned NewMask = LCC == ISD::SETO ? Mask->getZExtValue() & ~OrdMask
15159 : Mask->getZExtValue() & OrdMask;
15160
15161 SDLoc DL(N);
15162 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, RHS.getOperand(0),
15163 DAG.getConstant(NewMask, DL, MVT::i32));
15164 }
15165 }
15166
15167 if (VT == MVT::i32 && (RHS.getOpcode() == ISD::SIGN_EXTEND ||
15168 LHS.getOpcode() == ISD::SIGN_EXTEND)) {
15169 // and x, (sext cc from i1) => select cc, x, 0
15170 if (RHS.getOpcode() != ISD::SIGN_EXTEND)
15171 std::swap(LHS, RHS);
15172 if (isBoolSGPR(RHS.getOperand(0)))
15173 return DAG.getSelect(SDLoc(N), MVT::i32, RHS.getOperand(0), LHS,
15174 DAG.getConstant(0, SDLoc(N), MVT::i32));
15175 }
15176
15177 // and (op x, c1), (op y, c2) -> perm x, y, permute_mask(c1, c2)
15178 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
15179 if (VT == MVT::i32 && LHS.hasOneUse() && RHS.hasOneUse() &&
15180 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15181 uint32_t LHSMask = getPermuteMask(LHS);
15182 uint32_t RHSMask = getPermuteMask(RHS);
15183 if (LHSMask != ~0u && RHSMask != ~0u) {
15184 // Canonicalize the expression in an attempt to have fewer unique masks
15185 // and therefore fewer registers used to hold the masks.
15186 if (LHSMask > RHSMask) {
15187 std::swap(LHSMask, RHSMask);
15188 std::swap(LHS, RHS);
15189 }
15190
15191 // Select 0xc for each lane used from source operand. Zero has 0xc mask
15192 // set, 0xff have 0xff in the mask, actual lanes are in the 0-3 range.
15193 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15194 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15195
15196 // Check of we need to combine values from two sources within a byte.
15197 if (!(LHSUsedLanes & RHSUsedLanes) &&
15198 // If we select high and lower word keep it for SDWA.
15199 // TODO: teach SDWA to work with v_perm_b32 and remove the check.
15200 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15201 // Each byte in each mask is either selector mask 0-3, or has higher
15202 // bits set in either of masks, which can be 0xff for 0xff or 0x0c for
15203 // zero. If 0x0c is in either mask it shall always be 0x0c. Otherwise
15204 // mask which is not 0xff wins. By anding both masks we have a correct
15205 // result except that 0x0c shall be corrected to give 0x0c only.
15206 uint32_t Mask = LHSMask & RHSMask;
15207 for (unsigned I = 0; I < 32; I += 8) {
15208 uint32_t ByteSel = 0xff << I;
15209 if ((LHSMask & ByteSel) == 0x0c || (RHSMask & ByteSel) == 0x0c)
15210 Mask &= (0x0c << I) & 0xffffffff;
15211 }
15212
15213 // Add 4 to each active LHS lane. It will not affect any existing 0xff
15214 // or 0x0c.
15215 uint32_t Sel = Mask | (LHSUsedLanes & 0x04040404);
15216 SDLoc DL(N);
15217
15218 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15219 RHS.getOperand(0),
15220 DAG.getConstant(Sel, DL, MVT::i32));
15221 }
15222 }
15223 }
15224
15225 return SDValue();
15226}
15227
15228// A key component of v_perm is a mapping between byte position of the src
15229// operands, and the byte position of the dest. To provide such, we need: 1. the
15230// node that provides x byte of the dest of the OR, and 2. the byte of the node
15231// used to provide that x byte. calculateByteProvider finds which node provides
15232// a certain byte of the dest of the OR, and calculateSrcByte takes that node,
15233// and finds an ultimate src and byte position For example: The supported
15234// LoadCombine pattern for vector loads is as follows
15235// t1
15236// or
15237// / \
15238// t2 t3
15239// zext shl
15240// | | \
15241// t4 t5 16
15242// or anyext
15243// / \ |
15244// t6 t7 t8
15245// srl shl or
15246// / | / \ / \
15247// t9 t10 t11 t12 t13 t14
15248// trunc* 8 trunc* 8 and and
15249// | | / | | \
15250// t15 t16 t17 t18 t19 t20
15251// trunc* 255 srl -256
15252// | / \
15253// t15 t15 16
15254//
15255// *In this example, the truncs are from i32->i16
15256//
15257// calculateByteProvider would find t6, t7, t13, and t14 for bytes 0-3
15258// respectively. calculateSrcByte would find (given node) -> ultimate src &
15259// byteposition: t6 -> t15 & 1, t7 -> t16 & 0, t13 -> t15 & 0, t14 -> t15 & 3.
15260// After finding the mapping, we can combine the tree into vperm t15, t16,
15261// 0x05000407
15262
15263// Find the source and byte position from a node.
15264// \p DestByte is the byte position of the dest of the or that the src
15265// ultimately provides. \p SrcIndex is the byte of the src that maps to this
15266// dest of the or byte. \p Depth tracks how many recursive iterations we have
15267// performed.
15268static const std::optional<ByteProvider<SDValue>>
15269calculateSrcByte(const SDValue Op, uint64_t DestByte, uint64_t SrcIndex = 0,
15270 unsigned Depth = 0) {
15271 // We may need to recursively traverse a series of SRLs
15272 if (Depth >= 6)
15273 return std::nullopt;
15274
15275 if (Op.getValueSizeInBits() < 8)
15276 return std::nullopt;
15277
15278 if (Op.getValueType().isVector())
15279 return ByteProvider<SDValue>::getSrc(Op, DestByte, SrcIndex);
15280
15281 switch (Op->getOpcode()) {
15282 case ISD::TRUNCATE: {
15283 return calculateSrcByte(Op->getOperand(0), DestByte, SrcIndex, Depth + 1);
15284 }
15285
15286 case ISD::ANY_EXTEND:
15287 case ISD::SIGN_EXTEND:
15288 case ISD::ZERO_EXTEND:
15290 SDValue NarrowOp = Op->getOperand(0);
15291 auto NarrowVT = NarrowOp.getValueType();
15292 if (Op->getOpcode() == ISD::SIGN_EXTEND_INREG) {
15293 auto *VTSign = cast<VTSDNode>(Op->getOperand(1));
15294 NarrowVT = VTSign->getVT();
15295 }
15296 if (!NarrowVT.isByteSized())
15297 return std::nullopt;
15298 uint64_t NarrowByteWidth = NarrowVT.getStoreSize();
15299
15300 if (SrcIndex >= NarrowByteWidth)
15301 return std::nullopt;
15302 return calculateSrcByte(Op->getOperand(0), DestByte, SrcIndex, Depth + 1);
15303 }
15304
15305 case ISD::SRA:
15306 case ISD::SRL: {
15307 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15308 if (!ShiftOp)
15309 return std::nullopt;
15310
15311 uint64_t BitShift = ShiftOp->getZExtValue();
15312
15313 if (BitShift % 8 != 0)
15314 return std::nullopt;
15315
15316 uint64_t NewSrcIndex = SrcIndex + BitShift / 8;
15317 if (NewSrcIndex >= Op.getScalarValueSizeInBits() / 8)
15318 return std::nullopt;
15319
15320 return calculateSrcByte(Op->getOperand(0), DestByte, NewSrcIndex,
15321 Depth + 1);
15322 }
15323
15324 default: {
15325 return ByteProvider<SDValue>::getSrc(Op, DestByte, SrcIndex);
15326 }
15327 }
15328 llvm_unreachable("fully handled switch");
15329}
15330
15331// For a byte position in the result of an Or, traverse the tree and find the
15332// node (and the byte of the node) which ultimately provides this {Or,
15333// BytePosition}. \p Op is the operand we are currently examining. \p Index is
15334// the byte position of the Op that corresponds with the originally requested
15335// byte of the Or \p Depth tracks how many recursive iterations we have
15336// performed. \p StartingIndex is the originally requested byte of the Or
15337static const std::optional<ByteProvider<SDValue>>
15338calculateByteProvider(const SDValue &Op, unsigned Index, unsigned Depth,
15339 unsigned StartingIndex = 0) {
15340 // Finding Src tree of RHS of or typically requires at least 1 additional
15341 // depth
15342 if (Depth > 6)
15343 return std::nullopt;
15344
15345 unsigned BitWidth = Op.getScalarValueSizeInBits();
15346 if (BitWidth % 8 != 0)
15347 return std::nullopt;
15348 if (Index > BitWidth / 8 - 1)
15349 return std::nullopt;
15350
15351 bool IsVec = Op.getValueType().isVector();
15352 switch (Op.getOpcode()) {
15353 case ISD::OR: {
15354 if (IsVec)
15355 return std::nullopt;
15356
15357 auto RHS = calculateByteProvider(Op.getOperand(1), Index, Depth + 1,
15358 StartingIndex);
15359 if (!RHS)
15360 return std::nullopt;
15361 auto LHS = calculateByteProvider(Op.getOperand(0), Index, Depth + 1,
15362 StartingIndex);
15363 if (!LHS)
15364 return std::nullopt;
15365 // A well formed Or will have two ByteProviders for each byte, one of which
15366 // is constant zero
15367 if (!LHS->isConstantZero() && !RHS->isConstantZero())
15368 return std::nullopt;
15369 if (!LHS || LHS->isConstantZero())
15370 return RHS;
15371 if (!RHS || RHS->isConstantZero())
15372 return LHS;
15373 return std::nullopt;
15374 }
15375
15376 case ISD::AND: {
15377 if (IsVec)
15378 return std::nullopt;
15379
15380 auto *BitMaskOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15381 if (!BitMaskOp)
15382 return std::nullopt;
15383
15384 uint32_t BitMask = BitMaskOp->getZExtValue();
15385 // Bits we expect for our StartingIndex
15386 uint32_t IndexMask = 0xFF << (Index * 8);
15387
15388 if ((IndexMask & BitMask) != IndexMask) {
15389 // If the result of the and partially provides the byte, then it
15390 // is not well formatted
15391 if (IndexMask & BitMask)
15392 return std::nullopt;
15394 }
15395
15396 return calculateSrcByte(Op->getOperand(0), StartingIndex, Index);
15397 }
15398
15399 case ISD::FSHR: {
15400 if (IsVec)
15401 return std::nullopt;
15402
15403 // fshr(X,Y,Z): (X << (BW - (Z % BW))) | (Y >> (Z % BW))
15404 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(2));
15405 if (!ShiftOp || Op.getValueType().isVector())
15406 return std::nullopt;
15407
15408 uint64_t BitsProvided = Op.getValueSizeInBits();
15409 if (BitsProvided % 8 != 0)
15410 return std::nullopt;
15411
15412 uint64_t BitShift = ShiftOp->getAPIntValue().urem(BitsProvided);
15413 if (BitShift % 8)
15414 return std::nullopt;
15415
15416 uint64_t ConcatSizeInBytes = BitsProvided / 4;
15417 uint64_t ByteShift = BitShift / 8;
15418
15419 uint64_t NewIndex = (Index + ByteShift) % ConcatSizeInBytes;
15420 uint64_t BytesProvided = BitsProvided / 8;
15421 SDValue NextOp = Op.getOperand(NewIndex >= BytesProvided ? 0 : 1);
15422 NewIndex %= BytesProvided;
15423 return calculateByteProvider(NextOp, NewIndex, Depth + 1, StartingIndex);
15424 }
15425
15426 case ISD::SRA:
15427 case ISD::SRL: {
15428 if (IsVec)
15429 return std::nullopt;
15430
15431 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15432 if (!ShiftOp)
15433 return std::nullopt;
15434
15435 uint64_t BitShift = ShiftOp->getZExtValue();
15436 if (BitShift % 8)
15437 return std::nullopt;
15438
15439 auto BitsProvided = Op.getScalarValueSizeInBits();
15440 if (BitsProvided % 8 != 0)
15441 return std::nullopt;
15442
15443 uint64_t BytesProvided = BitsProvided / 8;
15444 uint64_t ByteShift = BitShift / 8;
15445 if (Index + ByteShift < BytesProvided)
15446 return calculateSrcByte(Op->getOperand(0), StartingIndex,
15447 Index + ByteShift);
15448 // SRA's out-of-range bytes are sign bits, not constant zero.
15449 if (Op.getOpcode() == ISD::SRA)
15450 return std::nullopt;
15452 }
15453
15454 case ISD::SHL: {
15455 if (IsVec)
15456 return std::nullopt;
15457
15458 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15459 if (!ShiftOp)
15460 return std::nullopt;
15461
15462 uint64_t BitShift = ShiftOp->getZExtValue();
15463 if (BitShift % 8 != 0)
15464 return std::nullopt;
15465 uint64_t ByteShift = BitShift / 8;
15466
15467 // If we are shifting by an amount greater than (or equal to)
15468 // the index we are trying to provide, then it provides 0s. If not,
15469 // then this bytes are not definitively 0s, and the corresponding byte
15470 // of interest is Index - ByteShift of the src
15471 return Index < ByteShift
15473 : calculateByteProvider(Op.getOperand(0), Index - ByteShift,
15474 Depth + 1, StartingIndex);
15475 }
15476 case ISD::ANY_EXTEND:
15477 case ISD::SIGN_EXTEND:
15478 case ISD::ZERO_EXTEND:
15480 case ISD::AssertZext:
15481 case ISD::AssertSext: {
15482 if (IsVec)
15483 return std::nullopt;
15484
15485 SDValue NarrowOp = Op->getOperand(0);
15486 unsigned NarrowBitWidth = NarrowOp.getValueSizeInBits();
15487 if (Op->getOpcode() == ISD::SIGN_EXTEND_INREG ||
15488 Op->getOpcode() == ISD::AssertZext ||
15489 Op->getOpcode() == ISD::AssertSext) {
15490 auto *VTSign = cast<VTSDNode>(Op->getOperand(1));
15491 NarrowBitWidth = VTSign->getVT().getSizeInBits();
15492 }
15493 if (NarrowBitWidth % 8 != 0)
15494 return std::nullopt;
15495 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15496
15497 if (Index >= NarrowByteWidth)
15498 return Op.getOpcode() == ISD::ZERO_EXTEND
15499 ? std::optional<ByteProvider<SDValue>>(
15501 : std::nullopt;
15502 return calculateByteProvider(NarrowOp, Index, Depth + 1, StartingIndex);
15503 }
15504
15505 case ISD::TRUNCATE: {
15506 if (IsVec)
15507 return std::nullopt;
15508
15509 uint64_t NarrowByteWidth = BitWidth / 8;
15510
15511 if (NarrowByteWidth >= Index) {
15512 return calculateByteProvider(Op.getOperand(0), Index, Depth + 1,
15513 StartingIndex);
15514 }
15515
15516 return std::nullopt;
15517 }
15518
15519 case ISD::CopyFromReg: {
15520 if (BitWidth / 8 > Index)
15521 return calculateSrcByte(Op, StartingIndex, Index);
15522
15523 return std::nullopt;
15524 }
15525
15526 case ISD::LOAD: {
15527 auto *L = cast<LoadSDNode>(Op.getNode());
15528
15529 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
15530 if (NarrowBitWidth % 8 != 0)
15531 return std::nullopt;
15532 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15533
15534 // If the width of the load does not reach byte we are trying to provide for
15535 // and it is not a ZEXTLOAD, then the load does not provide for the byte in
15536 // question
15537 if (Index >= NarrowByteWidth) {
15538 return L->getExtensionType() == ISD::ZEXTLOAD
15539 ? std::optional<ByteProvider<SDValue>>(
15541 : std::nullopt;
15542 }
15543
15544 if (NarrowByteWidth > Index) {
15545 return calculateSrcByte(Op, StartingIndex, Index);
15546 }
15547
15548 return std::nullopt;
15549 }
15550
15551 case ISD::BSWAP: {
15552 if (IsVec)
15553 return std::nullopt;
15554
15555 return calculateByteProvider(Op->getOperand(0), BitWidth / 8 - Index - 1,
15556 Depth + 1, StartingIndex);
15557 }
15558
15560 auto *IdxOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15561 if (!IdxOp)
15562 return std::nullopt;
15563 auto VecIdx = IdxOp->getZExtValue();
15564 auto ScalarSize = Op.getScalarValueSizeInBits();
15565 if (ScalarSize < 32)
15566 Index = ScalarSize == 8 ? VecIdx : VecIdx * 2 + Index;
15567 return calculateSrcByte(ScalarSize >= 32 ? Op : Op.getOperand(0),
15568 StartingIndex, Index);
15569 }
15570
15571 case AMDGPUISD::PERM: {
15572 if (IsVec)
15573 return std::nullopt;
15574
15575 auto *PermMask = dyn_cast<ConstantSDNode>(Op->getOperand(2));
15576 if (!PermMask)
15577 return std::nullopt;
15578
15579 auto IdxMask =
15580 (PermMask->getZExtValue() & (0xFF << (Index * 8))) >> (Index * 8);
15581 if (IdxMask > 0x07 && IdxMask != 0x0c)
15582 return std::nullopt;
15583
15584 auto NextOp = Op.getOperand(IdxMask > 0x03 ? 0 : 1);
15585 auto NextIndex = IdxMask > 0x03 ? IdxMask % 4 : IdxMask;
15586
15587 return IdxMask != 0x0c ? calculateSrcByte(NextOp, StartingIndex, NextIndex)
15590 }
15591
15592 default: {
15593 return std::nullopt;
15594 }
15595 }
15596
15597 llvm_unreachable("fully handled switch");
15598}
15599
15600// Returns true if the Operand is a scalar and is 16 bits
15601static bool isExtendedFrom16Bits(SDValue &Operand) {
15602
15603 switch (Operand.getOpcode()) {
15604 case ISD::ANY_EXTEND:
15605 case ISD::SIGN_EXTEND:
15606 case ISD::ZERO_EXTEND: {
15607 auto OpVT = Operand.getOperand(0).getValueType();
15608 return !OpVT.isVector() && OpVT.getSizeInBits() == 16;
15609 }
15610 case ISD::LOAD: {
15611 LoadSDNode *L = cast<LoadSDNode>(Operand.getNode());
15612 auto ExtType = cast<LoadSDNode>(L)->getExtensionType();
15613 if (ExtType == ISD::ZEXTLOAD || ExtType == ISD::SEXTLOAD ||
15614 ExtType == ISD::EXTLOAD) {
15615 auto MemVT = L->getMemoryVT();
15616 return !MemVT.isVector() && MemVT.getSizeInBits() == 16;
15617 }
15618 return L->getMemoryVT().getSizeInBits() == 16;
15619 }
15620 default:
15621 return false;
15622 }
15623}
15624
15625// Returns true if the mask matches consecutive bytes, and the first byte
15626// begins at a power of 2 byte offset from 0th byte
15627static bool addresses16Bits(int Mask) {
15628 int Low8 = Mask & 0xff;
15629 int Hi8 = (Mask & 0xff00) >> 8;
15630
15631 assert(Low8 < 8 && Hi8 < 8);
15632 // Are the bytes contiguous in the order of increasing addresses.
15633 bool IsConsecutive = (Hi8 - Low8 == 1);
15634 // Is the first byte at location that is aligned for 16 bit instructions.
15635 // A counter example is taking 2 consecutive bytes starting at the 8th bit.
15636 // In this case, we still need code to extract the 16 bit operand, so it
15637 // is better to use i8 v_perm
15638 bool Is16Aligned = !(Low8 % 2);
15639
15640 return IsConsecutive && Is16Aligned;
15641}
15642
15643// Do not lower into v_perm if the operands are actually 16 bit
15644// and the selected bits (based on PermMask) correspond with two
15645// easily addressable 16 bit operands.
15647 SDValue &OtherOp) {
15648 int Low16 = PermMask & 0xffff;
15649 int Hi16 = (PermMask & 0xffff0000) >> 16;
15650
15651 auto TempOp = peekThroughBitcasts(Op);
15652 auto TempOtherOp = peekThroughBitcasts(OtherOp);
15653
15654 auto OpIs16Bit =
15655 TempOp.getValueSizeInBits() == 16 || isExtendedFrom16Bits(TempOp);
15656 if (!OpIs16Bit)
15657 return true;
15658
15659 auto OtherOpIs16Bit = TempOtherOp.getValueSizeInBits() == 16 ||
15660 isExtendedFrom16Bits(TempOtherOp);
15661 if (!OtherOpIs16Bit)
15662 return true;
15663
15664 // Do we cleanly address both
15665 return !addresses16Bits(Low16) || !addresses16Bits(Hi16);
15666}
15667
15669 unsigned DWordOffset) {
15670 SDValue Ret;
15671
15672 auto TypeSize = Src.getValueSizeInBits().getFixedValue();
15673 // ByteProvider must be at least 8 bits
15674 assert(Src.getValueSizeInBits().isKnownMultipleOf(8));
15675
15676 if (TypeSize <= 32)
15677 return DAG.getBitcastedAnyExtOrTrunc(Src, SL, MVT::i32);
15678
15679 if (Src.getValueType().isVector()) {
15680 auto ScalarTySize = Src.getScalarValueSizeInBits();
15681 auto ScalarTy = Src.getValueType().getScalarType();
15682 if (ScalarTySize == 32) {
15683 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Src,
15684 DAG.getConstant(DWordOffset, SL, MVT::i32));
15685 }
15686 if (ScalarTySize > 32) {
15687 Ret = DAG.getNode(
15688 ISD::EXTRACT_VECTOR_ELT, SL, ScalarTy, Src,
15689 DAG.getConstant(DWordOffset / (ScalarTySize / 32), SL, MVT::i32));
15690 auto ShiftVal = 32 * (DWordOffset % (ScalarTySize / 32));
15691 if (ShiftVal)
15692 Ret = DAG.getNode(ISD::SRL, SL, Ret.getValueType(), Ret,
15693 DAG.getConstant(ShiftVal, SL, MVT::i32));
15694 return DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15695 }
15696
15697 assert(ScalarTySize < 32);
15698 if (TypeSize % 32 == 0) {
15699 assert(DWordOffset < TypeSize / 32);
15700 SDValue Cast = DAG.getBitcast(
15701 EVT::getVectorVT(*DAG.getContext(), MVT::i32, TypeSize / 32), Src);
15702 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Cast,
15703 DAG.getConstant(DWordOffset, SL, MVT::i32));
15704 }
15705
15706 auto NumElements = TypeSize / ScalarTySize;
15707 auto Trunc32Elements = (ScalarTySize * NumElements) / 32;
15708 auto NormalizedTrunc = Trunc32Elements * 32 / ScalarTySize;
15709 auto NumElementsIn32 = 32 / ScalarTySize;
15710 auto NumAvailElements = DWordOffset < Trunc32Elements
15711 ? NumElementsIn32
15712 : NumElements - NormalizedTrunc;
15713
15715 DAG.ExtractVectorElements(Src, VecSrcs, DWordOffset * NumElementsIn32,
15716 NumAvailElements);
15717
15718 Ret = DAG.getBuildVector(
15719 MVT::getVectorVT(MVT::getIntegerVT(ScalarTySize), NumAvailElements), SL,
15720 VecSrcs);
15721 return Ret = DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15722 }
15723
15724 /// Scalar Type
15725 auto ShiftVal = 32 * DWordOffset;
15726 Ret = DAG.getNode(ISD::SRL, SL, Src.getValueType(), Src,
15727 DAG.getConstant(ShiftVal, SL, MVT::i32));
15728 return DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15729}
15730
15732 SelectionDAG &DAG = DCI.DAG;
15733 [[maybe_unused]] EVT VT = N->getValueType(0);
15735
15736 // VT is known to be MVT::i32, so we need to provide 4 bytes.
15737 assert(VT == MVT::i32);
15738 for (int i = 0; i < 4; i++) {
15739 // Find the ByteProvider that provides the ith byte of the result of OR
15740 std::optional<ByteProvider<SDValue>> P =
15741 calculateByteProvider(SDValue(N, 0), i, 0, /*StartingIndex = */ i);
15742 // TODO support constantZero
15743 if (!P || P->isConstantZero())
15744 return SDValue();
15745
15746 PermNodes.push_back(*P);
15747 }
15748 if (PermNodes.size() != 4)
15749 return SDValue();
15750
15751 std::pair<unsigned, unsigned> FirstSrc(0, PermNodes[0].SrcOffset / 4);
15752 std::optional<std::pair<unsigned, unsigned>> SecondSrc;
15753 uint64_t PermMask = 0x00000000;
15754 for (size_t i = 0; i < PermNodes.size(); i++) {
15755 auto PermOp = PermNodes[i];
15756 // Since the mask is applied to Src1:Src2, Src1 bytes must be offset
15757 // by sizeof(Src2) = 4
15758 int SrcByteAdjust = 4;
15759
15760 // If the Src uses a byte from a different DWORD, then it corresponds
15761 // with a difference source
15762 if (!PermOp.hasSameSrc(PermNodes[FirstSrc.first]) ||
15763 ((PermOp.SrcOffset / 4) != FirstSrc.second)) {
15764 if (SecondSrc)
15765 if (!PermOp.hasSameSrc(PermNodes[SecondSrc->first]) ||
15766 ((PermOp.SrcOffset / 4) != SecondSrc->second))
15767 return SDValue();
15768
15769 // Set the index of the second distinct Src node
15770 SecondSrc = {i, PermNodes[i].SrcOffset / 4};
15771 assert(!(PermNodes[SecondSrc->first].Src->getValueSizeInBits() % 8));
15772 SrcByteAdjust = 0;
15773 }
15774 assert((PermOp.SrcOffset % 4) + SrcByteAdjust < 8);
15776 PermMask |= ((PermOp.SrcOffset % 4) + SrcByteAdjust) << (i * 8);
15777 }
15778 SDLoc DL(N);
15779 SDValue Op = *PermNodes[FirstSrc.first].Src;
15780 Op = getDWordFromOffset(DAG, DL, Op, FirstSrc.second);
15781 assert(Op.getValueSizeInBits() == 32);
15782
15783 // Check that we are not just extracting the bytes in order from an op
15784 if (!SecondSrc) {
15785 int Low16 = PermMask & 0xffff;
15786 int Hi16 = (PermMask & 0xffff0000) >> 16;
15787
15788 bool WellFormedLow = (Low16 == 0x0504) || (Low16 == 0x0100);
15789 bool WellFormedHi = (Hi16 == 0x0706) || (Hi16 == 0x0302);
15790
15791 // The perm op would really just produce Op. So combine into Op
15792 if (WellFormedLow && WellFormedHi)
15793 return DAG.getBitcast(MVT::getIntegerVT(32), Op);
15794 }
15795
15796 SDValue OtherOp = SecondSrc ? *PermNodes[SecondSrc->first].Src : Op;
15797
15798 if (SecondSrc) {
15799 OtherOp = getDWordFromOffset(DAG, DL, OtherOp, SecondSrc->second);
15800 assert(OtherOp.getValueSizeInBits() == 32);
15801 }
15802
15803 // Check that we haven't just recreated the same FSHR node.
15804 if (N->getOpcode() == ISD::FSHR &&
15805 (N->getOperand(0) == Op || N->getOperand(0) == OtherOp) &&
15806 (N->getOperand(1) == Op || N->getOperand(1) == OtherOp))
15807 return SDValue();
15808
15809 if (hasNon16BitAccesses(PermMask, Op, OtherOp)) {
15810
15811 assert(Op.getValueType().isByteSized() &&
15812 OtherOp.getValueType().isByteSized());
15813
15814 // If the ultimate src is less than 32 bits, then we will only be
15815 // using bytes 0: Op.getValueSizeInBytes() - 1 in the or.
15816 // CalculateByteProvider would not have returned Op as source if we
15817 // used a byte that is outside its ValueType. Thus, we are free to
15818 // ANY_EXTEND as the extended bits are dont-cares.
15819 Op = DAG.getBitcastedAnyExtOrTrunc(Op, DL, MVT::i32);
15820 OtherOp = DAG.getBitcastedAnyExtOrTrunc(OtherOp, DL, MVT::i32);
15821
15822 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, Op, OtherOp,
15823 DAG.getConstant(PermMask, DL, MVT::i32));
15824 }
15825 return SDValue();
15826}
15827
15828SDValue SITargetLowering::performOrCombine(SDNode *N,
15829 DAGCombinerInfo &DCI) const {
15830 SelectionDAG &DAG = DCI.DAG;
15831 SDValue LHS = N->getOperand(0);
15832 SDValue RHS = N->getOperand(1);
15833
15834 EVT VT = N->getValueType(0);
15835 if (VT == MVT::i1) {
15836 // or (fp_class x, c1), (fp_class x, c2) -> fp_class x, (c1 | c2)
15837 if (LHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15838 RHS.getOpcode() == AMDGPUISD::FP_CLASS) {
15839 SDValue Src = LHS.getOperand(0);
15840 if (Src != RHS.getOperand(0))
15841 return SDValue();
15842
15843 const ConstantSDNode *CLHS = dyn_cast<ConstantSDNode>(LHS.getOperand(1));
15844 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(RHS.getOperand(1));
15845 if (!CLHS || !CRHS)
15846 return SDValue();
15847
15848 // Only 10 bits are used.
15849 static const uint32_t MaxMask = 0x3ff;
15850
15851 uint32_t NewMask =
15852 (CLHS->getZExtValue() | CRHS->getZExtValue()) & MaxMask;
15853 SDLoc DL(N);
15854 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, Src,
15855 DAG.getConstant(NewMask, DL, MVT::i32));
15856 }
15857
15858 return SDValue();
15859 }
15860
15861 // or (perm x, y, c1), c2 -> perm x, y, permute_mask(c1, c2)
15863 LHS.getOpcode() == AMDGPUISD::PERM &&
15864 isa<ConstantSDNode>(LHS.getOperand(2))) {
15865 uint32_t Sel = getConstantPermuteMask(N->getConstantOperandVal(1));
15866 if (!Sel)
15867 return SDValue();
15868
15869 Sel |= LHS.getConstantOperandVal(2);
15870 SDLoc DL(N);
15871 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15872 LHS.getOperand(1), DAG.getConstant(Sel, DL, MVT::i32));
15873 }
15874
15875 // or (op x, c1), (op y, c2) -> perm x, y, permute_mask(c1, c2)
15876 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
15877 if (VT == MVT::i32 && LHS.hasOneUse() && RHS.hasOneUse() &&
15878 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15879
15880 // If all the uses of an or need to extract the individual elements, do not
15881 // attempt to lower into v_perm
15882 auto usesCombinedOperand = [](SDNode *OrUse) {
15883 // If we have any non-vectorized use, then it is a candidate for v_perm
15884 if (OrUse->getOpcode() != ISD::BITCAST ||
15885 !OrUse->getValueType(0).isVector())
15886 return true;
15887
15888 // If we have any non-vectorized use, then it is a candidate for v_perm
15889 for (auto *VUser : OrUse->users()) {
15890 if (!VUser->getValueType(0).isVector())
15891 return true;
15892
15893 // If the use of a vector is a store, then combining via a v_perm
15894 // is beneficial.
15895 // TODO -- whitelist more uses
15896 for (auto VectorwiseOp : {ISD::STORE, ISD::CopyToReg, ISD::CopyFromReg})
15897 if (VUser->getOpcode() == VectorwiseOp)
15898 return true;
15899 }
15900 return false;
15901 };
15902
15903 if (!any_of(N->users(), usesCombinedOperand))
15904 return SDValue();
15905
15906 uint32_t LHSMask = getPermuteMask(LHS);
15907 uint32_t RHSMask = getPermuteMask(RHS);
15908
15909 if (LHSMask != ~0u && RHSMask != ~0u) {
15910 // Canonicalize the expression in an attempt to have fewer unique masks
15911 // and therefore fewer registers used to hold the masks.
15912 if (LHSMask > RHSMask) {
15913 std::swap(LHSMask, RHSMask);
15914 std::swap(LHS, RHS);
15915 }
15916
15917 // Select 0xc for each lane used from source operand. Zero has 0xc mask
15918 // set, 0xff have 0xff in the mask, actual lanes are in the 0-3 range.
15919 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15920 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15921
15922 // Check of we need to combine values from two sources within a byte.
15923 if (!(LHSUsedLanes & RHSUsedLanes) &&
15924 // If we select high and lower word keep it for SDWA.
15925 // TODO: teach SDWA to work with v_perm_b32 and remove the check.
15926 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15927 // Kill zero bytes selected by other mask. Zero value is 0xc.
15928 LHSMask &= ~RHSUsedLanes;
15929 RHSMask &= ~LHSUsedLanes;
15930 // Add 4 to each active LHS lane
15931 LHSMask |= LHSUsedLanes & 0x04040404;
15932 // Combine masks
15933 uint32_t Sel = LHSMask | RHSMask;
15934 SDLoc DL(N);
15935
15936 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15937 RHS.getOperand(0),
15938 DAG.getConstant(Sel, DL, MVT::i32));
15939 }
15940 }
15941 if (LHSMask == ~0u || RHSMask == ~0u) {
15942 if (SDValue Perm = matchPERM(N, DCI))
15943 return Perm;
15944 }
15945 }
15946
15947 // Detect identity v2i32 OR and replace with identity source node.
15948 // Specifically an Or that has operands constructed from the same source node
15949 // via extract_vector_elt and build_vector. I.E.
15950 // v2i32 or(
15951 // v2i32 build_vector(
15952 // i32 extract_elt(%IdentitySrc, 0),
15953 // i32 0
15954 // ),
15955 // v2i32 build_vector(
15956 // i32 0,
15957 // i32 extract_elt(%IdentitySrc, 1)
15958 // ) )
15959 // =>
15960 // v2i32 %IdentitySrc
15961
15962 if (VT == MVT::v2i32 && LHS->getOpcode() == ISD::BUILD_VECTOR &&
15963 RHS->getOpcode() == ISD::BUILD_VECTOR) {
15964
15965 ConstantSDNode *LC = dyn_cast<ConstantSDNode>(LHS->getOperand(1));
15966 ConstantSDNode *RC = dyn_cast<ConstantSDNode>(RHS->getOperand(0));
15967
15968 // Test for and normalise build vectors.
15969 if (LC && RC && LC->getZExtValue() == 0 && RC->getZExtValue() == 0) {
15970
15971 // Get the extract_vector_element operands.
15972 SDValue LEVE = LHS->getOperand(0);
15973 SDValue REVE = RHS->getOperand(1);
15974
15975 if (LEVE->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15977 // Check that different elements from the same vector are
15978 // extracted.
15979 if (LEVE->getOperand(0) == REVE->getOperand(0) &&
15980 LEVE->getOperand(1) != REVE->getOperand(1)) {
15981 SDValue IdentitySrc = LEVE.getOperand(0);
15982 return IdentitySrc;
15983 }
15984 }
15985 }
15986 }
15987
15988 if (VT != MVT::i64 || DCI.isBeforeLegalizeOps())
15989 return SDValue();
15990
15991 // TODO: This could be a generic combine with a predicate for extracting the
15992 // high half of an integer being free.
15993
15994 // (or i64:x, (zero_extend i32:y)) ->
15995 // i64 (bitcast (v2i32 build_vector (or i32:y, lo_32(x)), hi_32(x)))
15996 if (LHS.getOpcode() == ISD::ZERO_EXTEND &&
15997 RHS.getOpcode() != ISD::ZERO_EXTEND)
15998 std::swap(LHS, RHS);
15999
16000 if (RHS.getOpcode() == ISD::ZERO_EXTEND) {
16001 SDValue ExtSrc = RHS.getOperand(0);
16002 EVT SrcVT = ExtSrc.getValueType();
16003 if (SrcVT == MVT::i32) {
16004 SDLoc SL(N);
16005 auto [LowLHS, HiBits] = split64BitValue(LHS, DAG);
16006 SDValue LowOr = DAG.getNode(ISD::OR, SL, MVT::i32, LowLHS, ExtSrc);
16007
16008 DCI.AddToWorklist(LowOr.getNode());
16009 DCI.AddToWorklist(HiBits.getNode());
16010
16011 SDValue Vec =
16012 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, LowOr, HiBits);
16013 return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
16014 }
16015 }
16016
16017 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(N->getOperand(1));
16018 if (CRHS) {
16019 if (SDValue Split = splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::OR,
16020 N->getOperand(0), CRHS))
16021 return Split;
16022 }
16023
16024 return SDValue();
16025}
16026
16027SDValue SITargetLowering::performXorCombine(SDNode *N,
16028 DAGCombinerInfo &DCI) const {
16029 if (SDValue RV = reassociateScalarOps(N, DCI.DAG))
16030 return RV;
16031
16032 SDValue LHS = N->getOperand(0);
16033 SDValue RHS = N->getOperand(1);
16034
16035 const ConstantSDNode *CRHS = isConstOrConstSplat(RHS);
16036 SelectionDAG &DAG = DCI.DAG;
16037
16038 EVT VT = N->getValueType(0);
16039 if (CRHS && VT == MVT::i64) {
16040 if (SDValue Split =
16041 splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::XOR, LHS, CRHS))
16042 return Split;
16043 }
16044
16045 // v2i32 (xor (vselect cc, x, y), K) ->
16046 // (v2i32 svelect cc, (xor x, K), (xor y, K)) This enables the xor to be
16047 // replaced with source modifiers when the select is lowered to CNDMASK.
16048 unsigned Opc = LHS.getOpcode();
16049 if (((Opc == ISD::VSELECT && VT == MVT::v2i32) ||
16050 (Opc == ISD::SELECT && VT == MVT::i64)) &&
16051 CRHS && CRHS->getAPIntValue().isSignMask()) {
16052 SDValue CC = LHS->getOperand(0);
16053 SDValue TRUE = LHS->getOperand(1);
16054 SDValue FALSE = LHS->getOperand(2);
16055 SDValue XTrue = DAG.getNode(ISD::XOR, SDLoc(N), VT, TRUE, RHS);
16056 SDValue XFalse = DAG.getNode(ISD::XOR, SDLoc(N), VT, FALSE, RHS);
16057 SDValue XSelect =
16058 DAG.getNode(ISD::VSELECT, SDLoc(N), VT, CC, XTrue, XFalse);
16059 return XSelect;
16060 }
16061
16062 // Make sure to apply the 64-bit constant splitting fold before trying to fold
16063 // fneg-like xors into 64-bit select.
16064 if (LHS.getOpcode() == ISD::SELECT && VT == MVT::i32) {
16065 // This looks like an fneg, try to fold as a source modifier.
16066 if (CRHS && CRHS->getAPIntValue().isSignMask() &&
16068 // xor (select c, a, b), 0x80000000 ->
16069 // bitcast (select c, (fneg (bitcast a)), (fneg (bitcast b)))
16070 SDLoc DL(N);
16071 SDValue CastLHS =
16072 DAG.getNode(ISD::BITCAST, DL, MVT::f32, LHS->getOperand(1));
16073 SDValue CastRHS =
16074 DAG.getNode(ISD::BITCAST, DL, MVT::f32, LHS->getOperand(2));
16075 SDValue FNegLHS = DAG.getNode(ISD::FNEG, DL, MVT::f32, CastLHS);
16076 SDValue FNegRHS = DAG.getNode(ISD::FNEG, DL, MVT::f32, CastRHS);
16077 SDValue NewSelect = DAG.getNode(ISD::SELECT, DL, MVT::f32,
16078 LHS->getOperand(0), FNegLHS, FNegRHS);
16079 return DAG.getNode(ISD::BITCAST, DL, VT, NewSelect);
16080 }
16081 }
16082
16083 return SDValue();
16084}
16085
16086SDValue
16087SITargetLowering::performZeroOrAnyExtendCombine(SDNode *N,
16088 DAGCombinerInfo &DCI) const {
16089 if (!Subtarget->has16BitInsts() ||
16090 DCI.getDAGCombineLevel() < AfterLegalizeTypes)
16091 return SDValue();
16092
16093 EVT VT = N->getValueType(0);
16094 if (VT != MVT::i32)
16095 return SDValue();
16096
16097 SDValue Src = N->getOperand(0);
16098 if (Src.getValueType() != MVT::i16)
16099 return SDValue();
16100
16101 if (!Src->hasOneUse())
16102 return SDValue();
16103
16104 if (SDValue Ext = performExtendTruncShiftCombine(N, DCI))
16105 return Ext;
16106
16107 // TODO: We bail out below if SrcOffset is not in the first dword (>= 4). It's
16108 // possible we're missing out on some combine opportunities, but we'd need to
16109 // weigh the cost of extracting the byte from the upper dwords.
16110
16111 std::optional<ByteProvider<SDValue>> BP0 =
16112 calculateByteProvider(SDValue(N, 0), 0, 0, 0);
16113 if (!BP0 || BP0->SrcOffset >= 4 || !BP0->Src)
16114 return SDValue();
16115 SDValue V0 = *BP0->Src;
16116
16117 std::optional<ByteProvider<SDValue>> BP1 =
16118 calculateByteProvider(SDValue(N, 0), 1, 0, 1);
16119 if (!BP1 || BP1->SrcOffset >= 4 || !BP1->Src)
16120 return SDValue();
16121
16122 SDValue V1 = *BP1->Src;
16123
16124 if (V0 == V1)
16125 return SDValue();
16126
16127 SelectionDAG &DAG = DCI.DAG;
16128 SDLoc DL(N);
16129 uint32_t PermMask = 0x0c0c0c0c;
16130 if (V0) {
16131 V0 = DAG.getBitcastedAnyExtOrTrunc(V0, DL, MVT::i32);
16132 PermMask = (PermMask & ~0xFF) | (BP0->SrcOffset + 4);
16133 }
16134
16135 if (V1) {
16136 V1 = DAG.getBitcastedAnyExtOrTrunc(V1, DL, MVT::i32);
16137 PermMask = (PermMask & ~(0xFF << 8)) | (BP1->SrcOffset << 8);
16138 }
16139
16140 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, V0, V1,
16141 DAG.getConstant(PermMask, DL, MVT::i32));
16142}
16143
16144// zext (srl (trunc x), c) => and (srl x, c), lowbits
16145// aext (srl (trunc x), c) => and (srl x, c), lowbits
16146// sext (sra (trunc x), 8) => sext_inreg (srl x, 8), i8
16147SDValue
16148SITargetLowering::performExtendTruncShiftCombine(SDNode *N,
16149 DAGCombinerInfo &DCI) const {
16150 if (DCI.getDAGCombineLevel() < AfterLegalizeTypes)
16151 return SDValue();
16152
16153 const unsigned Opc = N->getOpcode();
16154 const bool IsSigned = Opc == ISD::SIGN_EXTEND;
16155 SDValue Src = N->getOperand(0);
16156 if (N->getValueType(0) != MVT::i32 || Src.getValueType() != MVT::i16 ||
16157 Src.getOpcode() != (IsSigned ? ISD::SRA : ISD::SRL) || !Src.hasOneUse() ||
16158 Src.getOperand(0).getOpcode() != ISD::TRUNCATE)
16159 return SDValue();
16160
16161 // A uniform i16 srl is promoted to i32 later and yields the same nodes.
16162 // Skip it so that the node order, and with it the schedule, stays the same.
16163 if (!IsSigned && !Src->isDivergent())
16164 return SDValue();
16165
16166 SDValue X = Src.getOperand(0).getOperand(0);
16167 auto *Shift = dyn_cast<ConstantSDNode>(Src.getOperand(1));
16168 if (X.getValueType() != MVT::i32 || !Shift || Shift->getZExtValue() == 0 ||
16169 Shift->getZExtValue() >= 16 || (IsSigned && Shift->getZExtValue() != 8))
16170 return SDValue();
16171
16172 SelectionDAG &DAG = DCI.DAG;
16173 SDLoc SL(N);
16174 const unsigned Width = 16 - Shift->getZExtValue();
16175 SDValue Srl = DAG.getNode(
16176 ISD::SRL, SL, MVT::i32, X,
16177 DAG.getShiftAmountConstant(Shift->getZExtValue(), MVT::i32, SL));
16178 if (IsSigned)
16179 return DAG.getNode(ISD::SIGN_EXTEND_INREG, SL, MVT::i32, Srl,
16180 DAG.getValueType(MVT::i8));
16181 return DAG.getNode(
16182 ISD::AND, SL, MVT::i32, Srl,
16183 DAG.getConstant(maskTrailingOnes<uint32_t>(Width), SL, MVT::i32));
16184}
16185
16186SDValue
16187SITargetLowering::performSignExtendInRegCombine(SDNode *N,
16188 DAGCombinerInfo &DCI) const {
16189 SDValue Src = N->getOperand(0);
16190 auto *VTSign = cast<VTSDNode>(N->getOperand(1));
16191
16192 // Combine s_buffer_load_u8 or s_buffer_load_u16 with sext and replace them
16193 // with s_buffer_load_i8 and s_buffer_load_i16 respectively.
16194 if (((Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE &&
16195 VTSign->getVT() == MVT::i8) ||
16196 (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_USHORT &&
16197 VTSign->getVT() == MVT::i16))) {
16198 assert(Subtarget->hasScalarSubwordLoads() &&
16199 "s_buffer_load_{u8, i8} are supported "
16200 "in GFX12 (or newer) architectures.");
16201 unsigned Opc = (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE)
16202 ? AMDGPUISD::SBUFFER_LOAD_BYTE
16203 : AMDGPUISD::SBUFFER_LOAD_SHORT;
16204 SDLoc DL(N);
16205 SDVTList ResList =
16206 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16207 SDValue Ops[] = {
16208 Src.getOperand(0), // Chain
16209 Src.getOperand(1), // source register
16210 Src.getOperand(2), // offset
16211 Src.getOperand(3) // cachePolicy
16212 };
16213 auto *M = cast<MemSDNode>(Src);
16214 SDValue BufferLoad = DCI.DAG.getMemIntrinsicNode(
16215 Opc, DL, ResList, Ops, M->getMemoryVT(), M->getMemOperand());
16216 return DCI.DAG.getMergeValues({BufferLoad, BufferLoad.getValue(1)}, DL);
16217 }
16218 if (((Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE &&
16219 VTSign->getVT() == MVT::i8) ||
16220 (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_USHORT &&
16221 VTSign->getVT() == MVT::i16)) &&
16222 Src.hasOneUse()) {
16223 auto *M = cast<MemSDNode>(Src);
16224 SDValue Ops[] = {Src.getOperand(0), // Chain
16225 Src.getOperand(1), // rsrc
16226 Src.getOperand(2), // vindex
16227 Src.getOperand(3), // voffset
16228 Src.getOperand(4), // soffset
16229 Src.getOperand(5), // offset
16230 Src.getOperand(6), Src.getOperand(7)};
16231 // replace with BUFFER_LOAD_BYTE/SHORT
16232 SDVTList ResList =
16233 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16234 unsigned Opc = (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE)
16235 ? AMDGPUISD::BUFFER_LOAD_BYTE
16236 : AMDGPUISD::BUFFER_LOAD_SHORT;
16237 SDValue BufferLoadSignExt = DCI.DAG.getMemIntrinsicNode(
16238 Opc, SDLoc(N), ResList, Ops, M->getMemoryVT(), M->getMemOperand());
16239 return DCI.DAG.getMergeValues(
16240 {BufferLoadSignExt, BufferLoadSignExt.getValue(1)}, SDLoc(N));
16241 }
16242 return SDValue();
16243}
16244
16245SDValue SITargetLowering::performClassCombine(SDNode *N,
16246 DAGCombinerInfo &DCI) const {
16247 SelectionDAG &DAG = DCI.DAG;
16248 SDValue Mask = N->getOperand(1);
16249
16250 // fp_class x, 0 -> false
16251 if (isNullConstant(Mask))
16252 return DAG.getConstant(0, SDLoc(N), MVT::i1);
16253
16254 if (N->getOperand(0).isUndef())
16255 return DAG.getUNDEF(MVT::i1);
16256
16257 return SDValue();
16258}
16259
16260SDValue SITargetLowering::performRcpCombine(SDNode *N,
16261 DAGCombinerInfo &DCI) const {
16262 EVT VT = N->getValueType(0);
16263 SDValue N0 = N->getOperand(0);
16264
16265 if (N0.isUndef()) {
16266 return DCI.DAG.getConstantFP(APFloat::getQNaN(VT.getFltSemantics()),
16267 SDLoc(N), VT);
16268 }
16269
16270 // TODO: Could handle f32 + amdgcn.sqrt but probably never reaches here.
16271 if ((VT == MVT::f16 && N0.getOpcode() == ISD::FSQRT) &&
16272 N->getFlags().hasAllowContract() && N0->getFlags().hasAllowContract()) {
16273 return DCI.DAG.getNode(AMDGPUISD::RSQ, SDLoc(N), VT, N0.getOperand(0),
16274 N->getFlags());
16275 }
16276
16278}
16279
16281 SDNodeFlags UserFlags,
16282 unsigned MaxDepth) const {
16283 EVT VT = Op.getValueType();
16284 assert(VT.isFloatingPoint() &&
16285 "expected a floating-point value to query canonicality of");
16286 return isCanonicalized(DAG, Op, VT.getScalarType(), UserFlags, MaxDepth);
16287}
16288
16290 EVT QueryVT, SDNodeFlags UserFlags,
16291 unsigned MaxDepth) const {
16292 assert(QueryVT.isFloatingPoint() && !QueryVT.isVector() &&
16293 "QueryVT must be a floating-point scalar type");
16294 EVT VT = Op.getValueType();
16295 if (VT.isFloatingPoint() && VT.getScalarType() != QueryVT)
16296 return false;
16297
16298 unsigned Opcode = Op.getOpcode();
16299 if (Opcode == ISD::FCANONICALIZE)
16300 return true;
16301
16302 if (auto *CFP = dyn_cast<ConstantFPSDNode>(Op)) {
16303 const auto &F = CFP->getValueAPF();
16304 if (F.isNaN() && F.isSignaling())
16305 return false;
16306 if (!F.isDenormal())
16307 return true;
16308
16309 DenormalMode Mode =
16310 DAG.getMachineFunction().getDenormalMode(F.getSemantics());
16311 return Mode == DenormalMode::getIEEE();
16312 }
16313
16314 // If source is a result of another standard FP operation it is already in
16315 // canonical form.
16316 if (MaxDepth == 0)
16317 return false;
16318
16319 switch (Opcode) {
16320 // These will flush denorms if required.
16321 case ISD::FADD:
16322 case ISD::FSUB:
16323 case ISD::FMUL:
16324 case ISD::FCEIL:
16325 case ISD::FFLOOR:
16326 case ISD::FMA:
16327 case ISD::FMAD:
16328 case ISD::FSQRT:
16329 case ISD::FDIV:
16330 case ISD::FREM:
16331 case ISD::FP_ROUND:
16332 case ISD::FP_EXTEND:
16333 case ISD::FP16_TO_FP:
16334 case ISD::FP_TO_FP16:
16335 case ISD::BF16_TO_FP:
16336 case ISD::FP_TO_BF16:
16337 case ISD::FLDEXP:
16338 case AMDGPUISD::FMUL_LEGACY:
16339 case AMDGPUISD::FMAD_FTZ:
16340 case AMDGPUISD::RCP:
16341 case AMDGPUISD::RSQ:
16342 case AMDGPUISD::RSQ_CLAMP:
16343 case AMDGPUISD::RCP_LEGACY:
16344 case AMDGPUISD::RCP_IFLAG:
16345 case AMDGPUISD::LOG:
16346 case AMDGPUISD::EXP:
16347 case AMDGPUISD::DIV_SCALE:
16348 case AMDGPUISD::DIV_FMAS:
16349 case AMDGPUISD::DIV_FIXUP:
16350 case AMDGPUISD::FRACT:
16351 case AMDGPUISD::CVT_PKRTZ_F16_F32:
16352 case AMDGPUISD::CVT_F32_UBYTE0:
16353 case AMDGPUISD::CVT_F32_UBYTE1:
16354 case AMDGPUISD::CVT_F32_UBYTE2:
16355 case AMDGPUISD::CVT_F32_UBYTE3:
16356 case AMDGPUISD::FP_TO_FP16:
16357 case AMDGPUISD::SIN_HW:
16358 case AMDGPUISD::COS_HW:
16359 return true;
16360
16361 // It can/will be lowered or combined as a bit operation.
16362 // Need to check their input recursively to handle.
16363 case ISD::FNEG:
16364 case ISD::FABS:
16365 case ISD::FCOPYSIGN:
16366 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16367 MaxDepth - 1);
16368
16369 case ISD::AND:
16370 if (Op.getValueType() == MVT::i32) {
16371 // Be careful as we only know it is a bitcast floating point type. It
16372 // could be f32, v2f16, we have no way of knowing. Luckily the constant
16373 // value that we optimize for, which comes up in fp32 to bf16 conversions,
16374 // is valid to optimize for all types.
16375 if (auto *RHS = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
16376 if (RHS->getZExtValue() == 0xffff0000) {
16377 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16378 MaxDepth - 1);
16379 }
16380 }
16381 }
16382 break;
16383
16384 case ISD::FSIN:
16385 case ISD::FCOS:
16386 case ISD::FSINCOS:
16387 return Op.getValueType().getScalarType() != MVT::f16;
16388
16389 case ISD::FMINNUM:
16390 case ISD::FMAXNUM:
16391 case ISD::FMINNUM_IEEE:
16392 case ISD::FMAXNUM_IEEE:
16393 case ISD::FMINIMUM:
16394 case ISD::FMAXIMUM:
16395 case ISD::FMINIMUMNUM:
16396 case ISD::FMAXIMUMNUM:
16397 case AMDGPUISD::CLAMP:
16398 case AMDGPUISD::FMED3:
16399 case AMDGPUISD::FMAX3:
16400 case AMDGPUISD::FMIN3:
16401 case AMDGPUISD::FMAXIMUM3:
16402 case AMDGPUISD::FMINIMUM3: {
16403 // FIXME: Shouldn't treat the generic operations different based these.
16404 // However, we aren't really required to flush the result from
16405 // minnum/maxnum..
16406
16407 // snans will be quieted, so we only need to worry about denormals.
16408 if (Subtarget->supportsMinMaxDenormModes() ||
16409 // FIXME: denormalsEnabledForType is broken for dynamic
16410 denormalsEnabledForType(DAG, Op.getValueType()))
16411 return true;
16412
16413 // Flushing may be required.
16414 // In pre-GFX9 targets V_MIN_F32 and others do not flush denorms. For such
16415 // targets need to check their input recursively.
16416
16417 // FIXME: Does this apply with clamp? It's implemented with max.
16418 for (unsigned I = 0, E = Op.getNumOperands(); I != E; ++I) {
16419 if (!isCanonicalized(DAG, Op.getOperand(I), QueryVT, UserFlags,
16420 MaxDepth - 1))
16421 return false;
16422 }
16423
16424 return true;
16425 }
16426 case ISD::SELECT: {
16427 return isCanonicalized(DAG, Op.getOperand(1), QueryVT, UserFlags,
16428 MaxDepth - 1) &&
16429 isCanonicalized(DAG, Op.getOperand(2), QueryVT, UserFlags,
16430 MaxDepth - 1);
16431 }
16432 case ISD::BUILD_VECTOR: {
16433 for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
16434 SDValue SrcOp = Op.getOperand(i);
16435 if (!isCanonicalized(DAG, SrcOp, QueryVT, UserFlags, MaxDepth - 1))
16436 return false;
16437 }
16438
16439 return true;
16440 }
16443 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16444 MaxDepth - 1);
16445 }
16447 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16448 MaxDepth - 1) &&
16449 isCanonicalized(DAG, Op.getOperand(1), QueryVT, UserFlags,
16450 MaxDepth - 1);
16451 }
16452 case ISD::POISON:
16453 return true;
16454 case ISD::UNDEF:
16455 // Could be anything.
16456 return false;
16457
16458 case ISD::BITCAST: {
16459 // Carry QueryVT through the bitcast unchanged. The top-of-function guard
16460 // rejects a source whose FP format differs from the consumed type, so a
16461 // value canonical in one FP format is not assumed canonical in another.
16462 SDValue Src = peekThroughBitcasts(Op.getOperand(0));
16463 return isCanonicalized(DAG, Src, QueryVT, UserFlags, MaxDepth - 1);
16464 }
16465 case ISD::TRUNCATE: {
16466 // Hack round the mess we make when legalizing extract_vector_elt
16467 if (Op.getValueType() == MVT::i16) {
16468 SDValue TruncSrc = Op.getOperand(0);
16469 if (TruncSrc.getValueType() == MVT::i32 &&
16470 TruncSrc.getOpcode() == ISD::BITCAST &&
16471 TruncSrc.getOperand(0).getValueType() == MVT::v2f16) {
16472 return isCanonicalized(DAG, TruncSrc.getOperand(0), QueryVT, UserFlags,
16473 MaxDepth - 1);
16474 }
16475 }
16476 return false;
16477 }
16479 unsigned IntrinsicID = Op.getConstantOperandVal(0);
16480 // TODO: Handle more intrinsics
16481 switch (IntrinsicID) {
16482 case Intrinsic::amdgcn_cvt_pkrtz:
16483 case Intrinsic::amdgcn_cubeid:
16484 case Intrinsic::amdgcn_frexp_mant:
16485 case Intrinsic::amdgcn_fdot2:
16486 case Intrinsic::amdgcn_rcp:
16487 case Intrinsic::amdgcn_rsq:
16488 case Intrinsic::amdgcn_rsq_clamp:
16489 case Intrinsic::amdgcn_rcp_legacy:
16490 case Intrinsic::amdgcn_rsq_legacy:
16491 case Intrinsic::amdgcn_trig_preop:
16492 case Intrinsic::amdgcn_tanh:
16493 case Intrinsic::amdgcn_log:
16494 case Intrinsic::amdgcn_exp2:
16495 case Intrinsic::amdgcn_sqrt:
16496 return true;
16497 default:
16498 break;
16499 }
16500
16501 break;
16502 }
16503 default:
16504 break;
16505 }
16506
16507 // FIXME: denormalsEnabledForType is broken for dynamic
16508 return denormalsEnabledForType(DAG, Op.getValueType()) &&
16509 (UserFlags.hasNoNaNs() || DAG.isKnownNeverSNaN(Op));
16510}
16511
16513 unsigned MaxDepth) const {
16514 const MachineRegisterInfo &MRI = MF.getRegInfo();
16515 MachineInstr *MI = MRI.getVRegDef(Reg);
16516 unsigned Opcode = MI->getOpcode();
16517
16518 if (Opcode == AMDGPU::G_FCANONICALIZE)
16519 return true;
16520
16521 std::optional<FPValueAndVReg> FCR;
16522 // Constant splat (can be padded with undef) or scalar constant.
16523 if (mi_match(Reg, MRI, MIPatternMatch::m_GFCstOrSplat(FCR))) {
16524 if (FCR->Value.isSignaling())
16525 return false;
16526 if (!FCR->Value.isDenormal())
16527 return true;
16528
16529 DenormalMode Mode = MF.getDenormalMode(FCR->Value.getSemantics());
16530 return Mode == DenormalMode::getIEEE();
16531 }
16532
16533 if (MaxDepth == 0)
16534 return false;
16535
16536 switch (Opcode) {
16537 case AMDGPU::G_FADD:
16538 case AMDGPU::G_FSUB:
16539 case AMDGPU::G_FMUL:
16540 case AMDGPU::G_FCEIL:
16541 case AMDGPU::G_FFLOOR:
16542 case AMDGPU::G_FRINT:
16543 case AMDGPU::G_FNEARBYINT:
16544 case AMDGPU::G_INTRINSIC_FPTRUNC_ROUND:
16545 case AMDGPU::G_INTRINSIC_TRUNC:
16546 case AMDGPU::G_INTRINSIC_ROUNDEVEN:
16547 case AMDGPU::G_FMA:
16548 case AMDGPU::G_FMAD:
16549 case AMDGPU::G_FSQRT:
16550 case AMDGPU::G_FDIV:
16551 case AMDGPU::G_FREM:
16552 case AMDGPU::G_FPOW:
16553 case AMDGPU::G_FPEXT:
16554 case AMDGPU::G_FLOG:
16555 case AMDGPU::G_FLOG2:
16556 case AMDGPU::G_FLOG10:
16557 case AMDGPU::G_FPTRUNC:
16558 case AMDGPU::G_AMDGPU_RCP_IFLAG:
16559 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE0:
16560 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE1:
16561 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE2:
16562 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE3:
16563 return true;
16564 case AMDGPU::G_FNEG:
16565 case AMDGPU::G_FABS:
16566 case AMDGPU::G_FCOPYSIGN:
16567 return isCanonicalized(MI->getOperand(1).getReg(), MF, MaxDepth - 1);
16568 case AMDGPU::G_FMINNUM:
16569 case AMDGPU::G_FMAXNUM:
16570 case AMDGPU::G_FMINNUM_IEEE:
16571 case AMDGPU::G_FMAXNUM_IEEE:
16572 case AMDGPU::G_FMINIMUM:
16573 case AMDGPU::G_FMAXIMUM:
16574 case AMDGPU::G_FMINIMUMNUM:
16575 case AMDGPU::G_FMAXIMUMNUM: {
16576 if (Subtarget->supportsMinMaxDenormModes() ||
16577 // FIXME: denormalsEnabledForType is broken for dynamic
16578 denormalsEnabledForType(MRI.getType(Reg), MF))
16579 return true;
16580
16581 [[fallthrough]];
16582 }
16583 case AMDGPU::G_BUILD_VECTOR:
16584 for (const MachineOperand &MO : llvm::drop_begin(MI->operands()))
16585 if (!isCanonicalized(MO.getReg(), MF, MaxDepth - 1))
16586 return false;
16587 return true;
16588 case AMDGPU::G_INTRINSIC:
16589 case AMDGPU::G_INTRINSIC_CONVERGENT:
16590 switch (cast<GIntrinsic>(MI)->getIntrinsicID()) {
16591 case Intrinsic::amdgcn_fmul_legacy:
16592 case Intrinsic::amdgcn_fmad_ftz:
16593 case Intrinsic::amdgcn_sqrt:
16594 case Intrinsic::amdgcn_fmed3:
16595 case Intrinsic::amdgcn_sin:
16596 case Intrinsic::amdgcn_cos:
16597 case Intrinsic::amdgcn_log:
16598 case Intrinsic::amdgcn_exp2:
16599 case Intrinsic::amdgcn_log_clamp:
16600 case Intrinsic::amdgcn_rcp:
16601 case Intrinsic::amdgcn_rcp_legacy:
16602 case Intrinsic::amdgcn_rsq:
16603 case Intrinsic::amdgcn_rsq_clamp:
16604 case Intrinsic::amdgcn_rsq_legacy:
16605 case Intrinsic::amdgcn_div_scale:
16606 case Intrinsic::amdgcn_div_fmas:
16607 case Intrinsic::amdgcn_div_fixup:
16608 case Intrinsic::amdgcn_fract:
16609 case Intrinsic::amdgcn_cvt_pkrtz:
16610 case Intrinsic::amdgcn_cubeid:
16611 case Intrinsic::amdgcn_cubema:
16612 case Intrinsic::amdgcn_cubesc:
16613 case Intrinsic::amdgcn_cubetc:
16614 case Intrinsic::amdgcn_frexp_mant:
16615 case Intrinsic::amdgcn_fdot2:
16616 case Intrinsic::amdgcn_trig_preop:
16617 case Intrinsic::amdgcn_tanh:
16618 return true;
16619 default:
16620 break;
16621 }
16622
16623 [[fallthrough]];
16624 default:
16625 return false;
16626 }
16627
16628 llvm_unreachable("invalid operation");
16629}
16630
16631// Constant fold canonicalize.
16632SDValue SITargetLowering::getCanonicalConstantFP(SelectionDAG &DAG,
16633 const SDLoc &SL, EVT VT,
16634 const APFloat &C) const {
16635 // Flush denormals to 0 if not enabled.
16636 if (C.isDenormal()) {
16637 DenormalMode Mode =
16638 DAG.getMachineFunction().getDenormalMode(C.getSemantics());
16639 if (Mode == DenormalMode::getPreserveSign()) {
16640 return DAG.getConstantFP(
16641 APFloat::getZero(C.getSemantics(), C.isNegative()), SL, VT);
16642 }
16643
16644 if (Mode != DenormalMode::getIEEE())
16645 return SDValue();
16646 }
16647
16648 if (C.isNaN()) {
16649 if (C.isSignaling()) {
16650 // Quiet a signaling NaN.
16651 return DAG.getConstantFP(C.makeQuiet(), SL, VT);
16652 }
16653 }
16654
16655 // Already canonical.
16656 return DAG.getConstantFP(C, SL, VT);
16657}
16658
16660 return Op.isUndef() || isa<ConstantFPSDNode>(Op);
16661}
16662
16663SDValue
16664SITargetLowering::performFCanonicalizeCombine(SDNode *N,
16665 DAGCombinerInfo &DCI) const {
16666 SelectionDAG &DAG = DCI.DAG;
16667 SDValue N0 = N->getOperand(0);
16668 EVT VT = N->getValueType(0);
16669
16670 // fcanonicalize undef -> qnan
16671 if (N0.isUndef()) {
16673 return DAG.getConstantFP(QNaN, SDLoc(N), VT);
16674 }
16675
16676 if (ConstantFPSDNode *CFP = isConstOrConstSplatFP(N0))
16677 return getCanonicalConstantFP(DAG, SDLoc(N), VT, CFP->getValueAPF());
16678
16679 // fcanonicalize (build_vector x, k) -> build_vector (fcanonicalize x),
16680 // (fcanonicalize k)
16681 //
16682 // fcanonicalize (build_vector x, undef) -> build_vector (fcanonicalize x), 0
16683
16684 // TODO: This could be better with wider vectors that will be split to v2f16,
16685 // and to consider uses since there aren't that many packed operations.
16686 if (N0.getOpcode() == ISD::BUILD_VECTOR && N0.getNumOperands() == 2 &&
16687 isTypeLegal(VT)) {
16688 SDLoc SL(N);
16689 SDValue NewElts[2];
16690 SDValue Lo = N0.getOperand(0);
16691 SDValue Hi = N0.getOperand(1);
16692 EVT EltVT = Lo.getValueType();
16693
16694 // Only apply this optimization if scalar canonicalize is legal for the
16695 // element type. Otherwise, scalarizing may require widening the scalar back
16696 // to a vector, adding overhead (e.g., bf16 has no scalar instructions).
16698 return SDValue();
16699
16701 for (unsigned I = 0; I != 2; ++I) {
16702 SDValue Op = N0.getOperand(I);
16703 if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(Op)) {
16704 NewElts[I] =
16705 getCanonicalConstantFP(DAG, SL, EltVT, CFP->getValueAPF());
16706 } else if (Op.isUndef()) {
16707 // Handled below based on what the other operand is.
16708 NewElts[I] = Op;
16709 } else {
16710 NewElts[I] = DAG.getNode(ISD::FCANONICALIZE, SL, EltVT, Op);
16711 }
16712 }
16713
16714 // If one half is undef, and one is constant, prefer a splat vector.
16715 // Otherwise, convert the undef to 0.0 since that's cheaper to use and may
16716 // be free with a packed operation.
16717 if (NewElts[0].isUndef()) {
16718 NewElts[0] = isa<ConstantFPSDNode>(NewElts[1])
16719 ? NewElts[1]
16720 : DAG.getConstantFP(0.0f, SL, EltVT);
16721 }
16722
16723 if (NewElts[1].isUndef()) {
16724 NewElts[1] = isa<ConstantFPSDNode>(NewElts[0])
16725 ? NewElts[0]
16726 : DAG.getConstantFP(0.0f, SL, EltVT);
16727 }
16728
16729 return DAG.getBuildVector(VT, SL, NewElts);
16730 }
16731 }
16732
16733 return SDValue();
16734}
16735
16736static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc) {
16737 switch (Opc) {
16738 case ISD::FMAXNUM:
16739 case ISD::FMAXNUM_IEEE:
16740 case ISD::FMAXIMUMNUM:
16741 return AMDGPUISD::FMAX3;
16742 case ISD::FMAXIMUM:
16743 return AMDGPUISD::FMAXIMUM3;
16744 case ISD::SMAX:
16745 return AMDGPUISD::SMAX3;
16746 case ISD::UMAX:
16747 return AMDGPUISD::UMAX3;
16748 case ISD::FMINNUM:
16749 case ISD::FMINNUM_IEEE:
16750 case ISD::FMINIMUMNUM:
16751 return AMDGPUISD::FMIN3;
16752 case ISD::FMINIMUM:
16753 return AMDGPUISD::FMINIMUM3;
16754 case ISD::SMIN:
16755 return AMDGPUISD::SMIN3;
16756 case ISD::UMIN:
16757 return AMDGPUISD::UMIN3;
16758 default:
16759 llvm_unreachable("Not a min/max opcode");
16760 }
16761}
16762
16763SDValue SITargetLowering::performIntMed3ImmCombine(SelectionDAG &DAG,
16764 const SDLoc &SL, SDValue Src,
16765 SDValue MinVal,
16766 SDValue MaxVal,
16767 bool Signed) const {
16768
16769 // med3 comes from
16770 // min(max(x, K0), K1), K0 < K1
16771 // max(min(x, K0), K1), K1 < K0
16772 //
16773 // "MinVal" and "MaxVal" respectively refer to the rhs of the
16774 // min/max op.
16775 ConstantSDNode *MinK = dyn_cast<ConstantSDNode>(MinVal);
16776 ConstantSDNode *MaxK = dyn_cast<ConstantSDNode>(MaxVal);
16777
16778 if (!MinK || !MaxK)
16779 return SDValue();
16780
16781 if (Signed) {
16782 if (MaxK->getAPIntValue().sge(MinK->getAPIntValue()))
16783 return SDValue();
16784 } else {
16785 if (MaxK->getAPIntValue().uge(MinK->getAPIntValue()))
16786 return SDValue();
16787 }
16788
16789 EVT VT = MinK->getValueType(0);
16790 unsigned Med3Opc = Signed ? AMDGPUISD::SMED3 : AMDGPUISD::UMED3;
16791 if (VT == MVT::i32 || (VT == MVT::i16 && Subtarget->hasMed3_16()))
16792 return DAG.getNode(Med3Opc, SL, VT, Src, MaxVal, MinVal);
16793
16794 // Note: we could also extend to i32 and use i32 med3 if i16 med3 is
16795 // not available, but this is unlikely to be profitable as constants
16796 // will often need to be materialized & extended, especially on
16797 // pre-GFX10 where VOP3 instructions couldn't take literal operands.
16798 return SDValue();
16799}
16800
16803 return C;
16804
16806 if (ConstantFPSDNode *C = BV->getConstantFPSplatNode())
16807 return C;
16808 }
16809
16810 return nullptr;
16811}
16812
16813SDValue SITargetLowering::performFPMed3ImmCombine(SelectionDAG &DAG,
16814 const SDLoc &SL, SDValue Op0,
16815 SDValue Op1,
16816 bool IsKnownNoNaNs) const {
16817 ConstantFPSDNode *K1 = getSplatConstantFP(Op1);
16818 if (!K1)
16819 return SDValue();
16820
16821 ConstantFPSDNode *K0 = getSplatConstantFP(Op0.getOperand(1));
16822 if (!K0)
16823 return SDValue();
16824
16825 // Ordered >= (although NaN inputs should have folded away by now).
16826 if (K0->getValueAPF() > K1->getValueAPF())
16827 return SDValue();
16828
16829 // med3 with a nan input acts like
16830 // v_min_f32(v_min_f32(S0.f32, S1.f32), S2.f32)
16831 //
16832 // So the result depends on whether the IEEE mode bit is enabled or not with a
16833 // signaling nan input.
16834 // ieee=1
16835 // s0 snan: yields s2
16836 // s1 snan: yields s2
16837 // s2 snan: qnan
16838
16839 // s0 qnan: min(s1, s2)
16840 // s1 qnan: min(s0, s2)
16841 // s2 qnan: min(s0, s1)
16842
16843 // ieee=0
16844 // s0 snan: min(s1, s2)
16845 // s1 snan: min(s0, s2)
16846 // s2 snan: qnan
16847
16848 // s0 qnan: min(s1, s2)
16849 // s1 qnan: min(s0, s2)
16850 // s2 qnan: min(s0, s1)
16851 const MachineFunction &MF = DAG.getMachineFunction();
16852 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
16853
16854 // TODO: Check IEEE bit enabled. We can form fmed3 with IEEE=0 regardless of
16855 // whether the input is a signaling nan if op0 is fmaximum or fmaximumnum. We
16856 // can only form if op0 is fmaxnum_ieee if IEEE=1.
16857 EVT VT = Op0.getValueType();
16858 if (Info->getMode().DX10Clamp) {
16859 // If dx10_clamp is enabled, NaNs clamp to 0.0. This is the same as the
16860 // hardware fmed3 behavior converting to a min.
16861 // FIXME: Should this be allowing -0.0?
16862 if (K1->isOne() && K0->isPosZero())
16863 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Op0.getOperand(0));
16864 }
16865
16866 // med3 for f16 is only available on gfx9+, and not available for v2f16.
16867 if (VT == MVT::f32 || (VT == MVT::f16 && Subtarget->hasMed3_16())) {
16868 // This isn't safe with signaling NaNs because in IEEE mode, min/max on a
16869 // signaling NaN gives a quiet NaN. The quiet NaN input to the min would
16870 // then give the other result, which is different from med3 with a NaN
16871 // input.
16872 SDValue Var = Op0.getOperand(0);
16873 if (!IsKnownNoNaNs && !DAG.isKnownNeverSNaN(Var))
16874 return SDValue();
16875
16876 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
16877
16878 if ((!K0->hasOneUse() || TII->isInlineConstant(K0->getValueAPF())) &&
16879 (!K1->hasOneUse() || TII->isInlineConstant(K1->getValueAPF()))) {
16880 return DAG.getNode(AMDGPUISD::FMED3, SL, K0->getValueType(0), Var,
16881 SDValue(K0, 0), SDValue(K1, 0));
16882 }
16883 }
16884
16885 return SDValue();
16886}
16887
16888/// \return true if the subtarget supports minimum3 and maximum3 with the given
16889/// base min/max opcode \p Opc for type \p VT.
16890static bool supportsMin3Max3(const GCNSubtarget &Subtarget, unsigned Opc,
16891 EVT VT) {
16892 switch (Opc) {
16893 case ISD::FMINNUM:
16894 case ISD::FMAXNUM:
16895 case ISD::FMINNUM_IEEE:
16896 case ISD::FMAXNUM_IEEE:
16897 case ISD::FMINIMUMNUM:
16898 case ISD::FMAXIMUMNUM:
16899 case AMDGPUISD::FMIN_LEGACY:
16900 case AMDGPUISD::FMAX_LEGACY:
16901 return (VT == MVT::f32) || (VT == MVT::f16 && Subtarget.hasMin3Max3_16()) ||
16902 (VT == MVT::v2f16 && Subtarget.hasMin3Max3PKF16());
16903 case ISD::FMINIMUM:
16904 case ISD::FMAXIMUM:
16905 return (VT == MVT::f32 && Subtarget.hasMinimum3Maximum3F32()) ||
16906 (VT == MVT::f16 && Subtarget.hasMinimum3Maximum3F16()) ||
16907 (VT == MVT::v2f16 && Subtarget.hasMinimum3Maximum3PKF16());
16908 case ISD::SMAX:
16909 case ISD::SMIN:
16910 case ISD::UMAX:
16911 case ISD::UMIN:
16912 return (VT == MVT::i32) || (VT == MVT::i16 && Subtarget.hasMin3Max3_16());
16913 default:
16914 return false;
16915 }
16916
16917 llvm_unreachable("not a min/max opcode");
16918}
16919
16920SDValue SITargetLowering::performMinMaxCombine(SDNode *N,
16921 DAGCombinerInfo &DCI) const {
16922 SelectionDAG &DAG = DCI.DAG;
16923
16924 EVT VT = N->getValueType(0);
16925 unsigned Opc = N->getOpcode();
16926 SDValue Op0 = N->getOperand(0);
16927 SDValue Op1 = N->getOperand(1);
16928
16929 // Only do this if the inner op has one use since this will just increases
16930 // register pressure for no benefit.
16931
16932 if (supportsMin3Max3(*Subtarget, Opc, VT)) {
16933 auto IsTreeWithCombinableChildren = [Opc](SDValue Op) {
16934 return (Op.getOperand(0).getOpcode() == Opc &&
16935 Op.getOperand(0).hasOneUse()) ||
16936 (Op.getOperand(1).getOpcode() == Opc &&
16937 Op.getOperand(1).hasOneUse());
16938 };
16939
16940 bool CanTreeCombineApply = Op0.getOpcode() == Opc && Op0.hasOneUse() &&
16941 Op1.getOpcode() == Opc && Op1.hasOneUse();
16942 bool HasCombinableTreeChild =
16943 CanTreeCombineApply && (IsTreeWithCombinableChildren(Op0) ||
16944 IsTreeWithCombinableChildren(Op1));
16945
16946 // Tree reduction: when both operands are the same min/max op, restructure
16947 // to keep a 2-op node on top so higher tree levels can still combine.
16948 //
16949 // max(max(a, b), max(c, d)) -> max(max3(a, b, c), d)
16950 // min(min(a, b), min(c, d)) -> min(min3(a, b, c), d)
16951 //
16952 // Defer when either inner op is a tree node with combinable children.
16953 if (CanTreeCombineApply && !HasCombinableTreeChild) {
16954 SDLoc DL(N);
16955 SDValue Inner =
16957 Op0.getOperand(1), Op1.getOperand(0));
16958 return DAG.getNode(Opc, DL, VT, Inner, Op1.getOperand(1));
16959 }
16960
16961 // max(max(a, b), c) -> max3(a, b, c)
16962 // min(min(a, b), c) -> min3(a, b, c)
16963 // Deferred when Op0 is a tree node with combinable children.
16964 if (Op0.getOpcode() == Opc && Op0.hasOneUse() && !HasCombinableTreeChild) {
16965 SDLoc DL(N);
16966 return DAG.getNode(minMaxOpcToMin3Max3Opc(Opc), DL, N->getValueType(0),
16967 Op0.getOperand(0), Op0.getOperand(1), Op1);
16968 }
16969
16970 // Try commuted.
16971 // max(a, max(b, c)) -> max3(a, b, c)
16972 // min(a, min(b, c)) -> min3(a, b, c)
16973 // Deferred when Op1 is a tree node with combinable children.
16974 if (Op1.getOpcode() == Opc && Op1.hasOneUse() && !HasCombinableTreeChild) {
16975 SDLoc DL(N);
16976 return DAG.getNode(minMaxOpcToMin3Max3Opc(Opc), DL, N->getValueType(0),
16977 Op0, Op1.getOperand(0), Op1.getOperand(1));
16978 }
16979 }
16980
16981 // umin(sffbh(x), bitwidth) -> sffbh(x) if x is known to be not 0 or -1.
16982 SDValue FfbhSrc;
16983 uint64_t Clamp = 0;
16984 if (Opc == ISD::UMIN &&
16985 sd_match(Op0,
16987 sd_match(Op1, m_ConstInt(Clamp))) {
16988 unsigned BitWidth = FfbhSrc.getValueType().getScalarSizeInBits();
16989 if (Clamp >= BitWidth) {
16990 KnownBits Known = DAG.computeKnownBits(FfbhSrc);
16991 if (Known.isNonZero() && Known.Zero.getBoolValue())
16992 return Op0;
16993 }
16994 }
16995
16996 // min(max(x, K0), K1), K0 < K1 -> med3(x, K0, K1)
16997 // max(min(x, K0), K1), K1 < K0 -> med3(x, K1, K0)
16998 if (Opc == ISD::SMIN && Op0.getOpcode() == ISD::SMAX && Op0.hasOneUse()) {
16999 if (SDValue Med3 = performIntMed3ImmCombine(
17000 DAG, SDLoc(N), Op0->getOperand(0), Op1, Op0->getOperand(1), true))
17001 return Med3;
17002 }
17003 if (Opc == ISD::SMAX && Op0.getOpcode() == ISD::SMIN && Op0.hasOneUse()) {
17004 if (SDValue Med3 = performIntMed3ImmCombine(
17005 DAG, SDLoc(N), Op0->getOperand(0), Op0->getOperand(1), Op1, true))
17006 return Med3;
17007 }
17008
17009 if (Opc == ISD::UMIN && Op0.getOpcode() == ISD::UMAX && Op0.hasOneUse()) {
17010 if (SDValue Med3 = performIntMed3ImmCombine(
17011 DAG, SDLoc(N), Op0->getOperand(0), Op1, Op0->getOperand(1), false))
17012 return Med3;
17013 }
17014 if (Opc == ISD::UMAX && Op0.getOpcode() == ISD::UMIN && Op0.hasOneUse()) {
17015 if (SDValue Med3 = performIntMed3ImmCombine(
17016 DAG, SDLoc(N), Op0->getOperand(0), Op0->getOperand(1), Op1, false))
17017 return Med3;
17018 }
17019
17020 // if !is_snan(x):
17021 // fminnum(fmaxnum(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
17022 // fminnum_ieee(fmaxnum_ieee(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
17023 // fminnumnum(fmaxnumnum(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
17024 // fmin_legacy(fmax_legacy(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
17025 if (((Opc == ISD::FMINNUM && Op0.getOpcode() == ISD::FMAXNUM) ||
17028 (Opc == AMDGPUISD::FMIN_LEGACY &&
17029 Op0.getOpcode() == AMDGPUISD::FMAX_LEGACY)) &&
17030 (VT == MVT::f32 || VT == MVT::f64 ||
17031 (VT == MVT::f16 && Subtarget->has16BitInsts()) ||
17032 (VT == MVT::bf16 && Subtarget->hasBF16PackedInsts()) ||
17033 (VT == MVT::v2bf16 && Subtarget->hasBF16PackedInsts()) ||
17034 (VT == MVT::v2f16 && Subtarget->hasVOP3PInsts())) &&
17035 Op0.hasOneUse()) {
17036 if (SDValue Res = performFPMed3ImmCombine(DAG, SDLoc(N), Op0, Op1,
17037 N->getFlags().hasNoNaNs()))
17038 return Res;
17039 }
17040
17041 // Prefer fminnum_ieee over fminimum. For gfx950, minimum/maximum are legal
17042 // for some types, but at a higher cost since it's implemented with a 3
17043 // operand form.
17044 const SDNodeFlags Flags = N->getFlags();
17045 if ((Opc == ISD::FMINIMUM || Opc == ISD::FMAXIMUM) && Flags.hasNoNaNs() &&
17046 !Subtarget->hasIEEEMinimumMaximumInsts() &&
17048 unsigned NewOpc =
17050 return DAG.getNode(NewOpc, SDLoc(N), VT, Op0, Op1, Flags);
17051 }
17052
17053 return SDValue();
17054}
17055
17059 // FIXME: Should this be allowing -0.0?
17060 return (CA->isPosZero() && CB->isOne()) ||
17061 (CA->isOne() && CB->isPosZero());
17062 }
17063 }
17064
17065 return false;
17066}
17067
17068// FIXME: Should only worry about snans for version with chain.
17069SDValue SITargetLowering::performFMed3Combine(SDNode *N,
17070 DAGCombinerInfo &DCI) const {
17071 EVT VT = N->getValueType(0);
17072 // v_med3_f32 and v_max_f32 behave identically wrt denorms, exceptions and
17073 // NaNs. With a NaN input, the order of the operands may change the result.
17074
17075 SelectionDAG &DAG = DCI.DAG;
17076 SDLoc SL(N);
17077
17078 SDValue Src0 = N->getOperand(0);
17079 SDValue Src1 = N->getOperand(1);
17080 SDValue Src2 = N->getOperand(2);
17081
17082 if (isClampZeroToOne(Src0, Src1)) {
17083 // const_a, const_b, x -> clamp is safe in all cases including signaling
17084 // nans.
17085 // FIXME: Should this be allowing -0.0?
17086 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Src2);
17087 }
17088
17089 const MachineFunction &MF = DAG.getMachineFunction();
17090 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
17091
17092 // FIXME: dx10_clamp behavior assumed in instcombine. Should we really bother
17093 // handling no dx10-clamp?
17094 if (Info->getMode().DX10Clamp) {
17095 // If NaNs is clamped to 0, we are free to reorder the inputs.
17096
17097 if (isa<ConstantFPSDNode>(Src0) && !isa<ConstantFPSDNode>(Src1))
17098 std::swap(Src0, Src1);
17099
17100 if (isa<ConstantFPSDNode>(Src1) && !isa<ConstantFPSDNode>(Src2))
17101 std::swap(Src1, Src2);
17102
17103 if (isa<ConstantFPSDNode>(Src0) && !isa<ConstantFPSDNode>(Src1))
17104 std::swap(Src0, Src1);
17105
17106 if (isClampZeroToOne(Src1, Src2))
17107 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Src0);
17108 }
17109
17110 return SDValue();
17111}
17112
17113SDValue SITargetLowering::performCvtPkRTZCombine(SDNode *N,
17114 DAGCombinerInfo &DCI) const {
17115 SDValue Src0 = N->getOperand(0);
17116 SDValue Src1 = N->getOperand(1);
17117 if (Src0.isUndef() && Src1.isUndef())
17118 return DCI.DAG.getUNDEF(N->getValueType(0));
17119 return SDValue();
17120}
17121
17122// Check if EXTRACT_VECTOR_ELT/INSERT_VECTOR_ELT (<n x e>, var-idx) should be
17123// expanded into a set of cmp/select instructions.
17125 unsigned NumElem,
17126 bool IsDivergentIdx,
17127 const GCNSubtarget *Subtarget) {
17129 return false;
17130
17131 unsigned VecSize = EltSize * NumElem;
17132
17133 // Sub-dword vectors of size 2 dword or less have better implementation.
17134 if (VecSize <= 64 && EltSize < 32)
17135 return false;
17136
17137 // Always expand the rest of sub-dword instructions, otherwise it will be
17138 // lowered via memory.
17139 if (EltSize < 32)
17140 return true;
17141
17142 // Always do this if var-idx is divergent, otherwise it will become a loop.
17143 if (IsDivergentIdx)
17144 return true;
17145
17146 // Large vectors would yield too many compares and v_cndmask_b32 instructions.
17147 unsigned NumInsts = NumElem /* Number of compares */ +
17148 ((EltSize + 31) / 32) * NumElem /* Number of cndmasks */;
17149
17150 // On some architectures (GFX9) movrel is not available and it's better
17151 // to expand.
17152 if (Subtarget->useVGPRIndexMode())
17153 return NumInsts <= 16;
17154
17155 // If movrel is available, use it instead of expanding for vector of 8
17156 // elements.
17157 if (Subtarget->hasMovrel())
17158 return NumInsts <= 15;
17159
17160 return true;
17161}
17162
17164 SDValue Idx = N->getOperand(N->getNumOperands() - 1);
17165 if (isa<ConstantSDNode>(Idx))
17166 return false;
17167
17168 SDValue Vec = N->getOperand(0);
17169 EVT VecVT = Vec.getValueType();
17170 EVT EltVT = VecVT.getVectorElementType();
17171 unsigned EltSize = EltVT.getSizeInBits();
17172 unsigned NumElem = VecVT.getVectorNumElements();
17173
17175 EltSize, NumElem, Idx->isDivergent(), getSubtarget());
17176}
17177
17178SDValue
17179SITargetLowering::performExtractVectorEltCombine(SDNode *N,
17180 DAGCombinerInfo &DCI) const {
17181 SDValue Vec = N->getOperand(0);
17182 SelectionDAG &DAG = DCI.DAG;
17183
17184 EVT VecVT = Vec.getValueType();
17185 EVT VecEltVT = VecVT.getVectorElementType();
17186 EVT ResVT = N->getValueType(0);
17187
17188 unsigned VecSize = VecVT.getSizeInBits();
17189 unsigned VecEltSize = VecEltVT.getSizeInBits();
17190
17191 if ((Vec.getOpcode() == ISD::FNEG || Vec.getOpcode() == ISD::FABS) &&
17193 SDLoc SL(N);
17194 SDValue Idx = N->getOperand(1);
17195 SDValue Elt =
17196 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT, Vec.getOperand(0), Idx);
17197 return DAG.getNode(Vec.getOpcode(), SL, ResVT, Elt);
17198 }
17199
17200 // (extract_vector_element (and {y0, y1}, (build_vector 0x1f, 0x1f)), index)
17201 // -> (and (extract_vector_element {y0, y1}, index), 0x1f)
17202 // There are optimisations to transform 64-bit shifts into 32-bit shifts
17203 // depending on the shift operand. See e.g. performSraCombine().
17204 // This combine ensures that the optimisation is compatible with v2i32
17205 // legalised AND.
17206 if (VecVT == MVT::v2i32 && Vec->getOpcode() == ISD::AND &&
17207 Vec->getOperand(1)->getOpcode() == ISD::BUILD_VECTOR) {
17208
17210 if (!C || C->getZExtValue() != 0x1f)
17211 return SDValue();
17212
17213 SDLoc SL(N);
17214 SDValue AndMask = DAG.getConstant(0x1f, SL, MVT::i32);
17215 SDValue EVE = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32,
17216 Vec->getOperand(0), N->getOperand(1));
17217 SDValue A = DAG.getNode(ISD::AND, SL, MVT::i32, EVE, AndMask);
17218 DAG.ReplaceAllUsesWith(N, A.getNode());
17219 }
17220
17221 // ScalarRes = EXTRACT_VECTOR_ELT ((vector-BINOP Vec1, Vec2), Idx)
17222 // =>
17223 // Vec1Elt = EXTRACT_VECTOR_ELT(Vec1, Idx)
17224 // Vec2Elt = EXTRACT_VECTOR_ELT(Vec2, Idx)
17225 // ScalarRes = scalar-BINOP Vec1Elt, Vec2Elt
17226 if (Vec.hasOneUse() && DCI.isBeforeLegalize() && VecEltVT == ResVT) {
17227 SDLoc SL(N);
17228 SDValue Idx = N->getOperand(1);
17229 unsigned Opc = Vec.getOpcode();
17230
17231 switch (Opc) {
17232 default:
17233 break;
17234 // TODO: Support other binary operations.
17235 case ISD::FADD:
17236 case ISD::FSUB:
17237 case ISD::FMUL:
17238 case ISD::ADD:
17239 case ISD::UMIN:
17240 case ISD::UMAX:
17241 case ISD::SMIN:
17242 case ISD::SMAX:
17243 case ISD::FMAXNUM:
17244 case ISD::FMINNUM:
17245 case ISD::FMAXNUM_IEEE:
17246 case ISD::FMINNUM_IEEE:
17247 case ISD::FMAXIMUM:
17248 case ISD::FMINIMUM: {
17249 SDValue Elt0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT,
17250 Vec.getOperand(0), Idx);
17251 SDValue Elt1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT,
17252 Vec.getOperand(1), Idx);
17253
17254 DCI.AddToWorklist(Elt0.getNode());
17255 DCI.AddToWorklist(Elt1.getNode());
17256 return DAG.getNode(Opc, SL, ResVT, Elt0, Elt1, Vec->getFlags());
17257 }
17258 }
17259 }
17260
17261 // EXTRACT_VECTOR_ELT (<n x e>, var-idx) => n x select (e, const-idx)
17263 SDLoc SL(N);
17264 SDValue Idx = N->getOperand(1);
17265 SDValue V;
17266 for (unsigned I = 0, E = VecVT.getVectorNumElements(); I < E; ++I) {
17267 SDValue IC = DAG.getVectorIdxConstant(I, SL);
17268 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT, Vec, IC);
17269 if (I == 0)
17270 V = Elt;
17271 else
17272 V = DAG.getSelectCC(SL, Idx, IC, Elt, V, ISD::SETEQ);
17273 }
17274 return V;
17275 }
17276
17277 // EXTRACT_VECTOR_ELT (v2i32 bitcast (i64/f64:k), Idx)
17278 // =>
17279 // i32:Lo(k) if Idx == 0, or
17280 // i32:Hi(k) if Idx == 1
17281 auto *Idx = dyn_cast<ConstantSDNode>(N->getOperand(1));
17282 if (Vec.getOpcode() == ISD::BITCAST && VecVT == MVT::v2i32 && Idx) {
17283 SDLoc SL(N);
17284 SDValue PeekThrough = Vec.getOperand(0);
17285 auto *KImm = dyn_cast<ConstantSDNode>(PeekThrough);
17286 if (KImm && KImm->getValueType(0).getSizeInBits() == 64) {
17287 uint64_t KImmValue = KImm->getZExtValue();
17288 return DAG.getConstant(
17289 (KImmValue >> (32 * Idx->getZExtValue())) & 0xffffffff, SL, MVT::i32);
17290 }
17291 auto *KFPImm = dyn_cast<ConstantFPSDNode>(PeekThrough);
17292 if (KFPImm && KFPImm->getValueType(0).getSizeInBits() == 64) {
17293 uint64_t KFPImmValue =
17294 KFPImm->getValueAPF().bitcastToAPInt().getZExtValue();
17295 return DAG.getConstant((KFPImmValue >> (32 * Idx->getZExtValue())) &
17296 0xffffffff,
17297 SL, MVT::i32);
17298 }
17299 }
17300
17301 if (!DCI.isBeforeLegalize())
17302 return SDValue();
17303
17304 // Try to turn sub-dword accesses of vectors into accesses of the same 32-bit
17305 // elements. This exposes more load reduction opportunities by replacing
17306 // multiple small extract_vector_elements with a single 32-bit extract.
17307 if (isa<MemSDNode>(Vec) && VecEltSize <= 16 && VecEltVT.isByteSized() &&
17308 VecSize > 32 && VecSize % 32 == 0 && Idx) {
17309 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VecVT);
17310
17311 unsigned BitIndex = Idx->getZExtValue() * VecEltSize;
17312 unsigned EltIdx = BitIndex / 32;
17313 unsigned LeftoverBitIdx = BitIndex % 32;
17314 SDLoc SL(N);
17315
17316 SDValue Cast = DAG.getNode(ISD::BITCAST, SL, NewVT, Vec);
17317 DCI.AddToWorklist(Cast.getNode());
17318
17319 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Cast,
17320 DAG.getConstant(EltIdx, SL, MVT::i32));
17321 DCI.AddToWorklist(Elt.getNode());
17322 SDValue Srl = DAG.getNode(ISD::SRL, SL, MVT::i32, Elt,
17323 DAG.getConstant(LeftoverBitIdx, SL, MVT::i32));
17324 DCI.AddToWorklist(Srl.getNode());
17325
17326 EVT VecEltAsIntVT = VecEltVT.changeTypeToInteger();
17327 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SL, VecEltAsIntVT, Srl);
17328 DCI.AddToWorklist(Trunc.getNode());
17329
17330 if (VecEltVT == ResVT) {
17331 return DAG.getNode(ISD::BITCAST, SL, VecEltVT, Trunc);
17332 }
17333
17334 assert(ResVT.isScalarInteger());
17335 return DAG.getAnyExtOrTrunc(Trunc, SL, ResVT);
17336 }
17337
17338 return SDValue();
17339}
17340
17341SDValue
17342SITargetLowering::performInsertVectorEltCombine(SDNode *N,
17343 DAGCombinerInfo &DCI) const {
17344 SDValue Vec = N->getOperand(0);
17345 SDValue Idx = N->getOperand(2);
17346 EVT VecVT = Vec.getValueType();
17347 EVT EltVT = VecVT.getVectorElementType();
17348
17349 // INSERT_VECTOR_ELT (<n x e>, var-idx)
17350 // => BUILD_VECTOR n x select (e, const-idx)
17352 return SDValue();
17353
17354 SelectionDAG &DAG = DCI.DAG;
17355 SDLoc SL(N);
17356 SDValue Ins = N->getOperand(1);
17357 EVT IdxVT = Idx.getValueType();
17358
17360 for (unsigned I = 0, E = VecVT.getVectorNumElements(); I < E; ++I) {
17361 SDValue IC = DAG.getConstant(I, SL, IdxVT);
17362 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec, IC);
17363 SDValue V = DAG.getSelectCC(SL, Idx, IC, Ins, Elt, ISD::SETEQ);
17364 Ops.push_back(V);
17365 }
17366
17367 return DAG.getBuildVector(VecVT, SL, Ops);
17368}
17369
17370/// Return the source of an fp_extend from f16 to f32, or a converted FP
17371/// constant.
17373 if (Src.getOpcode() == ISD::FP_EXTEND &&
17374 Src.getOperand(0).getValueType() == MVT::f16) {
17375 return Src.getOperand(0);
17376 }
17377
17378 if (auto *CFP = dyn_cast<ConstantFPSDNode>(Src)) {
17379 APFloat Val = CFP->getValueAPF();
17380 bool LosesInfo = true;
17382 if (!LosesInfo)
17383 return DAG.getConstantFP(Val, SDLoc(Src), MVT::f16);
17384 }
17385
17386 return SDValue();
17387}
17388
17389SDValue SITargetLowering::performFPRoundCombine(SDNode *N,
17390 DAGCombinerInfo &DCI) const {
17391 assert(Subtarget->has16BitInsts() && !Subtarget->hasMed3_16() &&
17392 "combine only useful on gfx8");
17393
17394 SDValue TruncSrc = N->getOperand(0);
17395 EVT VT = N->getValueType(0);
17396 if (VT != MVT::f16)
17397 return SDValue();
17398
17399 if (TruncSrc.getOpcode() != AMDGPUISD::FMED3 ||
17400 TruncSrc.getValueType() != MVT::f32 || !TruncSrc.hasOneUse())
17401 return SDValue();
17402
17403 SelectionDAG &DAG = DCI.DAG;
17404 SDLoc SL(N);
17405
17406 // Optimize f16 fmed3 pattern performed on f32. On gfx8 there is no f16 fmed3,
17407 // and expanding it with min/max saves 1 instruction vs. casting to f32 and
17408 // casting back.
17409
17410 // fptrunc (f32 (fmed3 (fpext f16:a, fpext f16:b, fpext f16:c))) =>
17411 // fmin(fmax(a, b), fmax(fmin(a, b), c))
17412 SDValue A = strictFPExtFromF16(DAG, TruncSrc.getOperand(0));
17413 if (!A)
17414 return SDValue();
17415
17416 SDValue B = strictFPExtFromF16(DAG, TruncSrc.getOperand(1));
17417 if (!B)
17418 return SDValue();
17419
17420 SDValue C = strictFPExtFromF16(DAG, TruncSrc.getOperand(2));
17421 if (!C)
17422 return SDValue();
17423
17424 // This changes signaling nan behavior. If an input is a signaling nan, it
17425 // would have been quieted by the fpext originally. We don't care because
17426 // these are unconstrained ops. If we needed to insert quieting canonicalizes
17427 // we would be worse off than just doing the promotion.
17428 SDValue A1 = DAG.getNode(ISD::FMINNUM_IEEE, SL, VT, A, B);
17429 SDValue B1 = DAG.getNode(ISD::FMAXNUM_IEEE, SL, VT, A, B);
17430 SDValue C1 = DAG.getNode(ISD::FMAXNUM_IEEE, SL, VT, A1, C);
17431 return DAG.getNode(ISD::FMINNUM_IEEE, SL, VT, B1, C1);
17432}
17433
17434unsigned SITargetLowering::getFusedOpcode(const SelectionDAG &DAG,
17435 const SDNode *N0,
17436 const SDNode *N1) const {
17437 EVT VT = N0->getValueType(0);
17438
17439 // Only do this if we are not trying to support denormals. v_mad_f32 does not
17440 // support denormals ever.
17441 if (((VT == MVT::f32 &&
17443 (VT == MVT::f16 && Subtarget->hasMadF16() &&
17446 return ISD::FMAD;
17447
17448 if (N0->getFlags().hasAllowContract() && N1->getFlags().hasAllowContract() &&
17450 return ISD::FMA;
17451 }
17452
17453 return 0;
17454}
17455
17456// For a reassociatable opcode perform:
17457// op x, (op y, z) -> op (op x, z), y, if x and z are uniform
17458SDValue SITargetLowering::reassociateScalarOps(SDNode *N,
17459 SelectionDAG &DAG) const {
17460 EVT VT = N->getValueType(0);
17461 if (VT != MVT::i32 && VT != MVT::i64)
17462 return SDValue();
17463
17464 if (DAG.isBaseWithConstantOffset(SDValue(N, 0)))
17465 return SDValue();
17466
17467 unsigned Opc = N->getOpcode();
17468 SDValue Op0 = N->getOperand(0);
17469 SDValue Op1 = N->getOperand(1);
17470
17471 if (!(Op0->isDivergent() ^ Op1->isDivergent()))
17472 return SDValue();
17473
17474 if (Op0->isDivergent())
17475 std::swap(Op0, Op1);
17476
17477 if (Op1.getOpcode() != Opc || !Op1.hasOneUse())
17478 return SDValue();
17479
17480 SDValue Op2 = Op1.getOperand(1);
17481 Op1 = Op1.getOperand(0);
17482 if (!(Op1->isDivergent() ^ Op2->isDivergent()))
17483 return SDValue();
17484
17485 if (Op1->isDivergent())
17486 std::swap(Op1, Op2);
17487
17488 SDLoc SL(N);
17489 SDValue Add1 = DAG.getNode(Opc, SL, VT, Op0, Op1);
17490 return DAG.getNode(Opc, SL, VT, Add1, Op2);
17491}
17492
17493static SDValue getMad64_32(SelectionDAG &DAG, const SDLoc &SL, EVT VT,
17494 SDValue N0, SDValue N1, SDValue N2, bool Signed) {
17496 SDVTList VTs = DAG.getVTList(MVT::i64, MVT::i1);
17497 SDValue Mad = DAG.getNode(MadOpc, SL, VTs, N0, N1, N2);
17498 return DAG.getNode(ISD::TRUNCATE, SL, VT, Mad);
17499}
17500
17501// Fold
17502// y = lshr i64 x, 32
17503// res = add (mul i64 y, Const), x where "Const" is a 64-bit constant
17504// with Const.hi == -1
17505// To
17506// res = mad_u64_u32 y.lo ,Const.lo, x.lo
17508 SDValue MulLHS, SDValue MulRHS,
17509 SDValue AddRHS) {
17510 if (MulRHS.getOpcode() == ISD::SRL)
17511 std::swap(MulLHS, MulRHS);
17512
17513 if (MulLHS.getValueType() != MVT::i64 || MulLHS.getOpcode() != ISD::SRL)
17514 return SDValue();
17515
17516 ConstantSDNode *ShiftVal = dyn_cast<ConstantSDNode>(MulLHS.getOperand(1));
17517 if (!ShiftVal || ShiftVal->getAsZExtVal() != 32 ||
17518 MulLHS.getOperand(0) != AddRHS)
17519 return SDValue();
17520
17522 if (!Const || Hi_32(Const->getZExtValue()) != uint32_t(-1))
17523 return SDValue();
17524
17525 SDValue ConstMul =
17526 DAG.getConstant(Lo_32(Const->getZExtValue()), SL, MVT::i32);
17527 return getMad64_32(DAG, SL, MVT::i64,
17528 DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulLHS), ConstMul,
17529 DAG.getZeroExtendInReg(AddRHS, SL, MVT::i32), false);
17530}
17531
17532// Fold (add (mul x, y), z) --> (mad_[iu]64_[iu]32 x, y, z) plus high
17533// multiplies, if any.
17534//
17535// Full 64-bit multiplies that feed into an addition are lowered here instead
17536// of using the generic expansion. The generic expansion ends up with
17537// a tree of ADD nodes that prevents us from using the "add" part of the
17538// MAD instruction. The expansion produced here results in a chain of ADDs
17539// instead of a tree.
17540SDValue SITargetLowering::tryFoldToMad64_32(SDNode *N,
17541 DAGCombinerInfo &DCI) const {
17542 assert(N->isAnyAdd());
17543
17544 SelectionDAG &DAG = DCI.DAG;
17545 EVT VT = N->getValueType(0);
17546 SDLoc SL(N);
17547 SDValue LHS = N->getOperand(0);
17548 SDValue RHS = N->getOperand(1);
17549
17550 if (VT.isVector())
17551 return SDValue();
17552
17553 // S_MUL_HI_[IU]32 was added in gfx9, which allows us to keep the overall
17554 // result in scalar registers for uniform values.
17555 if (!N->isDivergent() && Subtarget->hasSMulHi())
17556 return SDValue();
17557
17558 unsigned NumBits = VT.getScalarSizeInBits();
17559 if (NumBits <= 32 || NumBits > 64)
17560 return SDValue();
17561
17562 if (LHS.getOpcode() != ISD::MUL) {
17563 assert(RHS.getOpcode() == ISD::MUL);
17564 std::swap(LHS, RHS);
17565 }
17566
17567 // Avoid the fold if it would unduly increase the number of multiplies due to
17568 // multiple uses, except on hardware with full-rate multiply-add (which is
17569 // part of full-rate 64-bit ops).
17570 if (!Subtarget->hasFullRate64Ops()) {
17571 unsigned NumUsers = 0;
17572 for (SDNode *User : LHS->users()) {
17573 // There is a use that does not feed into addition, so the multiply can't
17574 // be removed. We prefer MUL + ADD + ADDC over MAD + MUL.
17575 if (!User->isAnyAdd())
17576 return SDValue();
17577
17578 // We prefer 2xMAD over MUL + 2xADD + 2xADDC (code density), and prefer
17579 // MUL + 3xADD + 3xADDC over 3xMAD.
17580 ++NumUsers;
17581 if (NumUsers >= 3)
17582 return SDValue();
17583 }
17584 }
17585
17586 SDValue MulLHS = LHS.getOperand(0);
17587 SDValue MulRHS = LHS.getOperand(1);
17588 SDValue AddRHS = RHS;
17589
17590 if (SDValue FoldedMAD = tryFoldMADwithSRL(DAG, SL, MulLHS, MulRHS, AddRHS))
17591 return FoldedMAD;
17592
17593 // Always check whether operands are small unsigned values, since that
17594 // knowledge is useful in more cases. Check for small signed values only if
17595 // doing so can unlock a shorter code sequence.
17596 bool MulLHSUnsigned32 = numBitsUnsigned(MulLHS, DAG) <= 32;
17597 bool MulRHSUnsigned32 = numBitsUnsigned(MulRHS, DAG) <= 32;
17598
17599 bool MulSignedLo = false;
17600 if (!MulLHSUnsigned32 || !MulRHSUnsigned32) {
17601 MulSignedLo =
17602 numBitsSigned(MulLHS, DAG) <= 32 && numBitsSigned(MulRHS, DAG) <= 32;
17603 }
17604
17605 // The operands and final result all have the same number of bits. If
17606 // operands need to be extended, they can be extended with garbage. The
17607 // resulting garbage in the high bits of the mad_[iu]64_[iu]32 result is
17608 // truncated away in the end.
17609 if (VT != MVT::i64) {
17610 MulLHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, MulLHS);
17611 MulRHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, MulRHS);
17612 AddRHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, AddRHS);
17613 }
17614
17615 // The basic code generated is conceptually straightforward. Pseudo code:
17616 //
17617 // accum = mad_64_32 lhs.lo, rhs.lo, accum
17618 // accum.hi = add (mul lhs.hi, rhs.lo), accum.hi
17619 // accum.hi = add (mul lhs.lo, rhs.hi), accum.hi
17620 //
17621 // The second and third lines are optional, depending on whether the factors
17622 // are {sign,zero}-extended or not.
17623 //
17624 // The actual DAG is noisier than the pseudo code, but only due to
17625 // instructions that disassemble values into low and high parts, and
17626 // assemble the final result.
17627 SDValue One = DAG.getConstant(1, SL, MVT::i32);
17628
17629 auto MulLHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulLHS);
17630 auto MulRHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulRHS);
17631 SDValue Accum =
17632 getMad64_32(DAG, SL, MVT::i64, MulLHSLo, MulRHSLo, AddRHS, MulSignedLo);
17633
17634 if (!MulSignedLo && (!MulLHSUnsigned32 || !MulRHSUnsigned32)) {
17635 auto [AccumLo, AccumHi] = DAG.SplitScalar(Accum, SL, MVT::i32, MVT::i32);
17636
17637 if (!MulLHSUnsigned32) {
17638 auto MulLHSHi =
17639 DAG.getNode(ISD::EXTRACT_ELEMENT, SL, MVT::i32, MulLHS, One);
17640 SDValue MulHi = DAG.getNode(ISD::MUL, SL, MVT::i32, MulLHSHi, MulRHSLo);
17641 AccumHi = DAG.getNode(ISD::ADD, SL, MVT::i32, MulHi, AccumHi);
17642 }
17643
17644 if (!MulRHSUnsigned32) {
17645 auto MulRHSHi =
17646 DAG.getNode(ISD::EXTRACT_ELEMENT, SL, MVT::i32, MulRHS, One);
17647 SDValue MulHi = DAG.getNode(ISD::MUL, SL, MVT::i32, MulLHSLo, MulRHSHi);
17648 AccumHi = DAG.getNode(ISD::ADD, SL, MVT::i32, MulHi, AccumHi);
17649 }
17650
17651 Accum = DAG.getBuildVector(MVT::v2i32, SL, {AccumLo, AccumHi});
17652 Accum = DAG.getBitcast(MVT::i64, Accum);
17653 }
17654
17655 if (VT != MVT::i64)
17656 Accum = DAG.getNode(ISD::TRUNCATE, SL, VT, Accum);
17657 return Accum;
17658}
17659
17660SDValue
17661SITargetLowering::foldAddSub64WithZeroLowBitsTo32(SDNode *N,
17662 DAGCombinerInfo &DCI) const {
17663 SDValue RHS = N->getOperand(1);
17664 auto *CRHS = dyn_cast<ConstantSDNode>(RHS);
17665 if (!CRHS)
17666 return SDValue();
17667
17668 // TODO: Worth using computeKnownBits? Maybe expensive since it's so
17669 // common.
17670 uint64_t Val = CRHS->getZExtValue();
17671 if (countr_zero(Val) >= 32) {
17672 SelectionDAG &DAG = DCI.DAG;
17673 SDLoc SL(N);
17674 SDValue LHS = N->getOperand(0);
17675
17676 // Avoid carry machinery if we know the low half of the add does not
17677 // contribute to the final result.
17678 //
17679 // add i64:x, K if computeTrailingZeros(K) >= 32
17680 // => build_pair (add x.hi, K.hi), x.lo
17681
17682 // Breaking the 64-bit add here with this strange constant is unlikely
17683 // to interfere with addressing mode patterns.
17684
17685 SDValue Hi = getHiHalf64(LHS, DAG);
17686 SDValue ConstHi32 = DAG.getConstant(Hi_32(Val), SL, MVT::i32);
17687 unsigned Opcode = N->getOpcode();
17688 if (Opcode == ISD::PTRADD)
17689 Opcode = ISD::ADD;
17690 SDValue AddHi =
17691 DAG.getNode(Opcode, SL, MVT::i32, Hi, ConstHi32, N->getFlags());
17692
17693 SDValue Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LHS);
17694 return DAG.getNode(ISD::BUILD_PAIR, SL, MVT::i64, Lo, AddHi);
17695 }
17696
17697 return SDValue();
17698}
17699
17700// Collect the ultimate src of each of the mul node's operands, and confirm
17701// each operand is 8 bytes.
17702static std::optional<ByteProvider<SDValue>>
17703handleMulOperand(const SDValue &MulOperand) {
17704 auto Byte0 = calculateByteProvider(MulOperand, 0, 0);
17705 if (!Byte0 || Byte0->isConstantZero()) {
17706 return std::nullopt;
17707 }
17708 auto Byte1 = calculateByteProvider(MulOperand, 1, 0);
17709 if (Byte1 && !Byte1->isConstantZero()) {
17710 return std::nullopt;
17711 }
17712 return Byte0;
17713}
17714
17715static unsigned addPermMasks(unsigned First, unsigned Second) {
17716 unsigned FirstCs = First & 0x0c0c0c0c;
17717 unsigned SecondCs = Second & 0x0c0c0c0c;
17718 unsigned FirstNoCs = First & ~0x0c0c0c0c;
17719 unsigned SecondNoCs = Second & ~0x0c0c0c0c;
17720
17721 assert((FirstCs & 0xFF) | (SecondCs & 0xFF));
17722 assert((FirstCs & 0xFF00) | (SecondCs & 0xFF00));
17723 assert((FirstCs & 0xFF0000) | (SecondCs & 0xFF0000));
17724 assert((FirstCs & 0xFF000000) | (SecondCs & 0xFF000000));
17725
17726 return (FirstNoCs | SecondNoCs) | (FirstCs & SecondCs);
17727}
17728
17729struct DotSrc {
17731 int64_t PermMask;
17733};
17734
17738 SmallVectorImpl<DotSrc> &Src1s, int Step) {
17739
17740 assert(Src0.Src.has_value() && Src1.Src.has_value());
17741 // Src0s and Src1s are empty, just place arbitrarily.
17742 if (Step == 0) {
17743 Src0s.push_back({*Src0.Src, ((Src0.SrcOffset % 4) << 24) + 0x0c0c0c,
17744 Src0.SrcOffset / 4});
17745 Src1s.push_back({*Src1.Src, ((Src1.SrcOffset % 4) << 24) + 0x0c0c0c,
17746 Src1.SrcOffset / 4});
17747 return;
17748 }
17749
17750 for (int BPI = 0; BPI < 2; BPI++) {
17751 std::pair<ByteProvider<SDValue>, ByteProvider<SDValue>> BPP = {Src0, Src1};
17752 if (BPI == 1) {
17753 BPP = {Src1, Src0};
17754 }
17755 unsigned ZeroMask = 0x0c0c0c0c;
17756 unsigned FMask = 0xFF << (8 * (3 - Step));
17757
17758 unsigned FirstMask =
17759 (BPP.first.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17760 unsigned SecondMask =
17761 (BPP.second.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17762 // Attempt to find Src vector which contains our SDValue, if so, add our
17763 // perm mask to the existing one. If we are unable to find a match for the
17764 // first SDValue, attempt to find match for the second.
17765 int FirstGroup = -1;
17766 for (int I = 0; I < 2; I++) {
17767 SmallVectorImpl<DotSrc> &Srcs = I == 0 ? Src0s : Src1s;
17768 auto MatchesFirst = [&BPP](DotSrc &IterElt) {
17769 return IterElt.SrcOp == *BPP.first.Src &&
17770 (IterElt.DWordOffset == (BPP.first.SrcOffset / 4));
17771 };
17772
17773 auto *Match = llvm::find_if(Srcs, MatchesFirst);
17774 if (Match != Srcs.end()) {
17775 Match->PermMask = addPermMasks(FirstMask, Match->PermMask);
17776 FirstGroup = I;
17777 break;
17778 }
17779 }
17780 if (FirstGroup != -1) {
17781 SmallVectorImpl<DotSrc> &Srcs = FirstGroup == 1 ? Src0s : Src1s;
17782 auto MatchesSecond = [&BPP](DotSrc &IterElt) {
17783 return IterElt.SrcOp == *BPP.second.Src &&
17784 (IterElt.DWordOffset == (BPP.second.SrcOffset / 4));
17785 };
17786 auto *Match = llvm::find_if(Srcs, MatchesSecond);
17787 if (Match != Srcs.end()) {
17788 Match->PermMask = addPermMasks(SecondMask, Match->PermMask);
17789 } else
17790 Srcs.push_back({*BPP.second.Src, SecondMask, BPP.second.SrcOffset / 4});
17791 return;
17792 }
17793 }
17794
17795 // If we have made it here, then we could not find a match in Src0s or Src1s
17796 // for either Src0 or Src1, so just place them arbitrarily.
17797
17798 unsigned ZeroMask = 0x0c0c0c0c;
17799 unsigned FMask = 0xFF << (8 * (3 - Step));
17800
17801 Src0s.push_back(
17802 {*Src0.Src,
17803 ((Src0.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17804 Src0.SrcOffset / 4});
17805 Src1s.push_back(
17806 {*Src1.Src,
17807 ((Src1.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17808 Src1.SrcOffset / 4});
17809}
17810
17812 SmallVectorImpl<DotSrc> &Srcs, bool IsSigned,
17813 bool IsAny) {
17814
17815 // If we just have one source, just permute it accordingly.
17816 if (Srcs.size() == 1) {
17817 auto *Elt = Srcs.begin();
17818 auto EltOp = getDWordFromOffset(DAG, SL, Elt->SrcOp, Elt->DWordOffset);
17819
17820 // v_perm will produce the original value
17821 if (Elt->PermMask == 0x3020100)
17822 return EltOp;
17823
17824 return DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17825 DAG.getConstant(Elt->PermMask, SL, MVT::i32));
17826 }
17827
17828 auto *FirstElt = Srcs.begin();
17829 auto *SecondElt = std::next(FirstElt);
17830
17832
17833 // If we have multiple sources in the chain, combine them via perms (using
17834 // calculated perm mask) and Ors.
17835 while (true) {
17836 auto FirstMask = FirstElt->PermMask;
17837 auto SecondMask = SecondElt->PermMask;
17838
17839 unsigned FirstCs = FirstMask & 0x0c0c0c0c;
17840 unsigned FirstPlusFour = FirstMask | 0x04040404;
17841 // 0x0c + 0x04 = 0x10, so anding with 0x0F will produced 0x00 for any
17842 // original 0x0C.
17843 FirstMask = (FirstPlusFour & 0x0F0F0F0F) | FirstCs;
17844
17845 auto PermMask = addPermMasks(FirstMask, SecondMask);
17846 auto FirstVal =
17847 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
17848 auto SecondVal =
17849 getDWordFromOffset(DAG, SL, SecondElt->SrcOp, SecondElt->DWordOffset);
17850
17851 Perms.push_back(DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, FirstVal,
17852 SecondVal,
17853 DAG.getConstant(PermMask, SL, MVT::i32)));
17854
17855 FirstElt = std::next(SecondElt);
17856 if (FirstElt == Srcs.end())
17857 break;
17858
17859 SecondElt = std::next(FirstElt);
17860 // If we only have a FirstElt, then just combine that into the cumulative
17861 // source node.
17862 if (SecondElt == Srcs.end()) {
17863 auto EltOp =
17864 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
17865
17866 Perms.push_back(
17867 DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17868 DAG.getConstant(FirstElt->PermMask, SL, MVT::i32)));
17869 break;
17870 }
17871 }
17872
17873 assert(Perms.size() == 1 || Perms.size() == 2);
17874 return Perms.size() == 2
17875 ? DAG.getNode(ISD::OR, SL, MVT::i32, Perms[0], Perms[1])
17876 : Perms[0];
17877}
17878
17879static void fixMasks(SmallVectorImpl<DotSrc> &Srcs, unsigned ChainLength) {
17880 for (auto &[EntryVal, EntryMask, EntryOffset] : Srcs) {
17881 EntryMask = EntryMask >> ((4 - ChainLength) * 8);
17882 auto ZeroMask = ChainLength == 2 ? 0x0c0c0000 : 0x0c000000;
17883 EntryMask += ZeroMask;
17884 }
17885}
17886
17887static bool isMul(const SDValue Op) {
17888 auto Opcode = Op.getOpcode();
17889
17890 return (Opcode == ISD::MUL || Opcode == AMDGPUISD::MUL_U24 ||
17891 Opcode == AMDGPUISD::MUL_I24);
17892}
17893
17894static std::optional<bool>
17896 ByteProvider<SDValue> &Src1, const SDValue &S0Op,
17897 const SDValue &S1Op, const SelectionDAG &DAG) {
17898 // If we both ops are i8s (pre legalize-dag), then the signedness semantics
17899 // of the dot4 is irrelevant.
17900 if (S0Op.getValueSizeInBits() == 8 && S1Op.getValueSizeInBits() == 8)
17901 return false;
17902
17903 auto Known0 = DAG.computeKnownBits(S0Op, 0);
17904 bool S0IsUnsigned = Known0.countMinLeadingZeros() > 0;
17905 bool S0IsSigned = Known0.countMinLeadingOnes() > 0;
17906 auto Known1 = DAG.computeKnownBits(S1Op, 0);
17907 bool S1IsUnsigned = Known1.countMinLeadingZeros() > 0;
17908 bool S1IsSigned = Known1.countMinLeadingOnes() > 0;
17909
17910 assert(!(S0IsUnsigned && S0IsSigned));
17911 assert(!(S1IsUnsigned && S1IsSigned));
17912
17913 // There are 9 possible permutations of
17914 // {S0IsUnsigned, S0IsSigned, S1IsUnsigned, S1IsSigned}
17915
17916 // In two permutations, the sign bits are known to be the same for both Ops,
17917 // so simply return Signed / Unsigned corresponding to the MSB
17918
17919 if ((S0IsUnsigned && S1IsUnsigned) || (S0IsSigned && S1IsSigned))
17920 return S0IsSigned;
17921
17922 // In another two permutations, the sign bits are known to be opposite. In
17923 // this case return std::nullopt to indicate a bad match.
17924
17925 if ((S0IsUnsigned && S1IsSigned) || (S0IsSigned && S1IsUnsigned))
17926 return std::nullopt;
17927
17928 // In the remaining five permutations, we don't know the value of the sign
17929 // bit for at least one Op. Since we have a valid ByteProvider, we know that
17930 // the upper bits must be extension bits. Thus, the only ways for the sign
17931 // bit to be unknown is if it was sign extended from unknown value, or if it
17932 // was any extended. In either case, it is correct to use the signed
17933 // version of the signedness semantics of dot4
17934
17935 // In two of such permutations, we known the sign bit is set for
17936 // one op, and the other is unknown. It is okay to used signed version of
17937 // dot4.
17938 if ((S0IsSigned && !(S1IsSigned || S1IsUnsigned)) ||
17939 ((S1IsSigned && !(S0IsSigned || S0IsUnsigned))))
17940 return true;
17941
17942 // In one such permutation, we don't know either of the sign bits. It is okay
17943 // to used the signed version of dot4.
17944 if ((!(S1IsSigned || S1IsUnsigned) && !(S0IsSigned || S0IsUnsigned)))
17945 return true;
17946
17947 // In two of such permutations, we known the sign bit is unset for
17948 // one op, and the other is unknown. Return std::nullopt to indicate a
17949 // bad match.
17950 if ((S0IsUnsigned && !(S1IsSigned || S1IsUnsigned)) ||
17951 ((S1IsUnsigned && !(S0IsSigned || S0IsUnsigned))))
17952 return std::nullopt;
17953
17954 llvm_unreachable("Fully covered condition");
17955}
17956
17957SDValue SITargetLowering::performAddCombine(SDNode *N,
17958 DAGCombinerInfo &DCI) const {
17959 SelectionDAG &DAG = DCI.DAG;
17960 EVT VT = N->getValueType(0);
17961 SDLoc SL(N);
17962 SDValue LHS = N->getOperand(0);
17963 SDValue RHS = N->getOperand(1);
17964
17965 if (LHS.getOpcode() == ISD::MUL || RHS.getOpcode() == ISD::MUL) {
17966 if (Subtarget->hasMad64_32()) {
17967 if (SDValue Folded = tryFoldToMad64_32(N, DCI))
17968 return Folded;
17969 }
17970 }
17971
17972 if (SDValue V = reassociateScalarOps(N, DAG)) {
17973 return V;
17974 }
17975
17976 if (VT == MVT::i64) {
17977 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
17978 return Folded;
17979 }
17980
17981 // dot4 produces a 32-bit result, so a wider VT can't be folded.
17982 if (!VT.isVector() && VT.getSizeInBits() <= 32 &&
17983 (isMul(LHS) || isMul(RHS)) && Subtarget->hasDot7Insts() &&
17984 (Subtarget->hasDot1Insts() || Subtarget->hasDot8Insts())) {
17985 SDValue TempNode(N, 0);
17986 std::optional<bool> IsSigned;
17990
17991 // Match the v_dot4 tree, while collecting src nodes.
17992 int ChainLength = 0;
17993 for (int I = 0; I < 4; I++) {
17994 auto MulIdx = isMul(LHS) ? 0 : isMul(RHS) ? 1 : -1;
17995 if (MulIdx == -1)
17996 break;
17997 auto Src0 = handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(0));
17998 if (!Src0)
17999 break;
18000 auto Src1 = handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(1));
18001 if (!Src1)
18002 break;
18003
18004 auto IterIsSigned = checkDot4MulSignedness(
18005 TempNode->getOperand(MulIdx), *Src0, *Src1,
18006 TempNode->getOperand(MulIdx)->getOperand(0),
18007 TempNode->getOperand(MulIdx)->getOperand(1), DAG);
18008 if (!IterIsSigned)
18009 break;
18010 if (!IsSigned)
18011 IsSigned = *IterIsSigned;
18012 if (*IterIsSigned != *IsSigned)
18013 break;
18014 placeSources(*Src0, *Src1, Src0s, Src1s, I);
18015 auto AddIdx = 1 - MulIdx;
18016 // Allow the special case where add (add (mul24, 0), mul24) became ->
18017 // add (mul24, mul24).
18018 if (I == 2 && isMul(TempNode->getOperand(AddIdx))) {
18019 Src2s.push_back(TempNode->getOperand(AddIdx));
18020 auto Src0 =
18021 handleMulOperand(TempNode->getOperand(AddIdx)->getOperand(0));
18022 if (!Src0)
18023 break;
18024 auto Src1 =
18025 handleMulOperand(TempNode->getOperand(AddIdx)->getOperand(1));
18026 if (!Src1)
18027 break;
18028 auto IterIsSigned = checkDot4MulSignedness(
18029 TempNode->getOperand(AddIdx), *Src0, *Src1,
18030 TempNode->getOperand(AddIdx)->getOperand(0),
18031 TempNode->getOperand(AddIdx)->getOperand(1), DAG);
18032 if (!IterIsSigned)
18033 break;
18034 assert(IsSigned);
18035 if (*IterIsSigned != *IsSigned)
18036 break;
18037 placeSources(*Src0, *Src1, Src0s, Src1s, I + 1);
18038 Src2s.push_back(DAG.getConstant(0, SL, MVT::i32));
18039 ChainLength = I + 2;
18040 break;
18041 }
18042
18043 TempNode = TempNode->getOperand(AddIdx);
18044 Src2s.push_back(TempNode);
18045 ChainLength = I + 1;
18046 // The loop body treats TempNode's operands as addends.
18047 if (TempNode.getOpcode() != ISD::ADD)
18048 break;
18049 LHS = TempNode->getOperand(0);
18050 RHS = TempNode->getOperand(1);
18051 }
18052
18053 if (ChainLength < 2)
18054 return SDValue();
18055
18056 // Masks were constructed with assumption that we would find a chain of
18057 // length 4. If not, then we need to 0 out the MSB bits (via perm mask of
18058 // 0x0c) so they do not affect dot calculation.
18059 if (ChainLength < 4) {
18060 fixMasks(Src0s, ChainLength);
18061 fixMasks(Src1s, ChainLength);
18062 }
18063
18064 SDValue Src0, Src1;
18065
18066 // If we are just using a single source for both, and have permuted the
18067 // bytes consistently, we can just use the sources without permuting
18068 // (commutation).
18069 bool UseOriginalSrc = false;
18070 if (ChainLength == 4 && Src0s.size() == 1 && Src1s.size() == 1 &&
18071 Src0s.begin()->PermMask == Src1s.begin()->PermMask &&
18072 Src0s.begin()->SrcOp.getValueSizeInBits() >= 32 &&
18073 Src1s.begin()->SrcOp.getValueSizeInBits() >= 32) {
18074 SmallVector<unsigned, 4> SrcBytes;
18075 auto Src0Mask = Src0s.begin()->PermMask;
18076 SrcBytes.push_back(Src0Mask & 0xFF000000);
18077 bool UniqueEntries = true;
18078 for (auto I = 1; I < 4; I++) {
18079 auto NextByte = Src0Mask & (0xFF << ((3 - I) * 8));
18080
18081 if (is_contained(SrcBytes, NextByte)) {
18082 UniqueEntries = false;
18083 break;
18084 }
18085 SrcBytes.push_back(NextByte);
18086 }
18087
18088 if (UniqueEntries) {
18089 UseOriginalSrc = true;
18090
18091 auto *FirstElt = Src0s.begin();
18092 auto FirstEltOp =
18093 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
18094
18095 auto *SecondElt = Src1s.begin();
18096 auto SecondEltOp = getDWordFromOffset(DAG, SL, SecondElt->SrcOp,
18097 SecondElt->DWordOffset);
18098
18099 Src0 = DAG.getBitcastedAnyExtOrTrunc(FirstEltOp, SL,
18100 MVT::getIntegerVT(32));
18101 Src1 = DAG.getBitcastedAnyExtOrTrunc(SecondEltOp, SL,
18102 MVT::getIntegerVT(32));
18103 }
18104 }
18105
18106 if (!UseOriginalSrc) {
18107 Src0 = resolveSources(DAG, SL, Src0s, false, true);
18108 Src1 = resolveSources(DAG, SL, Src1s, false, true);
18109 }
18110
18111 assert(IsSigned);
18112 SDValue Src2 =
18113 DAG.getExtOrTrunc(*IsSigned, Src2s[ChainLength - 1], SL, MVT::i32);
18114
18115 SDValue IID = DAG.getTargetConstant(*IsSigned ? Intrinsic::amdgcn_sdot4
18116 : Intrinsic::amdgcn_udot4,
18117 SL, MVT::i64);
18118
18119 assert(!VT.isVector());
18120 auto Dot = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32, IID, Src0,
18121 Src1, Src2, DAG.getTargetConstant(0, SL, MVT::i1));
18122
18123 return DAG.getExtOrTrunc(*IsSigned, Dot, SL, VT);
18124 }
18125
18126 if (VT != MVT::i32 || !DCI.isAfterLegalizeDAG())
18127 return SDValue();
18128
18129 // add x, zext (setcc) => uaddo_carry x, 0, setcc
18130 // add x, sext (setcc) => usubo_carry x, 0, setcc
18131 unsigned Opc = LHS.getOpcode();
18134 std::swap(RHS, LHS);
18135
18136 Opc = RHS.getOpcode();
18137 switch (Opc) {
18138 default:
18139 break;
18140 case ISD::ZERO_EXTEND:
18141 case ISD::SIGN_EXTEND:
18142 case ISD::ANY_EXTEND: {
18143 auto Cond = RHS.getOperand(0);
18144 // If this won't be a real VOPC output, we would still need to insert an
18145 // extra instruction anyway.
18146 if (!isBoolSGPR(Cond))
18147 break;
18148 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::i1);
18149 SDValue Args[] = {LHS, DAG.getConstant(0, SL, MVT::i32), Cond};
18151 return DAG.getNode(Opc, SL, VTList, Args);
18152 }
18153 case ISD::UADDO_CARRY: {
18154 // add x, (uaddo_carry y, 0, cc) => uaddo_carry x, y, cc
18155 if (!isNullConstant(RHS.getOperand(1)))
18156 break;
18157 SDValue Args[] = {LHS, RHS.getOperand(0), RHS.getOperand(2)};
18158 return DAG.getNode(ISD::UADDO_CARRY, SDLoc(N), RHS->getVTList(), Args);
18159 }
18160 }
18161 return SDValue();
18162}
18163
18164SDValue SITargetLowering::performPtrAddCombine(SDNode *N,
18165 DAGCombinerInfo &DCI) const {
18166 SelectionDAG &DAG = DCI.DAG;
18167 SDLoc DL(N);
18168 EVT VT = N->getValueType(0);
18169 SDValue N0 = N->getOperand(0);
18170 SDValue N1 = N->getOperand(1);
18171
18172 // The following folds transform PTRADDs into regular arithmetic in cases
18173 // where the PTRADD wouldn't be folded as an immediate offset into memory
18174 // instructions anyway. They are target-specific in that other targets might
18175 // prefer to not lose information about the pointer arithmetic.
18176
18177 // Fold (ptradd x, shl(0 - v, k)) -> sub(x, shl(v, k)).
18178 // Adapted from DAGCombiner::visitADDLikeCommutative.
18179 SDValue V, K;
18180 if (sd_match(N1, m_Shl(m_Neg(m_Value(V)), m_Value(K)))) {
18181 SDNodeFlags ShlFlags = N1->getFlags();
18182 // If the original shl is NUW and NSW, the first k+1 bits of 0-v are all 0,
18183 // so v is either 0 or the first k+1 bits of v are all 1 -> NSW can be
18184 // preserved.
18185 SDNodeFlags NewShlFlags =
18186 ShlFlags.hasNoUnsignedWrap() && ShlFlags.hasNoSignedWrap()
18188 : SDNodeFlags();
18189 SDValue Inner = DAG.getNode(ISD::SHL, DL, VT, V, K, NewShlFlags);
18190 DCI.AddToWorklist(Inner.getNode());
18191 return DAG.getNode(ISD::SUB, DL, VT, N0, Inner);
18192 }
18193
18194 // Fold into Mad64 if the right-hand side is a MUL. Analogous to a fold in
18195 // performAddCombine.
18196 if (N1.getOpcode() == ISD::MUL) {
18197 if (Subtarget->hasMad64_32()) {
18198 if (SDValue Folded = tryFoldToMad64_32(N, DCI))
18199 return Folded;
18200 }
18201 }
18202
18203 // If the 32 low bits of the constant are all zero, there is nothing to fold
18204 // into an immediate offset, so it's better to eliminate the unnecessary
18205 // addition for the lower 32 bits than to preserve the PTRADD.
18206 // Analogous to a fold in performAddCombine.
18207 if (VT == MVT::i64) {
18208 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
18209 return Folded;
18210 }
18211
18212 if (N1.getOpcode() != ISD::ADD || !N1.hasOneUse())
18213 return SDValue();
18214
18215 SDValue X = N0;
18216 SDValue Y = N1.getOperand(0);
18217 SDValue Z = N1.getOperand(1);
18218 bool YIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Y);
18219 bool ZIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Z);
18220
18221 if (!YIsConstant && !ZIsConstant && !X->isDivergent() &&
18222 Y->isDivergent() != Z->isDivergent()) {
18223 // Reassociate (ptradd x, (add y, z)) -> (ptradd (ptradd x, y), z) if x and
18224 // y are uniform and z isn't.
18225 // Reassociate (ptradd x, (add y, z)) -> (ptradd (ptradd x, z), y) if x and
18226 // z are uniform and y isn't.
18227 // The goal is to push uniform operands up in the computation, so that they
18228 // can be handled with scalar operations. We can't use reassociateScalarOps
18229 // for this since it requires two identical commutative operations to
18230 // reassociate.
18231 if (Y->isDivergent())
18232 std::swap(Y, Z);
18233 // If both additions in the original were NUW, reassociation preserves that.
18234 SDNodeFlags ReassocFlags =
18235 (N->getFlags() & N1->getFlags()) & SDNodeFlags::NoUnsignedWrap;
18236 SDValue UniformInner = DAG.getMemBasePlusOffset(X, Y, DL, ReassocFlags);
18237 DCI.AddToWorklist(UniformInner.getNode());
18238 return DAG.getMemBasePlusOffset(UniformInner, Z, DL, ReassocFlags);
18239 }
18240
18241 return SDValue();
18242}
18243
18244static bool isCtlzOpc(unsigned Opc) {
18245 return Opc == ISD::CTLZ || Opc == ISD::CTLZ_ZERO_POISON;
18246}
18247
18248SDValue SITargetLowering::performSubCombine(SDNode *N,
18249 DAGCombinerInfo &DCI) const {
18250 SelectionDAG &DAG = DCI.DAG;
18251 EVT VT = N->getValueType(0);
18252
18253 if (VT == MVT::i64) {
18254 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
18255 return Folded;
18256 }
18257
18258 if (VT != MVT::i32)
18259 return SDValue();
18260
18261 SDLoc SL(N);
18262 SDValue LHS = N->getOperand(0);
18263 SDValue RHS = N->getOperand(1);
18264
18265 // sub x, zext (setcc) => usubo_carry x, 0, setcc
18266 // sub x, sext (setcc) => uaddo_carry x, 0, setcc
18267 unsigned Opc = RHS.getOpcode();
18268 switch (Opc) {
18269 default:
18270 break;
18271 case ISD::ZERO_EXTEND:
18272 case ISD::SIGN_EXTEND:
18273 case ISD::ANY_EXTEND: {
18274 auto Cond = RHS.getOperand(0);
18275 // If this won't be a real VOPC output, we would still need to insert an
18276 // extra instruction anyway.
18277 if (!isBoolSGPR(Cond))
18278 break;
18279 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::i1);
18280 SDValue Args[] = {LHS, DAG.getConstant(0, SL, MVT::i32), Cond};
18282 return DAG.getNode(Opc, SL, VTList, Args);
18283 }
18284 }
18285
18286 if (LHS.getOpcode() == ISD::USUBO_CARRY) {
18287 // sub (usubo_carry x, 0, cc), y => usubo_carry x, y, cc
18288 if (!isNullConstant(LHS.getOperand(1)))
18289 return SDValue();
18290 SDValue Args[] = {LHS.getOperand(0), RHS, LHS.getOperand(2)};
18291 return DAG.getNode(ISD::USUBO_CARRY, SDLoc(N), LHS->getVTList(), Args);
18292 }
18293
18294 // sub (ctlz (xor x, (sra x, 31))), 1 -> ctls x.
18295 if (isOneConstant(RHS) && isCtlzOpc(LHS.getOpcode())) {
18296 SDValue CtlzSrc = LHS.getOperand(0);
18297 // Check for xor x, (sra x, 31) pattern.
18298 if (CtlzSrc.getOpcode() == ISD::XOR) {
18299 SDValue X = CtlzSrc.getOperand(0);
18300 SDValue SignExt = CtlzSrc.getOperand(1);
18301 // Try both ordering of XOR operands.
18302 if (SignExt.getOpcode() != ISD::SRA)
18303 std::swap(X, SignExt);
18304 if (SignExt.getOpcode() == ISD::SRA && SignExt.getOperand(0) == X) {
18305 ConstantSDNode *ShiftAmt =
18307 unsigned BitWidth = X.getValueType().getScalarSizeInBits();
18308 if (ShiftAmt && ShiftAmt->getZExtValue() == BitWidth - 1)
18309 return DAG.getNode(ISD::CTLS, SL, VT, X);
18310 }
18311 }
18312 }
18313
18314 return SDValue();
18315}
18316
18317SDValue SITargetLowering::performFAddCombine(SDNode *N,
18318 DAGCombinerInfo &DCI) const {
18319 if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
18320 return SDValue();
18321
18322 SelectionDAG &DAG = DCI.DAG;
18323 EVT VT = N->getValueType(0);
18324
18325 SDLoc SL(N);
18326 SDValue LHS = N->getOperand(0);
18327 SDValue RHS = N->getOperand(1);
18328
18329 // These should really be instruction patterns, but writing patterns with
18330 // source modifiers is a pain.
18331
18332 // fadd (fadd (a, a), b) -> mad 2.0, a, b
18333 if (LHS.getOpcode() == ISD::FADD) {
18334 SDValue A = LHS.getOperand(0);
18335 if (A == LHS.getOperand(1)) {
18336 unsigned FusedOp = getFusedOpcode(DAG, N, LHS.getNode());
18337 if (FusedOp != 0) {
18338 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18339 return DAG.getNode(FusedOp, SL, VT, A, Two, RHS);
18340 }
18341 }
18342 }
18343
18344 // fadd (b, fadd (a, a)) -> mad 2.0, a, b
18345 if (RHS.getOpcode() == ISD::FADD) {
18346 SDValue A = RHS.getOperand(0);
18347 if (A == RHS.getOperand(1)) {
18348 unsigned FusedOp = getFusedOpcode(DAG, N, RHS.getNode());
18349 if (FusedOp != 0) {
18350 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18351 return DAG.getNode(FusedOp, SL, VT, A, Two, LHS);
18352 }
18353 }
18354 }
18355
18356 return SDValue();
18357}
18358
18359SDValue SITargetLowering::performFSubCombine(SDNode *N,
18360 DAGCombinerInfo &DCI) const {
18361 if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
18362 return SDValue();
18363
18364 SelectionDAG &DAG = DCI.DAG;
18365 SDLoc SL(N);
18366 EVT VT = N->getValueType(0);
18367 assert(!VT.isVector());
18368
18369 // Try to get the fneg to fold into the source modifier. This undoes generic
18370 // DAG combines and folds them into the mad.
18371 //
18372 // Only do this if we are not trying to support denormals. v_mad_f32 does
18373 // not support denormals ever.
18374 SDValue LHS = N->getOperand(0);
18375 SDValue RHS = N->getOperand(1);
18376 if (LHS.getOpcode() == ISD::FADD) {
18377 // (fsub (fadd a, a), c) -> mad 2.0, a, (fneg c)
18378 SDValue A = LHS.getOperand(0);
18379 if (A == LHS.getOperand(1)) {
18380 unsigned FusedOp = getFusedOpcode(DAG, N, LHS.getNode());
18381 if (FusedOp != 0) {
18382 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18383 SDValue NegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
18384
18385 return DAG.getNode(FusedOp, SL, VT, A, Two, NegRHS);
18386 }
18387 }
18388 }
18389
18390 if (RHS.getOpcode() == ISD::FADD) {
18391 // (fsub c, (fadd a, a)) -> mad -2.0, a, c
18392
18393 SDValue A = RHS.getOperand(0);
18394 if (A == RHS.getOperand(1)) {
18395 unsigned FusedOp = getFusedOpcode(DAG, N, RHS.getNode());
18396 if (FusedOp != 0) {
18397 const SDValue NegTwo = DAG.getConstantFP(-2.0, SL, VT);
18398 return DAG.getNode(FusedOp, SL, VT, A, NegTwo, LHS);
18399 }
18400 }
18401 }
18402
18403 return SDValue();
18404}
18405
18406SDValue SITargetLowering::performFDivCombine(SDNode *N,
18407 DAGCombinerInfo &DCI) const {
18408 SelectionDAG &DAG = DCI.DAG;
18409 SDLoc SL(N);
18410 EVT VT = N->getValueType(0);
18411
18412 if (VT != MVT::f16 && VT != MVT::bf16)
18413 return SDValue();
18414
18415 SDValue LHS = N->getOperand(0);
18416 SDValue RHS = N->getOperand(1);
18417
18418 SDNodeFlags Flags = N->getFlags();
18419 SDNodeFlags RHSFlags = RHS->getFlags();
18420 if (!Flags.hasAllowContract() || !RHSFlags.hasAllowContract() ||
18421 !RHS->hasOneUse())
18422 return SDValue();
18423
18424 if (const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(LHS)) {
18425 bool IsNegative = false;
18426 if (CLHS->isOne() || (IsNegative = CLHS->isMinusOne())) {
18427 // fdiv contract 1.0, (sqrt contract x) -> rsq
18428 // fdiv contract -1.0, (sqrt contract x) -> fneg(rsq)
18429 if (RHS.getOpcode() == ISD::FSQRT) {
18430 // TODO: Or in RHS flags, somehow missing from SDNodeFlags
18431 SDValue SqrtOp = RHS.getOperand(0);
18432 SDValue Rsq;
18433 if (isOperationLegal(ISD::FSQRT, VT)) {
18434 // fsqrt legality correlates to rsq availability of the same type.
18435 Rsq = DAG.getNode(AMDGPUISD::RSQ, SL, VT, SqrtOp, Flags);
18436 } else if (VT == MVT::f16) {
18437 // Targets without 16-bit instructions (gfx6/gfx7) have no f16 rsq,
18438 // but v_rsq_f32 is more than accurate enough for f16. Unlike bf16,
18439 // every f16 value (including denormals) extends to a normal f32, and
18440 // an f16 rsq result is never denormal, so the f32 reciprocal square
18441 // root needs no denormal handling. Compute it in f32 and round back.
18442 SDValue Ext =
18443 DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, SqrtOp, Flags);
18444 SDValue F32Rsq =
18445 DAG.getNode(AMDGPUISD::RSQ, SL, MVT::f32, Ext, Flags);
18446 Rsq = DAG.getNode(ISD::FP_ROUND, SL, VT, F32Rsq,
18447 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
18448 } else {
18449 // bf16 shares f32's exponent range, so bf16 denormals would extend to
18450 // f32 denormals that v_rsq_f32 does not handle. Leave it expanded.
18451 return SDValue();
18452 }
18453 return IsNegative ? DAG.getNode(ISD::FNEG, SL, VT, Rsq, Flags) : Rsq;
18454 }
18455 }
18456 }
18457
18458 return SDValue();
18459}
18460
18461SDValue SITargetLowering::performFMulCombine(SDNode *N,
18462 DAGCombinerInfo &DCI) const {
18463 SelectionDAG &DAG = DCI.DAG;
18464 EVT VT = N->getValueType(0);
18465 EVT ScalarVT = VT.getScalarType();
18466 EVT IntVT = VT.changeElementType(*DAG.getContext(), MVT::i32);
18467
18468 if (!N->isDivergent() && getSubtarget()->hasSALUFloatInsts() &&
18469 (ScalarVT == MVT::f32 || ScalarVT == MVT::f16)) {
18470 // Prefer to use s_mul_f16/f32 instead of v_ldexp_f16/f32.
18471 return SDValue();
18472 }
18473
18474 SDValue LHS = N->getOperand(0);
18475 SDValue RHS = N->getOperand(1);
18476
18477 // It is cheaper to realize i32 inline constants as compared against
18478 // materializing f16 or f64 (or even non-inline f32) values,
18479 // possible via ldexp usage, as shown below :
18480 //
18481 // Given : A = 2^a & B = 2^b ; where a and b are integers.
18482 // fmul x, (select y, A, B) -> ldexp( x, (select i32 y, a, b) )
18483 // fmul x, (select y, -A, -B) -> ldexp( (fneg x), (select i32 y, a, b) )
18484 if ((ScalarVT == MVT::f64 || ScalarVT == MVT::f32 || ScalarVT == MVT::f16) &&
18485 (RHS.hasOneUse() && RHS.getOpcode() == ISD::SELECT)) {
18486 const ConstantFPSDNode *TrueNode = isConstOrConstSplatFP(RHS.getOperand(1));
18487 if (!TrueNode)
18488 return SDValue();
18489 const ConstantFPSDNode *FalseNode =
18490 isConstOrConstSplatFP(RHS.getOperand(2));
18491 if (!FalseNode)
18492 return SDValue();
18493
18494 if (TrueNode->isNegative() != FalseNode->isNegative())
18495 return SDValue();
18496
18497 // For f32, only non-inline constants should be transformed.
18498 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
18499 if (ScalarVT == MVT::f32 &&
18500 TII->isInlineConstant(TrueNode->getValueAPF()) &&
18501 TII->isInlineConstant(FalseNode->getValueAPF()))
18502 return SDValue();
18503
18504 int TrueNodeExpVal = TrueNode->getValueAPF().getExactLog2Abs();
18505 if (TrueNodeExpVal == INT_MIN)
18506 return SDValue();
18507 int FalseNodeExpVal = FalseNode->getValueAPF().getExactLog2Abs();
18508 if (FalseNodeExpVal == INT_MIN)
18509 return SDValue();
18510
18511 SDLoc SL(N);
18512 SDValue SelectNode =
18513 DAG.getNode(ISD::SELECT, SL, IntVT, RHS.getOperand(0),
18514 DAG.getSignedConstant(TrueNodeExpVal, SL, IntVT),
18515 DAG.getSignedConstant(FalseNodeExpVal, SL, IntVT));
18516
18517 LHS = TrueNode->isNegative()
18518 ? DAG.getNode(ISD::FNEG, SL, VT, LHS, LHS->getFlags())
18519 : LHS;
18520
18521 return DAG.getNode(ISD::FLDEXP, SL, VT, LHS, SelectNode, N->getFlags());
18522 }
18523
18524 return SDValue();
18525}
18526
18527SDValue SITargetLowering::performFMACombine(SDNode *N,
18528 DAGCombinerInfo &DCI) const {
18529 SelectionDAG &DAG = DCI.DAG;
18530 EVT VT = N->getValueType(0);
18531 SDLoc SL(N);
18532
18533 if (!Subtarget->hasDot10Insts() || VT != MVT::f32)
18534 return SDValue();
18535
18536 // FMA((F32)S0.x, (F32)S1. x, FMA((F32)S0.y, (F32)S1.y, (F32)z)) ->
18537 // FDOT2((V2F16)S0, (V2F16)S1, (F32)z))
18538 SDValue Op1 = N->getOperand(0);
18539 SDValue Op2 = N->getOperand(1);
18540 SDValue FMA = N->getOperand(2);
18541
18542 if (FMA.getOpcode() != ISD::FMA || Op1.getOpcode() != ISD::FP_EXTEND ||
18543 Op2.getOpcode() != ISD::FP_EXTEND)
18544 return SDValue();
18545
18546 // The fdot2 fold (fma_mix -> dot2) is only safe when both instructions agree
18547 // on how f16 subnormal inputs are handled. However, if both FMAs carry afn
18548 // the caller accepts approximate results, so any subnormal flushing
18549 // introduced by dot2 is acceptable regardless of mode.
18550 //
18551 // gfx90a (CDNA2) is the sole exception (dot2UnconditionalFlush): v_dot2c
18552 // unconditionally flushes f16 subnormal inputs to zero regardless of MODE,
18553 // while v_fma_mix_f32 preserves them when ieee=1 (the default compute kernel
18554 // mode). The fold is safe only when f32 denorm = PreserveSign, which implies
18555 // ieee=0 so both flush.
18556 //
18557 // All other GPUs: v_dot2 does NOT flush f16 subnormal inputs. v_fma_mix_f32
18558 // flushes them only when f32 denorm = PreserveSign. The fold is safe only
18559 // when f32 denorm is IEEE (both preserve the subnormal). Dynamic mode is
18560 // also rejected since the runtime value is unknown.
18561 bool AllowInaccuracy = N->getFlags().hasApproximateFuncs() &&
18562 FMA->getFlags().hasApproximateFuncs();
18563 if (!AllowInaccuracy) {
18564 const MachineFunction &MF = DAG.getMachineFunction();
18565 DenormalMode Mode = MF.getDenormalMode(APFloat::IEEEsingle());
18566 if (Subtarget->dot2UnconditionalFlush()) {
18567 // gfx90a: fold safe only when f32 denorm flushes.
18569 return SDValue();
18570 } else {
18571 // All other GPUs: fold safe only when f32 denorm is IEEE.
18572 if (Mode != DenormalMode::getIEEE())
18573 return SDValue();
18574 }
18575 }
18576
18577 // fp-contract allows reassociating the fma tree into a dot product.
18578 if (N->getFlags().hasAllowContract() && FMA->getFlags().hasAllowContract()) {
18579 Op1 = Op1.getOperand(0);
18580 Op2 = Op2.getOperand(0);
18581 if (Op1.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
18583 return SDValue();
18584
18585 SDValue Vec1 = Op1.getOperand(0);
18586 SDValue Idx1 = Op1.getOperand(1);
18587 SDValue Vec2 = Op2.getOperand(0);
18588
18589 SDValue FMAOp1 = FMA.getOperand(0);
18590 SDValue FMAOp2 = FMA.getOperand(1);
18591 SDValue FMAAcc = FMA.getOperand(2);
18592
18593 if (FMAOp1.getOpcode() != ISD::FP_EXTEND ||
18594 FMAOp2.getOpcode() != ISD::FP_EXTEND)
18595 return SDValue();
18596
18597 FMAOp1 = FMAOp1.getOperand(0);
18598 FMAOp2 = FMAOp2.getOperand(0);
18599 if (FMAOp1.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
18601 return SDValue();
18602
18603 SDValue Vec3 = FMAOp1.getOperand(0);
18604 SDValue Vec4 = FMAOp2.getOperand(0);
18605 SDValue Idx2 = FMAOp1.getOperand(1);
18606
18607 if (Idx1 != Op2.getOperand(1) || Idx2 != FMAOp2.getOperand(1))
18608 return SDValue();
18609
18610 if (!isa<ConstantSDNode>(Idx1) || !isa<ConstantSDNode>(Idx2) ||
18611 Idx1 == Idx2)
18612 return SDValue();
18613
18614 if (Vec1 == Vec2 || Vec3 == Vec4)
18615 return SDValue();
18616
18617 if (Vec1.getValueType() != MVT::v2f16 || Vec2.getValueType() != MVT::v2f16)
18618 return SDValue();
18619
18620 if ((Vec1 == Vec3 && Vec2 == Vec4) || (Vec1 == Vec4 && Vec2 == Vec3)) {
18621 return DAG.getNode(AMDGPUISD::FDOT2, SL, MVT::f32, Vec1, Vec2, FMAAcc,
18622 DAG.getTargetConstant(0, SL, MVT::i1));
18623 }
18624 }
18625 return SDValue();
18626}
18627
18628// Given a double-precision ordered or unordered comparison, return the
18629// condition code for an equivalent integral comparison of the operands' upper
18630// 32 bits, or `SETCC_INVALID` if not possible.
18631// For simplicity, no simplification occurs if the operands are not both known
18632// to have sign bit zero.
18633//
18634// EQ/NE:
18635// If LHS.lo32 == RHS.lo32:
18636// setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, eq/ne
18637// If LHS.lo32 != RHS.lo32:
18638// setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, false/true
18639// The reduction is not possible if operands may be +0 and -0.
18640// For ordered eq / unordered ne, at most one operand may be NaN.
18641// For unordered eq / ordered ne, neither operand can be NaN.
18642//
18643// LT/GE:
18644// If LHS.lo32 >= RHS.lo32 (unsigned):
18645// setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]lt/ge
18646// If LHS.lo32 < RHS.lo32 (unsigned):
18647// setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]le/gt
18648// The reduction is only supported if both operands are nonnegative.
18649// For ordered lt / unordered ge, the RHS cannot be NaN.
18650// For unordered lt / ordered ge, neither operand can be NaN.
18651//
18652// LE/GT:
18653// If LHS.lo32 > RHS.lo32 (unsigned):
18654// setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]lt/ge
18655// If LHS.lo32 <= RHS.lo32 (unsigned):
18656// setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]le/gt
18657// The reduction is only supported if both operands are nonnegative.
18658// For unordered le / ordered gt, the LHS cannot be NaN.
18659// For ordered le / unordered gt, neither operand can be NaN.
18661 const SDValue LHS,
18662 const SDValue RHS,
18663 const SelectionDAG &DAG) {
18664 EVT VT = LHS.getValueType();
18665 assert(VT == MVT::f64 && "Incorrect operand type!");
18666
18667 const KnownBits RHSBits = DAG.computeKnownBits(RHS);
18668 // Bail if RHS sign bit is not known to be zero.
18669 if (!RHSBits.Zero.isSignBitSet())
18670 return ISD::SETCC_INVALID;
18671
18672 const KnownBits RHSKnownLo32 = RHSBits.trunc(32);
18673 const KnownFPClass RHSFPClass =
18675 const bool RHSMaybeNaN = !RHSFPClass.isKnownNeverNaN();
18676
18677 const KnownBits LHSBits = DAG.computeKnownBits(LHS);
18678 const KnownBits LHSKnownLo32 = LHSBits.trunc(32);
18679 const KnownFPClass LHSFPClass =
18681 const bool LHSMaybeNaN = !LHSFPClass.isKnownNeverNaN();
18682
18683 // Bail if LHS sign bit is not known to be zero.
18684 if (!LHSBits.Zero.isSignBitSet())
18685 return ISD::SETCC_INVALID;
18686
18687 switch (CC) {
18688 default:
18689 break;
18690 case ISD::SETEQ:
18691 case ISD::SETOEQ:
18692 case ISD::SETUEQ:
18693 case ISD::SETONE:
18694 case ISD::SETUNE: {
18695 // OEQ should be false if either operand is NaN, so it suffices that at
18696 // least one operand is not NaN.
18697 if (CC == ISD::SETOEQ && LHSMaybeNaN && RHSMaybeNaN)
18698 break;
18699 // UEQ should be true if either operand is NaN, but this cannot be checked
18700 // on underlying bits.
18701 if (CC == ISD::SETUEQ && (LHSMaybeNaN || RHSMaybeNaN))
18702 break;
18703 // ONE should be false if either operand is NaN, but this cannot be
18704 // checked on underlying bits.
18705 if (CC == ISD::SETONE && (LHSMaybeNaN || RHSMaybeNaN))
18706 break;
18707 // UNE should be true if either operand is NaN, so it suffices that they
18708 // are not both NaN.
18709 if (CC == ISD::SETUNE && LHSMaybeNaN && RHSMaybeNaN)
18710 break;
18711
18712 const std::optional<bool> KnownEq =
18713 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
18714
18715 if (!KnownEq)
18716 break;
18717
18718 if (*KnownEq)
18719 return (CC == ISD::SETEQ || CC == ISD::SETOEQ || CC == ISD::SETUEQ)
18720 ? ISD::SETEQ
18721 : ISD::SETNE;
18722
18723 return (CC == ISD::SETEQ || CC == ISD::SETOEQ || CC == ISD::SETUEQ)
18725 : ISD::SETTRUE;
18726 }
18727 case ISD::SETLT:
18728 case ISD::SETOLT:
18729 case ISD::SETULT:
18730 case ISD::SETGE:
18731 case ISD::SETOGE:
18732 case ISD::SETUGE: {
18733 // OLT should be false if either operand is NaN.
18734 // Since NaNs have maximum exponent and nonzero mantissa, false positives
18735 // are only possible if the RHS is NaN. (No issue with RHS == +inf since
18736 // the inequality is strict)
18737 if (CC == ISD::SETOLT && RHSMaybeNaN)
18738 break;
18739 // ULT should be true if either operand is NaN, but this cannot be ensured
18740 // with a truncated comparison.
18741 if (CC == ISD::SETULT && (LHSMaybeNaN || RHSMaybeNaN))
18742 break;
18743 // OGE should be false if either operand is NaN, but this cannot be
18744 // ensured with a truncated comparison.
18745 if (CC == ISD::SETOGE && (LHSMaybeNaN || RHSMaybeNaN))
18746 break;
18747 // UGE should be true if either operand is NaN.
18748 // False negatives are only possible if the RHS is NaN.
18749 // (No issue with RHS == +inf since the inequality is inclusive)
18750 if (CC == ISD::SETUGE && RHSMaybeNaN)
18751 break;
18752
18753 const std::optional<bool> KnownUge =
18754 KnownBits::uge(LHSKnownLo32, RHSKnownLo32);
18755
18756 if (!KnownUge)
18757 break;
18758
18759 if (*KnownUge) {
18760 // LHS.lo32 uge RHS.lo32, so LHS >= RHS iff LHS.hi32 >= RHS.hi32
18761 return (CC == ISD::SETLT || CC == ISD::SETOLT || CC == ISD::SETULT)
18762 ? ISD::SETLT
18763 : ISD::SETGE;
18764 }
18765 // LHS.lo32 ult RHS.lo32, so LHS >= RHS iff LHS.hi32 > RHS.hi32
18766 return (CC == ISD::SETLT || CC == ISD::SETOLT || CC == ISD::SETULT)
18767 ? ISD::SETLE
18768 : ISD::SETGT;
18769 }
18770 case ISD::SETLE:
18771 case ISD::SETOLE:
18772 case ISD::SETULE:
18773 case ISD::SETGT:
18774 case ISD::SETOGT:
18775 case ISD::SETUGT: {
18776 // OLE should be false if either operand is NaN, but this cannot be
18777 // ensured with a truncated comparison.
18778 if (CC == ISD::SETOLE && (LHSMaybeNaN || RHSMaybeNaN))
18779 break;
18780 // ULE should be true if either operand is NaN.
18781 // False negatives are only possible if the LHS is NaN.
18782 // (No issue with LHS == +inf since the inequality is inclusive)
18783 if (CC == ISD::SETULE && LHSMaybeNaN)
18784 break;
18785 // OGT should be false if either operand is NaN.
18786 // False positives are only possible if the LHS is NaN.
18787 // (No issue with LHS == +inf since the inequality is strict)
18788 if (CC == ISD::SETOGT && LHSMaybeNaN)
18789 break;
18790 // UGT should be true if either operand is NaN, but this cannot be ensured
18791 // with a truncated comparison.
18792 if (CC == ISD::SETUGT && (LHSMaybeNaN || RHSMaybeNaN))
18793 break;
18794
18795 const std::optional<bool> KnownUle =
18796 KnownBits::ule(LHSKnownLo32, RHSKnownLo32);
18797
18798 if (!KnownUle)
18799 break;
18800
18801 if (*KnownUle) {
18802 // LHS.lo32 ule RHS.lo32, so LHS <= RHS iff LHS.hi32 <= RHS.hi32
18803 return (CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE)
18804 ? ISD::SETLE
18805 : ISD::SETGT;
18806 }
18807 // LHS.lo32 ugt RHS.lo32, so LHS <= RHS iff LHS.hi32 < RHS.hi32
18808 return (CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE)
18809 ? ISD::SETLT
18810 : ISD::SETGE;
18811 }
18812 }
18813
18814 return ISD::SETCC_INVALID;
18815}
18816
18817SDValue SITargetLowering::performSetCCCombine(SDNode *N,
18818 DAGCombinerInfo &DCI) const {
18819 SelectionDAG &DAG = DCI.DAG;
18820 SDLoc SL(N);
18821
18822 SDValue LHS = N->getOperand(0);
18823 SDValue RHS = N->getOperand(1);
18824 EVT VT = LHS.getValueType();
18825 ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
18826
18827 auto *CRHS = dyn_cast<ConstantSDNode>(RHS);
18828 if (!CRHS) {
18830 if (CRHS) {
18831 std::swap(LHS, RHS);
18832 CC = getSetCCSwappedOperands(CC);
18833 }
18834 }
18835
18836 if (CRHS) {
18837 if (VT == MVT::i32 && LHS.getOpcode() == ISD::SIGN_EXTEND &&
18838 isBoolSGPR(LHS.getOperand(0))) {
18839 // setcc (sext from i1 cc), -1, ne|sgt|ult) => not cc => xor cc, -1
18840 // setcc (sext from i1 cc), -1, eq|sle|uge) => cc
18841 // setcc (sext from i1 cc), 0, eq|sge|ule) => not cc => xor cc, -1
18842 // setcc (sext from i1 cc), 0, ne|ugt|slt) => cc
18843 if ((CRHS->isAllOnes() &&
18844 (CC == ISD::SETNE || CC == ISD::SETGT || CC == ISD::SETULT)) ||
18845 (CRHS->isZero() &&
18846 (CC == ISD::SETEQ || CC == ISD::SETGE || CC == ISD::SETULE)))
18847 return DAG.getNode(ISD::XOR, SL, MVT::i1, LHS.getOperand(0),
18848 DAG.getAllOnesConstant(SL, MVT::i1));
18849 if ((CRHS->isAllOnes() &&
18850 (CC == ISD::SETEQ || CC == ISD::SETLE || CC == ISD::SETUGE)) ||
18851 (CRHS->isZero() &&
18852 (CC == ISD::SETNE || CC == ISD::SETUGT || CC == ISD::SETLT)))
18853 return LHS.getOperand(0);
18854 }
18855
18856 const APInt &CRHSVal = CRHS->getAPIntValue();
18857 if ((CC == ISD::SETEQ || CC == ISD::SETNE) &&
18858 LHS.getOpcode() == ISD::SELECT &&
18859 isa<ConstantSDNode>(LHS.getOperand(1)) &&
18860 isa<ConstantSDNode>(LHS.getOperand(2)) &&
18861 isBoolSGPR(LHS.getOperand(0))) {
18862 // Given CT != FT:
18863 // setcc (select cc, CT, CF), CF, eq => xor cc, -1
18864 // setcc (select cc, CT, CF), CF, ne => cc
18865 // setcc (select cc, CT, CF), CT, ne => xor cc, -1
18866 // setcc (select cc, CT, CF), CT, eq => cc
18867 const APInt &CT = LHS.getConstantOperandAPInt(1);
18868 const APInt &CF = LHS.getConstantOperandAPInt(2);
18869
18870 if (CT != CF) {
18871 if ((CF == CRHSVal && CC == ISD::SETEQ) ||
18872 (CT == CRHSVal && CC == ISD::SETNE))
18873 return DAG.getNOT(SL, LHS.getOperand(0), MVT::i1);
18874 if ((CF == CRHSVal && CC == ISD::SETNE) ||
18875 (CT == CRHSVal && CC == ISD::SETEQ))
18876 return LHS.getOperand(0);
18877 }
18878 }
18879 }
18880
18881 // Truncate 64-bit setcc to only test upper or lower 32-bits.
18882 if (VT == MVT::i64) {
18883 const KnownBits LHSKnown = DAG.computeKnownBits(LHS);
18884 const KnownBits RHSKnown = DAG.computeKnownBits(RHS);
18885 const KnownBits LHSKnownLo32 = LHSKnown.trunc(32);
18886 const KnownBits RHSKnownLo32 = RHSKnown.trunc(32);
18887 // Truncate 64-bit setcc to test only upper 32-bits of its operands in the
18888 // following cases where information about the lower 32-bits of its operands
18889 // is known:
18890 //
18891 // If LHS.lo32 == RHS.lo32:
18892 // setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, eq/ne
18893 // If LHS.lo32 != RHS.lo32:
18894 // setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, false/true
18895 // If LHS.lo32 >= RHS.lo32 (unsigned):
18896 // setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]lt/ge
18897 // If LHS.lo32 > RHS.lo32 (unsigned):
18898 // setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]lt/ge
18899 // If LHS.lo32 <= RHS.lo32 (unsigned):
18900 // setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]le/gt
18901 // If LHS.lo32 < RHS.lo32 (unsigned):
18902 // setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]le/gt
18903
18904 // NewCC is valid iff we can truncate the setcc to only test the upper 32
18905 // bits
18907
18908 switch (CC) {
18909 default:
18910 llvm_unreachable("Unexpected condition code for integer setcc");
18911 break;
18912 case ISD::SETEQ: {
18913 const std::optional<bool> KnownEq =
18914 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
18915 if (KnownEq)
18916 NewCC = *KnownEq ? ISD::SETEQ : ISD::SETFALSE;
18917
18918 break;
18919 }
18920 case ISD::SETNE: {
18921 const std::optional<bool> KnownEq =
18922 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
18923 if (KnownEq)
18924 NewCC = *KnownEq ? ISD::SETNE : ISD::SETTRUE;
18925
18926 break;
18927 }
18928 case ISD::SETULT:
18929 case ISD::SETUGE:
18930 case ISD::SETLT:
18931 case ISD::SETGE: {
18932 const std::optional<bool> KnownUge =
18933 KnownBits::uge(LHSKnownLo32, RHSKnownLo32);
18934 if (KnownUge) {
18935 if (*KnownUge) {
18936 // LHS.lo32 uge RHS.lo32, so LHS >= RHS iff LHS.hi32 >= RHS.hi32
18937 NewCC = CC;
18938 } else {
18939 // LHS.lo32 ult RHS.lo32, so LHS >= RHS iff LHS.hi32 > RHS.hi32
18940 NewCC = CC == ISD::SETULT ? ISD::SETULE
18941 : CC == ISD::SETUGE ? ISD::SETUGT
18942 : CC == ISD::SETLT ? ISD::SETLE
18943 : ISD::SETGT;
18944 }
18945 }
18946 break;
18947 }
18948 case ISD::SETULE:
18949 case ISD::SETUGT:
18950 case ISD::SETLE:
18951 case ISD::SETGT: {
18952 const std::optional<bool> KnownUle =
18953 KnownBits::ule(LHSKnownLo32, RHSKnownLo32);
18954 if (KnownUle) {
18955 if (*KnownUle) {
18956 // LHS.lo32 ule RHS.lo32, so LHS <= RHS iff LHS.hi32 <= RHS.hi32
18957 NewCC = CC;
18958 } else {
18959 // LHS.lo32 ugt RHS.lo32, so LHS <= RHS iff LHS.hi32 < RHS.hi32
18960 NewCC = CC == ISD::SETULE ? ISD::SETULT
18961 : CC == ISD::SETUGT ? ISD::SETUGE
18962 : CC == ISD::SETLE ? ISD::SETLT
18963 : ISD::SETGE;
18964 }
18965 }
18966 break;
18967 }
18968 }
18969
18970 if (NewCC != ISD::SETCC_INVALID)
18971 return DAG.getSetCC(SL, N->getValueType(0), getHiHalf64(LHS, DAG),
18972 getHiHalf64(RHS, DAG), NewCC);
18973
18974 // Truncate 64-bit setcc to test only lower 32-bits when upper 32-bits are
18975 // known equal.
18976 const KnownBits LHSKnownHi32 = LHSKnown.extractBits(32, 32);
18977 const KnownBits RHSKnownHi32 = RHSKnown.extractBits(32, 32);
18978 const std::optional<bool> KnownEq =
18979 KnownBits::eq(LHSKnownHi32, RHSKnownHi32);
18980
18981 if (KnownEq == true) {
18982 // For signed comparisons, convert to unsigned since upper halves match
18984
18985 SDValue LHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LHS);
18986 SDValue RHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, RHS);
18987 return DAG.getSetCC(SL, N->getValueType(0), LHSLo, RHSLo, NewCC);
18988 }
18989 }
18990
18991 // Eliminate setcc by using carryout from add/sub instruction
18992
18993 // LHS = ADD i64 RHS, Z LHSlo = UADDO i32 RHSlo, Zlo
18994 // setcc LHS ult RHS -> LHSHi = UADDO_CARRY i32 RHShi, Zhi
18995 // similarly for subtraction
18996
18997 // LHS = ADD i64 Y, 1 LHSlo = UADDO i32 Ylo, 1
18998 // setcc LHS eq 0 -> LHSHi = UADDO_CARRY i32 Yhi, 0
18999
19000 if (VT == MVT::i64 && ((CC == ISD::SETULT &&
19002 (CC == ISD::SETUGT &&
19004 (CC == ISD::SETEQ && CRHS && CRHS->isZero() &&
19005 sd_match(LHS, m_Add(m_Value(), m_One()))))) {
19006 bool IsAdd = LHS.getOpcode() == ISD::ADD;
19007
19008 SDValue Op0 = LHS.getOperand(0);
19009 SDValue Op1 = LHS.getOperand(1);
19010
19011 SDValue Op0Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Op0);
19012 SDValue Op1Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Op1);
19013
19014 SDValue Op0Hi = getHiHalf64(Op0, DAG);
19015 SDValue Op1Hi = getHiHalf64(Op1, DAG);
19016
19017 SDValue NodeLo =
19018 DAG.getNode(IsAdd ? ISD::UADDO : ISD::USUBO, SL,
19019 DAG.getVTList(MVT::i32, MVT::i1), {Op0Lo, Op1Lo});
19020
19021 SDValue CarryInHi = NodeLo.getValue(1);
19022 SDValue NodeHi = DAG.getNode(IsAdd ? ISD::UADDO_CARRY : ISD::USUBO_CARRY,
19023 SL, DAG.getVTList(MVT::i32, MVT::i1),
19024 {Op0Hi, Op1Hi, CarryInHi});
19025
19026 SDValue ResultLo = NodeLo.getValue(0);
19027 SDValue ResultHi = NodeHi.getValue(0);
19028
19029 SDValue JoinedResult =
19030 DAG.getBuildVector(MVT::v2i32, SL, {ResultLo, ResultHi});
19031
19032 SDValue Result = DAG.getNode(ISD::BITCAST, SL, VT, JoinedResult);
19033 SDValue Overflow = NodeHi.getValue(1);
19034 DCI.CombineTo(LHS.getNode(), Result);
19035 return Overflow;
19036 }
19037
19038 if (VT != MVT::f32 && VT != MVT::f64 &&
19039 (!Subtarget->has16BitInsts() || VT != MVT::f16))
19040 return SDValue();
19041
19042 // Match isinf/isfinite pattern
19043 // (fcmp oeq (fabs x), inf) -> (fp_class x, (p_infinity | n_infinity))
19044 // (fcmp one (fabs x), inf) -> (fp_class x,
19045 // (p_normal | n_normal | p_subnormal | n_subnormal | p_zero | n_zero)
19046 if ((CC == ISD::SETOEQ || CC == ISD::SETONE) &&
19047 LHS.getOpcode() == ISD::FABS) {
19048 const ConstantFPSDNode *CRHS = dyn_cast<ConstantFPSDNode>(RHS);
19049 if (!CRHS)
19050 return SDValue();
19051
19052 const APFloat &APF = CRHS->getValueAPF();
19053 if (APF.isInfinity() && !APF.isNegative()) {
19054 const unsigned IsInfMask =
19056 const unsigned IsFiniteMask =
19060 unsigned Mask = CC == ISD::SETOEQ ? IsInfMask : IsFiniteMask;
19061 return DAG.getNode(AMDGPUISD::FP_CLASS, SL, MVT::i1, LHS.getOperand(0),
19062 DAG.getConstant(Mask, SL, MVT::i32));
19063 }
19064 }
19065
19066 if (VT == MVT::f64) {
19067 ISD::CondCode HiHalfCC = tryReduceF64CompareToHiHalf(CC, LHS, RHS, DAG);
19068 if (HiHalfCC != ISD::SETCC_INVALID)
19069 return DAG.getSetCC(SL, N->getValueType(0), getHiHalf64(LHS, DAG),
19070 getHiHalf64(RHS, DAG), HiHalfCC);
19071 }
19072
19073 return SDValue();
19074}
19075
19076SDValue
19077SITargetLowering::performCvtF32UByteNCombine(SDNode *N,
19078 DAGCombinerInfo &DCI) const {
19079 SelectionDAG &DAG = DCI.DAG;
19080 SDLoc SL(N);
19081 unsigned Offset = N->getOpcode() - AMDGPUISD::CVT_F32_UBYTE0;
19082
19083 SDValue Src = N->getOperand(0);
19084 SDValue Shift = N->getOperand(0);
19085
19086 // TODO: Extend type shouldn't matter (assuming legal types).
19087 if (Shift.getOpcode() == ISD::ZERO_EXTEND)
19088 Shift = Shift.getOperand(0);
19089
19090 if (Shift.getOpcode() == ISD::SRL || Shift.getOpcode() == ISD::SHL) {
19091 // cvt_f32_ubyte1 (shl x, 8) -> cvt_f32_ubyte0 x
19092 // cvt_f32_ubyte3 (shl x, 16) -> cvt_f32_ubyte1 x
19093 // cvt_f32_ubyte0 (srl x, 16) -> cvt_f32_ubyte2 x
19094 // cvt_f32_ubyte1 (srl x, 16) -> cvt_f32_ubyte3 x
19095 // cvt_f32_ubyte0 (srl x, 8) -> cvt_f32_ubyte1 x
19096 if (auto *C = dyn_cast<ConstantSDNode>(Shift.getOperand(1))) {
19097 SDValue Shifted = DAG.getZExtOrTrunc(
19098 Shift.getOperand(0), SDLoc(Shift.getOperand(0)), MVT::i32);
19099
19100 unsigned ShiftOffset = 8 * Offset;
19101 if (Shift.getOpcode() == ISD::SHL)
19102 ShiftOffset -= C->getZExtValue();
19103 else
19104 ShiftOffset += C->getZExtValue();
19105
19106 if (ShiftOffset < 32 && (ShiftOffset % 8) == 0) {
19107 return DAG.getNode(AMDGPUISD::CVT_F32_UBYTE0 + ShiftOffset / 8, SL,
19108 MVT::f32, Shifted);
19109 }
19110 }
19111 }
19112
19113 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
19114 APInt DemandedBits = APInt::getBitsSet(32, 8 * Offset, 8 * Offset + 8);
19115 if (TLI.SimplifyDemandedBits(Src, DemandedBits, DCI)) {
19116 // We simplified Src. If this node is not dead, visit it again so it is
19117 // folded properly.
19118 if (N->getOpcode() != ISD::DELETED_NODE)
19119 DCI.AddToWorklist(N);
19120 return SDValue(N, 0);
19121 }
19122
19123 // Handle (or x, (srl y, 8)) pattern when known bits are zero.
19124 if (SDValue DemandedSrc =
19125 TLI.SimplifyMultipleUseDemandedBits(Src, DemandedBits, DAG))
19126 return DAG.getNode(N->getOpcode(), SL, MVT::f32, DemandedSrc);
19127
19128 return SDValue();
19129}
19130
19131SDValue SITargetLowering::performClampCombine(SDNode *N,
19132 DAGCombinerInfo &DCI) const {
19133 ConstantFPSDNode *CSrc = dyn_cast<ConstantFPSDNode>(N->getOperand(0));
19134 if (!CSrc)
19135 return SDValue();
19136
19137 const MachineFunction &MF = DCI.DAG.getMachineFunction();
19138 const APFloat &F = CSrc->getValueAPF();
19139 APFloat Zero = APFloat::getZero(F.getSemantics());
19140 if (F < Zero ||
19141 (F.isNaN() && MF.getInfo<SIMachineFunctionInfo>()->getMode().DX10Clamp)) {
19142 return DCI.DAG.getConstantFP(Zero, SDLoc(N), N->getValueType(0));
19143 }
19144
19145 APFloat One = APFloat::getOne(F.getSemantics());
19146 if (F > One)
19147 return DCI.DAG.getConstantFP(One, SDLoc(N), N->getValueType(0));
19148
19149 return getCanonicalConstantFP(DCI.DAG, SDLoc(N), N->getValueType(0), F);
19150}
19151
19152// Check if V is the exponent result of a frexp operation. Returns the frexp
19153// input via FrexpInput if matched. We only match the exponent (not mantissa)
19154// because V_FREXP_MANT returns its input for Inf/NaN, not zero.
19155static bool isFrexpExp(SDValue V, SDValue &FrexpInput) {
19156 // ISD::FFREXP returns {mant, exp} - only match if using the exp result
19157 // (result number 1).
19158 if (V.getOpcode() == ISD::FFREXP && V.getResNo() == 1) {
19159 FrexpInput = V.getOperand(0);
19160 return true;
19161 }
19163 m_Value(FrexpInput))))
19164 return true;
19165 return false;
19166}
19167
19168SDValue
19169SITargetLowering::performFrexpSelectCombine(SDNode *N,
19170 DAGCombinerInfo &DCI) const {
19171 // This optimization only applies when the hardware handles inf/nan correctly.
19172 if (Subtarget->hasFractBug())
19173 return SDValue();
19174
19175 SDValue Cond = N->getOperand(0);
19176 SDValue TrueVal = N->getOperand(1);
19177 SDValue FalseVal = N->getOperand(2);
19178
19179 // Identify which operand is the frexp result and which is the zero constant.
19180 // Pattern 1: select cond, 0, frexp_result (cond true -> return 0)
19181 // Pattern 2: select cond, frexp_result, 0 (cond false -> return 0)
19182 SDValue FrexpVal;
19183 SDValue ZeroVal;
19184 bool CondSelectsZero; // If true, condition=true selects zero
19185
19186 // Check if FrexpVal comes from ISD::FFREXP (exponent result only) or
19187 // amdgcn_frexp_exp intrinsic.
19188 SDValue FrexpInput;
19189 if (isFrexpExp(FalseVal, FrexpInput)) {
19190 FrexpVal = FalseVal;
19191 ZeroVal = TrueVal;
19192 CondSelectsZero = true;
19193 } else if (isFrexpExp(TrueVal, FrexpInput)) {
19194 FrexpVal = TrueVal;
19195 ZeroVal = FalseVal;
19196 CondSelectsZero = false;
19197 } else {
19198 return SDValue();
19199 }
19200
19201 // frexp_exp returns integer, so check for integer zero.
19202 if (!isNullConstant(ZeroVal))
19203 return SDValue();
19204
19205 // The frexp intrinsics ignore sign, so we can strip sign ops when comparing.
19206 SDValue FrexpInputStripped = peekFPSignOps(FrexpInput);
19207
19208 bool IsNonFiniteTest = false;
19209
19210 // Handle SETCC conditions for inf/nan tests.
19211 // The canonical form of these checks is fcmp + fabs.
19212 if (Cond.getOpcode() == ISD::SETCC) {
19213 ISD::CondCode CC = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
19214 SDValue CondLHS = Cond.getOperand(0);
19215 SDValue CondRHS = Cond.getOperand(1);
19216
19217 // Check if LHS is fabs(FrexpInput) - required for infinity comparisons.
19218 SDValue FAbsInput;
19219 bool LHSIsFabs = sd_match(CondLHS, m_FAbs(m_Value(FAbsInput)));
19220 bool LHSMatchesFrexp =
19221 (CondLHS == FrexpInput) ||
19222 (LHSIsFabs && peekFPSignOps(FAbsInput) == FrexpInputStripped) ||
19223 (peekFPSignOps(CondLHS) == FrexpInputStripped);
19224 bool RHSMatchesFrexp = (CondRHS == FrexpInput) ||
19225 (peekFPSignOps(CondRHS) == FrexpInputStripped);
19226
19227 if (CC == ISD::SETUO) {
19228 // fcmp uno x, y - true if either x or y is NaN
19229 // We can only fold if the non-frexp operand is known to never be NaN,
19230 // otherwise the comparison could be true due to the other operand.
19231 // Special case: fcmp uno x, x (same operand) is a valid NaN test.
19232 SelectionDAG &DAG = DCI.DAG;
19233 if (LHSMatchesFrexp &&
19234 (CondLHS == CondRHS || DAG.isKnownNeverNaN(CondRHS)))
19235 IsNonFiniteTest = CondSelectsZero;
19236 else if (RHSMatchesFrexp && DAG.isKnownNeverNaN(CondLHS))
19237 IsNonFiniteTest = CondSelectsZero;
19238 } else if ((CC == ISD::SETOEQ || CC == ISD::SETUEQ) && LHSMatchesFrexp &&
19239 LHSIsFabs &&
19240 sd_match(CondRHS,
19242 CondRHS.getValueType().getFltSemantics())))) {
19243 // fcmp oeq/ueq fabs(x), +inf - true if x is inf (or inf/nan for ueq)
19244 IsNonFiniteTest = CondSelectsZero;
19245 } else if ((CC == ISD::SETONE || CC == ISD::SETUNE) && LHSMatchesFrexp &&
19246 LHSIsFabs &&
19247 sd_match(CondRHS,
19249 CondRHS.getValueType().getFltSemantics())))) {
19250 // fcmp one/une fabs(x), +inf - true if x is NOT inf
19251 IsNonFiniteTest = !CondSelectsZero;
19252 } else if (CC == ISD::SETO) {
19253 // fcmp ord x, y - true if both are NOT NaN
19254 // We can only fold if the non-frexp operand is known to never be NaN,
19255 // otherwise the comparison could be false due to the other operand.
19256 // Special case: fcmp ord x, x (same operand) is a valid not-NaN test.
19257 SelectionDAG &DAG = DCI.DAG;
19258 if (LHSMatchesFrexp &&
19259 (CondLHS == CondRHS || DAG.isKnownNeverNaN(CondRHS)))
19260 IsNonFiniteTest = !CondSelectsZero;
19261 else if (RHSMatchesFrexp && DAG.isKnownNeverNaN(CondLHS))
19262 IsNonFiniteTest = !CondSelectsZero;
19263 }
19264 }
19265
19266 if (!IsNonFiniteTest)
19267 return SDValue();
19268
19269 // The select can be eliminated - just return the frexp result directly.
19270 return FrexpVal;
19271}
19272
19273SDValue SITargetLowering::performSelectCombine(SDNode *N,
19274 DAGCombinerInfo &DCI) const {
19275
19276 // Try to fold CMP + SELECT patterns with shared constants (both FP and
19277 // integer).
19278 // Detect when CMP and SELECT use the same constant and fold them to avoid
19279 // loading the constant twice. Specifically handles patterns like:
19280 // %cmp = icmp eq i32 %val, 4242
19281 // %sel = select i1 %cmp, i32 4242, i32 %other
19282 // It can be optimized to reuse %val instead of 4242 in select.
19283 SDValue Cond = N->getOperand(0);
19284 SDValue TrueVal = N->getOperand(1);
19285 SDValue FalseVal = N->getOperand(2);
19286
19287 // Check if condition is a comparison.
19288 if (Cond.getOpcode() != ISD::SETCC)
19289 return SDValue();
19290
19291 SDValue LHS = Cond.getOperand(0);
19292 SDValue RHS = Cond.getOperand(1);
19293 ISD::CondCode CC = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
19294
19295 bool isFloatingPoint = LHS.getValueType().isFloatingPoint();
19296 bool isInteger = LHS.getValueType().isInteger();
19297
19298 // Handle simple floating-point and integer types only.
19299 if (!isFloatingPoint && !isInteger)
19300 return SDValue();
19301
19302 // Bare SETEQ/SETNE is the builder's NaN-impossible downgrade.
19303 bool isEquality = CC == ISD::SETEQ || (isFloatingPoint && CC == ISD::SETOEQ);
19304 bool isNonEquality =
19305 CC == ISD::SETNE || (isFloatingPoint && CC == ISD::SETONE);
19306 if (!isEquality && !isNonEquality)
19307 return SDValue();
19308
19309 SDValue ArgVal, ConstVal;
19310 if ((isFloatingPoint && isa<ConstantFPSDNode>(RHS)) ||
19311 (isInteger && isa<ConstantSDNode>(RHS))) {
19312 ConstVal = RHS;
19313 ArgVal = LHS;
19314 } else if ((isFloatingPoint && isa<ConstantFPSDNode>(LHS)) ||
19315 (isInteger && isa<ConstantSDNode>(LHS))) {
19316 ConstVal = LHS;
19317 ArgVal = RHS;
19318 } else {
19319 return SDValue();
19320 }
19321
19322 // Skip optimization for inlinable immediates.
19323 if (isFloatingPoint) {
19324 const APFloat &Val = cast<ConstantFPSDNode>(ConstVal)->getValueAPF();
19325 if (!Val.isNormal() || Subtarget->getInstrInfo()->isInlineConstant(Val))
19326 return SDValue();
19327 } else {
19328 const std::optional<int64_t> Val =
19329 cast<ConstantSDNode>(ConstVal)->getAPIntValue().trySExtValue();
19330 if (Val && AMDGPU::isInlinableIntLiteral(*Val))
19331 return SDValue();
19332 }
19333
19334 // For equality and non-equality comparisons, patterns:
19335 // select (setcc x, const), const, y -> select (setcc x, const), x, y
19336 // select (setccinv x, const), y, const -> select (setccinv x, const), y, x
19337 if (!(isEquality && TrueVal == ConstVal) &&
19338 !(isNonEquality && FalseVal == ConstVal))
19339 return SDValue();
19340
19341 // SETONE's false arm is also taken for NaN ArgVal, so require NaN excluded.
19342 if (isFloatingPoint && isNonEquality && FalseVal == ConstVal &&
19343 !Cond->getFlags().hasNoNaNs() && !DCI.DAG.isKnownNeverNaN(ArgVal))
19344 return SDValue();
19345
19346 SDValue SelectLHS = (isEquality && TrueVal == ConstVal) ? ArgVal : TrueVal;
19347 SDValue SelectRHS =
19348 (isNonEquality && FalseVal == ConstVal) ? ArgVal : FalseVal;
19349 return DCI.DAG.getNode(ISD::SELECT, SDLoc(N), N->getValueType(0), Cond,
19350 SelectLHS, SelectRHS);
19351}
19352
19354 DAGCombinerInfo &DCI) const {
19355 switch (N->getOpcode()) {
19356 case ISD::ABS:
19357 if (SDValue Res = promoteUniformUnaryOpToI32(SDValue(N, 0), DCI))
19358 return Res;
19359 break;
19360 case ISD::ADD:
19361 case ISD::SUB:
19362 case ISD::SHL:
19363 case ISD::SRL:
19364 case ISD::SRA:
19365 case ISD::AND:
19366 case ISD::OR:
19367 case ISD::XOR:
19368 case ISD::MUL:
19369 case ISD::SETCC:
19370 case ISD::SELECT:
19371 case ISD::SMIN:
19372 case ISD::SMAX:
19373 case ISD::UMIN:
19374 case ISD::UMAX:
19375 case ISD::USUBSAT:
19376 case ISD::UADDSAT:
19377 if (auto Res = promoteUniformOpToI32(SDValue(N, 0), DCI))
19378 return Res;
19379 break;
19380 default:
19381 break;
19382 }
19383
19384 if (getTargetMachine().getOptLevel() == CodeGenOptLevel::None)
19385 return SDValue();
19386
19387 switch (N->getOpcode()) {
19388 case ISD::ADD:
19389 return performAddCombine(N, DCI);
19390 case ISD::PTRADD:
19391 return performPtrAddCombine(N, DCI);
19392 case ISD::SUB:
19393 return performSubCombine(N, DCI);
19394 case ISD::FADD:
19395 return performFAddCombine(N, DCI);
19396 case ISD::FSUB:
19397 return performFSubCombine(N, DCI);
19398 case ISD::FDIV:
19399 return performFDivCombine(N, DCI);
19400 case ISD::FMUL:
19401 return performFMulCombine(N, DCI);
19402 case ISD::SETCC:
19403 return performSetCCCombine(N, DCI);
19404 case ISD::SELECT:
19405 if (auto Res = performFrexpSelectCombine(N, DCI))
19406 return Res;
19407 if (auto Res = performSelectCombine(N, DCI))
19408 return Res;
19409 break;
19410 case ISD::FMAXNUM:
19411 case ISD::FMINNUM:
19412 case ISD::FMAXNUM_IEEE:
19413 case ISD::FMINNUM_IEEE:
19414 case ISD::FMAXIMUM:
19415 case ISD::FMINIMUM:
19416 case ISD::FMAXIMUMNUM:
19417 case ISD::FMINIMUMNUM:
19418 case ISD::SMAX:
19419 case ISD::SMIN:
19420 case ISD::UMAX:
19421 case ISD::UMIN:
19422 case AMDGPUISD::FMIN_LEGACY:
19423 case AMDGPUISD::FMAX_LEGACY:
19424 return performMinMaxCombine(N, DCI);
19425 case ISD::FMA:
19426 return performFMACombine(N, DCI);
19427 case ISD::AND:
19428 return performAndCombine(N, DCI);
19429 case ISD::OR:
19430 return performOrCombine(N, DCI);
19431 case ISD::FSHR: {
19433 if (N->getValueType(0) == MVT::i32 && N->isDivergent() &&
19434 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
19435 return matchPERM(N, DCI);
19436 }
19437 break;
19438 }
19439 case ISD::XOR:
19440 return performXorCombine(N, DCI);
19441 case ISD::ANY_EXTEND:
19442 case ISD::ZERO_EXTEND:
19443 return performZeroOrAnyExtendCombine(N, DCI);
19444 case ISD::SIGN_EXTEND:
19445 return performExtendTruncShiftCombine(N, DCI);
19447 return performSignExtendInRegCombine(N, DCI);
19448 case AMDGPUISD::FP_CLASS:
19449 return performClassCombine(N, DCI);
19450 case ISD::FCANONICALIZE:
19451 return performFCanonicalizeCombine(N, DCI);
19452 case AMDGPUISD::RCP:
19453 return performRcpCombine(N, DCI);
19454 case ISD::FLDEXP:
19455 case AMDGPUISD::FRACT:
19456 case AMDGPUISD::RSQ:
19457 case AMDGPUISD::RCP_LEGACY:
19458 case AMDGPUISD::RCP_IFLAG:
19459 case AMDGPUISD::RSQ_CLAMP: {
19460 // FIXME: This is probably wrong. If src is an sNaN, it won't be quieted
19461 SDValue Src = N->getOperand(0);
19462 if (Src.isUndef())
19463 return Src;
19464 break;
19465 }
19466 case ISD::SINT_TO_FP:
19467 case ISD::UINT_TO_FP:
19468 return performUCharToFloatCombine(N, DCI);
19469 case ISD::FCOPYSIGN:
19470 return performFCopySignCombine(N, DCI);
19471 case AMDGPUISD::CVT_F32_UBYTE0:
19472 case AMDGPUISD::CVT_F32_UBYTE1:
19473 case AMDGPUISD::CVT_F32_UBYTE2:
19474 case AMDGPUISD::CVT_F32_UBYTE3:
19475 return performCvtF32UByteNCombine(N, DCI);
19476 case AMDGPUISD::FMED3:
19477 return performFMed3Combine(N, DCI);
19478 case AMDGPUISD::CVT_PKRTZ_F16_F32:
19479 return performCvtPkRTZCombine(N, DCI);
19480 case AMDGPUISD::CLAMP:
19481 return performClampCombine(N, DCI);
19482 case ISD::SCALAR_TO_VECTOR: {
19483 SelectionDAG &DAG = DCI.DAG;
19484 EVT VT = N->getValueType(0);
19485
19486 // When bf16 inline constants live in the upper half of the expanded fp32
19487 // constant, only a splat is encodable as an inline constant. The high lane
19488 // is dead here, so splat it.
19489 if (VT == MVT::v2bf16 && Subtarget->hasBF16InlineConstFromUpperFP32()) {
19490 auto *C = dyn_cast<ConstantFPSDNode>(N->getOperand(0));
19492 C->getValueAPF().bitcastToAPInt().getSExtValue(),
19493 Subtarget->hasInv2PiInlineImm()))
19494 return DAG.getBuildVector(VT, SDLoc(N),
19495 {N->getOperand(0), N->getOperand(0)});
19496 }
19497
19498 // v2i16 (scalar_to_vector i16:x) -> v2i16 (bitcast (any_extend i16:x))
19499 if (VT == MVT::v2i16 || VT == MVT::v2f16 || VT == MVT::v2bf16) {
19500 SDLoc SL(N);
19501 SDValue Src = N->getOperand(0);
19502 EVT EltVT = Src.getValueType();
19503 if (EltVT != MVT::i16)
19504 Src = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
19505
19506 SDValue Ext = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Src);
19507 return DAG.getNode(ISD::BITCAST, SL, VT, Ext);
19508 }
19509
19510 break;
19511 }
19513 return performExtractVectorEltCombine(N, DCI);
19515 return performInsertVectorEltCombine(N, DCI);
19516 case ISD::FP_ROUND:
19517 return performFPRoundCombine(N, DCI);
19518 case ISD::LOAD: {
19519 if (SDValue Widened = widenLoad(cast<LoadSDNode>(N), DCI))
19520 return Widened;
19521 [[fallthrough]];
19522 }
19523 default: {
19524 if (!DCI.isBeforeLegalize()) {
19525 if (MemSDNode *MemNode = dyn_cast<MemSDNode>(N))
19526 return performMemSDNodeCombine(MemNode, DCI);
19527 }
19528
19529 break;
19530 }
19531 }
19532
19534}
19535
19536/// Helper function for adjustWritemask
19537static unsigned SubIdx2Lane(unsigned Idx) {
19538 switch (Idx) {
19539 default:
19540 return ~0u;
19541 case AMDGPU::sub0:
19542 return 0;
19543 case AMDGPU::sub1:
19544 return 1;
19545 case AMDGPU::sub2:
19546 return 2;
19547 case AMDGPU::sub3:
19548 return 3;
19549 case AMDGPU::sub4:
19550 return 4; // Possible with TFE/LWE
19551 }
19552}
19553
19554/// Adjust the writemask of MIMG, VIMAGE or VSAMPLE instructions
19555SDNode *SITargetLowering::adjustWritemask(MachineSDNode *&Node,
19556 SelectionDAG &DAG) const {
19557 unsigned Opcode = Node->getMachineOpcode();
19558
19559 // Subtract 1 because the vdata output is not a MachineSDNode operand.
19560 int D16Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::d16) - 1;
19561 if (D16Idx >= 0 && Node->getConstantOperandVal(D16Idx))
19562 return Node; // not implemented for D16
19563
19564 SDNode *Users[5] = {nullptr};
19565 unsigned Lane = 0;
19566 unsigned DmaskIdx =
19567 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::dmask) - 1;
19568 unsigned OldDmask = Node->getConstantOperandVal(DmaskIdx);
19569 unsigned NewDmask = 0;
19570 unsigned TFEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::tfe) - 1;
19571 unsigned LWEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::lwe) - 1;
19572 bool UsesTFC = (int(TFEIdx) >= 0 && Node->getConstantOperandVal(TFEIdx)) ||
19573 (int(LWEIdx) >= 0 && Node->getConstantOperandVal(LWEIdx));
19574 unsigned TFCLane = 0;
19575 bool HasChain = Node->getNumValues() > 1;
19576
19577 if (OldDmask == 0) {
19578 // These are folded out, but on the chance it happens don't assert.
19579 return Node;
19580 }
19581
19582 unsigned OldBitsSet = llvm::popcount(OldDmask);
19583 // Work out which is the TFE/LWE lane if that is enabled.
19584 if (UsesTFC) {
19585 TFCLane = OldBitsSet;
19586 }
19587
19588 // Try to figure out the used register components
19589 for (SDUse &Use : Node->uses()) {
19590
19591 // Don't look at users of the chain.
19592 if (Use.getResNo() != 0)
19593 continue;
19594
19595 SDNode *User = Use.getUser();
19596
19597 // Abort if we can't understand the usage
19598 if (!User->isMachineOpcode() ||
19599 User->getMachineOpcode() != TargetOpcode::EXTRACT_SUBREG)
19600 return Node;
19601
19602 // Lane means which subreg of %vgpra_vgprb_vgprc_vgprd is used.
19603 // Note that subregs are packed, i.e. Lane==0 is the first bit set
19604 // in OldDmask, so it can be any of X,Y,Z,W; Lane==1 is the second bit
19605 // set, etc.
19606 Lane = SubIdx2Lane(User->getConstantOperandVal(1));
19607 if (Lane == ~0u)
19608 return Node;
19609
19610 // Check if the use is for the TFE/LWE generated result at VGPRn+1.
19611 if (UsesTFC && Lane == TFCLane) {
19612 Users[Lane] = User;
19613 } else {
19614 // Set which texture component corresponds to the lane.
19615 unsigned Comp;
19616 for (unsigned i = 0, Dmask = OldDmask; (i <= Lane) && (Dmask != 0); i++) {
19617 Comp = llvm::countr_zero(Dmask);
19618 Dmask &= ~(1 << Comp);
19619 }
19620
19621 // Abort if we have more than one user per component.
19622 if (Users[Lane])
19623 return Node;
19624
19625 Users[Lane] = User;
19626 NewDmask |= 1 << Comp;
19627 }
19628 }
19629
19630 // Don't allow 0 dmask, as hardware assumes one channel enabled.
19631 bool NoChannels = !NewDmask;
19632 if (NoChannels) {
19633 if (!UsesTFC) {
19634 // No uses of the result and not using TFC. Then do nothing.
19635 return Node;
19636 }
19637 // If the original dmask has one channel - then nothing to do
19638 if (OldBitsSet == 1)
19639 return Node;
19640 // Use an arbitrary dmask - required for the instruction to work
19641 NewDmask = 1;
19642 }
19643 // Abort if there's no change
19644 if (NewDmask == OldDmask)
19645 return Node;
19646
19647 unsigned BitsSet = llvm::popcount(NewDmask);
19648
19649 // Check for TFE or LWE - increase the number of channels by one to account
19650 // for the extra return value
19651 // This will need adjustment for D16 if this is also included in
19652 // adjustWriteMask (this function) but at present D16 are excluded.
19653 unsigned NewChannels = BitsSet + UsesTFC;
19654
19655 int NewOpcode =
19656 AMDGPU::getMaskedMIMGOp(Node->getMachineOpcode(), NewChannels);
19657 assert(NewOpcode != -1 &&
19658 NewOpcode != static_cast<int>(Node->getMachineOpcode()) &&
19659 "failed to find equivalent MIMG op");
19660
19661 // Adjust the writemask in the node
19663 llvm::append_range(Ops, Node->ops().take_front(DmaskIdx));
19664 Ops.push_back(DAG.getTargetConstant(NewDmask, SDLoc(Node), MVT::i32));
19665 llvm::append_range(Ops, Node->ops().drop_front(DmaskIdx + 1));
19666
19667 MVT SVT = Node->getValueType(0).getVectorElementType().getSimpleVT();
19668
19669 MVT ResultVT = NewChannels == 1
19670 ? SVT
19671 : MVT::getVectorVT(SVT, NewChannels == 3 ? 4
19672 : NewChannels == 5 ? 8
19673 : NewChannels);
19674 SDVTList NewVTList =
19675 HasChain ? DAG.getVTList(ResultVT, MVT::Other) : DAG.getVTList(ResultVT);
19676
19677 MachineSDNode *NewNode =
19678 DAG.getMachineNode(NewOpcode, SDLoc(Node), NewVTList, Ops);
19679
19680 if (HasChain) {
19681 // Update chain.
19682 DAG.setNodeMemRefs(NewNode, Node->memoperands());
19683 DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 1), SDValue(NewNode, 1));
19684 }
19685
19686 if (NewChannels == 1) {
19687 assert(Node->hasNUsesOfValue(1, 0));
19688 SDNode *Copy =
19689 DAG.getMachineNode(TargetOpcode::COPY, SDLoc(Node),
19690 Users[Lane]->getValueType(0), SDValue(NewNode, 0));
19691 DAG.ReplaceAllUsesWith(Users[Lane], Copy);
19692 return nullptr;
19693 }
19694
19695 // Update the users of the node with the new indices
19696 for (unsigned i = 0, Idx = AMDGPU::sub0; i < 5; ++i) {
19697 SDNode *User = Users[i];
19698 if (!User) {
19699 // Handle the special case of NoChannels. We set NewDmask to 1 above, but
19700 // Users[0] is still nullptr because channel 0 doesn't really have a use.
19701 if (i || !NoChannels)
19702 continue;
19703 } else {
19704 SDValue Op = DAG.getTargetConstant(Idx, SDLoc(User), MVT::i32);
19705 SDNode *NewUser = DAG.UpdateNodeOperands(User, SDValue(NewNode, 0), Op);
19706 if (NewUser != User) {
19707 DAG.ReplaceAllUsesWith(SDValue(User, 0), SDValue(NewUser, 0));
19708 DAG.RemoveDeadNode(User);
19709 }
19710 }
19711
19712 switch (Idx) {
19713 default:
19714 break;
19715 case AMDGPU::sub0:
19716 Idx = AMDGPU::sub1;
19717 break;
19718 case AMDGPU::sub1:
19719 Idx = AMDGPU::sub2;
19720 break;
19721 case AMDGPU::sub2:
19722 Idx = AMDGPU::sub3;
19723 break;
19724 case AMDGPU::sub3:
19725 Idx = AMDGPU::sub4;
19726 break;
19727 }
19728 }
19729
19730 DAG.RemoveDeadNode(Node);
19731 return nullptr;
19732}
19733
19735 if (Op.getOpcode() == ISD::AssertZext)
19736 Op = Op.getOperand(0);
19737
19738 return isa<FrameIndexSDNode>(Op);
19739}
19740
19741/// Legalize target independent instructions (e.g. INSERT_SUBREG)
19742/// with frame index operands.
19743/// LLVM assumes that inputs are to these instructions are registers.
19744SDNode *
19746 SelectionDAG &DAG) const {
19747 if (Node->getOpcode() == ISD::CopyToReg) {
19748 RegisterSDNode *DestReg = cast<RegisterSDNode>(Node->getOperand(1));
19749 SDValue SrcVal = Node->getOperand(2);
19750
19751 // Insert a copy to a VReg_1 virtual register so LowerI1Copies doesn't have
19752 // to try understanding copies to physical registers.
19753 if (SrcVal.getValueType() == MVT::i1 && DestReg->getReg().isPhysical()) {
19754 SDLoc SL(Node);
19756 SDValue VReg = DAG.getRegister(
19757 MRI.createVirtualRegister(&AMDGPU::VReg_1RegClass), MVT::i1);
19758
19759 SDNode *Glued = Node->getGluedNode();
19760 SDValue ToVReg = DAG.getCopyToReg(
19761 Node->getOperand(0), SL, VReg, SrcVal,
19762 SDValue(Glued, Glued ? Glued->getNumValues() - 1 : 0));
19763 SDValue ToResultReg = DAG.getCopyToReg(ToVReg, SL, SDValue(DestReg, 0),
19764 VReg, ToVReg.getValue(1));
19765 DAG.ReplaceAllUsesWith(Node, ToResultReg.getNode());
19766 DAG.RemoveDeadNode(Node);
19767 return ToResultReg.getNode();
19768 }
19769 }
19770
19772 for (unsigned i = 0; i < Node->getNumOperands(); ++i) {
19773 if (!isFrameIndexOp(Node->getOperand(i))) {
19774 Ops.push_back(Node->getOperand(i));
19775 continue;
19776 }
19777
19778 SDLoc DL(Node);
19779 Ops.push_back(SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL,
19780 Node->getOperand(i).getValueType(),
19781 Node->getOperand(i)),
19782 0));
19783 }
19784
19785 return DAG.UpdateNodeOperands(Node, Ops);
19786}
19787
19788/// Fold the instructions after selecting them.
19789/// Returns null if users were already updated.
19791 SelectionDAG &DAG) const {
19793 unsigned Opcode = Node->getMachineOpcode();
19794
19795 if (TII->isImage(Opcode) && !TII->get(Opcode).mayStore() &&
19796 !TII->isGather4(Opcode) &&
19797 AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::dmask)) {
19798 return adjustWritemask(Node, DAG);
19799 }
19800
19801 if (Opcode == AMDGPU::INSERT_SUBREG || Opcode == AMDGPU::REG_SEQUENCE) {
19803 return Node;
19804 }
19805
19806 switch (Opcode) {
19807 case AMDGPU::V_DIV_SCALE_F32_e64:
19808 case AMDGPU::V_DIV_SCALE_F64_e64: {
19809 // Satisfy the operand register constraint when one of the inputs is
19810 // undefined. Ordinarily each undef value will have its own implicit_def of
19811 // a vreg, so force these to use a single register.
19812 SDValue Src0 = Node->getOperand(1);
19813 SDValue Src1 = Node->getOperand(3);
19814 SDValue Src2 = Node->getOperand(5);
19815
19816 if ((Src0.isMachineOpcode() &&
19817 Src0.getMachineOpcode() != AMDGPU::IMPLICIT_DEF) &&
19818 (Src0 == Src1 || Src0 == Src2))
19819 break;
19820
19821 MVT VT = Src0.getValueType().getSimpleVT();
19822 const TargetRegisterClass *RC =
19823 getRegClassFor(VT, Src0.getNode()->isDivergent());
19824
19826 SDValue UndefReg = DAG.getRegister(MRI.createVirtualRegister(RC), VT);
19827
19828 SDValue ImpDef = DAG.getCopyToReg(DAG.getEntryNode(), SDLoc(Node), UndefReg,
19829 Src0, SDValue());
19830
19831 // src0 must be the same register as src1 or src2, even if the value is
19832 // undefined, so make sure we don't violate this constraint.
19833 if (Src0.isMachineOpcode() &&
19834 Src0.getMachineOpcode() == AMDGPU::IMPLICIT_DEF) {
19835 if (Src1.isMachineOpcode() &&
19836 Src1.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19837 Src0 = Src1;
19838 else if (Src2.isMachineOpcode() &&
19839 Src2.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19840 Src0 = Src2;
19841 else {
19842 assert(Src1.getMachineOpcode() == AMDGPU::IMPLICIT_DEF);
19843 Src0 = UndefReg;
19844 Src1 = UndefReg;
19845 }
19846 } else
19847 break;
19848
19850 Ops[1] = Src0;
19851 Ops[3] = Src1;
19852 Ops[5] = Src2;
19853 Ops.push_back(ImpDef.getValue(1));
19854 return DAG.getMachineNode(Opcode, SDLoc(Node), Node->getVTList(), Ops);
19855 }
19856 default:
19857 break;
19858 }
19859
19860 return Node;
19861}
19862
19863// Any MIMG instructions that use tfe or lwe require an initialization of the
19864// result register that will be written in the case of a memory access failure.
19865// The required code is also added to tie this init code to the result of the
19866// img instruction.
19869 const SIRegisterInfo &TRI = TII->getRegisterInfo();
19870 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
19871 MachineBasicBlock &MBB = *MI.getParent();
19872
19873 int DstIdx =
19874 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
19875 unsigned InitIdx = 0;
19876
19877 if (TII->isImage(MI)) {
19878 MachineOperand *TFE = TII->getNamedOperand(MI, AMDGPU::OpName::tfe);
19879 MachineOperand *LWE = TII->getNamedOperand(MI, AMDGPU::OpName::lwe);
19880 MachineOperand *D16 = TII->getNamedOperand(MI, AMDGPU::OpName::d16);
19881
19882 if (!TFE && !LWE) // intersect_ray
19883 return;
19884
19885 unsigned TFEVal = TFE ? TFE->getImm() : 0;
19886 unsigned LWEVal = LWE ? LWE->getImm() : 0;
19887 unsigned D16Val = D16 ? D16->getImm() : 0;
19888
19889 if (!TFEVal && !LWEVal)
19890 return;
19891
19892 // At least one of TFE or LWE are non-zero
19893 // We have to insert a suitable initialization of the result value and
19894 // tie this to the dest of the image instruction.
19895
19896 // Calculate which dword we have to initialize to 0.
19897 MachineOperand *MO_Dmask = TII->getNamedOperand(MI, AMDGPU::OpName::dmask);
19898
19899 // check that dmask operand is found.
19900 assert(MO_Dmask && "Expected dmask operand in instruction");
19901
19902 unsigned dmask = MO_Dmask->getImm();
19903 // Determine the number of active lanes taking into account the
19904 // Gather4 special case
19905 unsigned ActiveLanes = TII->isGather4(MI) ? 4 : llvm::popcount(dmask);
19906
19907 bool Packed = !Subtarget->hasUnpackedD16VMem();
19908
19909 InitIdx = D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1;
19910
19911 // Abandon attempt if the dst size isn't large enough
19912 // - this is in fact an error but this is picked up elsewhere and
19913 // reported correctly.
19914 const TargetRegisterClass *DstRC = TII->getRegClass(MI.getDesc(), DstIdx);
19915
19916 uint32_t DstSize = TRI.getRegSizeInBits(*DstRC) / 32;
19917 if (DstSize < InitIdx)
19918 return;
19919 } else if (TII->isMUBUF(MI) && AMDGPU::getMUBUFTfe(MI.getOpcode())) {
19920 const TargetRegisterClass *DstRC = TII->getRegClass(MI.getDesc(), DstIdx);
19921 InitIdx = TRI.getRegSizeInBits(*DstRC) / 32;
19922 } else {
19923 return;
19924 }
19925
19926 const DebugLoc &DL = MI.getDebugLoc();
19927
19928 // Create a register for the initialization value.
19929 Register PrevDst = MRI.cloneVirtualRegister(MI.getOperand(DstIdx).getReg());
19930 unsigned NewDst = 0; // Final initialized value will be in here
19931
19932 // If PRTStrictNull feature is enabled (the default) then initialize
19933 // all the result registers to 0, otherwise just the error indication
19934 // register (VGPRn+1)
19935 unsigned SizeLeft = Subtarget->usePRTStrictNull() ? InitIdx : 1;
19936 unsigned CurrIdx = Subtarget->usePRTStrictNull() ? 0 : (InitIdx - 1);
19937
19938 BuildMI(MBB, MI, DL, TII->get(AMDGPU::IMPLICIT_DEF), PrevDst);
19939 for (; SizeLeft; SizeLeft--, CurrIdx++) {
19940 NewDst = MRI.createVirtualRegister(TII->getOpRegClass(MI, DstIdx));
19941 // Initialize dword
19942 Register SubReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
19943 // clang-format off
19944 BuildMI(MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), SubReg)
19945 .addImm(0);
19946 // clang-format on
19947 // Insert into the super-reg
19948 BuildMI(MBB, MI, DL, TII->get(TargetOpcode::INSERT_SUBREG), NewDst)
19949 .addReg(PrevDst)
19950 .addReg(SubReg)
19952
19953 PrevDst = NewDst;
19954 }
19955
19956 // Add as an implicit operand
19957 MI.addOperand(MachineOperand::CreateReg(NewDst, false, true));
19958
19959 // Tie the just added implicit operand to the dst
19960 MI.tieOperands(DstIdx, MI.getNumOperands() - 1);
19961}
19962
19963/// Assign the register class depending on the number of
19964/// bits set in the writemask
19966 SDNode *Node) const {
19968
19969 MachineFunction *MF = MI.getMF();
19970 MachineRegisterInfo &MRI = MF->getRegInfo();
19971
19972 if (TII->isVOP3(MI.getOpcode())) {
19973 // Make sure constant bus requirements are respected.
19974 TII->legalizeOperandsVOP3(MRI, MI);
19975
19976 // Fix GFX950 v_pk_fma_f32 invalid op_sel by decomposing.
19977 if (MI.getOpcode() == AMDGPU::V_PK_FMA_F32 &&
19978 !TII->isLegalPkFMAF32OpSel(MI)) {
19979 TII->decomposePkFMAF32(MI, MRI);
19980 return;
19981 }
19982
19983 if (TII->isMAI(MI)) {
19984 // The ordinary src0, src1, src2 were legalized above.
19985 //
19986 // We have to also legalize the appended v_mfma_ld_scale_b32 operands,
19987 // as a separate instruction.
19988 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
19989 AMDGPU::OpName::scale_src0);
19990 if (Src0Idx != -1) {
19991 int Src1Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
19992 AMDGPU::OpName::scale_src1);
19993 if (TII->usesConstantBus(MRI, MI, Src0Idx) &&
19994 TII->usesConstantBus(MRI, MI, Src1Idx))
19995 TII->legalizeOpWithMove(MI, Src1Idx);
19996 }
19997 }
19998
19999 return;
20000 }
20001
20002 if (TII->isImage(MI))
20003 TII->enforceOperandRCAlignment(MI, AMDGPU::OpName::vaddr);
20004}
20005
20007 uint64_t Val) {
20008 SDValue K = DAG.getTargetConstant(Val, DL, MVT::i32);
20009 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, K), 0);
20010}
20011
20013 const SDLoc &DL,
20014 SDValue Ptr) const {
20016
20017 // Build the half of the subregister with the constants before building the
20018 // full 128-bit register. If we are building multiple resource descriptors,
20019 // this will allow CSEing of the 2-component register.
20020 const SDValue Ops0[] = {
20021 DAG.getTargetConstant(AMDGPU::SGPR_64RegClassID, DL, MVT::i32),
20022 buildSMovImm32(DAG, DL, 0),
20023 DAG.getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
20024 buildSMovImm32(DAG, DL, TII->getDefaultRsrcDataFormat() >> 32),
20025 DAG.getTargetConstant(AMDGPU::sub1, DL, MVT::i32)};
20026
20027 SDValue SubRegHi = SDValue(
20028 DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v2i32, Ops0), 0);
20029
20030 // Combine the constants and the pointer.
20031 const SDValue Ops1[] = {
20032 DAG.getTargetConstant(AMDGPU::SGPR_128RegClassID, DL, MVT::i32), Ptr,
20033 DAG.getTargetConstant(AMDGPU::sub0_sub1, DL, MVT::i32), SubRegHi,
20034 DAG.getTargetConstant(AMDGPU::sub2_sub3, DL, MVT::i32)};
20035
20036 return DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v4i32, Ops1);
20037}
20038
20039/// Return a resource descriptor with the 'Add TID' bit enabled
20040/// The TID (Thread ID) is multiplied by the stride value (bits [61:48]
20041/// of the resource descriptor) to create an offset, which is added to
20042/// the resource pointer.
20044 SDValue Ptr, uint32_t RsrcDword1,
20045 uint64_t RsrcDword2And3) const {
20046 SDValue PtrLo = DAG.getTargetExtractSubreg(AMDGPU::sub0, DL, MVT::i32, Ptr);
20047 SDValue PtrHi = DAG.getTargetExtractSubreg(AMDGPU::sub1, DL, MVT::i32, Ptr);
20048 if (RsrcDword1) {
20049 PtrHi = DAG.getNode(ISD::OR, DL, MVT::i32, PtrHi,
20050 DAG.getConstant(RsrcDword1, DL, MVT::i32));
20051 }
20052
20053 SDValue DataLo =
20054 buildSMovImm32(DAG, DL, RsrcDword2And3 & UINT64_C(0xFFFFFFFF));
20055 SDValue DataHi = buildSMovImm32(DAG, DL, RsrcDword2And3 >> 32);
20056
20057 const SDValue Ops[] = {
20058 DAG.getTargetConstant(AMDGPU::SGPR_128RegClassID, DL, MVT::i32),
20059 PtrLo,
20060 DAG.getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
20061 PtrHi,
20062 DAG.getTargetConstant(AMDGPU::sub1, DL, MVT::i32),
20063 DataLo,
20064 DAG.getTargetConstant(AMDGPU::sub2, DL, MVT::i32),
20065 DataHi,
20066 DAG.getTargetConstant(AMDGPU::sub3, DL, MVT::i32)};
20067
20068 return DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v4i32, Ops);
20069}
20070
20071//===----------------------------------------------------------------------===//
20072// SI Inline Assembly Support
20073//===----------------------------------------------------------------------===//
20074
20075std::pair<unsigned, const TargetRegisterClass *>
20077 StringRef Constraint,
20078 MVT VT) const {
20079 const SIRegisterInfo *TRI = static_cast<const SIRegisterInfo *>(TRI_);
20080
20081 const TargetRegisterClass *RC = nullptr;
20082 if (Constraint.size() == 1) {
20083 // Check if we cannot determine the bit size of the given value type. This
20084 // can happen, for example, in this situation where we have an empty struct
20085 // (size 0): `call void asm "", "v"({} poison)`-
20086 if (VT == MVT::Other)
20087 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
20088 const unsigned BitWidth = VT.getSizeInBits();
20089 switch (Constraint[0]) {
20090 default:
20091 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
20092 case 's':
20093 case 'r':
20094 switch (BitWidth) {
20095 case 16:
20096 RC = &AMDGPU::SReg_32RegClass;
20097 break;
20098 case 64:
20099 RC = &AMDGPU::SGPR_64RegClass;
20100 break;
20101 default:
20103 if (!RC)
20104 return std::pair(0U, nullptr);
20105 break;
20106 }
20107 break;
20108 case 'v':
20109 switch (BitWidth) {
20110 case 1:
20111 return std::pair(0U, nullptr);
20112 case 16:
20113 RC = Subtarget->useRealTrue16Insts() ? &AMDGPU::VGPR_16RegClass
20114 : &AMDGPU::VGPR_32_Lo256RegClass;
20115 break;
20116 default:
20117 RC = Subtarget->has1024AddressableVGPRs()
20118 ? TRI->getAlignedLo256VGPRClassForBitWidth(BitWidth)
20119 : TRI->getVGPRClassForBitWidth(BitWidth);
20120 if (!RC)
20121 return std::pair(0U, nullptr);
20122 break;
20123 }
20124 break;
20125 case 'a':
20126 if (!Subtarget->hasMAIInsts())
20127 break;
20128 switch (BitWidth) {
20129 case 1:
20130 return std::pair(0U, nullptr);
20131 case 16:
20132 RC = &AMDGPU::AGPR_32RegClass;
20133 break;
20134 default:
20135 RC = TRI->getAGPRClassForBitWidth(BitWidth);
20136 if (!RC)
20137 return std::pair(0U, nullptr);
20138 break;
20139 }
20140 break;
20141 }
20142 } else if (Constraint == "VA" && Subtarget->hasGFX90AInsts()) {
20143 const unsigned BitWidth = VT.getSizeInBits();
20144 switch (BitWidth) {
20145 case 16:
20146 RC = &AMDGPU::AV_32RegClass;
20147 break;
20148 default:
20149 RC = TRI->getVectorSuperClassForBitWidth(BitWidth);
20150 if (!RC)
20151 return std::pair(0U, nullptr);
20152 break;
20153 }
20154 }
20155
20156 // We actually support i128, i16 and f16 as inline parameters
20157 // even if they are not reported as legal
20158 if (RC && (isTypeLegal(VT) || VT.SimpleTy == MVT::i128 ||
20159 VT.SimpleTy == MVT::i16 || VT.SimpleTy == MVT::f16))
20160 return std::pair(0U, RC);
20161
20162 auto [Kind, Idx, NumRegs] = AMDGPU::parseAsmConstraintPhysReg(Constraint);
20163 if (Kind != '\0') {
20164 if (Kind == 'v') {
20165 RC = &AMDGPU::VGPR_32_Lo256RegClass;
20166 } else if (Kind == 's') {
20167 RC = &AMDGPU::SGPR_32RegClass;
20168 } else if (Kind == 'a') {
20169 RC = &AMDGPU::AGPR_32RegClass;
20170 }
20171
20172 if (RC) {
20173 if (NumRegs > 1) {
20174 if (Idx >= RC->getNumRegs() || Idx + NumRegs - 1 >= RC->getNumRegs())
20175 return std::pair(0U, nullptr);
20176
20177 uint32_t Width = NumRegs * 32;
20178 // Prohibit constraints for register ranges with a width that does not
20179 // match the required type.
20180 if (VT.SimpleTy != MVT::Other && Width != VT.getSizeInBits())
20181 return std::pair(0U, nullptr);
20182
20183 MCRegister Reg = RC->getRegister(Idx);
20185 RC = TRI->getVGPRClassForBitWidth(Width);
20186 else if (SIRegisterInfo::isSGPRClass(RC))
20187 RC = TRI->getSGPRClassForBitWidth(Width);
20188 else if (SIRegisterInfo::isAGPRClass(RC))
20189 RC = TRI->getAGPRClassForBitWidth(Width);
20190 if (RC) {
20191 Reg = TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
20192 if (!Reg) {
20193 // The register class does not contain the requested register,
20194 // e.g., because it is an SGPR pair that would violate alignment
20195 // requirements.
20196 return std::pair(0U, nullptr);
20197 }
20198 return std::pair(Reg, RC);
20199 }
20200 }
20201
20202 // Reject types that do not fit a single 32-bit register: any scalar wider
20203 // than 32 bits, or a vector that is not exactly 32 bits.
20204 if (VT.SimpleTy != MVT::Other &&
20205 (VT.getSizeInBits() > 32 ||
20206 (VT.isVector() && VT.getSizeInBits() != 32)))
20207 return std::pair(0U, nullptr);
20208 if (RC && Idx < RC->getNumRegs())
20209 return std::pair(RC->getRegister(Idx), RC);
20210 return std::pair(0U, nullptr);
20211 }
20212 }
20213
20214 auto Ret = TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
20215 if (Ret.first) {
20216 Ret.second = TRI->getPhysRegBaseClass(Ret.first);
20217 if (!Subtarget->useRealTrue16Insts() &&
20218 TRI->getRegSizeInBits(*Ret.second) == 16)
20219 return std::pair(0U, nullptr);
20220 }
20221
20222 return Ret;
20223}
20224
20225static bool isImmConstraint(StringRef Constraint) {
20226 if (Constraint.size() == 1) {
20227 switch (Constraint[0]) {
20228 default:
20229 break;
20230 case 'I':
20231 case 'J':
20232 case 'A':
20233 case 'B':
20234 case 'C':
20235 return true;
20236 }
20237 } else if (Constraint == "DA" || Constraint == "DB") {
20238 return true;
20239 }
20240 return false;
20241}
20242
20245 if (Constraint.size() == 1) {
20246 switch (Constraint[0]) {
20247 default:
20248 break;
20249 case 's':
20250 case 'v':
20251 case 'a':
20252 return C_RegisterClass;
20253 }
20254 } else if (Constraint.size() == 2) {
20255 if (Constraint == "VA")
20256 return C_RegisterClass;
20257 }
20258 if (isImmConstraint(Constraint)) {
20259 return C_Other;
20260 }
20261 return TargetLowering::getConstraintType(Constraint);
20262}
20263
20264static uint64_t clearUnusedBits(uint64_t Val, unsigned Size) {
20266 Val = Val & maskTrailingOnes<uint64_t>(Size);
20267 }
20268 return Val;
20269}
20270
20272 StringRef Constraint,
20273 std::vector<SDValue> &Ops,
20274 SelectionDAG &DAG) const {
20275 if (isImmConstraint(Constraint)) {
20276 uint64_t Val;
20277 if (getAsmOperandConstVal(Op, Val) &&
20278 checkAsmConstraintVal(Op, Constraint, Val)) {
20279 Val = clearUnusedBits(Val, Op.getScalarValueSizeInBits());
20280 Ops.push_back(DAG.getTargetConstant(Val, SDLoc(Op), MVT::i64));
20281 }
20282 } else {
20284 }
20285}
20286
20288 unsigned Size = Op.getScalarValueSizeInBits();
20289 if (Size > 64)
20290 return false;
20291
20292 if (Size == 16 && !Subtarget->has16BitInsts())
20293 return false;
20294
20296 Val = C->getSExtValue();
20297 return true;
20298 }
20300 Val = C->getValueAPF().bitcastToAPInt().getSExtValue();
20301 return true;
20302 }
20304 if (Size != 16 || Op.getNumOperands() != 2)
20305 return false;
20306 if (Op.getOperand(0).isUndef() || Op.getOperand(1).isUndef())
20307 return false;
20308 if (ConstantSDNode *C = V->getConstantSplatNode()) {
20309 Val = C->getSExtValue();
20310 return true;
20311 }
20312 if (ConstantFPSDNode *C = V->getConstantFPSplatNode()) {
20313 Val = C->getValueAPF().bitcastToAPInt().getSExtValue();
20314 return true;
20315 }
20316 }
20317
20318 return false;
20319}
20320
20322 uint64_t Val) const {
20323 if (Constraint.size() == 1) {
20324 switch (Constraint[0]) {
20325 case 'I':
20327 case 'J':
20328 return isInt<16>(Val);
20329 case 'A':
20330 return checkAsmConstraintValA(Op, Val);
20331 case 'B':
20332 return isInt<32>(Val);
20333 case 'C':
20334 return isUInt<32>(clearUnusedBits(Val, Op.getScalarValueSizeInBits())) ||
20336 default:
20337 break;
20338 }
20339 } else if (Constraint.size() == 2) {
20340 if (Constraint == "DA") {
20341 int64_t HiBits = static_cast<int32_t>(Val >> 32);
20342 int64_t LoBits = static_cast<int32_t>(Val);
20343 return checkAsmConstraintValA(Op, HiBits, 32) &&
20344 checkAsmConstraintValA(Op, LoBits, 32);
20345 }
20346 if (Constraint == "DB") {
20347 return true;
20348 }
20349 }
20350 llvm_unreachable("Invalid asm constraint");
20351}
20352
20354 unsigned MaxSize) const {
20355 unsigned Size = std::min<unsigned>(Op.getScalarValueSizeInBits(), MaxSize);
20356 bool HasInv2Pi = Subtarget->hasInv2PiInlineImm();
20357 if (Size == 16) {
20358 MVT VT = Op.getSimpleValueType();
20359 switch (VT.SimpleTy) {
20360 default:
20361 return false;
20362 case MVT::i16:
20363 return AMDGPU::isInlinableLiteralI16(Val, HasInv2Pi);
20364 case MVT::f16:
20365 return AMDGPU::isInlinableLiteralFP16(Val, HasInv2Pi);
20366 case MVT::bf16:
20367 return AMDGPU::isInlinableLiteralBF16(Val, HasInv2Pi);
20368 case MVT::v2i16:
20369 return AMDGPU::getInlineEncodingV2I16(Val).has_value();
20370 case MVT::v2f16:
20371 return AMDGPU::getInlineEncodingV2F16(Val).has_value();
20372 case MVT::v2bf16:
20373 return AMDGPU::getInlineEncodingV2BF16(Val).has_value();
20374 }
20375 }
20376 if ((Size == 32 && AMDGPU::isInlinableLiteral32(Val, HasInv2Pi)) ||
20377 (Size == 64 && AMDGPU::isInlinableLiteral64(Val, HasInv2Pi)))
20378 return true;
20379 return false;
20380}
20381
20382static int getAlignedAGPRClassID(unsigned UnalignedClassID) {
20383 switch (UnalignedClassID) {
20384 case AMDGPU::VReg_64RegClassID:
20385 return AMDGPU::VReg_64_Align2RegClassID;
20386 case AMDGPU::VReg_96RegClassID:
20387 return AMDGPU::VReg_96_Align2RegClassID;
20388 case AMDGPU::VReg_128RegClassID:
20389 return AMDGPU::VReg_128_Align2RegClassID;
20390 case AMDGPU::VReg_160RegClassID:
20391 return AMDGPU::VReg_160_Align2RegClassID;
20392 case AMDGPU::VReg_192RegClassID:
20393 return AMDGPU::VReg_192_Align2RegClassID;
20394 case AMDGPU::VReg_224RegClassID:
20395 return AMDGPU::VReg_224_Align2RegClassID;
20396 case AMDGPU::VReg_256RegClassID:
20397 return AMDGPU::VReg_256_Align2RegClassID;
20398 case AMDGPU::VReg_288RegClassID:
20399 return AMDGPU::VReg_288_Align2RegClassID;
20400 case AMDGPU::VReg_320RegClassID:
20401 return AMDGPU::VReg_320_Align2RegClassID;
20402 case AMDGPU::VReg_352RegClassID:
20403 return AMDGPU::VReg_352_Align2RegClassID;
20404 case AMDGPU::VReg_384RegClassID:
20405 return AMDGPU::VReg_384_Align2RegClassID;
20406 case AMDGPU::VReg_512RegClassID:
20407 return AMDGPU::VReg_512_Align2RegClassID;
20408 case AMDGPU::VReg_1024RegClassID:
20409 return AMDGPU::VReg_1024_Align2RegClassID;
20410 case AMDGPU::AReg_64RegClassID:
20411 return AMDGPU::AReg_64_Align2RegClassID;
20412 case AMDGPU::AReg_96RegClassID:
20413 return AMDGPU::AReg_96_Align2RegClassID;
20414 case AMDGPU::AReg_128RegClassID:
20415 return AMDGPU::AReg_128_Align2RegClassID;
20416 case AMDGPU::AReg_160RegClassID:
20417 return AMDGPU::AReg_160_Align2RegClassID;
20418 case AMDGPU::AReg_192RegClassID:
20419 return AMDGPU::AReg_192_Align2RegClassID;
20420 case AMDGPU::AReg_256RegClassID:
20421 return AMDGPU::AReg_256_Align2RegClassID;
20422 case AMDGPU::AReg_512RegClassID:
20423 return AMDGPU::AReg_512_Align2RegClassID;
20424 case AMDGPU::AReg_1024RegClassID:
20425 return AMDGPU::AReg_1024_Align2RegClassID;
20426 default:
20427 return -1;
20428 }
20429}
20430
20431// Figure out which registers should be reserved for stack access. Only after
20432// the function is legalized do we know all of the non-spill stack objects or if
20433// calls are present.
20435 MachineRegisterInfo &MRI = MF.getRegInfo();
20437 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
20438 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
20439 const SIInstrInfo *TII = ST.getInstrInfo();
20440
20441 if (Info->isEntryFunction()) {
20442 // Callable functions have fixed registers used for stack access.
20444 }
20445
20446 // TODO: Move this logic to getReservedRegs()
20447 // Reserve the SGPR(s) to save/restore EXEC for WWM spill/copy handling.
20448 unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF);
20449 Register SReg = ST.isWave32()
20450 ? AMDGPU::SGPR_32RegClass.getRegister(MaxNumSGPRs - 1)
20451 : TRI->getAlignedHighSGPRForRC(MF, /*Align=*/2,
20452 &AMDGPU::SGPR_64RegClass);
20453 Info->setSGPRForEXECCopy(SReg);
20454
20455 assert(!TRI->isSubRegister(Info->getScratchRSrcReg(),
20456 Info->getStackPtrOffsetReg()));
20457 if (Info->getStackPtrOffsetReg() != AMDGPU::SP_REG)
20458 MRI.replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
20459
20460 // We need to worry about replacing the default register with itself in case
20461 // of MIR testcases missing the MFI.
20462 if (Info->getScratchRSrcReg() != AMDGPU::PRIVATE_RSRC_REG)
20463 MRI.replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
20464
20465 if (Info->getFrameOffsetReg() != AMDGPU::FP_REG)
20466 MRI.replaceRegWith(AMDGPU::FP_REG, Info->getFrameOffsetReg());
20467
20468 Info->limitOccupancy(MF);
20469
20470 if (ST.isWave32() && !MF.empty()) {
20471 for (auto &MBB : MF) {
20472 for (auto &MI : MBB) {
20473 TII->fixImplicitOperands(MI);
20474 }
20475 }
20476 }
20477
20478 // FIXME: This is a hack to fixup AGPR classes to use the properly aligned
20479 // classes if required. Ideally the register class constraints would differ
20480 // per-subtarget, but there's no easy way to achieve that right now. This is
20481 // not a problem for VGPRs because the correctly aligned VGPR class is implied
20482 // from using them as the register class for legal types.
20483 if (ST.needsAlignedVGPRs()) {
20484 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
20485 const Register Reg = Register::index2VirtReg(I);
20486 const TargetRegisterClass *RC = MRI.getRegClassOrNull(Reg);
20487 if (!RC)
20488 continue;
20489 int NewClassID = getAlignedAGPRClassID(RC->getID());
20490 if (NewClassID != -1)
20491 MRI.setRegClass(Reg, TRI->getRegClass(NewClassID));
20492 }
20493 }
20494
20496}
20497
20500 const APInt &DemandedElts,
20501 const SelectionDAG &DAG,
20502 unsigned Depth) const {
20503 Known.resetAll();
20504 unsigned Opc = Op.getOpcode();
20505 switch (Opc) {
20507 unsigned IID = Op.getConstantOperandVal(0);
20508 switch (IID) {
20509 case Intrinsic::amdgcn_mbcnt_lo:
20510 case Intrinsic::amdgcn_mbcnt_hi: {
20511 const GCNSubtarget &ST =
20513 // Wave64 mbcnt_lo returns at most 32 + src1. Otherwise these return at
20514 // most 31 + src1.
20515 Known.Zero.setBitsFrom(
20516 IID == Intrinsic::amdgcn_mbcnt_lo ? ST.getWavefrontSizeLog2() : 5);
20517 KnownBits Known2 = DAG.computeKnownBits(Op.getOperand(2), Depth + 1);
20518 Known = KnownBits::add(Known, Known2);
20519 return;
20520 }
20521 }
20522 break;
20523 }
20524 }
20526 Op, Known, DemandedElts, DAG, Depth);
20527}
20528
20530 KnownBits &Known, const MachineFunction &MF, Align Alignment) const {
20532
20533 // Set the high bits to zero based on the maximum allowed scratch size per
20534 // wave. We can't use vaddr in MUBUF instructions if we don't know the address
20535 // calculation won't overflow, so assume the sign bit is never set.
20536 Known.Zero.setHighBits(getSubtarget()->getKnownHighZeroBitsForFrameIndex());
20537}
20538
20541 unsigned Dim) {
20542 unsigned MaxValue =
20543 ST.getMaxWorkitemID(VT.getMachineFunction().getFunction(), Dim);
20544 Known.Zero.setHighBits(llvm::countl_zero(MaxValue));
20545}
20546
20548 KnownBits &Known, const APInt &DemandedElts,
20549 unsigned BFEWidth, bool SExt, unsigned Depth) {
20551 const MachineOperand &Src1 = MI.getOperand(2);
20552
20553 unsigned Src1Cst = 0;
20554 if (Src1.isImm()) {
20555 Src1Cst = Src1.getImm();
20556 } else if (Src1.isReg()) {
20557 auto Cst = getIConstantVRegValWithLookThrough(Src1.getReg(), MRI);
20558 if (!Cst)
20559 return;
20560 Src1Cst = Cst->Value.getZExtValue();
20561 } else {
20562 return;
20563 }
20564
20565 // Offset is at bits [4:0] for 32 bit, [5:0] for 64 bit.
20566 // Width is always [22:16].
20567 const unsigned Offset =
20568 Src1Cst & maskTrailingOnes<unsigned>((BFEWidth == 32) ? 5 : 6);
20569 const unsigned Width = (Src1Cst >> 16) & maskTrailingOnes<unsigned>(6);
20570
20571 if (Width >= BFEWidth) // Ill-formed.
20572 return;
20573
20574 VT.computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, DemandedElts,
20575 Depth + 1);
20576
20577 Known = Known.extractBits(Width, Offset);
20578
20579 if (SExt)
20580 Known = Known.sext(BFEWidth);
20581 else
20582 Known = Known.zext(BFEWidth);
20583}
20584
20587 const APInt &DemandedElts, const MachineRegisterInfo &MRI,
20588 unsigned Depth) const {
20589 Known.resetAll();
20590 const MachineInstr *MI = MRI.getVRegDef(R);
20591 switch (MI->getOpcode()) {
20592 case AMDGPU::S_BFE_I32:
20593 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/32,
20594 /*SExt=*/true, Depth);
20595 case AMDGPU::S_BFE_U32:
20596 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/32,
20597 /*SExt=*/false, Depth);
20598 case AMDGPU::S_BFE_I64:
20599 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/64,
20600 /*SExt=*/true, Depth);
20601 case AMDGPU::S_BFE_U64:
20602 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/64,
20603 /*SExt=*/false, Depth);
20604 case AMDGPU::G_INTRINSIC:
20605 case AMDGPU::G_INTRINSIC_CONVERGENT: {
20606 Intrinsic::ID IID = cast<GIntrinsic>(MI)->getIntrinsicID();
20607 switch (IID) {
20608 case Intrinsic::amdgcn_workitem_id_x:
20610 break;
20611 case Intrinsic::amdgcn_workitem_id_y:
20613 break;
20614 case Intrinsic::amdgcn_workitem_id_z:
20616 break;
20617 case Intrinsic::amdgcn_mbcnt_lo:
20618 case Intrinsic::amdgcn_mbcnt_hi: {
20619 // Wave64 mbcnt_lo returns at most 32 + src1. Otherwise these return at
20620 // most 31 + src1.
20621 Known.Zero.setBitsFrom(IID == Intrinsic::amdgcn_mbcnt_lo
20622 ? getSubtarget()->getWavefrontSizeLog2()
20623 : 5);
20624 KnownBits Known2;
20625 VT.computeKnownBitsImpl(MI->getOperand(3).getReg(), Known2, DemandedElts,
20626 Depth + 1);
20627 Known = KnownBits::add(Known, Known2);
20628 break;
20629 }
20630 case Intrinsic::amdgcn_groupstaticsize: {
20631 // We can report everything over the maximum size as 0. We can't report
20632 // based on the actual size because we don't know if it's accurate or not
20633 // at any given point.
20634 Known.Zero.setHighBits(
20635 llvm::countl_zero(getSubtarget()->getAddressableLocalMemorySize()));
20636 break;
20637 }
20638 case Intrinsic::amdgcn_readfirstlane:
20639 case Intrinsic::amdgcn_readlane: {
20640 // Result is the data operand's value from some lane.
20641 VT.computeKnownBitsImpl(MI->getOperand(2).getReg(), Known, DemandedElts,
20642 Depth + 1);
20643 break;
20644 }
20645 }
20646 break;
20647 }
20648 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
20649 Known.Zero.setHighBits(24);
20650 break;
20651 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
20652 Known.Zero.setHighBits(16);
20653 break;
20654 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
20655 // G_AMDGPU_COPY_SCC_VCC converts a uniform boolean in VCC to SGPR s32,
20656 // producing exactly 0 or 1.
20657 Known.Zero.setHighBits(Known.getBitWidth() - 1);
20658 break;
20659 case AMDGPU::G_AMDGPU_SMED3:
20660 case AMDGPU::G_AMDGPU_UMED3: {
20661 auto [Dst, Src0, Src1, Src2] = MI->getFirst4Regs();
20662
20663 KnownBits Known2;
20664 VT.computeKnownBitsImpl(Src2, Known2, DemandedElts, Depth + 1);
20665 if (Known2.isUnknown())
20666 break;
20667
20668 KnownBits Known1;
20669 VT.computeKnownBitsImpl(Src1, Known1, DemandedElts, Depth + 1);
20670 if (Known1.isUnknown())
20671 break;
20672
20673 KnownBits Known0;
20674 VT.computeKnownBitsImpl(Src0, Known0, DemandedElts, Depth + 1);
20675 if (Known0.isUnknown())
20676 break;
20677
20678 // TODO: Handle LeadZero/LeadOne from UMIN/UMAX handling.
20679 Known.Zero = Known0.Zero & Known1.Zero & Known2.Zero;
20680 Known.One = Known0.One & Known1.One & Known2.One;
20681 break;
20682 }
20683 }
20684}
20685
20688 unsigned Depth) const {
20689 const MachineInstr *MI = MRI.getVRegDef(R);
20690 if (auto *GI = dyn_cast<GIntrinsic>(MI)) {
20691 // FIXME: Can this move to generic code? What about the case where the call
20692 // site specifies a lower alignment?
20693 Intrinsic::ID IID = GI->getIntrinsicID();
20695 AttributeList Attrs =
20696 Intrinsic::getAttributes(Ctx, IID, Intrinsic::getType(Ctx, IID));
20697 if (MaybeAlign RetAlign = Attrs.getRetAlignment())
20698 return *RetAlign;
20699 }
20700 return Align(1);
20701}
20702
20704 MachineLoop *ML, const MachineBasicBlock *BlockToAlign) const {
20706 const Align CacheLineAlign = Align(64);
20707
20708 // GFX950: Prevent an 8-byte instruction at the block being aligned from being
20709 // split by the 32-byte instruction fetch window boundary. This avoids a
20710 // significant fetch delay after a backward branch. We use 32-byte alignment
20711 // with max padding of 4 bytes (one s_nop), see
20712 // getMaxPermittedBytesForAlignment().
20713 if (ML && !DisableLoopAlignment &&
20714 getSubtarget()->hasLoopHeadInstSplitSensitivity()) {
20715 // Loop rotation can make the backedge destination a block other than the
20716 // LoopInfo header, so prefer the block the caller is actually aligning.
20717 if (!BlockToAlign)
20718 BlockToAlign = ML->getHeader();
20719 // Respect user-specified or previously set alignment.
20720 if (BlockToAlign->getAlignment() != PrefAlign)
20721 return BlockToAlign->getAlignment();
20722 if (needsFetchWindowAlignment(*BlockToAlign))
20723 return Align(32);
20724 }
20725
20726 // Pre-GFX10 target did not benefit from loop alignment
20727 if (!ML || DisableLoopAlignment || !getSubtarget()->hasInstPrefetch() ||
20728 getSubtarget()->hasInstFwdPrefetchBug())
20729 return PrefAlign;
20730
20731 // On GFX10 I$ is 4 x 64 bytes cache lines.
20732 // By default prefetcher keeps one cache line behind and reads two ahead.
20733 // We can modify it with S_INST_PREFETCH for larger loops to have two lines
20734 // behind and one ahead.
20735 // Therefor we can benefit from aligning loop headers if loop fits 192 bytes.
20736 // If loop fits 64 bytes it always spans no more than two cache lines and
20737 // does not need an alignment.
20738 // Else if loop is less or equal 128 bytes we do not need to modify prefetch,
20739 // Else if loop is less or equal 192 bytes we need two lines behind.
20740
20742 const MachineBasicBlock *Header = ML->getHeader();
20743 if (Header->getAlignment() != PrefAlign)
20744 return Header->getAlignment(); // Already processed.
20745
20746 unsigned LoopSize = 0;
20747 for (const MachineBasicBlock *MBB : ML->blocks()) {
20748 // If inner loop block is aligned assume in average half of the alignment
20749 // size to be added as nops.
20750 if (MBB != Header)
20751 LoopSize += MBB->getAlignment().value() / 2;
20752
20753 for (const MachineInstr &MI : *MBB) {
20754 LoopSize += TII->getInstSizeInBytes(MI);
20755 if (LoopSize > 192)
20756 return PrefAlign;
20757 }
20758 }
20759
20760 if (LoopSize <= 64)
20761 return PrefAlign;
20762
20763 if (LoopSize <= 128)
20764 return CacheLineAlign;
20765
20766 // If any of parent loops is surrounded by prefetch instructions do not
20767 // insert new for inner loop, which would reset parent's settings.
20768 for (MachineLoop *P = ML->getParentLoop(); P; P = P->getParentLoop()) {
20769 if (MachineBasicBlock *Exit = P->getExitBlock()) {
20770 auto I = Exit->getFirstNonDebugInstr();
20771 if (I != Exit->end() && I->getOpcode() == AMDGPU::S_INST_PREFETCH)
20772 return CacheLineAlign;
20773 }
20774 }
20775
20776 MachineBasicBlock *Pre = ML->getLoopPreheader();
20777 MachineBasicBlock *Exit = ML->getExitBlock();
20778
20779 if (Pre && Exit) {
20780 auto PreTerm = Pre->getFirstTerminator();
20781 if (PreTerm == Pre->begin() ||
20782 std::prev(PreTerm)->getOpcode() != AMDGPU::S_INST_PREFETCH)
20783 BuildMI(*Pre, PreTerm, DebugLoc(), TII->get(AMDGPU::S_INST_PREFETCH))
20784 .addImm(1); // prefetch 2 lines behind PC
20785
20786 auto ExitHead = Exit->getFirstNonDebugInstr();
20787 if (ExitHead == Exit->end() ||
20788 ExitHead->getOpcode() != AMDGPU::S_INST_PREFETCH)
20789 BuildMI(*Exit, ExitHead, DebugLoc(), TII->get(AMDGPU::S_INST_PREFETCH))
20790 .addImm(2); // prefetch 1 line behind PC
20791 }
20792
20793 return CacheLineAlign;
20794}
20795
20797 MachineBasicBlock *MBB) const {
20798 // GFX950: Limit padding to 4 bytes (one s_nop) for blocks where an 8-byte
20799 // instruction could be split by the 32-byte fetch window boundary.
20800 // See getPrefLoopAlignment() for context.
20801 if (needsFetchWindowAlignment(*MBB))
20802 return 4;
20804}
20805
20806bool SITargetLowering::needsFetchWindowAlignment(
20807 const MachineBasicBlock &MBB) const {
20808 if (!getSubtarget()->hasLoopHeadInstSplitSensitivity())
20809 return false;
20811 for (const MachineInstr &MI : MBB) {
20812 if (MI.isMetaInstruction())
20813 continue;
20814 // Instructions larger than 4 bytes can be split by a 32-byte boundary.
20815 return TII->getInstSizeInBytes(MI) > 4;
20816 }
20817 return false;
20818}
20819
20820[[maybe_unused]]
20821static bool isCopyFromRegOfInlineAsm(const SDNode *N) {
20822 assert(N->getOpcode() == ISD::CopyFromReg);
20823 do {
20824 // Follow the chain until we find an INLINEASM node.
20825 N = N->getOperand(0).getNode();
20826 if (N->getOpcode() == ISD::INLINEASM || N->getOpcode() == ISD::INLINEASM_BR)
20827 return true;
20828 } while (N->getOpcode() == ISD::CopyFromReg);
20829 return false;
20830}
20831
20834 UniformityInfo *UA) const {
20835 switch (N->getOpcode()) {
20836 case ISD::CopyFromReg: {
20837 const RegisterSDNode *R = cast<RegisterSDNode>(N->getOperand(1));
20838 const MachineRegisterInfo &MRI = FLI->MF->getRegInfo();
20839 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
20840 Register Reg = R->getReg();
20841
20842 // FIXME: Why does this need to consider isLiveIn?
20843 if (Reg.isPhysical() || MRI.isLiveIn(Reg))
20844 return !TRI->isSGPRReg(MRI, Reg);
20845
20846 if (const Value *V = FLI->getValueFromVirtualReg(R->getReg()))
20847 return UA->isDivergentAtDef(V);
20848
20850 return !TRI->isSGPRReg(MRI, Reg);
20851 }
20852 case ISD::LOAD: {
20853 const LoadSDNode *L = cast<LoadSDNode>(N);
20854 unsigned AS = L->getAddressSpace();
20855 // A flat load may access private memory.
20857 }
20858 case ISD::CALLSEQ_END:
20859 return true;
20861 return AMDGPU::isIntrinsicSourceOfDivergence(N->getConstantOperandVal(0));
20863 return AMDGPU::isIntrinsicSourceOfDivergence(N->getConstantOperandVal(1));
20864 case AMDGPUISD::ATOMIC_CMP_SWAP:
20865 case AMDGPUISD::BUFFER_ATOMIC_SWAP:
20866 case AMDGPUISD::BUFFER_ATOMIC_ADD:
20867 case AMDGPUISD::BUFFER_ATOMIC_SUB:
20868 case AMDGPUISD::BUFFER_ATOMIC_SMIN:
20869 case AMDGPUISD::BUFFER_ATOMIC_UMIN:
20870 case AMDGPUISD::BUFFER_ATOMIC_SMAX:
20871 case AMDGPUISD::BUFFER_ATOMIC_UMAX:
20872 case AMDGPUISD::BUFFER_ATOMIC_AND:
20873 case AMDGPUISD::BUFFER_ATOMIC_OR:
20874 case AMDGPUISD::BUFFER_ATOMIC_XOR:
20875 case AMDGPUISD::BUFFER_ATOMIC_INC:
20876 case AMDGPUISD::BUFFER_ATOMIC_DEC:
20877 case AMDGPUISD::BUFFER_ATOMIC_CMPSWAP:
20878 case AMDGPUISD::BUFFER_ATOMIC_FADD:
20879 case AMDGPUISD::BUFFER_ATOMIC_FMIN:
20880 case AMDGPUISD::BUFFER_ATOMIC_FMAX:
20881 // Target-specific read-modify-write atomics are sources of divergence.
20882 return true;
20883 default:
20884 if (auto *A = dyn_cast<AtomicSDNode>(N)) {
20885 // Generic read-modify-write atomics are sources of divergence.
20886 return A->readMem() && A->writeMem();
20887 }
20888 return false;
20889 }
20890}
20891
20893 EVT VT) const {
20894 switch (VT.getScalarType().getSimpleVT().SimpleTy) {
20895 case MVT::f32:
20897 case MVT::f64:
20898 case MVT::f16:
20900 default:
20901 return false;
20902 }
20903}
20904
20906 LLT Ty, const MachineFunction &MF) const {
20907 switch (Ty.getScalarSizeInBits()) {
20908 case 32:
20909 return !denormalModeIsFlushAllF32(MF);
20910 case 64:
20911 case 16:
20912 return !denormalModeIsFlushAllF64F16(MF);
20913 default:
20914 return false;
20915 }
20916}
20917
20919 const APInt &DemandedElts,
20920 const SelectionDAG &DAG,
20921 bool SNaN,
20922 unsigned Depth) const {
20923 if (Op.getOpcode() == AMDGPUISD::CLAMP) {
20924 const MachineFunction &MF = DAG.getMachineFunction();
20926
20927 if (Info->getMode().DX10Clamp)
20928 return true; // Clamped to 0.
20929 return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1);
20930 }
20931
20933 DAG, SNaN, Depth);
20934}
20935
20936namespace {
20937
20938/// Why a floating-point atomic instruction which may flush denormals is
20939/// acceptable.
20940enum class AtomicFlushDenormalReason {
20941 Native,
20942 IEEE,
20943 IgnoreDenormalMode,
20944 FunctionFlushesDenormals
20945};
20946
20947/// Why a native floating-point atomic instruction is acceptable for a global
20948/// memory address.
20949enum class GlobalFPAtomicLegality {
20950 Illegal,
20951 AgentScopeFineGrainedRemoteMemory,
20952 EmulatedSystemScope,
20953 NoRemoteMemory,
20954 NoFineGrainedMemory
20955};
20956
20957} // end anonymous namespace
20958
20959// On older subtargets, global FP atomic instructions have a hardcoded FP mode
20960// and do not support FP32 denormals, and only support v2f16/f64 denormals.
20961static AtomicFlushDenormalReason
20963 if (RMW->hasMetadata(LLVMContext::MD_atomic_ignore_denormal_mode))
20964 return AtomicFlushDenormalReason::IgnoreDenormalMode;
20965
20966 const fltSemantics &Flt = RMW->getType()->getScalarType()->getFltSemantics();
20967 auto DenormMode = RMW->getFunction()->getDenormalMode(Flt);
20968 return DenormMode == DenormalMode::getPreserveSign()
20969 ? AtomicFlushDenormalReason::FunctionFlushesDenormals
20970 : AtomicFlushDenormalReason::IEEE;
20971}
20972
20973static OptimizationRemark
20975 GlobalFPAtomicLegality MemLegality,
20976 AtomicFlushDenormalReason DenormReason) {
20977 LLVMContext &Ctx = RMW->getContext();
20978 StringRef MemScope = Ctx.getSyncScopeName(RMW->getSyncScopeID()).value_or("");
20979 if (MemScope.empty())
20980 MemScope = "system";
20981
20982 OptimizationRemark R(DEBUG_TYPE, "Passed", RMW);
20983 R << "hardware instruction generated for atomic "
20984 << ore::NV("Operation", RMW->getOperationName(RMW->getOperation()))
20985 << " at " << ore::NV("SyncScope", MemScope) << " scope since ";
20986
20987 switch (MemLegality) {
20988 case GlobalFPAtomicLegality::AgentScopeFineGrainedRemoteMemory:
20989 R << "fine-grained remote memory atomics work below system scope";
20990 break;
20991 case GlobalFPAtomicLegality::EmulatedSystemScope:
20992 R << "system scope atomics are emulated in hardware";
20993 break;
20994 case GlobalFPAtomicLegality::NoRemoteMemory:
20995 R << "memory is not remote (!amdgpu.no.remote.memory)";
20996 break;
20997 case GlobalFPAtomicLegality::NoFineGrainedMemory:
20998 R << "memory is not fine-grained (!amdgpu.no.fine.grained.memory)";
20999 break;
21000 case GlobalFPAtomicLegality::Illegal:
21001 llvm_unreachable("remark for illegal atomic");
21002 }
21003
21004 switch (DenormReason) {
21005 case AtomicFlushDenormalReason::Native:
21006 break;
21007 case AtomicFlushDenormalReason::IgnoreDenormalMode:
21008 R << ", and denormals may be flushed (!atomic.ignore.denormal.mode)";
21009 break;
21010 case AtomicFlushDenormalReason::FunctionFlushesDenormals:
21011 R << ", and the floating-point environment flushes denormals";
21012 break;
21013 case AtomicFlushDenormalReason::IEEE:
21014 llvm_unreachable("remark for illegal atomic");
21015 }
21016
21017 return R;
21018}
21019
21020static bool isV2F16OrV2BF16(Type *Ty) {
21021 if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
21022 Type *EltTy = VT->getElementType();
21023 return VT->getNumElements() == 2 &&
21024 (EltTy->isHalfTy() || EltTy->isBFloatTy());
21025 }
21026
21027 return false;
21028}
21029
21030static bool isV2F16(Type *Ty) {
21032 return VT && VT->getNumElements() == 2 && VT->getElementType()->isHalfTy();
21033}
21034
21035static bool isV2BF16(Type *Ty) {
21037 return VT && VT->getNumElements() == 2 && VT->getElementType()->isBFloatTy();
21038}
21039
21040/// \return true if atomicrmw integer ops work for the type.
21041static bool isAtomicRMWLegalIntTy(Type *Ty) {
21042 if (auto *IT = dyn_cast<IntegerType>(Ty)) {
21043 unsigned BW = IT->getBitWidth();
21044 return BW == 32 || BW == 64;
21045 }
21046
21047 return false;
21048}
21049
21050/// \return true if this atomicrmw xchg type can be selected.
21051static bool isAtomicRMWLegalXChgTy(const AtomicRMWInst *RMW) {
21052 Type *Ty = RMW->getType();
21053 if (isAtomicRMWLegalIntTy(Ty))
21054 return true;
21055
21056 if (PointerType *PT = dyn_cast<PointerType>(Ty)) {
21057 const DataLayout &DL = RMW->getFunction()->getDataLayout();
21058 unsigned BW = DL.getPointerSizeInBits(PT->getAddressSpace());
21059 return BW == 32 || BW == 64;
21060 }
21061
21062 if (Ty->isFloatTy() || Ty->isDoubleTy())
21063 return true;
21064
21066 return VT->getNumElements() == 2 &&
21067 VT->getElementType()->getPrimitiveSizeInBits() == 16;
21068 }
21069
21070 return false;
21071}
21072
21073/// \returns whether it's valid to emit a native instruction for \p RMW, and
21074/// why, based on the properties of the target memory.
21075static GlobalFPAtomicLegality
21077 const AtomicRMWInst *RMW, bool HasSystemScope) {
21078 // The remote/fine-grained access logic is different from the integer
21079 // atomics. Without AgentScopeFineGrainedRemoteMemoryAtomics support,
21080 // fine-grained access does not work, even for a device local allocation.
21081 //
21082 // With AgentScopeFineGrainedRemoteMemoryAtomics, system scoped device local
21083 // allocations work.
21084 if (HasSystemScope) {
21085 if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics() &&
21086 RMW->hasMetadata("amdgpu.no.remote.memory"))
21087 return GlobalFPAtomicLegality::NoRemoteMemory;
21088 if (Subtarget.hasEmulatedSystemScopeAtomics())
21089 return GlobalFPAtomicLegality::EmulatedSystemScope;
21090 } else if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics())
21091 return GlobalFPAtomicLegality::AgentScopeFineGrainedRemoteMemory;
21092
21093 return RMW->hasMetadata("amdgpu.no.fine.grained.memory")
21094 ? GlobalFPAtomicLegality::NoFineGrainedMemory
21095 : GlobalFPAtomicLegality::Illegal;
21096}
21097
21098/// \return Action to perform on AtomicRMWInsts for integer operations.
21105
21106/// Return if a flat address space atomicrmw can access private memory.
21108 const MDNode *MD = I->getMetadata(LLVMContext::MD_noalias_addrspace);
21109 return !MD ||
21111}
21112
21115 // For GAS, lower to flat atomic.
21116 return STI.hasGloballyAddressableScratch()
21119}
21120
21123 unsigned AS = RMW->getPointerAddressSpace();
21124 if (AS == AMDGPUAS::PRIVATE_ADDRESS)
21126
21127 // 64-bit flat atomics that dynamically reside in private memory will silently
21128 // be dropped.
21129 //
21130 // Note that we will emit a new copy of the original atomic in the expansion,
21131 // which will be incrementally relegalized.
21132 const DataLayout &DL = RMW->getFunction()->getDataLayout();
21133 if (AS == AMDGPUAS::FLAT_ADDRESS &&
21134 DL.getTypeSizeInBits(RMW->getType()) == 64 &&
21137
21138 GlobalFPAtomicLegality MemLegality = GlobalFPAtomicLegality::Illegal;
21139 AtomicFlushDenormalReason DenormReason = AtomicFlushDenormalReason::Native;
21140 auto ReportHWInst = [&](TargetLowering::AtomicExpansionKind Kind) {
21142 ORE.emit([&]() {
21143 return emitAtomicRMWLegalRemark(RMW, MemLegality, DenormReason);
21144 });
21145 return Kind;
21146 };
21147
21148 auto SSID = RMW->getSyncScopeID();
21149 bool HasSystemScope =
21150 SSID == SyncScope::System ||
21152 getTargetMachine().getTargetTriple(), AtomicScope::System,
21153 /*OneAddressSpace=*/true));
21154
21155 auto Op = RMW->getOperation();
21156 switch (Op) {
21158 // PCIe supports add and xchg for system atomics.
21159 return isAtomicRMWLegalXChgTy(RMW)
21162 case AtomicRMWInst::Add:
21163 // PCIe supports add and xchg for system atomics.
21165 case AtomicRMWInst::Sub:
21166 case AtomicRMWInst::And:
21167 case AtomicRMWInst::Or:
21168 case AtomicRMWInst::Xor:
21169 case AtomicRMWInst::Max:
21170 case AtomicRMWInst::Min:
21177 if (Op == AtomicRMWInst::USubCond && !Subtarget->hasCondSubInsts())
21179 if (Op == AtomicRMWInst::USubSat) {
21180 // The global and buffer forms predate the LDS and flat ones.
21181 if (!Subtarget->hasSubClampInsts() ||
21182 (AS == AMDGPUAS::LOCAL_ADDRESS &&
21183 !Subtarget->hasAtomicDsCondSubClampInsts()) ||
21184 (AS == AMDGPUAS::FLAT_ADDRESS &&
21185 !Subtarget->hasAtomicCondSubClampFlatInsts()))
21187 }
21189 auto *IT = dyn_cast<IntegerType>(RMW->getType());
21190 if (!IT || IT->getBitWidth() != 32)
21192 }
21193
21196 if (Subtarget->hasEmulatedSystemScopeAtomics())
21198
21199 // On most subtargets, for atomicrmw operations other than add/xchg,
21200 // whether or not the instructions will behave correctly depends on where
21201 // the address physically resides and what interconnect is used in the
21202 // system configuration. On some some targets the instruction will nop,
21203 // and in others synchronization will only occur at degraded device scope.
21204 //
21205 // If the allocation is known local to the device, the instructions should
21206 // work correctly.
21207 if (RMW->hasMetadata("amdgpu.no.remote.memory"))
21209
21210 // If fine-grained remote memory works at device scope, we don't need to
21211 // do anything.
21212 if (!HasSystemScope &&
21213 Subtarget->hasAgentScopeFineGrainedRemoteMemoryAtomics())
21215
21216 // If we are targeting a remote allocated address, it depends what kind of
21217 // allocation the address belongs to.
21218 //
21219 // If the allocation is fine-grained (in host memory, or in PCIe peer
21220 // device memory), the operation will fail depending on the target.
21221 //
21222 // Note fine-grained host memory access does work on APUs or if XGMI is
21223 // used, but we do not know if we are targeting an APU or the system
21224 // configuration from the ISA version/target-cpu.
21225 if (RMW->hasMetadata("amdgpu.no.fine.grained.memory"))
21227
21230 // Atomic sub/or/xor do not work over PCI express, but atomic add
21231 // does. InstCombine transforms these with 0 to or, so undo that.
21232 // Sub-word types are not selectable and take the cmpxchg expansion.
21233 if (const Constant *ConstVal = dyn_cast<Constant>(RMW->getValOperand());
21234 ConstVal && ConstVal->isNullValue() &&
21237 }
21238
21239 // If the allocation could be in remote, fine-grained memory, the rmw
21240 // instructions may fail. cmpxchg should work, so emit that. On some
21241 // system configurations, PCIe atomics aren't supported so cmpxchg won't
21242 // even work, so you're out of luck anyway.
21243
21244 // In summary:
21245 //
21246 // Cases that may fail:
21247 // - fine-grained pinned host memory
21248 // - fine-grained migratable host memory
21249 // - fine-grained PCIe peer device
21250 //
21251 // Cases that should work, but may be treated overly conservatively.
21252 // - fine-grained host memory on an APU
21253 // - fine-grained XGMI peer device
21255 }
21256
21258 }
21259 case AtomicRMWInst::FAdd: {
21260 Type *Ty = RMW->getType();
21261
21262 // TODO: Handle REGION_ADDRESS
21263 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
21264 // DS F32 FP atomics do respect the denormal mode, but the rounding mode
21265 // is fixed to round-to-nearest-even.
21266 //
21267 // F64 / PK_F16 / PK_BF16 never flush and are also fixed to
21268 // round-to-nearest-even.
21269 //
21270 // We ignore the rounding mode problem, even in strictfp. The C++ standard
21271 // suggests it is OK if the floating-point mode may not match the calling
21272 // thread.
21273 if (Ty->isFloatTy()) {
21274 return Subtarget->hasLDSFPAtomicAddF32() ? AtomicExpansionKind::None
21276 }
21277
21278 if (Ty->isDoubleTy()) {
21279 // Ignores denormal mode, but we don't consider flushing mandatory.
21280 return Subtarget->hasLdsAtomicAddF64() ? AtomicExpansionKind::None
21282 }
21283
21284 if (Subtarget->hasAtomicDsPkAdd16Insts() && isV2F16OrV2BF16(Ty))
21286
21288 }
21289
21290 // LDS atomics respect the denormal mode from the mode register.
21291 //
21292 // Traditionally f32 global/buffer memory atomics would unconditionally
21293 // flush denormals, but newer targets do not flush. f64/f16/bf16 cases never
21294 // flush.
21295 //
21296 // On targets with flat atomic fadd, denormals would flush depending on
21297 // whether the target address resides in LDS or global memory. We consider
21298 // this flat-maybe-flush as will-flush.
21299 if (Ty->isFloatTy() &&
21300 !Subtarget->hasMemoryAtomicFaddF32DenormalSupport()) {
21301 DenormReason = getAtomicFlushDenormalReason(RMW);
21302 if (DenormReason == AtomicFlushDenormalReason::IEEE)
21304 }
21305
21306 MemLegality =
21307 getGlobalMemoryFPAtomicLegality(*Subtarget, RMW, HasSystemScope);
21308 if (MemLegality != GlobalFPAtomicLegality::Illegal) {
21309 if (AS == AMDGPUAS::FLAT_ADDRESS) {
21310 // gfx942, gfx12
21311 if (Subtarget->hasAtomicFlatPkAdd16Insts() && isV2F16OrV2BF16(Ty))
21312 return ReportHWInst(AtomicExpansionKind::None);
21313 } else if (AMDGPU::isExtendedGlobalAddrSpace(AS)) {
21314 // gfx90a, gfx942, gfx12
21315 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() && isV2F16(Ty))
21316 return ReportHWInst(AtomicExpansionKind::None);
21317
21318 // gfx942, gfx12
21319 if (Subtarget->hasAtomicGlobalPkAddBF16Inst() && isV2BF16(Ty))
21320 return ReportHWInst(AtomicExpansionKind::None);
21321 } else if (AS == AMDGPUAS::BUFFER_FAT_POINTER) {
21322 // gfx90a, gfx942, gfx12
21323 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() && isV2F16(Ty))
21324 return ReportHWInst(AtomicExpansionKind::None);
21325
21326 // While gfx90a/gfx942 supports v2bf16 for global/flat, it does not for
21327 // buffer. gfx12 does have the buffer version.
21328 if (Subtarget->hasAtomicBufferPkAddBF16Inst() && isV2BF16(Ty))
21329 return ReportHWInst(AtomicExpansionKind::None);
21330 }
21331
21332 // global and flat atomic fadd f64: gfx90a, gfx942.
21333 if (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() && Ty->isDoubleTy())
21334 return ReportHWInst(AtomicExpansionKind::None);
21335
21336 if (AS != AMDGPUAS::FLAT_ADDRESS) {
21337 if (Ty->isFloatTy()) {
21338 // global/buffer atomic fadd f32 no-rtn: gfx908, gfx90a, gfx942,
21339 // gfx11+.
21340 if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21341 return ReportHWInst(AtomicExpansionKind::None);
21342 // global/buffer atomic fadd f32 rtn: gfx90a, gfx942, gfx11+.
21343 if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21344 return ReportHWInst(AtomicExpansionKind::None);
21345 } else {
21346 // gfx908
21347 if (RMW->use_empty() &&
21348 Subtarget->hasAtomicBufferGlobalPkAddF16NoRtnInsts() &&
21349 isV2F16(Ty))
21350 return ReportHWInst(AtomicExpansionKind::None);
21351 }
21352 }
21353
21354 // flat atomic fadd f32: gfx942, gfx11+.
21355 if (AS == AMDGPUAS::FLAT_ADDRESS && Ty->isFloatTy()) {
21356 if (Subtarget->hasFlatAtomicFaddF32Inst())
21357 return ReportHWInst(AtomicExpansionKind::None);
21358
21359 // If it is in flat address space, and the type is float, we will try to
21360 // expand it, if the target supports global and lds atomic fadd. The
21361 // reason we need that is, in the expansion, we emit the check of
21362 // address space. If it is in global address space, we emit the global
21363 // atomic fadd; if it is in shared address space, we emit the LDS atomic
21364 // fadd.
21365 if (Subtarget->hasLDSFPAtomicAddF32()) {
21366 if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21368 if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21370 }
21371 }
21372 }
21373
21375 }
21377 case AtomicRMWInst::FMax: {
21378 Type *Ty = RMW->getType();
21379
21380 // LDS float and double fmin/fmax were always supported.
21381 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
21382 return Ty->isFloatTy() || Ty->isDoubleTy() ? AtomicExpansionKind::None
21384 }
21385
21386 MemLegality =
21387 getGlobalMemoryFPAtomicLegality(*Subtarget, RMW, HasSystemScope);
21388 if (MemLegality != GlobalFPAtomicLegality::Illegal) {
21389 // For flat and global cases:
21390 // float, double in gfx7. Manual claims denormal support.
21391 // Removed in gfx8.
21392 // float, double restored in gfx10.
21393 // double removed again in gfx11, so only f32 for gfx11/gfx12.
21394 //
21395 // For gfx9, gfx90a and gfx942 support f64 for global (same as fadd), but
21396 // no f32.
21397 if (AS == AMDGPUAS::FLAT_ADDRESS) {
21398 if (Subtarget->hasAtomicFMinFMaxF32FlatInsts() && Ty->isFloatTy())
21399 return ReportHWInst(AtomicExpansionKind::None);
21400 if (Subtarget->hasAtomicFMinFMaxF64FlatInsts() && Ty->isDoubleTy())
21401 return ReportHWInst(AtomicExpansionKind::None);
21402 } else if (AMDGPU::isExtendedGlobalAddrSpace(AS) ||
21404 if (Subtarget->hasAtomicFMinFMaxF32GlobalInsts() && Ty->isFloatTy())
21405 return ReportHWInst(AtomicExpansionKind::None);
21406 if (Subtarget->hasAtomicFMinFMaxF64GlobalInsts() && Ty->isDoubleTy())
21407 return ReportHWInst(AtomicExpansionKind::None);
21408 }
21409 }
21410
21412 }
21415 default:
21417 }
21418
21419 llvm_unreachable("covered atomicrmw op switch");
21420}
21421
21428
21435
21438 const AtomicCmpXchgInst *CmpX) const {
21439 unsigned AddrSpace = CmpX->getPointerAddressSpace();
21440 if (AddrSpace == AMDGPUAS::PRIVATE_ADDRESS)
21442
21443 if (AddrSpace != AMDGPUAS::FLAT_ADDRESS || !flatInstrMayAccessPrivate(CmpX))
21445
21446 const DataLayout &DL = CmpX->getDataLayout();
21447
21448 Type *ValTy = CmpX->getNewValOperand()->getType();
21449
21450 // If a 64-bit flat atomic may alias private, we need to avoid using the
21451 // atomic in the private case.
21452 return DL.getTypeSizeInBits(ValTy) == 64 ? AtomicExpansionKind::CustomExpand
21454}
21455
21456const TargetRegisterClass *
21457SITargetLowering::getRegClassFor(MVT VT, bool isDivergent) const {
21459 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
21460 if (RC == &AMDGPU::VReg_1RegClass && !isDivergent)
21461 return Subtarget->isWave64() ? &AMDGPU::SReg_64RegClass
21462 : &AMDGPU::SReg_32RegClass;
21463 if (!TRI->isSGPRClass(RC) && !isDivergent)
21464 return TRI->getEquivalentSGPRClass(RC);
21465 if (TRI->isSGPRClass(RC) && isDivergent) {
21466 if (Subtarget->hasGFX90AInsts())
21467 return TRI->getEquivalentAVClass(RC);
21468 return TRI->getEquivalentVGPRClass(RC);
21469 }
21470
21471 return RC;
21472}
21473
21474// FIXME: This is a workaround for DivergenceAnalysis not understanding always
21475// uniform values (as produced by the mask results of control flow intrinsics)
21476// used outside of divergent blocks. The phi users need to also be treated as
21477// always uniform.
21478//
21479// FIXME: DA is no longer in-use. Does this still apply to UniformityAnalysis?
21480static bool hasCFUser(const Value *V, SmallPtrSet<const Value *, 16> &Visited,
21481 unsigned WaveSize) {
21482 // FIXME: We assume we never cast the mask results of a control flow
21483 // intrinsic.
21484 // Early exit if the type won't be consistent as a compile time hack.
21485 IntegerType *IT = dyn_cast<IntegerType>(V->getType());
21486 if (!IT || IT->getBitWidth() != WaveSize)
21487 return false;
21488
21489 if (!isa<Instruction>(V))
21490 return false;
21491 if (!Visited.insert(V).second)
21492 return false;
21493 bool Result = false;
21494 for (const auto *U : V->users()) {
21496 if (V == U->getOperand(1)) {
21497 switch (Intrinsic->getIntrinsicID()) {
21498 default:
21499 Result = false;
21500 break;
21501 case Intrinsic::amdgcn_if_break:
21502 case Intrinsic::amdgcn_if:
21503 case Intrinsic::amdgcn_else:
21504 Result = true;
21505 break;
21506 }
21507 }
21508 if (V == U->getOperand(0)) {
21509 switch (Intrinsic->getIntrinsicID()) {
21510 default:
21511 Result = false;
21512 break;
21513 case Intrinsic::amdgcn_end_cf:
21514 case Intrinsic::amdgcn_loop:
21515 Result = true;
21516 break;
21517 }
21518 }
21519 } else {
21520 Result = hasCFUser(U, Visited, WaveSize);
21521 }
21522 if (Result)
21523 break;
21524 }
21525 return Result;
21526}
21527
21529 const Value *V) const {
21530 if (const CallInst *CI = dyn_cast<CallInst>(V)) {
21531 if (CI->isInlineAsm()) {
21532 // FIXME: This cannot give a correct answer. This should only trigger in
21533 // the case where inline asm returns mixed SGPR and VGPR results, used
21534 // outside the defining block. We don't have a specific result to
21535 // consider, so this assumes if any value is SGPR, the overall register
21536 // also needs to be SGPR.
21537 const SIRegisterInfo *SIRI = Subtarget->getRegisterInfo();
21539 MF.getDataLayout(), Subtarget->getRegisterInfo(), *CI);
21540 for (auto &TC : TargetConstraints) {
21541 if (TC.Type == InlineAsm::isOutput) {
21543 const TargetRegisterClass *RC =
21544 getRegForInlineAsmConstraint(SIRI, TC.ConstraintCode,
21545 TC.ConstraintVT)
21546 .second;
21547 if (RC && SIRI->isSGPRClass(RC))
21548 return true;
21549 }
21550 }
21551 }
21552 }
21554 return hasCFUser(V, Visited, Subtarget->getWavefrontSize());
21555}
21556
21558 for (SDUse &Use : N->uses()) {
21560 if (getBasePtrIndex(M) == Use.getOperandNo())
21561 return true;
21562 }
21563 }
21564 return false;
21565}
21566
21568 SDValue N1) const {
21569 if (!N0.hasOneUse())
21570 return false;
21571 // Take care of the opportunity to keep N0 uniform
21572 if (N0->isDivergent() || !N1->isDivergent())
21573 return true;
21574 // Check if we have a good chance to form the memory access pattern with the
21575 // base and offset
21576 return (DAG.isBaseWithConstantOffset(N0) &&
21578}
21579
21581 Register N0, Register N1) const {
21582 return MRI.hasOneNonDBGUse(N0); // FIXME: handle regbanks
21583}
21584
21587 // Propagate metadata set by AMDGPUAnnotateUniformValues to the MMO of a load.
21589 if (I.getMetadata("amdgpu.noclobber"))
21590 Flags |= MONoClobber;
21591 if (I.getMetadata("amdgpu.last.use"))
21592 Flags |= MOLastUse;
21593 if (MDNode *N = I.getMetadata("amdgpu.cfs")) {
21594 const ConstantAsMetadata *CAM = cast<ConstantAsMetadata>(N->getOperand(0));
21596 unsigned CFS = CI->getZExtValue() & AMDGPU::CPol::CFS_MASK;
21597 static_assert((MOCFSB0 << 1) == MOCFSB1,
21598 "MOCFSB0 and MOCFSB1 are not adjacent bits");
21599 Flags |= static_cast<MachineMemOperand::Flags>(CFS * MOCFSB0);
21600 }
21601 return Flags;
21602}
21603
21605 Instruction *AI) const {
21606 // Given: atomicrmw fadd ptr %addr, float %val ordering
21607 //
21608 // With this expansion we produce the following code:
21609 // [...]
21610 // %is.shared = call i1 @llvm.amdgcn.is.shared(ptr %addr)
21611 // br i1 %is.shared, label %atomicrmw.shared, label %atomicrmw.check.private
21612 //
21613 // atomicrmw.shared:
21614 // %cast.shared = addrspacecast ptr %addr to ptr addrspace(3)
21615 // %loaded.shared = atomicrmw fadd ptr addrspace(3) %cast.shared,
21616 // float %val ordering
21617 // br label %atomicrmw.phi
21618 //
21619 // atomicrmw.check.private:
21620 // %is.private = call i1 @llvm.amdgcn.is.private(ptr %int8ptr)
21621 // br i1 %is.private, label %atomicrmw.private, label %atomicrmw.global
21622 //
21623 // atomicrmw.private:
21624 // %cast.private = addrspacecast ptr %addr to ptr addrspace(5)
21625 // %loaded.private = load float, ptr addrspace(5) %cast.private
21626 // %val.new = fadd float %loaded.private, %val
21627 // store float %val.new, ptr addrspace(5) %cast.private
21628 // br label %atomicrmw.phi
21629 //
21630 // atomicrmw.global:
21631 // %cast.global = addrspacecast ptr %addr to ptr addrspace(1)
21632 // %loaded.global = atomicrmw fadd ptr addrspace(1) %cast.global,
21633 // float %val ordering
21634 // br label %atomicrmw.phi
21635 //
21636 // atomicrmw.phi:
21637 // %loaded.phi = phi float [ %loaded.shared, %atomicrmw.shared ],
21638 // [ %loaded.private, %atomicrmw.private ],
21639 // [ %loaded.global, %atomicrmw.global ]
21640 // br label %atomicrmw.end
21641 //
21642 // atomicrmw.end:
21643 // [...]
21644 //
21645 //
21646 // For 64-bit atomics which may reside in private memory, we perform a simpler
21647 // version that only inserts the private check, and uses the flat operation.
21648
21649 IRBuilder<> Builder(AI);
21650 LLVMContext &Ctx = Builder.getContext();
21651
21652 auto *RMW = dyn_cast<AtomicRMWInst>(AI);
21653 const unsigned PtrOpIdx = RMW ? AtomicRMWInst::getPointerOperandIndex()
21655 Value *Addr = AI->getOperand(PtrOpIdx);
21656
21657 /// TODO: Only need to check private, then emit flat-known-not private (no
21658 /// need for shared block, or cast to global).
21660
21661 Align Alignment;
21662 if (RMW)
21663 Alignment = RMW->getAlign();
21664 else if (CX)
21665 Alignment = CX->getAlign();
21666 else
21667 llvm_unreachable("unhandled atomic operation");
21668
21669 // FullFlatEmulation is true if we need to issue the private, shared, and
21670 // global cases.
21671 //
21672 // If this is false, we are only dealing with the flat-targeting-private case,
21673 // where we only insert a check for private and still use the flat instruction
21674 // for global and shared.
21675
21676 bool FullFlatEmulation =
21677 RMW && RMW->getOperation() == AtomicRMWInst::FAdd &&
21678 ((Subtarget->hasAtomicFaddInsts() && RMW->getType()->isFloatTy()) ||
21679 (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() &&
21680 RMW->getType()->isDoubleTy()));
21681
21682 // If the return value isn't used, do not introduce a false use in the phi.
21683 bool ReturnValueIsUsed = !AI->use_empty();
21684
21685 BasicBlock *BB = Builder.GetInsertBlock();
21686 Function *F = BB->getParent();
21687 BasicBlock *ExitBB =
21688 BB->splitBasicBlock(Builder.GetInsertPoint(), "atomicrmw.end");
21689 BasicBlock *SharedBB = nullptr;
21690
21691 BasicBlock *CheckPrivateBB = BB;
21692 if (FullFlatEmulation) {
21693 SharedBB = BasicBlock::Create(Ctx, "atomicrmw.shared", F, ExitBB);
21694 CheckPrivateBB =
21695 BasicBlock::Create(Ctx, "atomicrmw.check.private", F, ExitBB);
21696 }
21697
21698 BasicBlock *PrivateBB =
21699 BasicBlock::Create(Ctx, "atomicrmw.private", F, ExitBB);
21700 BasicBlock *GlobalBB = BasicBlock::Create(Ctx, "atomicrmw.global", F, ExitBB);
21701 BasicBlock *PhiBB = BasicBlock::Create(Ctx, "atomicrmw.phi", F, ExitBB);
21702
21703 std::prev(BB->end())->eraseFromParent();
21704 Builder.SetInsertPoint(BB);
21705
21706 Value *LoadedShared = nullptr;
21707 if (FullFlatEmulation) {
21708 Value *IsShared = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_shared,
21709 {Addr}, nullptr, "is.shared");
21710 Builder.CreateCondBr(IsShared, SharedBB, CheckPrivateBB);
21711 Builder.SetInsertPoint(SharedBB);
21712 Value *CastToLocal = Builder.CreateAddrSpaceCast(
21714
21715 Instruction *Clone = AI->clone();
21716 Clone->insertInto(SharedBB, SharedBB->end());
21717 Clone->getOperandUse(PtrOpIdx).set(CastToLocal);
21718 LoadedShared = Clone;
21719
21720 Builder.CreateBr(PhiBB);
21721 Builder.SetInsertPoint(CheckPrivateBB);
21722 }
21723
21724 Value *IsPrivate = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_private,
21725 {Addr}, nullptr, "is.private");
21726 Builder.CreateCondBr(IsPrivate, PrivateBB, GlobalBB);
21727
21728 Builder.SetInsertPoint(PrivateBB);
21729
21730 Value *CastToPrivate = Builder.CreateAddrSpaceCast(
21732
21733 Value *LoadedPrivate;
21734 if (RMW) {
21735 LoadedPrivate = Builder.CreateAlignedLoad(
21736 RMW->getType(), CastToPrivate, RMW->getAlign(), RMW->isVolatile(),
21737 "loaded.private");
21738
21739 Value *NewVal = buildAtomicRMWValue(RMW->getOperation(), Builder,
21740 LoadedPrivate, RMW->getValOperand());
21741
21742 Builder.CreateAlignedStore(NewVal, CastToPrivate, RMW->getAlign(),
21743 RMW->isVolatile());
21744 } else {
21745 auto [ResultLoad, Equal] = buildCmpXchgValue(
21746 Builder, CastToPrivate, CX->getCompareOperand(), CX->getNewValOperand(),
21747 CX->getAlign(), CX->isVolatile());
21748
21749 Value *Insert = Builder.CreateInsertValue(PoisonValue::get(CX->getType()),
21750 ResultLoad, 0);
21751 LoadedPrivate = Builder.CreateInsertValue(Insert, Equal, 1);
21752 }
21753
21754 Builder.CreateBr(PhiBB);
21755
21756 Builder.SetInsertPoint(GlobalBB);
21757
21758 // Continue using a flat instruction if we only emitted the check for private.
21759 Instruction *LoadedGlobal = AI;
21760 if (FullFlatEmulation) {
21761 Value *CastToGlobal = Builder.CreateAddrSpaceCast(
21763 AI->getOperandUse(PtrOpIdx).set(CastToGlobal);
21764 }
21765
21766 AI->removeFromParent();
21767 AI->insertInto(GlobalBB, GlobalBB->end());
21768
21769 // The new atomicrmw may go through another round of legalization later.
21770 if (!FullFlatEmulation) {
21771 // We inserted the runtime check already, make sure we do not try to
21772 // re-expand this.
21773 // TODO: Should union with any existing metadata.
21774 MDBuilder MDB(F->getContext());
21775 MDNode *RangeNotPrivate =
21778 LoadedGlobal->setMetadata(LLVMContext::MD_noalias_addrspace,
21779 RangeNotPrivate);
21780 }
21781
21782 Builder.CreateBr(PhiBB);
21783
21784 Builder.SetInsertPoint(PhiBB);
21785
21786 if (ReturnValueIsUsed) {
21787 PHINode *Loaded = Builder.CreatePHI(AI->getType(), 3);
21788 AI->replaceAllUsesWith(Loaded);
21789 if (FullFlatEmulation)
21790 Loaded->addIncoming(LoadedShared, SharedBB);
21791 Loaded->addIncoming(LoadedPrivate, PrivateBB);
21792 Loaded->addIncoming(LoadedGlobal, GlobalBB);
21793 Loaded->takeName(AI);
21794 }
21795
21796 Builder.CreateBr(ExitBB);
21797}
21798
21800 unsigned PtrOpIdx) {
21801 Value *PtrOp = I->getOperand(PtrOpIdx);
21804
21805 Type *FlatPtr = PointerType::get(I->getContext(), AMDGPUAS::FLAT_ADDRESS);
21806 Value *ASCast = CastInst::CreatePointerCast(PtrOp, FlatPtr, "scratch.ascast",
21807 I->getIterator());
21808 I->setOperand(PtrOpIdx, ASCast);
21809}
21810
21813
21816
21819 if (const auto *ConstVal = dyn_cast<Constant>(AI->getValOperand());
21820 ConstVal && ConstVal->isNullValue() &&
21822 // atomicrmw or %ptr, 0 -> atomicrmw add %ptr, 0
21824
21825 // We may still need the private-alias-flat handling below.
21826
21827 // TODO: Skip this for cases where we cannot access remote memory.
21828 }
21829 }
21830
21831 // The non-flat expansions should only perform the de-canonicalization of
21832 // identity values.
21834 return;
21835
21837}
21838
21845
21849
21851 "Expand Atomic Load only handles SCRATCH -> FLAT conversion");
21852}
21853
21855 if (SI->getPointerAddressSpace() == AMDGPUAS::PRIVATE_ADDRESS)
21856 return convertScratchAtomicToFlatAtomic(SI, SI->getPointerOperandIndex());
21857
21859 "Expand Atomic Store only handles SCRATCH -> FLAT conversion");
21860}
static bool isMul(MachineInstr *MI)
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU address space definition.
static constexpr std::pair< ImplicitArgumentMask, StringLiteral > ImplicitAttrs[]
static bool allUsesHaveSourceMods(MachineInstr &MI, MachineRegisterInfo &MRI, unsigned CostThreshold=4)
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
uint64_t uint64_t
uint64_t Imm
static bool isCtlzOpc(unsigned Opc)
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static bool isNoUnsignedWrap(MachineInstr *Addr)
static bool parseTexFail(uint64_t TexFailCtrl, bool &TFE, bool &LWE, bool &IsTexFail)
static bool isAsyncLDSDMA(Intrinsic::ID Intr)
static void packImage16bitOpsToDwords(MachineIRBuilder &B, MachineInstr &MI, SmallVectorImpl< Register > &PackedAddrs, unsigned ArgOffset, const AMDGPU::ImageDimIntrinsicInfo *Intr, bool IsA16, bool IsG16)
Turn a set of f16 typed registers in AddrRegs into a dword sized vector with f16 typed elements.
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
Provides AMDGPU specific target descriptions.
The AMDGPU TargetMachine interface definition for hw codegen targets.
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
Function Alias Analysis Results
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
@ DEFAULT
Default weight is used in cases when there is no dedicated execution weight set.
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< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< SDByteProvider > calculateByteProvider(SDValue Op, unsigned Index, unsigned Depth, std::optional< uint64_t > VectorIndex, unsigned StartingIndex=0, MutableArrayRef< uint8_t > ByteMask={})
dxil translate DXIL Translate Metadata
static bool isSigned(unsigned Opcode)
Utilities for dealing with flags related to floating point properties and mode controls.
AMD GCN specific subclass of TargetSubtarget.
Provides analysis for querying information about KnownBits during GISel passes.
#define DEBUG_TYPE
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
iv Induction Variable Users
Definition IVUsers.cpp:48
static constexpr Value * getValue(Ty &ValueOrUse)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RegName(no)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Contains matchers for matching SSA Machine Instructions.
static bool isUndef(const MachineInstr &MI)
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static unsigned getAddressSpace(const Value *V, unsigned MaxLookup)
uint64_t IntrinsicInst * II
#define P(N)
if(PassOpts->AAPipeline)
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
Contains matchers for matching SelectionDAG nodes and values.
static void r0(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:39
static void r3(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:57
static void r2(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:51
static void r1(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:45
#define FP_DENORM_FLUSH_NONE
Definition SIDefines.h:1516
#define FP_DENORM_FLUSH_IN_FLUSH_OUT
Definition SIDefines.h:1513
SI Fold Operands
static void reservePrivateMemoryRegs(const TargetMachine &TM, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info)
static SDValue adjustLoadValueTypeImpl(SDValue Result, EVT LoadVT, const SDLoc &DL, SelectionDAG &DAG, bool Unpacked)
static MachineBasicBlock * emitIndirectSrc(MachineInstr &MI, MachineBasicBlock &MBB, const GCNSubtarget &ST)
static bool denormalModeIsFlushAllF64F16(const MachineFunction &MF)
static bool isAtomicRMWLegalIntTy(Type *Ty)
static void knownBitsForWorkitemID(const GCNSubtarget &ST, GISelValueTracking &VT, KnownBits &Known, unsigned Dim)
static bool flatInstrMayAccessPrivate(const Instruction *I)
Return if a flat address space atomicrmw can access private memory.
static std::pair< unsigned, int > computeIndirectRegAndOffset(const SIRegisterInfo &TRI, const TargetRegisterClass *SuperRC, unsigned VecReg, int Offset)
static bool denormalModeIsFlushAllF32(const MachineFunction &MF)
static bool addresses16Bits(int Mask)
static MachineBasicBlock * expand64BitScalarArithmetic(MachineInstr &MI, MachineBasicBlock *BB)
static bool isClampZeroToOne(SDValue A, SDValue B)
static bool supportsMin3Max3(const GCNSubtarget &Subtarget, unsigned Opc, EVT VT)
static AtomicFlushDenormalReason getAtomicFlushDenormalReason(const AtomicRMWInst *RMW)
static unsigned findFirstFreeSGPR(CCState &CCInfo)
static uint32_t getPermuteMask(SDValue V)
static SDValue lowerLaneOp(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static int getAlignedAGPRClassID(unsigned UnalignedClassID)
static void processPSInputArgs(SmallVectorImpl< ISD::InputArg > &Splits, CallingConv::ID CallConv, ArrayRef< ISD::InputArg > Ins, BitVector &Skipped, FunctionType *FType, SIMachineFunctionInfo *Info)
static SDValue selectSOffset(SDValue SOffset, SelectionDAG &DAG, const GCNSubtarget *Subtarget)
static SDValue getLoadExtOrTrunc(SelectionDAG &DAG, ISD::LoadExtType ExtType, SDValue Op, const SDLoc &SL, EVT VT)
static std::tuple< unsigned, unsigned > getDPPOpcForWaveReduction(unsigned Opc, const GCNSubtarget &ST)
static void fixMasks(SmallVectorImpl< DotSrc > &Srcs, unsigned ChainLength)
static bool is32bitWaveReduceOperation(unsigned Opc)
static TargetLowering::AtomicExpansionKind atomicSupportedIfLegalIntType(const AtomicRMWInst *RMW)
static SDValue strictFPExtFromF16(SelectionDAG &DAG, SDValue Src)
Return the source of an fp_extend from f16 to f32, or a converted FP constant.
static bool isAtomicRMWLegalXChgTy(const AtomicRMWInst *RMW)
static bool bitOpWithConstantIsReducible(unsigned Opc, uint32_t Val)
static void convertScratchAtomicToFlatAtomic(Instruction *I, unsigned PtrOpIdx)
static bool isCopyFromRegOfInlineAsm(const SDNode *N)
static bool elementPairIsOddToEven(ArrayRef< int > Mask, int Elt)
static SDValue lowerBFEIntrinsic(SDValue Op, SelectionDAG &DAG, Intrinsic::ID IntrinsicID)
static cl::opt< bool > DisableLoopAlignment("amdgpu-disable-loop-alignment", cl::desc("Do not align and prefetch loops"), cl::init(false))
static SDValue getDWordFromOffset(SelectionDAG &DAG, SDLoc SL, SDValue Src, unsigned DWordOffset)
static MachineBasicBlock::iterator loadM0FromVGPR(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineInstr &MI, unsigned InitResultReg, unsigned PhiReg, int Offset, bool UseGPRIdxMode, Register &SGPRIdxReg)
static bool isFloatingPointWaveReduceOperation(unsigned Opc)
static bool isImmConstraint(StringRef Constraint)
static SDValue padEltsToUndef(SelectionDAG &DAG, const SDLoc &DL, EVT CastVT, SDValue Src, int ExtraElts)
static bool hasCFUser(const Value *V, SmallPtrSet< const Value *, 16 > &Visited, unsigned WaveSize)
static std::pair< Register, Register > ExtractSubRegs(MachineInstr &MI, MachineOperand &Op, const TargetRegisterClass *SrcRC, const GCNSubtarget &ST, MachineRegisterInfo &MRI)
static unsigned SubIdx2Lane(unsigned Idx)
Helper function for adjustWritemask.
static TargetLowering::AtomicExpansionKind getPrivateAtomicExpansionKind(const GCNSubtarget &STI)
static bool addressMayBeAccessedAsPrivate(const MachineMemOperand *MMO, const SIMachineFunctionInfo &Info)
static MachineBasicBlock * lowerWaveReduce(MachineInstr &MI, MachineBasicBlock &BB, const GCNSubtarget &ST, unsigned Opc)
static bool elementPairIsContiguous(ArrayRef< int > Mask, int Elt)
static bool isV2BF16(Type *Ty)
static bool isFrexpExp(SDValue V, SDValue &FrexpInput)
static ArgDescriptor allocateSGPR32InputImpl(CCState &CCInfo, const TargetRegisterClass *RC, unsigned NumArgRegs)
static SDValue getMad64_32(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue N0, SDValue N1, SDValue N2, bool Signed)
static SDValue resolveSources(SelectionDAG &DAG, SDLoc SL, SmallVectorImpl< DotSrc > &Srcs, bool IsSigned, bool IsAny)
static bool hasNon16BitAccesses(uint64_t PermMask, SDValue &Op, SDValue &OtherOp)
static SDValue lowerWaveShuffle(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static SDValue diagnoseUnsupportedImage(SelectionDAG &DAG, SDValue Op, ArrayRef< EVT > ResultTypes, const SDLoc &DL, const Twine &Msg)
Emit a DiagnosticInfoUnsupported for an unsupported image intrinsic and return poison values of Resul...
static void placeSources(ByteProvider< SDValue > &Src0, ByteProvider< SDValue > &Src1, SmallVectorImpl< DotSrc > &Src0s, SmallVectorImpl< DotSrc > &Src1s, int Step)
static unsigned parseSyncscopeMDArg(const CallBase &CI, unsigned ArgIdx)
static EVT memVTFromLoadIntrReturn(const SITargetLowering &TLI, const DataLayout &DL, Type *Ty, unsigned MaxNumLanes)
static MachineBasicBlock::iterator emitLoadM0FromVGPRLoop(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineBasicBlock &OrigBB, MachineBasicBlock &LoopBB, const DebugLoc &DL, const MachineOperand &Idx, unsigned InitReg, unsigned ResultReg, unsigned PhiReg, unsigned InitSaveExecReg, int Offset, bool UseGPRIdxMode, Register &SGPRIdxReg)
static SDValue matchPERM(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isFrameIndexOp(SDValue Op)
static ConstantFPSDNode * getSplatConstantFP(SDValue Op)
static void allocateSGPR32Input(CCState &CCInfo, ArgDescriptor &Arg)
static void knownBitsForSBFE(const MachineInstr &MI, GISelValueTracking &VT, KnownBits &Known, const APInt &DemandedElts, unsigned BFEWidth, bool SExt, unsigned Depth)
static bool isExtendedFrom16Bits(SDValue &Operand)
static std::optional< bool > checkDot4MulSignedness(const SDValue &N, ByteProvider< SDValue > &Src0, ByteProvider< SDValue > &Src1, const SDValue &S0Op, const SDValue &S1Op, const SelectionDAG &DAG)
static bool vectorEltWillFoldAway(SDValue Op)
static SDValue getSPDenormModeValue(uint32_t SPDenormMode, SelectionDAG &DAG, const SIMachineFunctionInfo *Info, const GCNSubtarget *ST)
static uint32_t getConstantPermuteMask(uint32_t C)
static AtomicOrdering parseAtomicOrderingCABIArg(const CallBase &CI, unsigned ArgIdx)
static MachineBasicBlock * emitIndirectDst(MachineInstr &MI, MachineBasicBlock &MBB, const GCNSubtarget &ST)
static void setM0ToIndexFromSGPR(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineInstr &MI, int Offset)
static DenormalFPEnv getDenormalFPEnv(const MachineFunction &MF)
static std::pair< MachineBasicBlock *, MachineBasicBlock * > splitBlockForLoop(MachineInstr &MI, MachineBasicBlock &MBB, bool InstInLoop)
static unsigned getBasePtrIndex(const MemSDNode *N)
MemSDNode::getBasePtr() does not work for intrinsics, which needs to offset by the chain and intrinsi...
static void allocateFixedSGPRInputImpl(CCState &CCInfo, const TargetRegisterClass *RC, MCRegister Reg)
static SDValue constructRetValue(SelectionDAG &DAG, MachineSDNode *Result, ArrayRef< EVT > ResultTypes, bool IsTexFail, bool Unpacked, bool IsD16, int DMaskPop, int NumVDataDwords, bool IsAtomicPacked16Bit, const SDLoc &DL)
static std::pair< SDValue, SDValue > splitTFEValueAndStatus(SDValue Op, EVT VT, const SDLoc &DL, SelectionDAG &DAG)
static std::optional< ByteProvider< SDValue > > handleMulOperand(const SDValue &MulOperand)
static ISD::CondCode tryReduceF64CompareToHiHalf(const ISD::CondCode CC, const SDValue LHS, const SDValue RHS, const SelectionDAG &DAG)
static Register getIndirectSGPRIdx(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineInstr &MI, int Offset)
static SDValue emitNonHSAIntrinsicError(SelectionDAG &DAG, const SDLoc &DL, EVT VT)
static EVT memVTFromLoadIntrData(const SITargetLowering &TLI, const DataLayout &DL, Type *Ty, unsigned MaxNumLanes)
static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc)
static unsigned getExtOpcodeForPromotedOp(SDValue Op)
static void expand64BitV_CNDMASK(MachineInstr &MI, MachineBasicBlock *BB)
static GlobalFPAtomicLegality getGlobalMemoryFPAtomicLegality(const GCNSubtarget &Subtarget, const AtomicRMWInst *RMW, bool HasSystemScope)
static SDValue lowerBALLOTIntrinsic(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static SDValue buildSMovImm32(SelectionDAG &DAG, const SDLoc &DL, uint64_t Val)
static SDValue tryFoldMADwithSRL(SelectionDAG &DAG, const SDLoc &SL, SDValue MulLHS, SDValue MulRHS, SDValue AddRHS)
static unsigned getIntrMemWidth(unsigned IntrID)
static SDValue getBuildDwordsVector(SelectionDAG &DAG, SDLoc DL, ArrayRef< SDValue > Elts)
static SDNode * findUser(SDValue Value, unsigned Opcode)
Helper function for LowerBRCOND.
static unsigned addPermMasks(unsigned First, unsigned Second)
static uint64_t clearUnusedBits(uint64_t Val, unsigned Size)
static SDValue getFPTernOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL, EVT VT, SDValue A, SDValue B, SDValue C, SDValue GlueChain, SDNodeFlags Flags)
static bool isV2F16OrV2BF16(Type *Ty)
static OptimizationRemark emitAtomicRMWLegalRemark(const AtomicRMWInst *RMW, GlobalFPAtomicLegality MemLegality, AtomicFlushDenormalReason DenormReason)
static SDValue emitRemovedIntrinsicError(SelectionDAG &DAG, const SDLoc &DL, EVT VT)
static SDValue getFPBinOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL, EVT VT, SDValue A, SDValue B, SDValue GlueChain, SDNodeFlags Flags)
static SDValue buildPCRelGlobalAddress(SelectionDAG &DAG, const GlobalValue *GV, const SDLoc &DL, int64_t Offset, EVT PtrVT, unsigned GAFlags=SIInstrInfo::MO_NONE)
static cl::opt< bool > UseDivergentRegisterIndexing("amdgpu-use-divergent-register-indexing", cl::Hidden, cl::desc("Use indirect register addressing for divergent indexes"), cl::init(false))
static const std::optional< ByteProvider< SDValue > > calculateSrcByte(const SDValue Op, uint64_t DestByte, uint64_t SrcIndex=0, unsigned Depth=0)
static bool isV2F16(Type *Ty)
static void initializeM0ToZeroForClusterLoad(SDValue Op, SelectionDAG &DAG, SDLoc DL)
static void allocateSGPR64Input(CCState &CCInfo, ArgDescriptor &Arg)
static uint64_t getIdentityValueForWaveReduction(unsigned Opc)
SI DAG Lowering interface definition.
Interface definition for SIRegisterInfo.
const char * Msg
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:480
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
static unsigned getScalarSizeInBits(Type *Ty)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
LLVM IR instance of the generic uniformity analysis.
static constexpr int Concat[]
Value * RHS
Value * LHS
The Input class is used to parse a yaml document into in-memory structs and vectors.
static std::optional< uint32_t > getLDSKernelIdMetadata(const Function &F)
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
static std::optional< uint32_t > get32BitAbsoluteAddress(const GlobalValue &GV, unsigned AS)
static unsigned numBitsSigned(SDValue Op, SelectionDAG &DAG)
SDValue SplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Split a vector load into 2 loads of half the vector.
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 storeStackInputValue(SelectionDAG &DAG, const SDLoc &SL, SDValue Chain, SDValue ArgVal, int64_t Offset) 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...
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 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 addTokenForArgument(SDValue Chain, SelectionDAG &DAG, MachineFrameInfo &MFI, int ClobberedFI) const
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 LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const
SDValue loadInputValue(SelectionDAG &DAG, const TargetRegisterClass *RC, EVT VT, const SDLoc &SL, const ArgDescriptor &Arg) const
AMDGPUTargetLowering(const TargetMachine &TM, const TargetSubtargetInfo &STI, const AMDGPUSubtarget &AMDGPUSTI)
static EVT getEquivalentMemType(LLVMContext &Context, EVT VT)
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.
std::pair< SDValue, SDValue > split64BitValue(SDValue Op, SelectionDAG &DAG) const
Return 64-bit value Op as two 32-bit integers.
static CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool IsVarArg)
static CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg)
Selects the correct CCAssignFn for a given CallingConvention value.
static unsigned numBitsUnsigned(SDValue Op, SelectionDAG &DAG)
static bool allowApproxFunc(const SelectionDAG &DAG, SDNodeFlags Flags)
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,...
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 LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) 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 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...
SDValue WidenOrSplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Widen a suitably aligned v3 load.
SDValue getHiHalf64(SDValue Op, SelectionDAG &DAG) const
bool isNoopAddrSpaceCast(const DataLayout &DL, unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
const std::array< unsigned, 3 > & getDims() const
static const LaneMaskConstants & get(const GCNSubtarget &ST)
static const fltSemantics & IEEEsingle()
Definition APFloat.h:304
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:361
static const fltSemantics & IEEEhalf()
Definition APFloat.h:302
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
Definition APFloat.h:1224
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition APFloat.cpp:6045
LLVM_READONLY int getExactLog2Abs() const
Definition APFloat.h:1639
bool isNegative() const
Definition APFloat.h:1583
bool isNormal() const
Definition APFloat.h:1587
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
Definition APFloat.h:1192
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
Definition APFloat.h:1242
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Definition APFloat.h:1202
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Definition APFloat.h:1183
bool isInfinity() const
Definition APFloat.h:1580
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1057
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
Definition APInt.h:202
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
Definition APInt.h:254
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:376
bool isSignMask() const
Check if the APInt's value is returned by getSignMask.
Definition APInt.h:462
unsigned countr_zero() const
Count the number of trailing zero bits.
Definition APInt.h:1659
bool isOneBitSet(unsigned BitNo) const
Determine if this APInt Value only has the specified bit set.
Definition APInt.h:362
bool isMask(unsigned numBits) const
Definition APInt.h:484
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
Definition APInt.h:337
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
Definition APInt.h:292
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
Definition APInt.h:1241
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
Definition APInt.h:1225
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const
Check if an argument has a given attribute.
Definition Function.cpp:332
const Function * getParent() const
Definition Argument.h:44
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
An instruction that atomically checks whether a specified value is in a memory location,...
bool isVolatile() const
Return true if this is a cmpxchg from a volatile memory location.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
static unsigned getPointerOperandIndex()
an instruction that atomically reads a memory location, combines it with another value,...
static unsigned getPointerOperandIndex()
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ Add
*p = old + v
@ FAdd
*p = old + v
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ Sub
*p = old - v
@ And
*p = old & v
@ Xor
*p = old ^ v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ FSub
*p = old - v
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ UMax
*p = old >unsigned v ? old : v
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
@ Nand
*p = ~(old & v)
void setOperation(BinOp Operation)
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
static LLVM_ABI StringRef getOperationName(BinOp Op)
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
bool isCompareAndSwap() const
Returns true if this SDNode represents cmpxchg atomic operation, false otherwise.
This class holds the attributes for a particular argument, parameter, function, or return value.
Definition Attributes.h:406
LLVM_ABI MemoryEffects getMemoryEffects() const
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator end()
Definition BasicBlock.h:453
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
A "pseudo-class" with methods for operating on BUILD_VECTORs.
Represents known origin of an individual byte in combine pattern.
static ByteProvider getConstantZero()
static ByteProvider getSrc(std::optional< ISelOp > Val, int64_t ByteOffset, int64_t VectorOffset)
CCState - This class holds information needed while lowering arguments and return values.
MachineFunction & getMachineFunction() const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
LLVM_ABI void AnalyzeCallResult(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeCallResult - Analyze the return values of a call, incorporating info about the passed values i...
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
int64_t AllocateStack(unsigned Size, Align Alignment)
AllocateStack - Allocate a chunk of stack space with the specified size and alignment.
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
bool isAllocated(MCRegister Reg) const
isAllocated - Return true if the specified register (or an alias) is allocated.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
bool isTailCall() const
static LLVM_ABI CastInst * CreatePointerCast(Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Create a BitCast, AddrSpaceCast or a PtrToInt cast instruction.
Constant * getValue() const
Definition Metadata.h:556
const APFloat & getValueAPF() const
bool isPosZero() const
Return true if the value is positive zero.
bool isOne() const
Returns true if this value is exactly +1.0.
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isNegative() const
Return true if the value is negative.
bool isInfinity() const
Return true if the value is an infinity.
This is the shared class of boolean and integer constants.
Definition Constants.h:87
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Definition Constants.h:219
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:168
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
This is an important base class in LLVM.
Definition Constant.h:44
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
LLVM_ABI Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
bool isBigEndian() const
Definition DataLayout.h:218
A debug info location.
Definition DebugLoc.h:126
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:306
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Register DemoteRegister
DemoteRegister - if CanLowerReturn is false, DemoteRegister is a vreg allocated to hold a pointer to ...
LLVM_ABI const Value * getValueFromVirtualReg(Register Vreg)
This method is called from TargetLowerinInfo::isSDNodeSourceOfDivergence to get the Value correspondi...
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:212
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Definition Function.cpp:356
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:352
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
Definition Function.cpp:807
size_t arg_size() const
Definition Function.h:886
Argument * getArg(unsigned i) const
Definition Function.h:871
const SIInstrInfo * getInstrInfo() const override
bool hasMadF16() const
unsigned getInstCacheLineSize() const
Instruction cache line size in bytes (64 for pre-GFX11, 128 for GFX11+).
const SIRegisterInfo * getRegisterInfo() const override
bool hasMin3Max3_16() const
bool supportsWaveWideBPermute() const
unsigned getMaxPrivateElementSize(bool ForBufferRSrc=false) const
bool isWave64() const
bool hasPrivateSegmentBuffer() const
const MachineFunction & getMachineFunction() const
void computeKnownBitsImpl(Register R, KnownBits &Known, const APInt &DemandedElts, unsigned Depth=0)
Evaluate a known-bits query with an explicit worklist instead of recursive descent.
bool isDivergentAtDef(ConstValueRefT V) const
Whether V is divergent at its definition.
LLVM_ABI unsigned getAddressSpace() const
const GlobalValue * getGlobal() const
bool hasExternalLinkage() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Definition Globals.cpp:205
Type * getValueType() const
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
Definition Globals.cpp:640
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2909
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
LLVM_ABI InstListType::iterator insertInto(BasicBlock *ParentBB, InstListType::iterator It)
Inserts an unlinked instruction into ParentBB at position It and returns the iterator of the inserted...
Class to represent integer types.
A wrapper class for inspecting calls to intrinsic functions.
constexpr unsigned getScalarSizeInBits() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
static LLT integer(unsigned SizeInBits)
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LLVM_ABI SyncScope::ID getOrInsertSyncScopeID(StringRef SSN)
getOrInsertSyncScopeID - Maps synchronization scope name to synchronization scope ID.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
static unsigned getPointerOperandIndex()
This class is used to represent ISD::LOAD nodes.
bool hasValue() const
TypeSize getValue() const
Describe properties that are true of each instruction in the target description file.
unsigned getID() const
getID() - Return the register class ID number.
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
iterator begin() const
begin/end - Return all of the registers in this class.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
LLVM_ABI MDNode * createRange(const APInt &Lo, const APInt &Hi)
Return metadata describing the range [Lo, Hi).
Definition MDBuilder.cpp:92
Metadata node.
Definition Metadata.h:1081
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1437
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
Machine Value Type.
SimpleValueType SimpleTy
uint64_t getScalarSizeInBits() const
bool bitsLE(MVT VT) const
Return true if this has no more bits than VT.
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
static auto all_valuetypes()
SimpleValueType Iteration.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
static MVT getVectorVT(MVT VT, unsigned NumElements)
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
Align getAlignment() const
Return alignment of the basic block.
MachineInstrBundleIterator< MachineInstr > iterator
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.
bool hasCalls() const
Return true if the current function has any function calls.
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
bool hasStackObjects() const
Return true if there are any stack objects in this function.
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
Representation of each machine instruction.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static MachineOperand CreateImm(int64_t Val)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
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.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
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...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI bool isLiveIn(Register Reg) const
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register getLiveInVirtReg(MCRegister PReg) const
getLiveInVirtReg - If PReg is a live-in physical register, return the corresponding live-in virtual r...
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
An SDNode that represents everything that will be needed to construct a MachineInstr.
This is an abstract virtual class for memory operations.
unsigned getAddressSpace() const
Return the address space for the associated pointer.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
EVT getMemoryVT() const
Return the type of the in-memory value.
bool onlyWritesMemory() const
Whether this function only (at most) writes memory.
Definition ModRef.h:252
bool doesNotAccessMemory() const
Whether this function accesses no memory.
Definition ModRef.h:246
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
Definition ModRef.h:249
const Triple & getTargetTriple() const
Get the target triple which is a string describing the target host.
Definition Module.h:328
The optimization diagnostic interface.
LLVM_ABI void emit(DiagnosticInfoOptimizationBase &OptDiag)
Output the remark via the diagnostic handler and to the optimization record file.
Diagnostic information for applied optimization remarks.
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
Definition Type.cpp:887
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
Definition Register.h:72
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool isDivergent() const
bool hasOneUse() const
Return true if there is exactly one use of this node.
value_iterator value_end() const
SDNodeFlags getFlags() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
op_iterator op_end() const
bool isAnyAdd() const
Returns true if the node type is ADD or PTRADD.
value_iterator value_begin() const
op_iterator op_begin() const
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isUndef() const
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
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
unsigned getNumOperands() const
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
const AMDGPUGWSResourcePseudoSourceValue * getGWSPSV(const AMDGPUTargetMachine &TM)
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
static bool isVGPRClass(const TargetRegisterClass *RC)
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
bool isTypeDesirableForOp(unsigned Op, EVT VT) const override
Return true if the target has native support for the specified value type and it is 'desirable' to us...
SDNode * PostISelFolding(MachineSDNode *N, SelectionDAG &DAG) const override
Fold the instructions after selecting them.
SDValue splitTernaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachineSDNode * wrapAddr64Rsrc(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr) const
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool requiresUniformRegister(MachineFunction &MF, const Value *V) const override
Allows target to decide about the register class of the specific value that is live outside the defin...
bool isFMADLegal(const SelectionDAG &DAG, const SDNode *N) const override
Returns true if be combined with to form an ISD::FMAD.
AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
void bundleInstWithWaitcnt(MachineInstr &MI) const
Insert MI into a BUNDLE with an S_WAITCNT 0 immediately following it.
SDValue lowerROTR(SDValue Op, SelectionDAG &DAG) const
MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override
Return the type to use for a scalar shift opcode, given the shifted amount type.
SDValue LowerCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
MVT getPointerTy(const DataLayout &DL, unsigned AS) const override
Map address space 7 to MVT::amdgpuBufferFatPointer because that's its in-memory representation.
bool denormalsEnabledForType(const SelectionDAG &DAG, EVT VT) const
void insertCopiesSplitCSR(MachineBasicBlock *Entry, const SmallVectorImpl< MachineBasicBlock * > &Exits) const override
Insert explicit copies in entry and exit blocks.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
SDNode * legalizeTargetIndependentNode(SDNode *Node, SelectionDAG &DAG) const
Legalize target independent instructions (e.g.
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
SDValue lowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const
const GCNSubtarget * getSubtarget() const
bool enableAggressiveFMAFusion(EVT VT) const override
Return true if target always benefits from combining into FMA for a given value type.
bool shouldEmitGOTReloc(const GlobalValue *GV) const
SDValue splitUnaryVectorOp(SDValue Op, SelectionDAG &DAG) const
SDValue lowerGET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool isCanonicalized(SelectionDAG &DAG, SDValue Op, SDNodeFlags UserFlags={}, unsigned MaxDepth=5) const
void allocateSpecialInputSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocateLDSKernelId(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue LowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const
bool isReassocProfitable(SelectionDAG &DAG, SDValue N0, SDValue N1) const override
void allocateHSAUserSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
ArrayRef< MCPhysReg > getRoundingControlRegisters() const override
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
ConstraintType getConstraintType(StringRef Constraint) const override
Given a constraint, return the type of constraint it is for this target.
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,...
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent) const override
Return the register class that should be used for the specified value type.
void AddMemOpInit(MachineInstr &MI) const
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
bool isLegalGlobalAddressingMode(const AddrMode &AM) const
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Return true if it is beneficial to convert a load of a constant to just the constant itself.
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
void emitExpandAtomicStore(StoreInst *SI) const override
Perform a atomic store using a target-specific way.
AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
Align computeKnownAlignForTargetInstr(GISelValueTracking &Analysis, Register R, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
Determine the known alignment for the pointer value R.
bool getAsmOperandConstVal(SDValue Op, uint64_t &Val) const
bool isShuffleMaskLegal(ArrayRef< int >, EVT) const override
Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations,...
void emitExpandAtomicLoad(LoadInst *LI) const override
Perform a atomic load using a target-specific way.
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const override
Determine known bits of a pointer to a known valid stack object.
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...
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
LLT getPreferredShiftAmountTy(LLT Ty) const override
Return the preferred type to use for a shift opcode, given the shifted amount type is ShiftValueTy.
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of extracting a subvector of type ResVT from a vector of type SrcVT,...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
Align getPrefLoopAlignment(MachineLoop *ML, const MachineBasicBlock *BlockToAlign) const override
Return the preferred loop alignment.
SDValue lowerSET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool shouldPreservePtrArith(const Function &F, EVT PtrVT) const override
True if target has some particular form of dealing with pointer arithmetic semantics for pointers wit...
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &, const CallBase &, MachineFunction &MF, unsigned IntrinsicID) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
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...
SDValue lowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
void allocateSpecialInputVGPRsFixed(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
Allocate implicit function VGPR arguments in fixed registers.
MachineBasicBlock * emitGWSMemViolTestLoop(MachineInstr &MI, MachineBasicBlock *BB) const
bool getAddrModeArguments(const IntrinsicInst *I, SmallVectorImpl< Value * > &Ops, Type *&AccessTy) const override
CodeGenPrepare sinks address calculations into the same BB as Load/Store instructions reading the add...
bool checkAsmConstraintValA(SDValue Op, uint64_t Val, unsigned MaxSize=64) const
bool shouldEmitFixup(const GlobalValue *GV) const
MachineBasicBlock * splitKillBlock(MachineInstr &MI, MachineBasicBlock *BB) const
void emitExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) const override
Perform a cmpxchg expansion using a target-specific method.
bool canTransformPtrArithOutOfBounds(const Function &F, EVT PtrVT) const override
True if the target allows transformations of in-bounds pointer arithmetic that cause out-of-bounds in...
bool hasMemSDNodeUser(SDNode *N) const
bool isSDNodeSourceOfDivergence(const SDNode *N, FunctionLoweringInfo *FLI, UniformityInfo *UA) const override
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
bool isEligibleForTailCallOptimization(SDValue Callee, CallingConv::ID CalleeCC, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SmallVectorImpl< ISD::InputArg > &Ins, SelectionDAG &DAG) const
bool isMemOpHasNoClobberedMemOperand(const SDNode *N) const
bool isLegalFlatAddressingMode(const AddrMode &AM, unsigned AddrSpace) const
SDValue LowerCallResult(SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals, bool isThisReturn, SDValue ThisVal) const
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
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...
bool isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode, EVT DestVT, EVT SrcVT) const override
Return true if an fpext operation input to an Opcode operation is free (for instance,...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
Assign the register class depending on the number of bits set in the writemask.
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
static bool isNonGlobalAddrSpace(unsigned AS)
void emitExpandAtomicAddrSpacePredicate(Instruction *AI) const
MachineSDNode * buildRSRC(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr, uint32_t RsrcDword1, uint64_t RsrcDword2And3) const
Return a resource descriptor with the 'Add TID' bit enabled The TID (Thread ID) is multiplied by the ...
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain targets require unusual breakdowns of certain types.
bool mayBeEmittedAsTailCall(const CallInst *) const override
Return true if the target may be able emit the call instruction as a tail call.
void passSpecialInputs(CallLoweringInfo &CLI, CCState &CCInfo, const SIMachineFunctionInfo &Info, SmallVectorImpl< std::pair< unsigned, SDValue > > &RegsToPass, SmallVectorImpl< SDValue > &MemOpChains, SDValue Chain) const
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...
bool checkAsmConstraintVal(SDValue Op, StringRef Constraint, uint64_t Val) const
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN=false, unsigned Depth=0) const override
If SNaN is false,.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
static bool shouldExpandVectorDynExt(unsigned EltSize, unsigned NumElem, bool IsDivergentIdx, const GCNSubtarget *Subtarget)
Check if EXTRACT_VECTOR_ELT/INSERT_VECTOR_ELT (<n x e>, var-idx) should be expanded into a set of cmp...
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool supportSplitCSR(MachineFunction *MF) const override
Return true if the target supports that a subset of CSRs for the given machine function is handled ex...
bool isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const
bool allowsMisalignedMemoryAccesses(LLT Ty, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const override
LLT handling variant.
bool canMergeStoresTo(unsigned AS, EVT MemVT, const MachineFunction &MF) const override
Returns if it's reasonable to merge stores to MemVT size.
SDValue lowerPREFETCH(SDValue Op, SelectionDAG &DAG) const
SITargetLowering(const TargetMachine &tm, const GCNSubtarget &STI)
void computeKnownBitsForTargetInstr(GISelValueTracking &Analysis, Register R, KnownBits &Known, const APInt &DemandedElts, const MachineRegisterInfo &MRI, 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 isFreeAddrSpaceCast(const DataLayout &DL, unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast from SrcAS to DestAS is "cheap", such that e.g.
bool shouldEmitPCReloc(const GlobalValue *GV) const
bool isUniformLoad(const LoadSDNode *Load) const
AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
void initializeSplitCSR(MachineBasicBlock *Entry) const override
Perform necessary initialization to handle a subset of CSRs explicitly via copies.
void allocateSpecialEntryInputVGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocatePreloadKernArgSGPRs(CCState &CCInfo, SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< ISD::InputArg > &Ins, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue copyToM0(SelectionDAG &DAG, SDValue Chain, const SDLoc &DL, SDValue V) const
SDValue splitBinaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const override
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
MVT getPointerMemTy(const DataLayout &DL, unsigned AS) const override
Similarly, the in-memory representation of a p7 is {p8, i32}, aka v8i32 when padding is added.
void allocateSystemSGPRs(CCState &CCInfo, MachineFunction &MF, SIMachineFunctionInfo &Info, CallingConv::ID CallConv, bool IsShader) const
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const override
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
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 ...
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
const SDValue & getRoot() const
Return the root tag of the SelectionDAG.
bool isKnownNeverSNaN(SDValue Op, const APInt &DemandedElts, unsigned Depth=0) const
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
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 MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
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 getAtomicLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO)
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI bool isConstantIntBuildVectorOrConstantInt(SDValue N, bool AllowOpaques=true) const
Test whether the given value is a constant int or similar node.
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr, unsigned SrcAS, unsigned DestAS, const SDNodeFlags Flags=SDNodeFlags())
Return an AddrSpaceCastSDNode.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI bool SignBitIsZeroFP(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero, for a floating-point value.
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO)
Gets a node for an atomic op, produces result (if relevant) and chain and takes 2 operands.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
const TargetLowering & getTargetLoweringInfo() const
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
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 getBitcastedAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by first bitcasting (from potentia...
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 void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
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 getTokenFactor(const SDLoc &DL, SmallVectorImpl< SDValue > &Vals)
Creates a new TokenFactor containing Vals.
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 SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
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 ...
LLVM_ABI void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
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,...
const TargetMachine & getTarget() const
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
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.
LLVM_ABI bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
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.
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getErrorMergeValues(ArrayRef< EVT > ResultTypes, SDValue Chain, const SDLoc &dl)
Return poison values for each of ResultTypes, substituting Chain for any result of type MVT::Other,...
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 getRegisterMask(const uint32_t *RegMask)
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 SDValue getCondCode(ISD::CondCode Cond)
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.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
int getMaskElt(unsigned Idx) const
ArrayRef< int > getMask() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
Definition SmallSet.h:176
bool empty() const
Definition SmallSet.h:169
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Information about stack frame layout on the target.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
TargetInstrInfo - Interface to description of machine instruction set.
Type * Ty
Same as OrigTy, or partially legalized for soft float libcalls.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
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...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual Align getPrefLoopAlignment(MachineLoop *ML=nullptr, const MachineBasicBlock *BlockToAlign=nullptr) const
Return the preferred loop alignment.
virtual unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
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 setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
Convenience method to set an operation to Promote and specify the type in a single call.
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setHasExtractBitsInsn(bool hasExtractInsn=true)
Tells the code generator that the target has BitExtract instructions.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
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/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
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...
virtual MVT getPointerMemTy(const DataLayout &DL, uint32_t AS=0) const
Return the in-memory pointer type for the given address space, defaults to the pointer type from the ...
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
LegalizeAction getOperationAction(unsigned Op, EVT VT) const
Return how this operation should be treated: either it is legal, needs to be promoted to a larger siz...
SDValue scalarizeVectorStore(StoreSDNode *ST, SelectionDAG &DAG) const
std::vector< AsmOperandInfo > AsmOperandInfoVector
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.
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
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.
SDValue expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminimumnum/fmaximumnum into multiple comparison with selects.
virtual bool isTypeDesirableForOp(unsigned, EVT VT) const
Return true if the target has native support for the specified value type and it is 'desirable' to us...
virtual void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const
Determine known bits of a pointer to a known valid stack object.
std::pair< SDValue, SDValue > scalarizeVectorLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Turn load of vector type into a load of the individual elements.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
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 MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
virtual AsmOperandInfoVector ParseConstraints(const DataLayout &DL, const TargetRegisterInfo *TRI, const CallBase &Call) const
Split up the constraint string from the inline assembly value into the specific constraints and their...
SDValue expandRoundInexactToOdd(EVT ResultVT, SDValue Op, const SDLoc &DL, SelectionDAG &DAG) const
Truncate Op to ResultVT.
virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, SDValue Op, SelectionDAG *DAG=nullptr) const
Determines the constraint code and constraint type to use for the specific AsmOperandInfo,...
SDValue annotateStackObjectPointer(SDValue Ptr, SelectionDAG &DAG, const SDLoc &DL, Align Alignment) const
Annotate a stack object pointer with known-bits assertions.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminnum/fmaxnum into fminnum_ieee/fmaxnum_ieee with quieted inputs.
Primary interface to the complete machine description for the target machine.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
const Triple & getTargetTriple() const
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
TargetOptions Options
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
OSType getOS() const
Get the parsed operating system type of this triple.
Definition Triple.h:524
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:348
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
Definition Type.h:147
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:363
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
Definition Type.h:144
bool isFunctionTy() const
True if this is an instance of FunctionType.
Definition Type.h:268
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
LLVM_ABI const fltSemantics & getFltSemantics() const
Definition Type.cpp:96
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
Definition Use.cpp:35
LLVM_ABI void set(Value *Val)
Definition Value.h:876
User * getUser() const
Returns the User that contains this Use.
Definition Use.h:61
const Use & getOperandUse(unsigned i) const
Definition User.h:220
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
bool hasOneUse() const
Return true if there is exactly one use of this value.
Definition Value.h:441
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:549
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:260
iterator_range< user_iterator > users()
Definition Value.h:428
bool use_empty() const
Definition Value.h:348
iterator_range< use_iterator > uses()
Definition Value.h:382
Type * getElementType() const
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:201
constexpr bool isKnownEven() const
A return value of true indicates we know at compile time that the number of elements (vscale * Min) i...
Definition TypeSize.h:177
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
self_iterator getIterator()
Definition ilist_node.h:123
CallInst * Call
#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.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ BARRIER
Address space for modeling barrier IDs as addresses.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ STREAMOUT_REGISTER
Internal address spaces. Can be freely renumbered.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char NumVGPRs[]
Key for Kernel::CodeProps::Metadata::mNumVGPRs.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
LLVM_READONLY const MIMGG16MappingInfo * getMIMGG16MappingInfo(unsigned G)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isShader(CallingConv::ID CC)
bool shouldEmitConstantsToTextSection(const Triple &TT)
bool isFlatGlobalAddrSpace(unsigned AS)
const uint64_t FltRoundToHWConversionTable
bool isGFX12Plus(const MCSubtargetInfo &STI)
unsigned getNSAMaxSize(const MCSubtargetInfo &STI, bool HasSampler)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
bool isGFX13(const MCSubtargetInfo &STI)
bool hasValueInRangeLikeMetadata(const MDNode &MD, int64_t Val)
Checks if Val is inside MD, a !range-like metadata.
LLVM_ABI IsaVersion getIsaVersion(StringRef GPU)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READNONE constexpr bool mayTailCallThisCC(CallingConv::ID CC)
Return true if we might ever do TCO for calls with this calling convention.
unsigned getAMDHSACodeObjectVersion(const Module &M)
LLVM_READONLY bool hasNamedOperand(uint32_t Opcode, OpName NamedIdx)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords, bool IndexedRsrc, bool IndexedSamp)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
bool getMUBUFTfe(unsigned Opc)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
LLVM_READONLY int32_t getGlobalSaddrOp(uint32_t Opcode)
bool isGFX11Plus(const MCSubtargetInfo &STI)
std::optional< unsigned > getInlineEncodingV2F16(uint32_t Literal)
std::tuple< char, unsigned, unsigned > parseAsmConstraintPhysReg(StringRef Constraint)
Returns a valid charcode or 0 in the first entry if this is a valid physical register constraint.
bool isGFX10Plus(const MCSubtargetInfo &STI)
bool isValidWMMAScaleFmtCombination(unsigned AFmt, unsigned AScale, unsigned BFmt, unsigned BScale)
bool isUniformMMO(const MachineMemOperand *MMO)
std::optional< unsigned > getInlineEncodingV2I16(uint32_t Literal)
uint32_t decodeFltRoundToHWConversionTable(uint32_t FltRounds)
Read the hardware rounding mode equivalent of a AMDGPUFltRounds value.
bool isExtendedGlobalAddrSpace(unsigned AS)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfo(unsigned DimEnum)
unsigned getBarrierMemberCountBitMask(const IsaVersion &Version)
std::optional< unsigned > getInlineEncodingV2BF16(uint32_t Literal)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
unsigned getSyntheticApertureNumber(unsigned AS)
LLVM_READNONE constexpr bool isChainCC(CallingConv::ID CC)
int getMaskedMIMGOp(unsigned Opc, unsigned NewChannels)
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool canGuaranteeTCO(CallingConv::ID CC)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
const RsrcIntrinsic * lookupRsrcIntrinsic(unsigned Intr)
const uint64_t FltRoundConversionTable
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
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_KERNEL
Used for AMDGPU code object kernels.
@ MaxID
The highest possible ID. Must be some 2^k - 1.
@ AMDGPU_Gfx
Used for AMD graphics targets.
@ AMDGPU_CS_ChainPreserve
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_CS_Chain
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:845
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
Definition ISDOpcodes.h:263
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ PTRADD
PTRADD represents pointer arithmetic semantics, for targets that opt in using shouldPreservePtrArith(...
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
Definition ISDOpcodes.h:47
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:238
@ SET_FPENV
Sets the current floating-point environment.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition ISDOpcodes.h:277
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:605
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:805
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ FMAD
FMAD - Perform a * b + c, while getting the same result as the separately rounded operations.
Definition ISDOpcodes.h:527
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:266
@ 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:879
@ ATOMIC_LOAD_USUB_COND
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:523
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
Definition ISDOpcodes.h:222
@ GlobalAddress
Definition ISDOpcodes.h:90
@ ATOMIC_CMP_SWAP_WITH_SUCCESS
Val, Success, OUTCHAIN = ATOMIC_CMP_SWAP_WITH_SUCCESS(INCHAIN, ptr, cmp, swap) N.b.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:906
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
Definition ISDOpcodes.h:589
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:420
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:765
@ 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:256
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ CONVERT_FROM_ARBITRARY_FP
CONVERT_FROM_ARBITRARY_FP - This operator converts from an arbitrary floating-point represented as an...
@ ATOMIC_LOAD_USUB_SAT
@ CTLZ_ZERO_POISON
Definition ISDOpcodes.h:814
@ SET_ROUNDING
Set rounding mode.
@ CONVERGENCECTRL_GLUE
This does not correspond to any convergence control intrinsic.
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:870
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition ISDOpcodes.h:675
@ READSTEADYCOUNTER
READSTEADYCOUNTER - This corresponds to the readfixedcounter intrinsic.
@ BR
Control flow instructions. These all have token chains.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
Definition ISDOpcodes.h:355
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition ISDOpcodes.h:546
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
Definition ISDOpcodes.h:553
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
Definition ISDOpcodes.h:377
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:822
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:235
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
Definition ISDOpcodes.h:249
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
Definition ISDOpcodes.h:232
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
Definition ISDOpcodes.h:351
@ CTLS
Count leading redundant sign bits.
Definition ISDOpcodes.h:818
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
Definition ISDOpcodes.h:996
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:714
@ GET_FPMODE
Reads the current dynamic floating-point control modes.
@ GET_FPENV
Gets the current floating-point environment.
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:787
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:659
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:619
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Same as FMINNUM/FMAXNUM, except that a signaling NaN operand deterministi...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:581
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
Definition ISDOpcodes.h:226
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:876
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:837
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Same semantics as the llvm.minnum/maxnum intrinsics.
@ SMULO
Same for multiplication.
Definition ISDOpcodes.h:359
@ 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:914
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:745
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:831
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
Definition ISDOpcodes.h:331
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ ATOMIC_LOAD_UDEC_WRAP
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
Definition ISDOpcodes.h:505
@ FMINIMUM
FMINIMUM/FMAXIMUM - Same semantics as the llvm.minimum/maximum intrinsics.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:952
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:510
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:757
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:207
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:570
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:55
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
Definition ISDOpcodes.h:813
@ ExternalSymbol
Definition ISDOpcodes.h:95
@ 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:985
@ SPONENTRY
SPONENTRY - Represents the llvm.sponentry intrinsic.
Definition ISDOpcodes.h:124
@ 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:971
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:882
@ BRCOND
BRCOND - Conditional branch.
@ CONVERT_TO_ARBITRARY_FP
CONVERT_TO_ARBITRARY_FP - Converts a native FP value to an arbitrary floating-point format,...
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
Definition ISDOpcodes.h:859
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:64
@ ATOMIC_LOAD_UINC_WRAP
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:539
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition ISDOpcodes.h:368
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - Same semantics as the llvm.minimumnum/maximumnum intrinsics.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition ISDOpcodes.h:215
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:561
CondCode getUnsignedSetCC(CondCode Code)
Convert a signed integer condition code to unsigned.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
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).
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
LLVM_ABI AttributeSet getFnAttributes(LLVMContext &C, ID id)
Return the function attributes for an intrinsic.
LLVM_ABI StringRef getBaseName(ID id)
Return the LLVM name for an intrinsic, without encoded types for overloading, such as "llvm....
LLVM_ABI AttributeList getAttributes(LLVMContext &C, ID id, FunctionType *FT)
Return the attributes for an intrinsic.
LLVM_ABI FunctionType * getType(LLVMContext &Context, ID id, ArrayRef< Type * > OverloadTys={})
Return the function type for an intrinsic.
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
GFCstOrSplatGFCstMatch m_GFCstOrSplat(std::optional< FPValueAndVReg > &FPValReg)
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
specific_fpval m_SpecificFP(double V)
Match a specific floating point value or vector with all elements equal to the value.
auto m_Value()
Match an arbitrary value and ignore it.
auto m_FAbs(const Opnd0 &Op0)
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
auto m_IntrinsicWOChain(const OpndPreds &...Opnds)
bool sd_match(SDValue N, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
Offsets
Offsets in bytes from the start of the input buffer.
@ System
Synchronized with respect to all concurrently executing threads.
Definition LLVMContext.h:66
initializer< Ty > init(const Ty &Val)
constexpr double inv_pi
@ User
could "use" a pointer
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< SSAContext > UniformityInfo
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
@ Offset
Definition DWP.cpp:577
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
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:1755
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
Definition STLExtras.h:856
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Known
Known to have no common set bits.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Done
Definition Threading.h:60
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).
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
Definition MathExtras.h:224
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition bit.h:325
SDValue peekFPSignOps(SDValue Val)
Strip fabs/fneg/fcopysign from a value to get the underlying source.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
static const MachineMemOperand::Flags MOCFSB1
Definition SIInstrInfo.h:71
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
Definition MathExtras.h:541
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
Definition ModRef.h:356
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
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
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
Definition MathExtras.h:274
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
Definition MathExtras.h:352
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
Definition SIInstrInfo.h:45
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
AtomicOrderingCABI
Atomic ordering for C11 / C++11's memory models.
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
bool isBoolSGPR(SDValue V)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:149
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
Definition SIInstrInfo.h:53
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI Value * buildAtomicRMWValue(AtomicRMWInst::BinOp Op, IRBuilderBase &Builder, Value *Loaded, Value *Val)
Emit IR to implement the given atomicrmw operation on values in registers, returning the new value.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
@ AfterLegalizeDAG
Definition DAGCombine.h:19
@ AfterLegalizeVectorOps
Definition DAGCombine.h:18
@ AfterLegalizeTypes
Definition DAGCombine.h:17
@ Or
Bitwise or logical OR of integers.
@ Mul
Product of integers.
@ Add
Sum of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
@ NearestTiesToEven
roundTiesToEven.
unsigned M0(unsigned Val)
Definition VE.h:376
ArrayRef(const T &OneElt) -> ArrayRef< T >
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 int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
Definition MathExtras.h:233
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 std::pair< Value *, Value * > buildCmpXchgValue(IRBuilderBase &Builder, Value *Ptr, Value *Cmp, Value *Val, Align Alignment, bool IsVolatile=false)
Emit IR to implement the given cmpxchg operation on values in registers, returning the new value.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
Definition Utils.cpp:436
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
std::optional< StringRef > getAtomicScopeIRString(const Triple &T, AtomicScope S, bool IsSingleAddressSpace=false)
Returns the LLVM IR syncscope string that T uses to spell S.
Definition AtomicScope.h:34
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
Definition SIInstrInfo.h:49
static const MachineMemOperand::Flags MOCFSB0
Use two MMO flags to encode the 2-bit cache fill size field for GFX13+.
Definition SIInstrInfo.h:68
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:206
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
constexpr RegState getUndefRegState(bool B)
@ Custom
The result value requires a custom uniformity check.
Definition Uniformity.h:31
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
int64_t DWordOffset
int64_t PermMask
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(PreloadedValue Value) const
static const AMDGPUFunctionArgInfo FixedABIFunctionInfo
static constexpr uint64_t encode(Fields... Values)
static std::tuple< typename Fields::ValueType... > decode(uint64_t Encoded)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
MCRegister getRegister() const
static ArgDescriptor createArg(const ArgDescriptor &Arg, unsigned Mask)
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
Helper struct shared between Function Specialization and SCCP Solver.
Definition SCCPSolver.h:42
Represents the full denormal controls for a function, including the default mode and the f32 specific...
Represent subnormal handling kind for floating point instruction inputs and outputs.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
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
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 bitsLT(EVT VT) const
Return true if this has less bits than VT.
Definition ValueTypes.h:323
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition ValueTypes.h:155
ElementCount getVectorElementCount() const
Definition ValueTypes.h:373
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
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
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
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
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
bool isVectorOf(EVT EltVT) const
Return true if this is a vector with matching element type.
Definition ValueTypes.h:181
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
Definition ValueTypes.h:165
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
unsigned getPointerAddrSpace() const
unsigned getByValSize() const
Align getNonZeroMemAlign() const
InputArg - This struct carries flags and type information about a single incoming (formal) argument o...
MVT VT
Legalized type of this argument part.
unsigned getOrigArgIndex() const
OutputArg - This struct carries flags and a value for a single outgoing (actual) argument or outgoing...
static LLVM_ABI std::optional< bool > eq(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_EQ result.
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
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
Definition KnownBits.h:361
KnownBits extractBits(unsigned NumBits, unsigned BitPosition) const
Return a subset of the known bits from [bitPosition,bitPosition+numBits).
Definition KnownBits.h:239
unsigned countMinLeadingZeros() const
Returns the minimum number of leading zero bits.
Definition KnownBits.h:262
static LLVM_ABI std::optional< bool > ule(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_ULE result.
static LLVM_ABI std::optional< bool > uge(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_UGE result.
bool isKnownNeverNaN() const
Return true if it's known this can never be a nan.
static LLVM_ABI KnownFPClass bitcast(const fltSemantics &FltSemantics, const KnownBits &Bits)
Report known values for a bitcast into a float with provided semantics.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:111
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoUnsignedWrap() const
bool hasAllowContract() const
bool hasNoSignedWrap() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
unsigned int NumVTs
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
std::optional< unsigned > fallbackAddressSpace
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs